ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/translat.txt
Revision: 1.1
Committed: Wed Sep 7 16:32:20 1994 UTC (29 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# User Rev Content
1 greg 1.1 TRANSLATING TO MGF FROM OTHER FORMATS
2     SCCSid "$SunId$ LBL"
3    
4     The description of the parser and the MGF specification should provide
5     enough information to get you started using MGF scene files, but we
6     thought it would be helpful to also provide some hints and
7     suggestions for translating to MGF from other formats.
8     Specifically, we will discuss several issues that come up repeatedly
9     when converting from more usual computer graphics scene formats to
10     MGF, most of them having to do with materials. First, let's look at
11     some geometry-related issues.
12    
13     Vertex Naming
14     =============
15     Many scene formats do not name vertices; many do not even share
16     vertices. Does it matter what names are given to vertices in MGF?
17     Not a lot, but it can affect memory and file size. In a way, vertex
18     sharing is nothing more than a form of file compression, and the
19     better you are at sharing vertex information, the smaller your file
20     will be. (Vertex sharing is also important for some rendering
21     algorithms, which depend on it for computing surface adjacency.)
22    
23     If you are translating from a format that shares unnamed vertices,
24     such as Wavefront's .OBJ format, you will want to name your MGF
25     vertices according to some simple pattern. In most cases, a name
26     such as "v%d" will do, where %d is replaced by an incremented
27     integer.
28    
29     If, on the other hand, you are translating from a format that does
30     not share vertices, you should do one of two things. You should
31     either select your MGF vertex names from a small, recycled pool of
32     names, or figure out some way to share vertices that were not shared
33     before. In the first case, you will just allocate as many vertex
34     names as you need for any given object, then reuse these names and
35     therefore the parsers memory for other objects. In the second case,
36     you will cache vertex names and values in some LRU table of
37     predetermined size, and use this table to merge vertices in the
38     file. (See rad2mgf.c as an example of how this can be done.)
39    
40     For some objects, there may be little point in merging vertices, and
41     you may want to treat these surfaces separately. For example,
42     putting out an MGF ring means putting out a central vertex, which
43     must have both a position point and a normal direction. It is somewhat
44     unlikely that any other MGF entity will share this point, and quite
45     unlikely that it will share the normal direction, so there is little
46     sense in trying to merge or otherwise reuse it.
47    
48     Points and Lines
49     ================
50     Although points and lines are really 3-d surfaces, many CAD
51     systems include them in their models. The question then is,
52     what do we do with these in MGF? If the idea is to produce a point
53     or line on the final display that is one or two pixels wide, there
54     is little one can do to guarantee such a thing will happen because
55     the pixel size is dependent on view and display parameters as well
56     as scene location.
57    
58     There are two ways of dealing with points and lines in MGF. The
59     first is to say, "Hey, these are 0 and 1 dimensional entities, so
60     they won't appear in 3 dimensions," and get rid of them. The second
61     approach is to assign some user-specified dimension for the "width"
62     of points and lines, and turn them into spheres and cylinders. It
63     might be best to instead create minimal polyhedron analogs, such as
64     tetrahedra for points and triangular prisms for lines. That way, an
65     itty-bitty point won't be converted into 200 polygons because the
66     translator reading in the MGF file can't handle curved surfaces.
67    
68     Polygons with Holes
69     ===================
70     There is no explicit representation of holes in MGF. A hole must be
71     represented implicitly by connecting vertices to form "seams." For
72     example, a wall with a window in it might look like this:
73    
74     v1.-----------------------------------------------.v4
75     | |
76     | v8.---------------.v5 |
77     | | | |
78     | | | |
79     | v7.---------------.v6 |
80     | |
81     | |
82     v2.-----------------------------------------------.v3
83    
84     In many systems, the wall itself would be represented with the first
85     list of vertices, (v1,v2,v3,v4) and the hole associated with that
86     wall as a second set of vertices (v5,v6,v7,v8). In MGF, we must
87     give the whole thing as a single polygon, connecting the vertices so
88     as to create a "seam," thus:
89    
90     v1.----------------------<------------------------.v4
91     | _____--><---'|
92     | v8.------->-------.v5 |
93     | | v |
94     v ^ | ^
95     | v7.-------<-------.v6 |
96     | |
97     | |
98     v2.---------------------->------------------------.v3
99    
100     which could be written in MGF as "f v1 v2 v3 v4 v5 v6 v7 v8 v5 v4".
101    
102     It is very important that the order of the hole be opposite to the
103     order of the outer perimeter, otherwise the polygon will be
104     "twisted" on top of itself. Note also that the seam was traversed
105     in both directions, once going from v4 to v5, and again returning
106     from v5 to v4. This is a necessary condition for a proper seam.
107     (The final edge from v4 back to v1 is implied in MGF.)
108    
109     The choice of vertices to make into a seam is somewhat arbitrary, but
110     some rendering systems may not give sane results if you cross over a
111     hole with part of your seam. If we had chosen to create the seam
112     between v2 and v5 in the above example instead of v4 and v5, the seam
113     would cross our hole and may not render correctly. (For systems that
114     are sensitive to this, it is probably necessary that their MGF
115     loader/translator re-expresses seams in terms of holes again, which can
116     be done easily so long as vertices are shared in the above fashion.)
117    
118     Non-planar Polygons
119     ===================
120     Polygons in MGF should be planar. There is nothing about the format
121     that enforces this, but the rendering or modeling software on the other
122     end may have real problems if this requirement is violated. The parser
123     itself does not test for non-planar polygons, so when in doubt about a
124     model it is safest to test for planarity and break a polygon into triangles
125     if it is even slightly non-planar.
126    
127     NURBS, CSG, Blobbies, Etc.
128     ==========================
129     Sorry, folks, this is just plain hard. If and until MGF supports these
130     higher-order entities, it will be necessary for you to convert them to
131     smoothed triangle meshes. Fortunately, a lot of modeling software
132     already knows how to do this, so if you wrote the modeler, you probably
133     have access to the necessary code. (By the way, if you ever want to see
134     these primitives in MGF, you might just think about sharing the wealth,
135     because the MGF parser needs to mesh every primitive it supports.)
136    
137     Materials
138     =========
139     The MGF material model was designed to accommodate most common
140     physical surfaces. Included are reasonable models for plastic
141     and metal, thin glass and translucent surfaces. Not included at
142     this time are surfaces with anisotropic reflection, refraction and/or
143     surface textures. These were deemed either unnecessary or too
144     difficult to standardize for the initial format. Also, light
145     sources are known only by the emissive nature of their surface(s),
146     and MGF itself only provides for diffuse emission. (As MGF is
147     destined to be part of the IES luminaire data standard, it was
148     assumed that this combined format would be used for such purposes as
149     describing light source output and geometry.)
150    
151     The "sides" entity is used to control the number of sides a surface
152     should have. In the real world, a surface can have only one side,
153     defining the interface between one volume and another. Many
154     object-space rendering packages (e.g. z-buffer algorithms) take
155     advantage of this fact by culling back-facing polygons and thus saving
156     roughly 50% of the calculation time. However, many models rely on an
157     approximation whereby a single surface is used to represent a very thin
158     volume, such as a pane of glass, and this also can provide significant
159     calculational savings in an image-space algorithm (such as
160     ray-tracing). Since both types of surfaces are useful and both types
161     of rendering algorithms may ultimately be applied, MGF provides a way
162     to specify sidedness rather than picking one model or the other.
163    
164     So-called specular reflection and transmission are modeled using a
165     Gaussian distribution of surface normals. The "alpha_r" and
166     "alpha_t" parameters to the respective "rs" and "ts" entities specify
167     the root-mean-squared (RMS) surface facet slope, which varies from 0
168     for a perfectly smooth surface to around .2 for a fairly rough one.
169     The effect this will have on the reflected component distribution is
170     well-defined, but predicting the behavior of the transmitted
171     component requires further assumptions. We assume that the surface
172     scatters light passing through it just as much as it scatters
173     reflected light. This assumption is approximately correct for a
174     two-sided transparent material with an index of refraction of 1.5
175     (about that of glass) and both sides having the given RMS facet
176     slope.
177    
178     Oftentimes, one is translating from a Phong exponent on the cosine
179     of the half-vector-to-normal angle to the more physical but less
180     familiar Gaussian model of MGF. The hardest part is translating
181     the specular power to a roughness value. For this, we recommend
182     the following approximation:
183    
184     roughness = 0.6/sqrt(specular_power)
185    
186     It's not a perfect correlation, but it's about as good as you can get.
187    
188     Colors
189     ======
190     Unlike most graphics languages, MGF does not use an RGB color model,
191     simply because there is no recognized definition for this model.
192     It is based on computer monitor phosphors, which vary from one
193     CRT to the next. (There is an RGB standard defined in the TV
194     industry, but this has a rather poor correlation to most graphics.)
195    
196     MGF uses two alternative, well-defined standards. The first is the CIE
197     standard for chromaticity coordinates. With this standard, any viewable
198     color may be exactly reproduced. Unfortunately, the interaction between
199     colors (i.e. colored light sources and interreflections) cannot be
200     specified exactly with any finite coordinate set, including CIE
201     chromaticities. So, MGF offers the ability to give reflectance,
202     transmittance or emittance as a function of wavelength over the visible
203     spectrum. This function is still discretized, but at a user-selectable
204     resolution. Furthermore, spectral colors may be mixed, providing (nearly)
205     arbitrary basis functions, which can produce more accurate results in
206     some cases and are a convenience in others.
207    
208     Conversion back and forth between CIE chromaticity coordinates and spectral
209     samples is provided within the MGF parser. Unfortunately, conversion
210     to and from RGB values depends on a particular RGB definition, and as we
211     have said, there is no recognized standard. We therefore recommend that
212     you decide yourself what chromaticity values to use for each RGB primary,
213     and adopt the following code to convert between CIE and RGB coordinates.
214    
215     #ifdef NTSC
216     #define CIE_x_r 0.670 /* standard NTSC primaries */
217     #define CIE_y_r 0.330
218     #define CIE_x_g 0.210
219     #define CIE_y_g 0.710
220     #define CIE_x_b 0.140
221     #define CIE_y_b 0.080
222     #define CIE_x_w 0.3333 /* monitor white point */
223     #define CIE_y_w 0.3333
224     #else
225     #define CIE_x_r 0.640 /* nominal CRT primaries */
226     #define CIE_y_r 0.330
227     #define CIE_x_g 0.290
228     #define CIE_y_g 0.600
229     #define CIE_x_b 0.150
230     #define CIE_y_b 0.060
231     #define CIE_x_w 0.3333 /* monitor white point */
232     #define CIE_y_w 0.3333
233     #endif
234    
235     #define CIE_D ( CIE_x_r*(CIE_y_g - CIE_y_b) + \
236     CIE_x_g*(CIE_y_b - CIE_y_r) + \
237     CIE_x_b*(CIE_y_r - CIE_y_g) )
238     #define CIE_C_rD ( (1./CIE_y_w) * \
239     ( CIE_x_w*(CIE_y_g - CIE_y_b) - \
240     CIE_y_w*(CIE_x_g - CIE_x_b) + \
241     CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g ) )
242     #define CIE_C_gD ( (1./CIE_y_w) * \
243     ( CIE_x_w*(CIE_y_b - CIE_y_r) - \
244     CIE_y_w*(CIE_x_b - CIE_x_r) - \
245     CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r ) )
246     #define CIE_C_bD ( (1./CIE_y_w) * \
247     ( CIE_x_w*(CIE_y_r - CIE_y_g) - \
248     CIE_y_w*(CIE_x_r - CIE_x_g) + \
249     CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r ) )
250    
251     #define CIE_rf (CIE_y_r*CIE_C_rD/CIE_D)
252     #define CIE_gf (CIE_y_g*CIE_C_gD/CIE_D)
253     #define CIE_bf (CIE_y_b*CIE_C_bD/CIE_D)
254    
255     float xyz2rgbmat[3][3] = { /* XYZ to RGB */
256     {(CIE_y_g - CIE_y_b - CIE_x_b*CIE_y_g + CIE_y_b*CIE_x_g)/CIE_C_rD,
257     (CIE_x_b - CIE_x_g - CIE_x_b*CIE_y_g + CIE_x_g*CIE_y_b)/CIE_C_rD,
258     (CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g)/CIE_C_rD},
259     {(CIE_y_b - CIE_y_r - CIE_y_b*CIE_x_r + CIE_y_r*CIE_x_b)/CIE_C_gD,
260     (CIE_x_r - CIE_x_b - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r)/CIE_C_gD,
261     (CIE_x_b*CIE_y_r - CIE_x_r*CIE_y_b)/CIE_C_gD},
262     {(CIE_y_r - CIE_y_g - CIE_y_r*CIE_x_g + CIE_y_g*CIE_x_r)/CIE_C_bD,
263     (CIE_x_g - CIE_x_r - CIE_x_g*CIE_y_r + CIE_x_r*CIE_y_g)/CIE_C_bD,
264     (CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r)/CIE_C_bD}
265     };
266    
267     float rgb2xyzmat[3][3] = { /* RGB to XYZ */
268     {CIE_x_r*CIE_C_rD/CIE_D,CIE_x_g*CIE_C_gD/CIE_D,CIE_x_b*CIE_C_bD/CIE_D},
269     {CIE_y_r*CIE_C_rD/CIE_D,CIE_y_g*CIE_C_gD/CIE_D,CIE_y_b*CIE_C_bD/CIE_D},
270     {(1.-CIE_x_r-CIE_y_r)*CIE_C_rD/CIE_D,
271     (1.-CIE_x_g-CIE_y_g)*CIE_C_gD/CIE_D,
272     (1.-CIE_x_b-CIE_y_b)*CIE_C_bD/CIE_D}
273     };
274    
275    
276     cie_rgb(rgbcolor, ciecolor) /* convert CIE to RGB */
277     register float *rgbcolor, *ciecolor;
278     {
279     register int i;
280    
281     for (i = 0; i < 3; i++) {
282     rgbcolor[i] = xyz2rgbmat[i][0]*ciecolor[0] +
283     xyz2rgbmat[i][1]*ciecolor[1] +
284     xyz2rgbmat[i][2]*ciecolor[2] ;
285     if (rgbcolor[i] < 0.0)
286     rgbcolor[i] = 0.0;
287     }
288     }
289    
290    
291     rgb_cie(ciecolor, rgbcolor) /* convert RGB to CIE */
292     register float *ciecolor, *rgbcolor;
293     {
294     register int i;
295    
296     for (i = 0; i < 3; i++)
297     ciecolor[i] = rgb2xyzmat[i][0]*rgbcolor[0] +
298     rgb2xyzmat[i][1]*rgbcolor[1] +
299     rgb2xyzmat[i][2]*rgbcolor[2] ;
300     }
301    
302     Another alternative is to use the MGF "cmix" entity to convert from RGB
303     directly by naming the three primaries in terms of their chromaticities, e.g:
304    
305     c r =
306     cxy 0.640 0.330
307     c g =
308     cxy 0.290 0.600
309     c b =
310     cxy 0.150 0.060
311    
312     Then, converting from RGB to MGF colors is as simple as multiplying each
313     component by its relative luminance in a cmix statement, for instance:
314    
315     c white =
316     cmix 0.265 r 0.670 g 0.065 b
317    
318     For the chosen RGB standard, the above specification would result a pure
319     white. The reason the coefficients are not all 1 as you might expect is
320     that cmix uses relative luminance as the standard for its weights. Since
321     blue is less luminous for the same energy than red, which is in turn
322     less luminous than green, the weights cannot be the same to achieve an
323     even spectral balance. Unfortunately, computing these relative weights
324     is not straightforward, so it is given in the above macros as CIE_rf,
325     CIE_gf and CIE_bf.