ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/mgfdoc.tr
Revision: 1.18
Committed: Fri Mar 21 12:32:30 1997 UTC (27 years, 1 month ago) by greg
Content type: application/x-troff
Branch: MAIN
Changes since 1.17: +15 -0 lines
Log Message:
small cleanup suggested by Philippe B.

File Contents

# User Rev Content
1 greg 1.1 .\" SCCSid "$SunId$ LBL"
2     .nr PS 11
3     .ps 11
4     .nr VS 12
5     .vs 12
6     .nr PD .5v
7     .ds LF MGF
8 greg 1.13 .ds RF Version 1.1
9     .\" !Remember to update date on each modification!
10     .DA February 1996
11 greg 1.1 .TL
12     The Materials and Geometry Format
13     .AU
14     Greg Ward
15     .br
16     Lawrence Berkeley Laboratory
17     .NH
18     Introduction
19     .LP
20     The Materials and Geometry Format (referred to henceforth as MGF)
21     is a description language for 3-dimensional environments expressly
22     suited to visible light simulation and rendering.
23     The materials are physically-based and rely on standard and
24     well-accepted definitions of color, reflectance and transmittance
25     for good accuracy and reproducibility.
26     The geometry is based on boundary representation using simple
27     geometric primitives such as polygons, spheres and cones.
28     The file format itself is terse but human-readable ASCII text.
29     .NH 2
30     What makes MGF special?
31     .LP
32     There are three principal reasons to use MGF as an input language for
33     lighting simulation and physically-based rendering:
34     .RS
35     .IP 1.
36     It's the only existing format that describes materials physically.
37     .IP 2.
38     It is endorsed by the Illuminating Engineering Society of North
39     America (IESNA) as part of their LM-63-1995 standard for luminaire data.
40     .IP 3.
41     It's easy and fun to support since it comes with a standard parser
42     and sample scenes and objects at the web site,
43     "http://radsite.lbl.gov/mgf/HOME.html".
44     .RE
45     .LP
46 greg 1.13 The standard parser provides both immediate and long-term
47 greg 1.1 benefits, since it presents a programming interface that is more
48     stable even than the language itself.
49     Unlike AutoCAD DXF and other de facto standards, a change to the
50     language will not break existing programs.
51     This is because the parser gives the calling software only those
52     entities it can handle.
53     If the translator understands only polygons, it will be given only
54     polygons.
55     If a new geometric primitive is included in a later version of the
56     standard, the new parser that comes with it will still be able to
57     express this entity as polygons.
58     Thus, the urgency of modifying code to support a changing standard
59     is removed, and long-term stability is assured.
60     .LP
61     This notion of
62     .I extensibility
63     is a cornerstone of the format, and it goes well beyond the
64     extensibility of other languages because is guarantees that new
65     versions of the standard will not break existing programs, and the
66     new information will be used as much as possible.
67     Other languages either require that all translators stay up to date
68     with the latest standard, or allow forward compatibility by simply
69     .I ignoring
70     new entities.
71     In MGF, if NURBS are added at some point and the translator or
72     loader does not handle them directly, the new version of the parser
73     will automatically convert them to smoothed polygons without
74     changing a single line of the calling program.
75     It is merely necessary to link to the new library, and all the new
76     entities are supported\(dg.
77     .FS
78     \(dgIf an old version of the parser encounters new entities it does
79     not recognize, the default action is to ignore them, printing a warning
80     message.
81     This may be overridden to support custom entities, but such
82     practice is discouraged because it weakens the standard.
83     .FE
84     .NH 2
85     What does MGF look like?
86     .LP
87     MGF has a simple entity-per-line structure, with a similar
88     appearance to Wavefront's .OBJ format.
89     Each entity is specified by a short keyword, and
90     arguments are separated by white space (tabs and/or spaces).
91     A newline may be escaped with a backslash ('\\'), in which case it
92     counts as a space.
93     Lines and continued lines may have up to 4096 characters, including
94     newlines, tabs and spaces.
95     A comment is an ignored entity whose keyword is the pound sign ('#').
96     .LP
97     Here is an MGF file that describes a simple two-drawer file cabinet:
98     .DS
99     # Conversion from inches to meters
100     xf -s .0254
101     # Surface material
102     m burgundy_formica =
103     c
104     cxy .362 .283
105     rd .0402
106     c
107     rs .0284 .05
108     sides 1
109     # Cabinet vertices
110     v fc.xy =
111     p .05 0 0
112     v fc.xY =
113     p .05 18 0
114     v fc.XY =
115     p 35.95 18 0
116     v fc.Xy =
117     p 35.95 0 0
118     # Cabinet
119     prism fc.xy fc.xY fc.XY fc.Xy 24
120     # Drawer vertices
121     v fcd.Xz =
122     p 34 0 0
123     v fcd.XZ =
124     p 34 0 10
125     v fcd.xZ =
126     p 0 0 10
127     v fcd.xz =
128     p 0 0 0
129     # Two drawers
130     o drawer
131     xf -t 1 18.1 2 -a 2 -t 0 0 11
132     prism fcd.xz fcd.Xz fcd.XZ fcd.xZ .9
133     xf
134     o
135     # End of units conversion
136     xf
137     .DE
138     .NH 2
139     MGF's place in the world of standards
140     .LP
141     MGF was developed initially to support detailed geometric
142     description of light fixtures for the IESNA luminaire data standard,
143     publication LM-63\(dg.
144     .FS
145     \(dgTo obtain the latest version of this standard, write to:
146     Illuminating Engineering Society of North America,
147     345 East 47th St.,
148     New York, NY 10017.
149     .FE
150     Existing standards for geometric description were either too
151     cumbersome (e.g.
152     .I Radiance)
153     or did not include physical materials (e.g. IGES).
154     It was noted early on that a standard able to fully describe
155     luminaires would necessarily be
156     capable of describing other objects as well; indeed whole
157     environments could be defined this way.
158     Since the descriptions would be physical, they could serve as input
159     to both lighting simulation and rendering software.
160     A standard language for describing the appearance of physical
161     objects has been lacking for some time, and current efforts in this
162     direction (i.e. STEP) seem several years away from fruition.
163     (There are other languages for describing realistic scenes
164     that deserve mention here, such as VRML and the Manchester Scene
165     Description Language, but none give specific attention to physical
166     material properties and are thus unsuitable for lighting
167     simulation.)\0
168     .LP
169     In short, we saw this as an opportunity to offer the lighting and
170     rendering community a simple and easy-to-support standard for
171     describing environments in a physically valid way.
172     Our hope is that this will promote sharing color, material and object
173     libraries as well as complete scene descriptions.
174     Sharing libraries is of obvious benefit to users and software
175     developers alike.
176     Sharing scenes should also permit
177     comparisons between rendering systems and
178     intervalidation of lighting calculations.
179     As anyone who works in this field knows, modeling is the most
180     difficult step in creating any simulation or rendering, and there is
181     no excuse for this data being held prisoner by a proprietary data
182     format.
183     .NH
184     MGF Basics
185     .LP
186     The default coordinate system in MGF is right-handed with
187     distances given in meters, though this can be effectively changed
188     by specifying a global transformation.
189     The transformation context is affected by the
190     .UL xf
191     entity, and the whole of MGF can be understood in terms of entities
192     and contexts.
193     .NH 2
194     Entities and Contexts
195     .LP
196     An
197     .I entity
198     in MGF is any non-blank line, which must be one of a finite set of
199     command keywords followed by zero or more arguments.
200     (As mentioned previously, an entity may continue over multiple lines
201     by escaping the newline with a backslash.)\0
202     Table 1 gives a list of entities and their expected arguments.
203     Section 3 gives more detailed information on each entity.
204     .KF
205     .TS
206     expand, box;
207     l l l.
208     Keyword Arguments Interpretation
209     = = =
210     # [anything ...] a comment
211     o [name] begin/end object context
212     xf [xform] begin/end transformation context
213     i pathname [xform] include file (with transformation)
214     ies pathname [-m f][xform] include IES luminaire (with transformation)
215     _ _ _
216     c [id [= [template]]] get/set color context
217     cxy x y set CIE (x,y) chromaticity for current color
218     cspec l_min l_max v1 v2 ... set relative spectrum for current color
219     cct temperature set spectrum based on black body temperature
220     cmix w1 c1 w2 c2 ... mix named colors to make current color
221     _ _ _
222     m [id [= [template]]] get/set material context
223     sides {1|2} set number of sides for current material
224     rd rho_d set diffuse reflectance for current material
225     td tau_d set diffuse transmittance for current material
226     ed epsilon_d set diffuse emittance for current material
227     rs rho_s alpha_r set specular reflectance for current material
228     ts tau_s alpha_t set specular transmittance for current material
229     ir n_real n_imag set index of refraction for current material
230     _ _ _
231     v [id [= [template]]] get/set vertex context
232     p x y z set point position for current vertex
233     n dx dy dz set surface normal for current vertex
234     _ _ _
235     f v1 v2 v3 ... polygon using current material, spec. vertices
236 greg 1.16 fh v1 v2 v3 - ... face with explicit holes
237 greg 1.1 sph vc radius sphere
238     cyl v1 radius v2 truncated right cylinder (open-ended)
239     cone v1 rad1 v2 rad2 truncated right cone (open-ended)
240     prism v1 v2 v3 ... length truncated right prism (closed solid)
241     ring vc rmin rmax circular ring with inner and outer radii
242     torus vc rmin rmax circular torus with inner and outer radii
243     .TE
244     .QP
245     .B "Table 1".
246     MGF entities and their arguments.
247     Arguments in brackets are optional.
248     Arguments in curly braces mean one of the given choices must
249     appear.
250     Ellipsis (...) mean that any number of arguments may be given.
251     .sp
252     .KE
253     .LP
254     A
255     .I context
256     describes the current state of the interpreter, and affects or is
257     affected by certain entities as they are read in.
258     MGF contexts can be divided into two types,
259     .I "hierarchical contexts"
260     and
261     .I "named contexts".
262     .LP
263     Hierarchical contexts are manipulated by a single entity and
264     have an associated "stack" onto which new
265     contexts are "pushed" using the entity.
266     The last context may be "popped" by giving the entity again with no
267     arguments.
268     The two hierarchical contexts in MGF are the current transformation,
269     manipulated with the
270     .UL xf
271     entity, and the current object, manipulated with the
272     .UL o
273     entity.
274     .KF
275     .TS
276     expand, allbox;
277     l c l l l.
278     Context Cntl. Entity Default Value Field Entities Affects
279     = = = = =
280     Object o - - -
281     Transform xf - - T{
282 greg 1.17 f, fh, sph, cyl, cone,
283 greg 1.1 ring, torus, prism
284     T}
285     Material m 2-sided black T{
286     sides, rd, td,
287 greg 1.14 ed, rs, ts, ir
288 greg 1.1 T} T{
289 greg 1.17 f, fh, sph, cyl, cone,
290 greg 1.1 ring, torus, prism
291     T}
292     Color c neutral grey T{
293     cxy, cspec, cct, cmix
294     T} T{
295     rd, td, ed, rs, ts
296     T}
297     Vertex v T{
298     (0,0,0),
299     no normal
300     T} p, n T{
301 greg 1.17 f, fh, sph, cyl, cone,
302 greg 1.1 ring, torus, prism
303     T}
304     .TE
305     .QP
306     .B "Table 2".
307     MGF contexts and their related entities and default values.
308     .sp
309     .KE
310     .LP
311     Named contexts in contrast hold sets of values that are swapped
312     in and out one at a time.
313     There are three named contexts in MGF, the current material, the
314     current color and the current vertex.
315     Each one may be associated with an identifier (any non-white
316     sequence of printing ASCII characters beginning with a letter),
317     and one of each is in effect at any given time.
318     Initially, these contexts are unnamed, and invoking an unnamed
319     context always returns to the original (default) values.
320     (See Table 2 for a list of contexts, their related
321     entities and defaults.)\0
322     .LP
323     It is easiest to think of a context as a "scratch space" where
324     values are written by some entities and read by others.
325     Naming a context allows us to reestablish the same scratch space
326     later, usually for reference but it can be altered as well.
327     Let us say we wanted to create a smooth blue plastic material with a
328     diffuse reflectance of 20% and a specular reflectance of 4%:
329     .DS
330     # Establish a new material context called "blue_plastic"
331     m blue_plastic =
332     # Reestablish a previous color context called "blue"
333     c blue
334     # Set the diffuse reflectance, which uses the above color
335     rd .20
336     # Get the unnamed color context (always starts out grey)
337     c
338     # Set the specular reflectance, which is uncolored
339     rs .04 0
340     # We're done, the current material context is now "blue_plastic"
341     .DE
342     Note that the above assumes that we have previously defined a color
343     context named "blue".
344     If we forgot to do that, the above description would generate an
345     "undefined" error.
346     The color context affects the material context indirectly because it
347     is read by the specular and diffuse reflectance entities, which are
348     in turn written to the current material.
349     It is not necessary to indent the entities that affect the material
350     definition, but it improves readability.
351     Note also that there is no explicit end to the material definition.
352     As long as a context remains in effect, its contents may be altered
353     by its field entities.
354     This will not affect previous uses of the context, however.
355     For example, a surface entity following the above definition will
356     have the specified color and reflectance, and later changes to the
357     material "blue_plastic" will have no effect on it.
358     .LP
359     Each of the three named contexts has an associated entity that
360     controls it.
361     The material context is controlled by the
362     .UL m
363     entity, the color context is controlled by the
364     .UL c
365     entity, and the vertex context is controlled by the
366     .UL v
367     entity.
368     There are exactly four forms for each entity.
369     The first form is the keyword by itself, which establishes
370     an unnamed context with predetermined default values.
371     This is a useful way to set values without worrying about saving
372     them for recall later.
373     The second form is to give the keyword with a previously defined
374     name.
375     This reestablishes a prior context for reuse.
376     The third form is to give the keyword with a name followed by an
377     equals sign.
378     (There must be a space between the name and the equals sign, since
379     it is a separate argument.)\0
380     This establishes a new context and assigns it the same default
381     values as the unnamed context.
382     The fourth and final form gives the keyword followed by a name then
383     an equals then the name of a previous context definition.
384     This establishes a new context for the first name, assigning the
385     values from the second named context rather than the usual defaults.
386     This is a convenient way create an alias or
387     to modify a context under a new name (i.e. "save as").
388     .NH 2
389     Hierarchical Contexts and Transformations
390     .LP
391     As mentioned in the last subsection, there are two hierarchical
392     contexts in MGF, the current object and the current transformation.
393     We will start by discussing the current object, since it is
394     the simpler of the two.
395     .NH 3
396     Objects
397     .LP
398     There is no particular need in lighting simulation or rendering to
399     name objects, but it may help the user
400     to know what object a particular surface is associated with.
401     The
402     .UL o
403     entity provides a convenient mechanism for associating names with
404     surfaces.
405     The basic use of this entity is as follows:
406     .DS
407     o object_name
408     [object entities...]
409     o subobject_name
410     [subobject entities...]
411     o
412     [more object entities and subobjects...]
413     o
414     .DE
415     The
416     .UL o
417     keyword by itself marks the end of an object context.
418     Any number of hierarchical context levels are supported, and there are no
419     rules governing the choice of object names except that they begin
420     with a letter and be made up of printing, non-white ASCII characters.
421     Indentation is not necessary of course, but it does improve
422     readability.
423     .NH 3
424     Transformations
425     .LP
426     MGF supports only rigid-body (i.e. non-distorting) transformations
427     with uniform scaling.
428     Unlike the other contexts, transformations have no associated
429     name, only arguments.
430     Thus, there is no way to reestablish a previous transformation other
431     than to give the same arguments over again.
432     Since the arguments are concise and self-explanatory, this was thought
433     sufficient.
434     The following transformation flags and
435     parameters are defined:
436 greg 1.2 .TS
437     center;
438 greg 1.1 l l.
439     -t dx dy dz translate objects along the given vector
440     -rx degrees rotate objects about the X-axis
441     -ry degrees rotate objects about the Y-axis
442     -rz degrees rotate objects about the Z-axis
443     -s scalefactor scale objects by the given factor
444     -mx mirror objects about the Y-Z plane
445     -my mirror objects about the X-Z plane
446     -mz mirror objects about the X-Y plane
447     -i N repeat the following arguments N times
448     -a N make an array of N geometric instances
449     .TE
450     Transform arguments have a cumulative effect.
451     That is, a rotation
452     about X of 20 degrees followed by a rotation about X of -50 degrees
453     results in a total rotation of -30 degrees.
454     However, if the two
455     rotations are separated by some translation vector, the cumulative
456     effect is quite different.
457     It is best to think of each argument as
458     acting on the included geometric objects, and each subsequent transformation
459     argument affects the objects relative to their new position/orientation.
460     .LP
461     For example, rotating an object about its center is most easily done
462     by translating
463     the object back to the origin, applying the desired rotation, and translating
464     it again back to its original position, like so:
465     .DS
466     # rotate an included object 20 degrees clockwise looking down
467     # an axis parallel to Y and passing through the point (15,0,-35)
468     xf -t -15 0 35 -ry -20 -t 15 0 -35
469     i object.mgf
470     xf
471     .DE
472     Note that the include entity,
473     .UL i,
474     permits a transformation to be given with it, so the above could
475     have been written more compactly as:
476     .DS
477     i object.mgf -t -15 0 35 -ry -20 -t 15 0 -35
478     .DE
479     .LP
480     Rotations are given in degrees counter-clockwise about a principal axis.
481     That is, with the thumb of the right hand pointing in the direction
482     of the axis, rotation follows the curl of the fingers.
483     .LP
484     The transform entity itself is cumulative, but in the reverse
485     order to its arguments.
486     That is, later transformations (i.e. enclosed transformations)
487     are prepended to existing (i.e. enclosing) ones.
488     A transform command
489     with no arguments is used to return to the previous condition.
490     It is
491     necessary that transforms and their end statements ("xf" by itself) be
492     balanced in a file, so that later or enclosing files are not affected.
493     .LP
494     Transformations apply only to geometric types, e.g. polygons, spheres, etc.
495     Vertices and the components that go into geometry are not directly affected.
496     This is to avoid confusion and the inadvertent multiple application of a
497     given transformation.
498     For example:
499     .DS
500     xf -t 5 0 0
501     v v1 =
502     p 0 10 0
503     n 0 0 1
504     xf -rx 180
505     # Transform now in effect is "-rx 180 -t 5 0 0"
506     ring v1 0 2
507     xf
508     xf
509     .DE
510     The final ring center is (5,-10,0) -- note that the vertex itself is
511     not affected by the transformation, only the geometry that calls on
512     it.
513     The normal orientation is (0,0,-1) due to the rotation about X,
514     which also reversed the sign of the central Y coordinate.
515     .NH 3
516     Arrays
517     .LP
518     The -a N transform specification causes the following transform
519     arguments to be repeated along with the contents of the included
520     objects N times.
521     The first instance of the geometry will be in its
522     initial location; the second instance will be repositioned according
523     to the named transformation; the third instance will be repositioned by
524     applying this transformation twice, and so on up to N-1 applications.
525     .LP
526     Multi-dimensional arrays may be specified with a single include
527     entity by giving multiple array commands separated by their
528     corresponding transforms.
529     A final transformation may be given
530     by preceding it with a -i 1 specification.
531     In other words, the
532     scope of an array command continues until the next -i or -a option.
533     .LP
534     The following MGF description places 60 spheres at a one unit spacing
535     in a 3x4x5 array, then moves the whole thing to an origin of
536     (15,30,45):
537     .DS
538     v v0 =
539     p 0 0 0
540     xf -a 3 -t 1 0 0 -a 4 -t 0 1 0 -a 5 -t 0 0 1 -i 1 -t 15 30 45
541     sph v0 0.1
542     xf
543     .DE
544     Note the "-i 1" in the specification, which marks the end of the
545     third array arguments before the final translation.
546     .NH 2
547     Detailed MGF Example
548     .LP
549     The following example of a simple room with a single door
550     and six file cabinets shows MGF in action, with copious comments to
551     help explain what's going on.
552 greg 1.2 .LP
553 greg 1.1 .DS
554     # "ceiling_tile" is a diffuse white surface with 75% reflectance:
555     # Create new named material context and clear it
556     m ceiling_tile =
557     # Specify one-sided material so we can see through from above
558     sides 1
559     # Set neutral color
560     c
561     # Set diffuse reflectance
562     rd .75
563     # "stainless_steel" is a mostly specular surface with 70% reflectance:
564     m stainless_steel =
565     sides 1
566     c
567     # Set specular reflectance to 50%, .08 roughness
568     rs .5 .08
569     # Other 20% reflectance is diffuse
570     rd .2
571    
572     # The following materials were measured with a spectrophotometer:
573     m beige_paint =
574     sides 1
575     # Set diffuse spectral reflectance
576     c
577     # Spectrum measured in 10 nm increments from 400 to 700 nm
578     cspec 400 700 35.29 44.87 47.25 47.03 46.87 47.00 47.09 \\\\
579     47.15 46.80 46.17 46.26 48.74 51.08 51.31 51.10 \\\\
580     51.11 50.52 50.36 51.72 53.61 53.95 52.08 49.49 \\\\
581     48.30 48.75 49.99 51.35 52.75 54.44 56.34 58.00
582     rd 0.5078
583     # Neutral (grey) specular component
584     c
585     rs 0.0099 0.08000
586     m mottled_carpet =
587     sides 1
588     c
589     cspec 400 700 11.23 11.28 11.39 11.49 11.61 11.73 11.88 \\\\
590     12.02 12.12 12.19 12.30 12.37 12.37 12.36 12.34 \\\\
591     12.28 12.22 12.29 12.45 12.59 12.70 12.77 12.82 \\\\
592     12.88 12.98 13.24 13.67 14.31 15.55 17.46 19.75
593     rd 0.1245
594     m reddish_cloth =
595     # 2-sided so we can observe it from behind
596     sides 2
597     c
598     cspec 400 700 28.62 27.96 27.86 28.28 29.28 30.49 31.61 \\\\
599     32.27 32.26 31.83 31.13 30.07 29.14 29.03 29.69 \\\\
600     30.79 32.30 33.90 34.56 34.32 33.85 33.51 33.30 \\\\
601     33.43 34.06 35.26 37.04 39.41 42.55 46.46 51.00
602     rd 0.3210
603     m burgundy_formica =
604     sides 1
605     c
606     cspec 400 700 3.86 3.74 3.63 3.51 3.34 3.21 3.14 \\\\
607     3.09 3.08 3.14 3.13 2.91 2.72 2.74 2.72 \\\\
608     2.60 2.68 3.40 4.76 6.05 6.65 6.75 6.68 \\\\
609     6.63 6.56 6.51 6.46 6.41 6.36 6.34 6.34
610     rd 0.0402
611     c
612     rs 0.0284 0.05000
613     m speckled_grey_formica =
614     sides 1
615     c
616     cspec 400 700 30.95 44.77 51.15 52.60 53.00 53.37 53.68 \\\\
617     54.07 54.33 54.57 54.85 55.20 55.42 55.51 55.54 \\\\
618     55.46 55.33 55.30 55.52 55.81 55.91 55.92 56.00 \\\\
619     56.22 56.45 56.66 56.72 56.58 56.44 56.39 56.39
620     rd 0.5550
621     c
622     rs 0.0149 0.15000
623    
624     # 40' x 22' x 9' office space with no windows and one door
625    
626     # All measurements are in inches, so enclose with a metric conversion:
627     xf -s .0254
628    
629     # The room corner vertices:
630     v rc.xyz =
631     p 0 0 0
632     v rc.Xyz =
633     p 480 0 0
634     v rc.xYz =
635     p 0 264 0
636     v rc.xyZ =
637     p 0 0 108
638     v rc.XYz =
639     p 480 264 0
640     v rc.xYZ =
641     p 0 264 108
642     v rc.XyZ =
643     p 480 0 108
644     v rc.XYZ =
645     p 480 264 108
646    
647     # The floor:
648     # Push object name
649     o floor
650     # Get previously defined carpet material
651     m mottled_carpet
652     # Polygonal face using defined vertices
653     f rc.xyz rc.Xyz rc.XYz rc.xYz
654     # Pop object name
655     o
656    
657     # The ceiling:
658     o ceiling
659     m ceiling_tile
660     f rc.xyZ rc.xYZ rc.XYZ rc.XyZ
661     o
662    
663     # The door outline vertices:
664     v do.xz =
665     p 216 0 0
666     v do.Xz =
667     p 264 0 0
668     v do.xZ =
669     p 216 0 84
670     v do.XZ =
671     p 264 0 84
672    
673     # The walls:
674     o wall
675     m beige_paint
676     o x
677     f rc.xyz rc.xYz rc.xYZ rc.xyZ
678     o
679     o X
680     f rc.Xyz rc.XyZ rc.XYZ rc.XYz
681     o
682     o y
683     f rc.xyz rc.xyZ rc.XyZ rc.Xyz do.Xz do.XZ do.xZ do.xz
684     o
685     o Y
686     f rc.xYz rc.XYz rc.XYZ rc.xYZ
687     o
688     o
689    
690     # The door and jam vertices:
691     v djo.xz =
692     p 216 .5 0
693     v djo.xZ =
694     p 216 .5 84
695     v djo.XZ =
696     p 264 .5 84
697     v djo.Xz =
698     p 264 .5 0
699     v dji.Xz =
700     p 262 .5 0
701     v dji.XZ =
702     p 262 .5 82
703     v dji.xZ =
704     p 218 .5 82
705     v dji.xz =
706     p 218 .5 0
707     v door.xz =
708     p 218 0 0
709     v door.xZ =
710     p 218 0 82
711     v door.XZ =
712     p 262 0 82
713     v door.Xz =
714     p 262 0 0
715    
716     # The door, jam and knob
717     o door
718     m burgundy_formica
719     f door.xz door.xZ door.XZ door.Xz
720     o jam
721     m beige_paint
722     f djo.xz djo.xZ djo.XZ djo.Xz dji.Xz dji.XZ dji.xZ dji.xz
723     f djo.xz do.xz do.xZ djo.xZ
724     f djo.xZ do.xZ do.XZ djo.XZ
725     f djo.Xz djo.XZ do.XZ do.Xz
726     f dji.xz dji.xZ door.xZ door.xz
727     f dji.xZ dji.XZ door.XZ door.xZ
728     f dji.Xz door.Xz door.XZ dji.XZ
729     o
730     o knob
731     m stainless_steel
732     # Define vertices needed for curved geometry
733     v kb1 =
734     p 257 0 36
735     v kb2 =
736     p 257 .25 36
737     n 0 1 0
738     v kb3 =
739     p 257 2 36
740     # 1" diameter cylindrical base from kb1 to kb2
741     cyl kb1 1 kb2
742     # Ring at base of knob stem
743     ring kb2 .4 1
744     # Knob stem
745     cyl kb2 .4 kb3
746     # Spherical knob
747     sph kb3 .85
748     o
749     o
750    
751     # Six file cabinets (36" wide each)
752     # ("filecab.inc" was given as an earlier example in Section 1.2)
753     o filecab.x
754     # include a file as an array of three 36" apart
755     i filecab.inc -t -36 0 0 -rz -90 -t 1 54 0 -a 3 -t 0 36 0
756     o
757     o filecab.X
758     # the other three cabinets
759     i filecab.inc -rz 90 -t 479 54 0 -a 3 -t 0 36 0
760     o
761    
762     # End of transform from inches to meters:
763     xf
764    
765     # The 10 recessed fluorescent ceiling fixtures
766     ies hlrs2gna.ies -t 1.2192 2.1336 2.74 -a 5 -t 2.4384 0 0 -a 2 -t 0 2.4384 0
767     .DE
768     .bp
769     .NH
770     MGF Entity Reference
771     .LP
772     There are currently 28 entities in the MGF specification.
773     For ease of reference we have broken these into five categories:
774     .IP 1.
775     General
776 greg 1.2 .TS
777 greg 1.1 lw(.75i) lw(1.75i) lw(3i).
778     # [anything ...] a comment
779     o [name] begin/end object context
780     xf [xform] begin/end transformation context
781     i pathname [xform] include file (with transformation)
782     ies pathname [-m f][xform] include IES luminaire (with transformation)
783     .TE
784     .IP 2.
785     Color
786 greg 1.2 .TS
787 greg 1.1 lw(.75i) lw(1.75i) lw(3i).
788     c [id [= [template]]] get/set color context
789     cxy x y set CIE (x,y) chromaticity for current color
790     cspec l_min l_max v1 v2 ... set relative spectrum for current color
791     cct temperature set spectrum based on black body temperature
792     cmix w1 c1 w2 c2 ... mix named colors to make current color
793     .TE
794     .IP 3.
795     Material
796     .TS
797     lw(.75i) lw(1.75i) lw(3i).
798     m [id [= [template]]] get/set material context
799     sides {1|2} set number of sides for current material
800     rd rho_d set diffuse reflectance for current material
801     td tau_d set diffuse transmittance for current material
802     ed epsilon_d set diffuse emittance for current material
803     rs rho_s alpha_r set specular reflectance for current material
804     ts tau_s alpha_t set specular transmittance for current material
805     ir n_real n_imag set index of refraction for current material
806     .TE
807     .IP 4.
808     Vertex
809     .TS
810     lw(.75i) lw(1.75i) lw(3i).
811     v [id [= [template]]] get/set vertex context
812     p x y z set point position for current vertex
813     n dx dy dz set surface normal for current vertex
814     .TE
815     .IP 5.
816     Geometry
817     .TS
818     lw(.75i) lw(1.75i) lw(3i).
819     f v1 v2 v3 ... polygon using current material, spec. vertices
820 greg 1.17 fh v1 v2 v3 - ... face with explicit holes
821 greg 1.1 sph vc radius sphere
822     cyl v1 radius v2 truncated right cylinder (open-ended)
823     cone v1 rad1 v2 rad2 truncated right cone (open-ended)
824     prism v1 v2 v3 ... length truncated right prism (closed solid)
825     ring vc rmin rmax circular ring with inner and outer radii
826     torus vc rmin rmax circular torus with inner and outer radii
827     .TE
828     .ds LH General Entities
829     .ds RH #
830     .bp
831     .SH
832     NAME
833     .LP
834     # - a comment
835     .SH
836     SYNOPSIS
837     .LP
838     .B #
839     [
840     .I anything
841     ]
842     .SH
843     DESCRIPTION
844     .LP
845     A comment is a bit of text explanation.
846     Since it is an entity like any other (except that it has no effect),
847     there must be at least one space between the keyword (which is a
848     pound sign) and the "arguments," and the end of line may be escaped
849     as usual with the backslash character ('\\').
850     .LP
851     A comment may actually be used to hold auxiliary information such as
852     view parameters, which may be interpreted by some destination program.
853     Care should be taken under such circumstances that the user does not
854     inadvertently mung or mimic this information in other comments, and
855     it is therefore advisable to use an additional set of identifying
856     characters to distinguish such data.
857     .SH
858     EXAMPLE
859     .DS
860     # The following include file is in inches, so convert to meters
861     i cubgeom.inc -s .0254
862     # Stuff we don't want to see at the moment:
863     # i person.mgf -t 3 2 0
864     # ies hlrs3gna.ies -rz 90 -t 1.524 1.8288 2.74 \\\\
865     -a 6 -t 1.8288 0 0 -a 2 -t 0 3.048 0
866     .DE
867     .ds RH O
868     .bp
869     .SH
870     NAME
871     .LP
872     o - begin or end object context
873     .SH
874     SYNOPSIS
875     .LP
876     .B o
877     [
878     .I name
879     ]
880     .SH
881     DESCRIPTION
882     .LP
883     If
884     .I name
885     is given, we push a new object context onto the stack, which is to
886     say that we begin a new subobject by this name\(dg.
887     .FS
888     \(dgA name is any sequence of printing, non-white ASCII characters
889     beginning with a letter.
890     .FE
891     If the
892     .UL o
893     keyword is given by itself, then we pop the last object context off
894     the stack, which means that we leave the current subobject.
895     .LP
896     All geometry between the start of an object context and its matching
897     end statement is associated with the given name.
898     This may be used in modeling software to help identify objects and
899     subobjects, or it may be ignored altogether.
900     .LP
901     Object begin and end statements should be balanced in a file, and
902     care should be taken not to overlap transform
903     .UL (xf)
904     contexts with object contexts, especially when arrays are involved.
905     This is because the standard parser will assign object contexts to
906     instanced geometry, which can get confused with other object
907     contexts if a clear enclosure is not maintained.
908     .SH
909     EXAMPLE
910     .DS
911     o body
912     o torso
913     i torso.mgf
914     o
915     o arm
916     o left
917     i leftarm.mgf
918     o
919     o right
920     i leftarm.mgf -mx
921     o
922     o
923     o
924     .DE
925     .SH
926     SEE ALSO
927     .LP
928     .UL xf
929     .ds RH XF
930     .bp
931     .SH
932     NAME
933     .LP
934     xf - begin or end transformation context
935     .SH
936     SYNOPSIS
937     .LP
938     .B xf
939     [
940     .I transform
941     ]
942     .SH
943     DESCRIPTION
944     .LP
945     If a set of
946     .I transform
947     arguments are given, we push a new transformation context onto the
948     stack.
949     If the
950     .UL xf
951     keyword is given by itself, then we pop the last transformation
952     context off the stack.
953     The total transformation in effect at any given time is
954     computed by prepending each set subcontext arguments onto those of
955     its enclosing context.
956     This and other details about transformation specifications
957     are explained in some detail in section 2.2.2.
958     .LP
959     The following transformation flags and
960     parameters are defined:
961     .TS
962     center;
963     l l.
964     -t dx dy dz translate objects along the given vector
965     -rx degrees rotate objects about the X-axis
966     -ry degrees rotate objects about the Y-axis
967     -rz degrees rotate objects about the Z-axis
968     -s scalefactor scale objects by the given factor
969     -mx mirror objects about the Y-Z plane
970     -my mirror objects about the X-Z plane
971     -mz mirror objects about the X-Y plane
972     -i N repeat the following arguments N times
973     -a N make an array of N geometric instances
974     .TE
975     .SH
976     EXAMPLE
977     .DS
978     # Create 3x5 array of evenly-spaced spheres (grid size = 3)
979     v vc =
980     p 0 0 0
981     xf -t 1 1 10 -a 3 -t 3 0 0 -a 5 -t 0 3 0
982     sph vc .5
983     xf
984     .DE
985     .SH
986     SEE ALSO
987     .LP
988     .UL i,
989     .UL ies,
990     .UL o
991     .ds RH I
992     .bp
993     .SH
994     NAME
995     .LP
996     i - include MGF data file
997     .SH
998     SYNOPSIS
999     .LP
1000     .B i
1001     .I pathname
1002     [
1003     .I transform
1004     ]
1005     .SH
1006     DESCRIPTION
1007     .LP
1008     Include the information contained in the file
1009     .I pathname.
1010     If a
1011     .I transform
1012     specification is given, then it will be applied as though the
1013     include statement were enclosed by beginning and ending
1014     .UL xf
1015     entities with this transformation.
1016     .LP
1017     The
1018     .I pathname
1019     will be interpreted relative to the enclosing MGF file.
1020     That is, if the file containing the include statement is in some
1021     parent or subdirectory, then the given pathname is appended to this
1022     directory.
1023     It is illegal to specify a
1024     .I pathname
1025     relative to the root directory, and the MGF standard requires that
1026     all filenames adhere to the ISO-9660 8.3 name format for maximum
1027     portability between systems.
1028     The directory separator is defined to be slash ('/'), and drive
1029     specifications (such as "c:") are not allowed.
1030     All pathnames should be given in lower case, and will be converted to
1031     upper case on systems that require it.
1032     (That way, there are no accidental name collisions.)\0
1033     .LP
1034     The suggested suffix for MGF-adherent files is ".mgf".
1035     Files that are not in metric units but are in MGF may be given any
1036     suffix, but we suggest using ".inc" as a convention.
1037     .SH
1038     EXAMPLE
1039     .DS
1040     # Define vertices for 62x30" partition
1041     i pv62x30.inc
1042     # Insert 2 62x30" partitions
1043     o cpart1
1044     i partn.inc -t 75 130.5 0
1045     o
1046     o cpart3
1047     i partn.inc -t 186 130.5 0
1048     o
1049     # Define vertices for 62x36" partition
1050     i pv62x36.inc
1051     # Insert 62x36" partition
1052     o cpart2
1053     i partn.inc -t 105 130.5 0
1054     o
1055     .DE
1056     .SH
1057     SEE ALSO
1058     .LP
1059     .UL ies,
1060     .UL o,
1061     .UL xf
1062     .ds RH IES
1063     .bp
1064     .SH
1065     NAME
1066     .LP
1067     ies - include IESNA luminaire file
1068     .SH
1069     SYNOPSIS
1070     .LP
1071     .B ies
1072     .I pathname
1073     [
1074     .B \-m
1075     .I multiplier
1076     ]
1077     [
1078     .I transform
1079     ]
1080     .SH
1081     DESCRIPTION
1082     .LP
1083     Load the IES standard luminaire information contained in the file
1084     .I pathname.
1085     If a
1086     .I multiplier
1087     is given, all candela values will be multiplied by this factor.
1088     (This option must appear first if present.)\0
1089     If a
1090     .I transform
1091     specification is given, then it will be applied as though the
1092     statement were enclosed by beginning and ending
1093     .UL xf
1094     entities with this transformation.
1095     .LP
1096     The
1097     .I pathname
1098     will be interpreted relative to the enclosing MGF file, and all
1099     restrictions discussed under the
1100     .UL i
1101     entity also apply to the IES file name.
1102     The suggested suffix is ".ies", but this has not been followed
1103     consistently by lighting manufacturers.
1104     .SH
1105     EXAMPLE
1106     .DS
1107     # Insert 10 2x4' fluorescent troffers in two groups
1108     ies cf9pr240.ies -t 3.6576 2.1336 2.74 -a 3 -t 2.4384 0 0 -a 2 -t 0 2.4384 0
1109     ies cf9pr240.ies -rz 90 -t 1.2192 1.8288 2.74 \\\\
1110     -a 2 -t 9.7536 0 0 -a 2 -t 0 3.048 0
1111     .DE
1112     .SH
1113     SEE ALSO
1114     .LP
1115     .UL i,
1116     .UL o,
1117     .UL xf
1118     .ds LH Color Entities
1119     .ds RH C
1120     .bp
1121     .SH
1122     NAME
1123     .LP
1124     c - get or set the current color context
1125     .SH
1126     SYNOPSIS
1127     .LP
1128     .B c
1129     [
1130     .I id
1131     [
1132     .B =
1133     [
1134     .I template
1135     ]
1136     ]
1137     ]
1138     .SH
1139     DESCRIPTION
1140     .LP
1141     If the
1142     .UL c
1143     keyword is given by itself, then it establishes the unnamed color
1144     context, which is neutral (i.e. equal-energy) grey.
1145     This context may be modified, but the changes will not be saved.
1146     .LP
1147     If the keyword is followed by an identifier
1148     .I id,
1149     then it reestablishes a previous context.
1150     If the specified context was never defined, an error will result.
1151     .LP
1152     If the entity is given with an identifier
1153     followed by an equals sign ('='), then a new context is established,
1154     and cleared to the default neutral grey.
1155     (Note that the equals sign must be separated from other
1156     arguments by white space to be properly recognized.)\0
1157     If the equals sign is followed by a second identifier
1158     .I template,
1159     then this previously defined color will be used as a source of
1160     default values rather than grey.
1161     This is most useful for establishing a color alias.
1162     .SH
1163     EXAMPLE
1164     .DS
1165     # Define the color "red32"
1166     c red32 =
1167     cxy .42 .15
1168     # Make "cabinet_color" an alias for "red32"
1169     c cabinet_color = red32
1170    
1171     # Later in another part of the description...
1172    
1173     # Get our cabinet color
1174     c cabinet_color
1175     # Get the geometry
1176     i cabgeom.mgf
1177     .DE
1178     .SH
1179     SEE ALSO
1180     .LP
1181     .UL cct,
1182     .UL cmix,
1183     .UL cspec,
1184     .UL cxy,
1185     .UL m
1186     .ds RH CXY
1187     .bp
1188     .SH
1189     NAME
1190     .LP
1191     cxy - set the CIE (x,y) chromaticity for the current color
1192     .SH
1193     SYNOPSIS
1194     .LP
1195     .B cxy
1196     .I "x y"
1197     .SH
1198     DESCRIPTION
1199     .LP
1200     This entity sets the current color using (x,y) chromaticity
1201     coordinates for the 1931 CIE standard 2 degree observer.
1202     Legal values for
1203     .I x
1204     and
1205     .I y
1206     are greater than zero and sum to less than one, and more
1207     specifically they must fit within the curve of the visible spectrum.
1208     The
1209     .I x
1210     coordinate roughly corresponds to the red part of the spectrum and
1211     the
1212     .I y
1213     coordinate corresponds to the green.
1214     The CIE z coordinate is implicit, since it is equal to (1-x-y).
1215     .LP
1216     All colors in MGF are absolute, thus colorimeter measurements should
1217     be conducted the same for surfaces as for light sources.
1218     Applying a standard illuminant calculation is redundant and
1219     introduces inaccuracies, and should therefore be avoided if
1220     possible.
1221     .LP
1222     Conversion between CIE colors and those more commonly used in
1223     computer graphics are described in the application notes section
1224     6.1.1.
1225     .SH
1226     EXAMPLE
1227     .DS
1228     # Set unnamed color context
1229     c
1230     # Set CIE chromaticity to a bluish hue
1231     cxy .15 .2
1232     # Apply color to diffuse reflectance of 15%
1233     rd .15
1234     .DE
1235     .SH
1236     SEE ALSO
1237     .LP
1238     .UL c,
1239     .UL cct,
1240     .UL cmix,
1241     .UL cspec
1242     .ds RH CSPEC
1243     .bp
1244     .SH
1245     NAME
1246     .LP
1247     cspec - set the relative spectrum for the current color
1248     .SH
1249     SYNOPSIS
1250     .LP
1251     .B cspec
1252     .I "l_min l_max o1 o2 ... oN"
1253     .SH
1254     DESCRIPTION
1255     .LP
1256     Assign a relative spectrum measured between
1257     .I l_min
1258     and
1259     .I l_max
1260     nanometers at evenly spaced intervals.
1261     The first value,
1262     .I o1
1263     corresponds to the measurement at
1264     .I l_min,
1265     and the last value,
1266     .I oN
1267     corresponds to the measurement at
1268     .I l_max.
1269     Values in between are separated by
1270     .I "(l_max-l_min)/(N-1)"
1271     nanometers.
1272 greg 1.6 All values should be non-negative unless defining a component for
1273     complementary color mixing, and the spectrum outside of the
1274 greg 1.1 specified range is assumed to be zero.
1275     (The visible range is 380 to 780 nm.)\0
1276     The actual units and scale of the measurements do not matter,
1277     since the total will be
1278     normalized according to whatever the color is modifying
1279     (e.g. photometric reflectance or emittance).
1280     .SH
1281     EXAMPLE
1282     .DS
1283     # Color measured at 10 nm increments from 400 to 700
1284     m reddish_cloth =
1285     c
1286     cspec 400 700 28.62 27.96 27.86 28.28 29.28 30.49 31.61 \\\\
1287     32.27 32.26 31.83 31.13 30.07 29.14 29.03 29.69 \\\\
1288     30.79 32.30 33.90 34.56 34.32 33.85 33.51 33.30 \\\\
1289     33.43 34.06 35.26 37.04 39.41 42.55 46.46 51.00
1290     rd 0.3210
1291     .DE
1292     .SH
1293     SEE ALSO
1294     .LP
1295     .UL c,
1296     .UL cct,
1297     .UL cmix,
1298     .UL cxy
1299     .ds RH CCT
1300     .bp
1301     .SH
1302     NAME
1303     .LP
1304     cct - set the current color to a black body spectrum
1305     .SH
1306     SYNOPSIS
1307     .LP
1308     .B cct
1309     .I temperature
1310     .SH
1311     DESCRIPTION
1312     .LP
1313     The
1314     .UL cct
1315     entity sets the current color to the spectrum of an ideal
1316     black body radiating at
1317     .I temperature
1318     degrees Kelvin.
1319     This is often the most convenient way to set the color of an
1320     incandescent light source, but it is not recommended for
1321     fluorescent lamps or other materials that do not fit a
1322     black body spectrum.
1323     .SH
1324     EXAMPLE
1325     .DS
1326     # Define an incandescent source material at 3000 degrees K
1327     m incand3000k =
1328     c
1329     cct 3000
1330     ed 1500
1331     .DE
1332     .SH
1333     SEE ALSO
1334     .LP
1335     .UL c,
1336     .UL cmix,
1337     .UL cspec,
1338     .UL cxy
1339     .ds RH CMIX
1340     .bp
1341     .SH
1342     NAME
1343     .LP
1344     cmix - mix two or more named colors to make the current color
1345     .SH
1346     SYNOPSIS
1347     .LP
1348     .B cmix
1349     .I "w1 c1 w2 c2 ..."
1350     .SH
1351     DESCRIPTION
1352     .LP
1353     The
1354     .UL cmix
1355     entity sums together two or more named colors using specified
1356     weighting coefficients, which correspond to the relative
1357     photometric brightness of each.
1358     As in all color specifications, the result is normalized so the
1359     absolute scale of the weights does not matter, only their relative
1360     values.
1361     .LP
1362     If any of the colors is a spectral quantity (i.e. from a
1363     .UL cspec
1364     or
1365     .UL cct
1366     entity), then all the colors are first converted to spectral
1367     quantities.
1368     This is done with an approximation for CIE (x,y) chromaticities,
1369     which may be problematic depending on their values.
1370     In general, it is safest to add together colors that are either
1371     all spectral quantities or all CIE quantities.
1372     .SH
1373     EXAMPLE
1374     .DS
1375     # Define RGB primaries for a standard color monitor
1376     c R =
1377     cxy 0.640 0.330
1378     c G =
1379     cxy 0.290 0.600
1380     c B =
1381     cxy 0.150 0.060
1382     # Mix them together in appropriate amounts for white
1383     c white =
1384     cmix 0.265 R 0.670 G 0.065 B
1385     .DE
1386     .SH
1387     SEE ALSO
1388     .LP
1389     .UL c,
1390     .UL cct,
1391     .UL cspec,
1392     .UL cxy
1393     .ds LH Material Entities
1394     .ds RH M
1395     .bp
1396     .SH
1397     NAME
1398     .LP
1399     m - get or set the current material context
1400     .SH
1401     SYNOPSIS
1402     .LP
1403     .B m
1404     [
1405     .I id
1406     [
1407     .B =
1408     [
1409     .I template
1410     ]
1411     ]
1412     ]
1413     .SH
1414     DESCRIPTION
1415     .LP
1416     If the
1417     .UL m
1418     keyword is given by itself, then it establishes
1419     the unnamed material context, which is a perfect two-sided black absorber.
1420     This context may be modified, but the changes will not be saved.
1421     .LP
1422     If the keyword is followed by an identifier
1423     .I id,
1424     then it reestablishes a previous context.
1425     If the specified context was never defined, an error will result.
1426     .LP
1427     If the entity is given with an identifier
1428     followed by an equals sign ('='), then a new context is established,
1429     and cleared to the default material.
1430     (Note that the equals sign must be separated from other
1431     arguments by white space to be properly recognized.)\0
1432     If the equals sign is followed by a second identifier
1433     .I template,
1434     then this previously defined material will be used as a source of
1435     default values instead.
1436     This may be used to establish a material alias, or to modify an
1437     existing material and give it a new name.
1438     .LP
1439     The sum of the diffuse and specular reflectances and transmittances
1440     must not be greater than one (with no negative values, obviously).
1441     These values are assumed to be measured at normal incidence.
1442     If an index of refraction is given, this may modify the balance between
1443     diffuse and specular reflectance at other incident angles.
1444     If the
1445     material is one-sided (see
1446     .UL sides
1447     entity), then it may be a dielectric interface.
1448     In this case, the specular transmittance given is that which would be
1449     measured at normal incidence for a pane of the material 5 mm thick.
1450     This is important for figuring the actual transmittance for non-planar
1451     geometries assuming a uniformly absorbing medium.
1452     (Diffuse transmittance will not be affected by thickness.)\0
1453     If the index of
1454     refraction has an imaginary part, then the surface is a metal and this
1455     implies other properties as well.
1456     The default index of refraction is that of a vacuum, i.e. (1,0).
1457     .SH
1458     EXAMPLE
1459     .DS
1460     # Define a blue enamel paint
1461     m blue_enamel =
1462     c
1463     cxy 0.2771 0.2975
1464     rd 0.5011
1465     c
1466     rs 0.0100 0.0350
1467     # Assign blue_enamel to be the color of the south wall
1468     m swall_mat = blue_enamel
1469     # ...
1470     # South wall face
1471     m swall_mat
1472     f sv1 sv2 sv3 sv4
1473     .DE
1474     .SH
1475     SEE ALSO
1476     .LP
1477     .UL ed,
1478     .UL ir,
1479     .UL rd,
1480     .UL rs,
1481     .UL sides,
1482     .UL td,
1483     .UL ts
1484     .ds RH SIDES
1485     .bp
1486     .SH
1487     NAME
1488     .LP
1489     sides - set the number of sides for the current material
1490     .SH
1491     SYNOPSIS
1492     .LP
1493     .B sides
1494     {
1495     .B 1
1496     |
1497     .B 2
1498     }
1499     .SH
1500     DESCRIPTION
1501     .LP
1502     The
1503     .UL sides
1504     entity is used to set the number of sides for the current material.
1505     If a surface is two-sided, then it will appear
1506     identical when viewed from either the front or the back.
1507     If a surface is one-sided,
1508     then it appears invisible when viewed from the back side.
1509     This means
1510     that a transmitting object will affect the light coming in through the
1511     front surface and ignore the characteristics of the back surface,
1512     unless the index of refraction is set.
1513     If the index of refraction is set, then the object will act as a
1514     solid piece of dielectric material.
1515     In either case, the transmission properties of the exiting surface
1516     should be the same as the incident surface for the model to be
1517     physically valid.
1518     .LP
1519     The default number of sides is two.
1520     .SH
1521     EXAMPLE
1522     .DS
1523     # Describe a blue crystal ball
1524     m blue_crystal =
1525     ir 1.650000 0
1526     # Solid dielectrics must use one-sided materials
1527     sides 1
1528     c
1529     rs 0.0602 0
1530     c
1531     cxy 0.3127 0.2881
1532     ts 0.6425 0
1533     v sc =
1534     p 10 15 1.5
1535     sph sc .02
1536     .DE
1537     .SH
1538     SEE ALSO
1539     .LP
1540     .UL ed,
1541     .UL ir,
1542     .UL m,
1543     .UL rd,
1544     .UL rs,
1545     .UL td,
1546     .UL ts
1547     .ds RH RD
1548     .bp
1549     .SH
1550     NAME
1551     .LP
1552     rd - set the diffuse reflectance for the current material
1553     .SH
1554     SYNOPSIS
1555     .LP
1556     .B rd
1557     .I rho_d
1558     .SH
1559     DESCRIPTION
1560     .LP
1561     Set the diffuse reflectance for the current material to
1562     .I rho_d
1563     using the current color to determine the spectral characteristics.
1564     This is the fraction of visible light that is reflected from a
1565     surface equally in all directions according to Lambert's law, and is
1566     often called the "Lambertian component."
1567     Photometric reflectance is measured according to v(lambda)
1568     response function of the 1931 CIE standard 2
1569     degree observer, and assumes an equal-energy white light source.
1570     The value must be between zero and one, and may be further
1571     restricted by the luminosity of the selected color.
1572     (I.e. it is impossible to have a violet material with a photometric
1573     reflectance close to one since the eye is less sensitive in this part
1574     of the spectrum.)\0
1575     .LP
1576     The default diffuse reflectance is zero.
1577     .SH
1578     EXAMPLE
1579     .DS
1580     # An off-white paint with 70% reflectance
1581     m flat_white70 =
1582     c
1583     cxy .3632 .3420
1584     rd .70
1585     .DE
1586     .SH
1587     SEE ALSO
1588     .LP
1589     .UL c,
1590     .UL ed,
1591     .UL ir,
1592     .UL m,
1593     .UL rs,
1594     .UL sides,
1595     .UL td,
1596     .UL ts
1597     .ds RH TD
1598     .bp
1599     .SH
1600     NAME
1601     .LP
1602     td - set the diffuse transmittance for the current material
1603     .SH
1604     SYNOPSIS
1605     .LP
1606     .B td
1607     .I tau_d
1608     .SH
1609     DESCRIPTION
1610     .LP
1611     Set the diffuse transmittance for the current material to
1612     .I tau_d
1613     using the current color to determine the spectral characteristics.
1614     This is the fraction of visible light that is transmitted through a
1615     surface equally in all (transmitted) directions.
1616     Like reflectance, transmittance is measured according to the
1617     standard v(lambda) curve, and assumes an equal-energy white light source.
1618     It is probably not possible to create a material with a diffuse
1619     transmittance above 50%, since well-diffused light will be reflected
1620     as well.
1621     .LP
1622     The default diffuse transmittance is zero.
1623     .SH
1624     EXAMPLE
1625     .DS
1626     # Model a perfect spherical diffuser, i.e. light hitting \
1627     either side will be scattered equally in all directions
1628     m wonderland_diffuser =
1629     c
1630     td .5
1631     rd .5
1632     .DE
1633     .SH
1634     SEE ALSO
1635     .LP
1636     .UL c,
1637     .UL ed,
1638     .UL ir,
1639     .UL m,
1640     .UL rd,
1641     .UL rs,
1642     .UL sides,
1643     .UL ts
1644     .ds RH ED
1645     .bp
1646     .SH
1647     NAME
1648     .LP
1649     ed - set the diffuse emittance for the current material
1650     .SH
1651     SYNOPSIS
1652     .LP
1653     .B ed
1654     .I epsilon_d
1655     .SH
1656     DESCRIPTION
1657     .LP
1658     Set the diffuse emittance for the current material to
1659     .I epsilon_d
1660     lumens per square meter using the current color to determine the
1661     spectral characteristics.
1662     Note that this is emittance rather than exitance, and therefore
1663     does not include reflected or transmitted light, which is a function
1664     of the other material settings and the illuminated environment.
1665     .LP
1666     The total lumen output of a convex emitting object
1667     is the radiating area of that object multiplied by its emittance.
1668     Therefore, one can compute the appropriate
1669     .I epsilon_d
1670     value for an emitter by dividing the total lumen output by the
1671     radiating area (in square meters).
1672     .LP
1673     The default emittance is zero.
1674     .SH
1675     EXAMPLE
1676     .DS
1677     # A 100-watt incandescent bulb (1600 lumens) modeled as a sphere
1678     m
1679     c
1680 greg 1.14 cct 3000
1681 greg 1.1 ed 87712
1682     v cent =
1683     p 0 0 0
1684     sph cent .0381
1685     .DE
1686     .SH
1687     SEE ALSO
1688     .LP
1689     .UL c,
1690     .UL ir,
1691     .UL m,
1692     .UL rd,
1693     .UL rs,
1694     .UL sides,
1695     .UL td,
1696     .UL ts
1697     .ds RH RS
1698     .bp
1699     .SH
1700     NAME
1701     .LP
1702     rs - set the specular reflectance for the current material
1703     .SH
1704     SYNOPSIS
1705     .LP
1706     .B rs
1707     .I "rho_s alpha_r"
1708     .SH
1709     DESCRIPTION
1710     .LP
1711     Set the specular reflectance for the current material to
1712     .I rho_s
1713     using the current color to determine the spectral characteristics.
1714     The surface roughness parameter is set to
1715     .I alpha_r,
1716     which is the RMS height of surface variations over the
1717     autocorrelation distance (equivalent to RMS facet slope).
1718     A roughness value of zero means a perfectly smooth surface, and
1719     values greater than 0.2 are unusual.
1720     (See application notes section 6.1.2 for a comparison between the
1721     roughness parameter and Phong specular power.)\0
1722     .LP
1723     The default specular reflectance is zero.
1724     .SH
1725     EXAMPLE
1726     .DS
1727     # Define a slightly rough brass metallic surface
1728     m rough_brass =
1729     c
1730     cxy .3820 .4035
1731     # 30% specular, 9% diffuse
1732     rs .30 .08
1733     rd .09
1734     .DE
1735     .SH
1736     SEE ALSO
1737     .LP
1738     .UL c,
1739     .UL ed,
1740     .UL ir,
1741     .UL m,
1742     .UL rd,
1743     .UL sides,
1744     .UL td,
1745     .UL ts
1746     .ds RH TS
1747     .bp
1748     .SH
1749     NAME
1750     .LP
1751     ts - set the specular transmittance for the current material
1752     .SH
1753     SYNOPSIS
1754     .LP
1755     .B ts
1756     .I "tau_s alpha_t"
1757     .SH
1758     DESCRIPTION
1759     .LP
1760     Set the specular transmittance for the current material to
1761     .I tau_s
1762     using the current color to determine the spectral characteristics.
1763     The effective surface roughness is set to
1764     .I alpha_t.
1765     Rays will be transmitted with the same distribution as they would
1766     have been reflected with if this roughness value were given to the
1767     .UL rs
1768     entity.
1769     .LP
1770     The default specular transmittance is zero.
1771     .SH
1772     EXAMPLE
1773     .DS
1774     # Define a green glass material (58% transmittance)
1775     m glass =
1776     sides 2
1777     ir 1.52 0
1778     c
1779     rs 0.0725 0
1780     c
1781     cxy .23 .38
1782     ts 0.5815 0
1783     # Define an uncolored translucent plastic (40% transmittance)
1784     m translucent =
1785     sides 2
1786     ir 1.4 0
1787     c
1788     rs .045 0
1789     ts .40 .05
1790     .DE
1791     .SH
1792     SEE ALSO
1793     .LP
1794     .UL c,
1795     .UL ed,
1796     .UL ir,
1797     .UL m,
1798     .UL rd,
1799     .UL rs,
1800     .UL sides,
1801     .UL td
1802     .ds RH IR
1803     .bp
1804     .SH
1805     NAME
1806     .LP
1807     ir - set the complex index of refraction for the current material
1808     .SH
1809     SYNOPSIS
1810     .LP
1811     .B ir
1812     .I "n_real n_imag"
1813     .SH
1814     DESCRIPTION
1815     .LP
1816     Set the index of refraction for the current material to
1817     .I (n_real,n_imag).
1818     If the material is a dielectric (as opposed to metallic), then
1819     .I n_imag
1820     should be zero.
1821     For solid dielectric objects, the material should be made one-sided.
1822     If it is being used for thin objects, then a two-sided
1823     material is appropriate.
1824     (See the
1825     .UL sides
1826     entity.)\0
1827     .LP
1828     The default index of refraction is that of a vacuum, (1,0).
1829     .SH
1830     EXAMPLE
1831     .DS
1832     # Define polished aluminum material
1833     m polished_aluminum =
1834     # Complex index of refraction (from physics table)
1835     ir .770058 6.08351
1836     c
1837     rs .75 0
1838     .DE
1839     .SH
1840     SEE ALSO
1841     .LP
1842     .UL c,
1843     .UL ed,
1844     .UL m,
1845     .UL rd,
1846     .UL rs,
1847     .UL sides,
1848     .UL td,
1849     .UL ts
1850     .ds LH Vertex Entities
1851     .ds RH V
1852     .bp
1853     .SH
1854     NAME
1855     .LP
1856     v - get or set the current vertex context
1857     .SH
1858     SYNOPSIS
1859     .LP
1860     .B v
1861     [
1862     .I id
1863     [
1864     .B =
1865     [
1866     .I template
1867     ]
1868     ]
1869     ]
1870     .SH
1871     DESCRIPTION
1872     .LP
1873     If the
1874     .UL v
1875     keyword is given by itself, then it establishes
1876     the unnamed vertex context, which is the origin with no normal.
1877     This context may be modified, but the changes will not be saved.
1878     (The unnamed vertex is never used except as a source of default
1879     values since all geometric entities call their vertices by name.)\0
1880     .LP
1881     If the keyword is followed by an identifier
1882     .I id,
1883     then it reestablishes a previous context.
1884     If the specified context was never defined, an error will result.
1885     .LP
1886     If the entity is given with an identifier
1887     followed by an equals sign ('='), then a new context is established,
1888     and cleared to the default vertex (the origin).
1889     (Note that the equals sign must be separated from other
1890     arguments by white space to be properly recognized.)\0
1891     If the equals sign is followed by a second identifier
1892     .I template,
1893     then this previously defined vertex will be used as a source of
1894     default values instead.
1895     This may be used to establish a vertex alias, or to modify an
1896     existing vertex and give it a new name.
1897     .LP
1898     A non-zero vertex normal must be given for
1899     certain entities, specifically
1900     .UL ring
1901     and
1902     .UL torus
1903     require a normal direction.
1904     An
1905     .UL f
1906 greg 1.18 or
1907     .UL fh
1908 greg 1.1 entity will interpolate vertex normals if given, and
1909     use the polygon plane normal otherwise.
1910     See the
1911     .UL prism
1912     entry for an explanation of how it interprets and uses vertex
1913     normals.
1914     The other entities ignore vertex normals if present.
1915     .LP
1916     The actual position and normal direction for a vertex is determined
1917     at the time of use by a geometric entity.
1918     Specifically, the transformation in effect at the time the vertex is
1919     defined is irrelevant.
1920     The only transformation that matters is the one that is applied to
1921     the geometry itself.
1922     This prevents double-transformation of vertices and allows one set
1923     of vertices to be used for multiple purposes, e.g. the front and
1924     back sides of a drawer.
1925     .SH
1926     EXAMPLE
1927     .DS
1928     # Make a capped cylinder
1929     v end1 =
1930     p 0 0 0
1931     n 0 0 -1
1932     v end2 =
1933     p 0 0 1
1934     cyl end1 1.2 end2
1935     # Forgot normal for end2
1936     v end2
1937     n 0 0 1
1938     ring end1 0 1.2
1939     ring end2 0 1.2
1940     .DE
1941     .SH
1942     SEE ALSO
1943     .LP
1944     .UL cone,
1945     .UL cyl,
1946     .UL f,
1947 greg 1.18 .UL fh,
1948 greg 1.1 .UL n,
1949     .UL p,
1950     .UL prism,
1951     .UL ring,
1952     .UL sph,
1953     .UL torus
1954     .ds RH P
1955     .bp
1956     .SH
1957     NAME
1958     .LP
1959     p - set the point location for the current vertex
1960     .SH
1961     SYNOPSIS
1962     .LP
1963     .B p
1964     .I "px py pz"
1965     .SH
1966     DESCRIPTION
1967     .LP
1968     Set the 3-dimensional position for the current vertex to
1969     .I (px,py,pz).
1970     The actual position of the vertex will be determined by the
1971     transformation in effect at the time the vertex is applied to a
1972     geometric surface entity.
1973     The transform current when the position is set is irrelevant.
1974     .LP
1975     The default vertex position is the origin, (0,0,0).
1976     .SH
1977     EXAMPLE
1978     .DS
1979     # Make a small circle of 6 spheres
1980     v scent =
1981     p 1 0 0
1982     xf -a 6 -rz 60
1983     sph scent .05
1984     xf
1985     .DE
1986     .SH
1987     SEE ALSO
1988     .LP
1989     .UL cone,
1990     .UL cyl,
1991     .UL f,
1992 greg 1.18 .UL fh,
1993 greg 1.1 .UL n,
1994     .UL prism,
1995     .UL ring,
1996     .UL sph,
1997     .UL torus,
1998     .UL v
1999     .ds RH N
2000     .bp
2001     .SH
2002     NAME
2003     .LP
2004     n - set the surface normal direction for the current vertex
2005     .SH
2006     SYNOPSIS
2007     .LP
2008     .B n
2009     .I "dx dy dz"
2010     .SH
2011     DESCRIPTION
2012     .LP
2013     Set the 3-dimensional surface normal for the current vertex to the
2014     normalized vector along
2015     .I (dx,dy,dz).
2016     If this vector is zero, then the surface normal is effectively
2017     unset.
2018     The actual surface normal orientation of the vertex will be determined
2019     by the transformation in effect at the time the vertex is applied to a
2020     geometric surface entity.
2021     The current transform when the normal is set is irrelevant.
2022     .LP
2023     The default vertex normal is the zero vector (i.e. no normal).
2024     .SH
2025     EXAMPLE
2026     .DS
2027     # Make a chain of 10 interlocking doughnuts
2028     v tcent =
2029     p 0 0 0
2030     n 0 1 0
2031     xf -a 10 -rx 90 -t .2 0 0
2032     torus tcent .1 .2
2033     xf
2034     .DE
2035     .SH
2036     SEE ALSO
2037     .LP
2038     .UL f,
2039 greg 1.18 .UL fh,
2040 greg 1.1 .UL p,
2041     .UL prism,
2042     .UL ring,
2043     .UL torus,
2044     .UL v
2045     .ds LH Geometric Entities
2046     .ds RH F
2047     .bp
2048     .SH
2049     NAME
2050     .LP
2051     f - create an N-sided polygonal face
2052     .SH
2053     SYNOPSIS
2054     .LP
2055     .B f
2056     .I "v1 v2 ... vN"
2057     .SH
2058     DESCRIPTION
2059     .LP
2060     Create a polygonal face made of the current material
2061     by connecting the named vertices in order, and connecting the last
2062     vertex to the first.
2063     There must be at least three vertices, and if any vertex is undefined,
2064     an error will result.
2065     .LP
2066     The surface orientation is determined by the right-hand rule; when
2067     the curl of the fingers follows the given order of the vertices, the
2068     surface normal points in the thumb direction.
2069     Face vertices should be coplanar, though this is difficult to guarantee
2070     in a 3-dimensional specification.
2071     .LP
2072     If any vertices have associated surface normals, they will be used
2073     instead of the average plane normal, though it is safest to specify
2074     either all normals or no normals, and to stick with triangles
2075     when normals are used.
2076     Also, specified normals should point in the general direction of the
2077     surface for best results.
2078     .LP
2079 greg 1.16 There is no explicit representation of holes in this entity, but see
2080     the
2081     .UL fh
2082     entity for an alternative specification.
2083     .LP
2084     A hole may be represented implicitly in a face entity
2085     by connecting vertices to form "seams."
2086     For
2087 greg 1.1 example, a wall with a window in it might look as shown in Figure 1.
2088     In many systems, the wall itself would be represented with the first
2089     list of vertices, (v1,v2,v3,v4) and the hole associated with that
2090 greg 1.16 wall as a second set of vertices (v5,v6,v7,v8).
2091     Using the face entity, we must
2092 greg 1.1 give the whole thing as a single polygon, connecting the vertices so
2093     as to create a "seam," as shown in Figure 2.
2094 greg 1.16 This could be written as "f v1 v2 v3 v4 v5 v6 v7 v8 v5 v4".
2095 greg 1.1 .LP
2096     It is very important that the order of the hole be opposite to the
2097     order of the outer perimeter, otherwise the polygon will be
2098     "twisted" on top of itself. Note also that the seam was traversed
2099     in both directions, once going from v4 to v5, and again returning
2100     from v5 to v4. This is a necessary condition for a proper seam.
2101     .LP
2102     The choice of vertices to make into a seam is somewhat arbitrary, but
2103     some rendering systems may not give sane results if you cross over a
2104     hole with part of your seam. If we had chosen to create the seam
2105     between v2 and v5 in the above example instead of v4 and v5, the seam
2106     would cross our hole and may not render correctly\(dg.
2107     .FS
2108     \(dgFor systems that
2109     are sensitive to this, it is probably safest for their MGF
2110     loader/translator to re-expresses seams in terms of holes again, which can
2111     be done easily so long as vertices are shared in the fashion shown.
2112     .FE
2113     .bp
2114     Replace this page with the first page from "figures.ps".
2115     .bp
2116     .SH
2117     EXAMPLE
2118     .DS
2119     # Make a pyramid
2120     v apex =
2121     p 1 1 1
2122     v base0 =
2123     p 0 0 0
2124     v base1 =
2125     p 0 2 0
2126     v base2 =
2127     p 2 2 0
2128     v base3 =
2129     p 2 0 0
2130     # Bottom
2131     f base0 base1 base2 base3
2132     # Sides
2133     f base0 apex base1
2134     f base1 apex base2
2135     f base2 apex base3
2136     f base3 apex base0
2137     .DE
2138     .SH
2139     SEE ALSO
2140     .LP
2141     .UL cone,
2142     .UL cyl,
2143 greg 1.16 .UL fh,
2144     .UL m,
2145     .UL prism,
2146     .UL ring,
2147     .UL sph,
2148     .UL torus,
2149     .UL v
2150     .ds RH FH
2151     .bp
2152     .SH
2153     NAME
2154     .LP
2155     fh - create a polygonal face with explicit holes
2156     .SH
2157     SYNOPSIS
2158     .LP
2159     .B fh
2160     .I "p1 p2 ... - h1.1 h1.2 ... - h2.1 h2.2 ..."
2161     .SH
2162     DESCRIPTION
2163     .LP
2164     Create a polygonal face with optional holes made of the current material.
2165     The first contour is the outer perimeter, with vertices given in
2166     counter-clockwise order as seen from the front side (the same as the
2167     .UL f
2168     entity).
2169     A hole is indicated by a hyphen ('-') followed by the hole's
2170     vertices, given in clockwise order as seen from the front side.
2171     Multiple hole contours are separated by additional hyphens.
2172     There must be at least three vertices for each contour, and the
2173     last vertex is implicitly connected to the first.
2174     If any vertex is undefined, an error will result.
2175     .LP
2176     If any vertices have associated surface normals, they will be used
2177     instead of the average plane normal, though it is safest to specify
2178     either all normals or no normals, and to stick with triangles
2179     when normals are used.
2180     Also, specified normals should point in the general direction of the
2181     surface for best results.
2182 greg 1.18 .LP
2183     Vertices should not be shared between any two contours.
2184     I.e., a hole should not share a vertex or edge with the perimeter or
2185     another hole, or incorrect rendering may result.
2186 greg 1.16 .SH
2187     EXAMPLE
2188     .DS
2189     # Make a wall with a window using an explicit hole.
2190     # (See Figures 1 and 2.)
2191     fh v1 v2 v3 v4 - v5 v6 v7 v8
2192     .DE
2193     .SH
2194     SEE ALSO
2195     .LP
2196     .UL cone,
2197     .UL cyl,
2198     .UL f,
2199 greg 1.1 .UL m,
2200     .UL prism,
2201     .UL ring,
2202     .UL sph,
2203     .UL torus,
2204     .UL v
2205     .ds RH SPH
2206     .bp
2207     .SH
2208     NAME
2209     .LP
2210     sph - create a sphere
2211     .SH
2212     SYNOPSIS
2213     .LP
2214     .B sph
2215     .I "vc rad"
2216     .SH
2217     DESCRIPTION
2218     .LP
2219     Create a sphere made of the current material with its center at the
2220     named vertex
2221     .I vc
2222     and a radius of
2223     .I rad.
2224     If the vertex is undefined an error will result.
2225     .LP
2226     The surface normal is usually directed outward, but will be directed
2227     inward if the given radius is negative.
2228     (This typically matters only for one-sided materials.)\0
2229     A zero radius is illegal.
2230     .SH
2231     EXAMPLE
2232     .DS
2233     # Create a thick glass sphere with a hollow inside
2234     m glass =
2235     sides 1
2236     ir 1.52 0
2237     c
2238     rs .06 0
2239     ts .88 0
2240     v cent =
2241     p 0 0 1.1
2242     # The outer shell
2243     sph cent .1
2244     # The inner bubble
2245     sph cent -.08
2246     .DE
2247     .SH
2248     SEE ALSO
2249     .LP
2250     .UL cone,
2251     .UL cyl,
2252     .UL f,
2253 greg 1.18 .UL fh,
2254 greg 1.1 .UL m,
2255     .UL prism,
2256     .UL ring,
2257     .UL torus,
2258     .UL v
2259     .ds RH CYL
2260     .bp
2261     .SH
2262     NAME
2263     .LP
2264     cyl - create an open-ended, truncated right cylinder
2265     .SH
2266     SYNOPSIS
2267     .LP
2268     .B cyl
2269     .I "v1 rad v2"
2270     .SH
2271     DESCRIPTION
2272     .LP
2273     Create a truncated right cylinder of radius
2274     .I rad
2275     using the current material, starting at the named vertex
2276     .I v1
2277     and continuing to
2278     .I v2.
2279     The ends will be open, but may be capped using the
2280     .UL ring
2281     entity if desired.
2282     .LP
2283     The surface normal will usually be directed outward, but may be
2284     directed inward by giving a negative value for
2285     .I rad.
2286     A zero radius is illegal, and
2287     .I v1
2288     cannot equal
2289     .I v2.
2290     .SH
2291     EXAMPLE
2292     .DS
2293     # A stylus with one rounded and one pointed end
2294     o stylus
2295     v vtip0 =
2296     p 0 0 0
2297     v vtip1 =
2298     p 0 0 .005
2299     v vend =
2300     p 0 0 .05
2301 greg 1.5 cyl vtip1 .0015 vend
2302 greg 1.1 sph vend .0015
2303     cone vtip0 0 vtip1 .0015
2304     o
2305     .DE
2306     .SH
2307     SEE ALSO
2308     .LP
2309     .UL cone,
2310     .UL f,
2311 greg 1.18 .UL fh,
2312 greg 1.1 .UL m,
2313     .UL prism,
2314     .UL ring,
2315     .UL sph,
2316     .UL torus,
2317     .UL v
2318     .ds RH CONE
2319     .bp
2320     .SH
2321     NAME
2322     .LP
2323     cone - create an open-ended, truncated right cone
2324     .SH
2325     SYNOPSIS
2326     .LP
2327     .B cone
2328     .I "v1 rad1 v2 rad2"
2329     .SH
2330     DESCRIPTION
2331     .LP
2332     Create a truncated right cone using the current material.
2333     The starting radius is
2334     .I rad1
2335     at
2336     .I v1
2337     and the ending radius is
2338     is
2339     .I rad2
2340     at
2341     .I v2.
2342     The ends will be open, but may be capped using the
2343     .UL ring
2344     entity if desired.
2345     .LP
2346     The surface normal will usually be directed outward, but may be
2347     directed inward by giving negative values for both radii.
2348     (It is illegal for the signs of the two radii to disagree.)\0
2349     One but not both radii may be zero, indicating that the cone comes
2350     to a point.
2351     .LP
2352     Although it is not strictly forbidden to have equal cone radii, the
2353     .UL cyl
2354     entity should be used in such cases.
2355     Likewise, the
2356     .UL ring
2357     entity must be used if
2358     .I v1
2359     and
2360     .I v2
2361     are equal.
2362     .SH
2363     EXAMPLE
2364     .DS
2365     # A parasol
2366     o parasol
2367     v v1 =
2368     p 0 0 0
2369     v v2 =
2370     p 0 0 .75
2371     v v3 =
2372     p 0 0 .7
2373     m handle_mat
2374     cyl v1 .002 v2
2375     m parasol_paper
2376     cyl v2 0 v3 .33
2377     o
2378     .DE
2379     .SH
2380     SEE ALSO
2381     .LP
2382     .UL cyl,
2383     .UL f,
2384 greg 1.18 .UL fh,
2385 greg 1.1 .UL m,
2386     .UL prism,
2387     .UL ring,
2388     .UL sph,
2389     .UL torus,
2390     .UL v
2391     .ds RH PRISM
2392     .bp
2393     .SH
2394     NAME
2395     .LP
2396     prism - create a closed right prism
2397     .SH
2398     SYNOPSIS
2399     .LP
2400     .B prism
2401     .I "v1 v2 ... vN length"
2402     .SH
2403     DESCRIPTION
2404     .LP
2405     Create a closed right prism using the current material.
2406     One end face will be enclosed by the named vertices, and the
2407     opposite end face will be a mirror image at a distance
2408     .I length
2409     from the original.
2410     The edges will be extruded into N quadrilaterals connecting
2411     the two end faces.
2412     .LP
2413     The order of vertices determines the original face orientation
2414     according to the right-hand rule as explained for the
2415     .UL f
2416     entity.
2417     Normally, the prism is extruded in the direction opposite to the
2418     original surface normal, resulting in faces that all point outward.
2419     If the specified
2420     .I length
2421     is negative, the prism will be extruded above the original face
2422     and all surface normals will point inward.
2423     .LP
2424     If the vertices have associated normals, they are applied to the
2425     side faces only, and should generally point in the appropriate
2426     direction (i.e. in or out depending on whether
2427     .I length
2428     is negative or positive).
2429     .SH
2430     EXAMPLE
2431     .DS
2432     # Make a unit cube starting at the origin and \\\\
2433     extending to the positive octant
2434     v cv0 =
2435     p 0 0 0
2436     v cv1 =
2437     p 0 1 0
2438     v cv2 =
2439     p 1 1 0
2440     v cv3 =
2441     p 1 0 0
2442     # Right hand rule has original face looking in -Z direction
2443     prism cv0 cv1 cv2 cv3 1
2444     .DE
2445     .SH
2446     SEE ALSO
2447     .LP
2448     .UL cyl,
2449     .UL cone,
2450     .UL f,
2451 greg 1.18 .UL fh,
2452 greg 1.1 .UL m,
2453     .UL ring,
2454     .UL sph,
2455     .UL torus,
2456     .UL v
2457     .ds RH RING
2458     .bp
2459     .SH
2460     NAME
2461     .LP
2462     ring - create a circular ring with inner and outer radii
2463     .SH
2464     SYNOPSIS
2465     .LP
2466 greg 1.7 .B ring
2467 greg 1.1 .I "vc rmin rmax"
2468     .SH
2469     DESCRIPTION
2470     .LP
2471     Create a circular face of the current material centered on the named
2472     vertex
2473     .I vc
2474     with an inner radius of
2475     .I rmin
2476     and an outer radius of
2477     .I rmax.
2478     The surface orientation is determined by the normal vector
2479     associated with
2480     .I vc.
2481     If this vertex is undefined or has no normal, an error will result.
2482     The minimum radius may be equal to but not less than zero, and the
2483     maximum radius must be strictly greater than the minimum.
2484     .SH
2485     EXAMPLE
2486     .DS
2487     # The proverbial brass ring
2488     o brass_ring
2489     m brass
2490     v end1 =
2491     p 0 -.005 0
2492     n 0 -1 0
2493     v end2 =
2494     p 0 .005 0
2495     n 0 1 0
2496     ring end1 .02 .03
2497     cyl end1 .03 end2
2498     ring end2 .02 .03
2499     cyl end2 -.02 end1
2500     o
2501     .DE
2502     .SH
2503     SEE ALSO
2504     .LP
2505     .UL cyl,
2506     .UL cone,
2507     .UL f,
2508 greg 1.18 .UL fh,
2509 greg 1.1 .UL m,
2510     .UL prism,
2511     .UL sph,
2512     .UL torus,
2513     .UL v
2514     .ds RH TORUS
2515     .bp
2516     .SH
2517     NAME
2518     .LP
2519     torus - create a regular torus
2520     .SH
2521     SYNOPSIS
2522     .LP
2523     .B torus
2524     .I "vc rmin rmax"
2525     .SH
2526     DESCRIPTION
2527     .LP
2528     Create a torus of the current material centered on the named vertex
2529     .I vc
2530     with an inner radius of
2531     .I rmin
2532     and an outer radius of
2533     .I rmax.
2534     The plane of the torus will be perpendicular to the normal vector
2535     associated with
2536     .I vc.
2537     If this vertex is undefined or has no normal, an error will result.
2538     .LP
2539     If a torus with an inward facing surface normal is desired,
2540     .I rmin
2541     and
2542     .I rmax
2543     may be negative.
2544     The minimum radius may be zero, but may not be negative when
2545     .I rmax
2546     is positive or vice versa.
2547     The magnitude or
2548     .I rmax
2549     must always be strictly greater than that of
2550     .I rmin.
2551     .SH
2552     EXAMPLE
2553     .DS
2554     # The proverbial brass ring -- easy grip version
2555     o brass_ring
2556     m brass
2557     v center =
2558     p 0 0 0
2559     n 0 1 0
2560     torus center .02 .03
2561     o
2562     .DE
2563     .SH
2564     SEE ALSO
2565     .LP
2566     .UL cyl,
2567     .UL cone,
2568     .UL f,
2569 greg 1.18 .UL fh,
2570 greg 1.1 .UL m,
2571     .UL prism,
2572     .UL ring,
2573     .UL sph,
2574     .UL v
2575     .ds RH
2576     .ds LH
2577     .bp
2578     .NH
2579     MGF Translators
2580     .LP
2581 greg 1.13 Initially, there are six translators for MGF data, and
2582     three of these are distributed with the MGF parser itself,
2583     .I mgfilt,
2584     .I mgf2inv
2585 greg 1.12 and
2586 greg 1.13 .I 3ds2mgf.
2587 greg 1.1 Two of the other translators,
2588     .I mgf2rad
2589     and
2590     .I rad2mgf
2591     convert between MGF and the Radiance scene description language,
2592     and are distributed for free with the rest of the Radiance
2593     package\(dg.
2594     .FS
2595     \(dgRadiance is available by anonymous ftp from hobbes.lbl.gov and
2596     nestor.epfl.ch, or by WWW from
2597     "http://radsite.lbl.gov/radiance/HOME.html"
2598     .FE
2599 greg 1.13 The sixth translator,
2600 greg 1.1 .I mgf2meta,
2601     converts to a 2-dimensional line plot, and is also
2602     distributed with Radiance.
2603     .LP
2604     Mgfilt is a simple but useful utility that takes MGF on its input
2605     and produces MGF on its output.
2606     It uses the parser to convert entities that are not wanted or
2607     understood, and produces only the requested ones.
2608     This is useful for seeing what exactly a program must understand
2609     when it supports a given set of entities, and may serve as a
2610     substitute for linking to the parser library for programmers who
2611     wish to interpret the ASCII input directly but without all the
2612     unwanted entities.
2613     In future releases of MGF, this utility will also be handy for
2614     taking new entities and producing older versions of MGF for
2615     translators that have not yet been updated properly.
2616 greg 1.12 .LP
2617     Mgf2inv converts from MGF to Inventor or VRML format.
2618     Some information is lost, because these formats do not support
2619     physical light sources or materials.
2620 greg 1.13 .LP
2621     3ds2mgf converts from 3D Studio binary format to MGF.
2622     Care must be taken to correct for errors in the material descriptions,
2623     since 3D Studio is completely non-physical.
2624 greg 1.1 .ds LH Translators
2625     .ds RH MGFILT
2626     .bp
2627     .SH
2628     NAME
2629     .LP
2630     mgfilt - get usable MGF entities from input
2631     .SH
2632     SYNOPSIS
2633     .LP
2634     .B mgfilt
2635     .B version
2636     [
2637     .B input ..
2638     ]
2639     .br
2640     or
2641     .br
2642     .B mgfilt
2643     .B "e1,e2,.."
2644     [
2645     .B input ..
2646     ]
2647     .SH
2648     DESCRIPTION
2649     .LP
2650     .I Mgfilt
2651     takes one or more MGF input files and converts all the entities to
2652     the types listed.
2653     In the first form, a single integer is given for the
2654     .I version
2655     of MGF that is to be produced.
2656     Since MGF is in its first major release, this is not yet a useful
2657     form, but it will be when the second major release comes out.
2658 greg 1.9 This has the necessary side-effect of expanding all included files.
2659     (See the
2660     .UL i
2661     entity.)\0
2662 greg 1.1 .LP
2663     In the second form,
2664     .I mgfilt
2665     produces only the entities listed in the first argument, which must
2666     be comma-separated.
2667     The listed entity order is not important, but all entities given
2668     must be defined in the current version of MGF.
2669     Unknown entities will be summarily discarded on the input, and a
2670     warning message will be printed to the standard error.
2671     .SH
2672     EXAMPLES
2673     .LP
2674     To take an MGF version 3 file and send it to a version 2
2675     translator:
2676     .IP
2677     mgfilt 2 input.mgf | mgf2rad > input.rad
2678     .LP
2679     To take an MGF file and produce only flat polygonal faces
2680     with no materials:
2681     .IP
2682     mgfilt f,v,p,xf input.mgf > flatpoly.mgf
2683     .SH
2684     SEE ALSO
2685     .LP
2686 greg 1.12 i, mgf2inv, mgf2rad, rad2mgf
2687     .ds RH MGF2INV
2688     .bp
2689     .SH
2690     NAME
2691     .LP
2692     mgf2inv - convert from MGF to Inventor or VRML format
2693     .SH
2694     SYNOPSIS
2695     .LP
2696     .B mgf2inv
2697     [
2698     .B "-1|-2|-vrml"
2699     ]
2700     [
2701     .B input ..
2702     ]
2703     .SH
2704     DESCRIPTION
2705     .LP
2706     .I Mgf2inv
2707     takes one or more MGF input files and converts it to
2708     Inventor or VRML format.
2709     If the
2710     .I \-1
2711     option is used, then Inventor 1.0 ASCII output is produced.
2712     If the
2713     .I \-2
2714     option is used, then Inventor 2.0 ASCII output is produced.
2715     (This is the default.)\0
2716     If the
2717     .I \-vrml
2718     option is used, then VRML 1.0 ASCII output is produced.
2719     .LP
2720     This converter does not work properly for light sources, since
2721     the output formats do not support IES-type luminaires with recorded
2722     distributions.
2723     Also, some material information may be lost because Inventor lacks
2724     a physically valid reflectance model.
2725     .SH
2726     EXAMPLES
2727     .LP
2728     To take an MGF file and convert it to VRML format:
2729     .IP
2730     mgf2inv -vrml myscene.mgf > myscene.iv
2731     .SH
2732     SEE ALSO
2733     .LP
2734 greg 1.13 mgf2rad(1), mgfilt(1), 3ds2mgf(1), rad2mgf(1)
2735     .ds RH 3DS2MGF
2736     .bp
2737     .SH
2738     NAME
2739     .LP
2740     3ds2mgf - convert 3D Studio binary file to Materials and Geometry Format
2741     .SH
2742     SYNOPSIS
2743     .LP
2744     .B 3ds2mgf
2745     .B input
2746     [
2747     .B output
2748     ]
2749     [
2750     .B -lMatlib
2751     ][
2752     .B -xObjname
2753     ][
2754     .B -sAngle
2755     ][
2756     .B -aAnimfile
2757     ][
2758     .B -fN
2759     ]
2760     .SH
2761     DESCRIPTION
2762     .LP
2763     .I 3ds2mgf
2764     converts a 3D Studio binary scene description
2765     to the Materials and Geometry Format (MGF).
2766     If no output file name is given, the input root name
2767     will be taken as the output root, and an "mgf" extension
2768     will be added.
2769     This file will contain any light sources and materials, and an include
2770     statement for a similarly named file ending in "inc", which will contain
2771     the MGF geometry of all the translated 3DS meshes.
2772     .LP
2773     The MGF material names and properties
2774     for the surfaces will be those assigned in 3D Studio,
2775     unless they are named in one or more MGF material libraries given in a
2776     .I -l
2777     option.
2778     .LP
2779     The
2780     .I -x
2781     option may be used to exclude a named object from the output.
2782     .LP
2783     The
2784     .I -s
2785     option may be used to adjust automatic mesh smoothing such that adjacent
2786     triangle faces with less than the given angle between them (in degrees)
2787     will be smoothed.
2788     A value of zero turns smoothing off.
2789     The default value is 60 degrees.
2790     .LP
2791     The
2792     .I -a
2793     option may be used to specify a 3D Studio animation file, and together with the
2794     .I -f
2795     option,
2796     .I 3ds2mgf
2797     will generate a scene description for the specified frame.
2798     .LP
2799     Note that there are no spaces between the options and their arguments.
2800     .SH
2801     LIMITATIONS
2802     .LP
2803     Obviously, since 3D Studio has no notion of physical materials, the
2804     translation to MGF material descriptions is very ad hoc, and it will
2805     usually be necessary to edit the materials and light sources in
2806     the output file or replace materials with proper entries from a material
2807     library using the
2808     .I -l
2809     option.
2810     .LP
2811     With smoothing turned on (i.e., a non-zero value for the
2812     .I -s
2813     option), vertices in the MGF output will not be linked in a proper
2814     mesh for each object.
2815     This is due to the way the automatic smoothing code was originally
2816     written, and is too difficult to repair.
2817     If a good mesh is needed, then smoothing must be turned off.
2818     .SH
2819     EXAMPLES
2820     .LP
2821     To convert a 3D Studio robot model to MGF without smoothing.
2822     (Output will be put into "robot.mgf" and "robot.inc".)
2823     .IP
2824     3ds2mgf robot.3ds -s0
2825     .LP
2826     To convert a DC10 jet model to MGF using a hand-created material library:
2827     .IP
2828     3ds2mgf dc10.3ds -ldc10mat.mgf
2829     .SH
2830     AUTHORS
2831     .LP
2832     Steve Anger, Jeff Bowermaster and Greg Ward
2833     .br
2834     Extended from 3ds2pov 1.8.
2835     .SH
2836     SEE ALSO
2837     .LP
2838     mgf2inv(1), mgf2meta(1), mgf2rad(1)
2839 greg 1.1 .ds RH MGF2RAD
2840     .bp
2841     .SH
2842     NAME
2843     .LP
2844     mgf2rad - convert Materials and Geometry Format file to RADIANCE description
2845     .SH
2846     SYNOPSIS
2847     .LP
2848     .B mgf2rad
2849     [
2850     .B "\-m matfile"
2851     ][
2852     .B "\-e mult"
2853     ][
2854     .B "\-g dist"
2855     ]
2856     [
2857     .B input ..
2858     ]
2859     .SH
2860     DESCRIPTION
2861     .LP
2862     .I Mgf2rad
2863     converts one or more Materials and Geometry Format (MGF)
2864     files to a RADIANCE scene description.
2865     By definition, all output dimensions are in meters.
2866     The material names and properties
2867     for the surfaces will be those assigned in MGF.
2868     Any materials not defined in MGF will result in an error during
2869     translation.
2870     Light sources are described inline as IES luminaire files, and
2871     .I mgf2rad
2872     calls the program
2873     .I ies2rad(1)
2874     to translate these files.
2875     If an IES file in turn contains an MGF description of the local
2876     fixture geometry, this may result in a recursive call to
2877     .I mgf2rad,
2878     which is normal and should be transparent.
2879     The only side-effect of this additional translation is the
2880     appearance of other RADIANCE scene and data files produced
2881     automatically by
2882     .I ies2rad.
2883     .LP
2884     The
2885     .I \-m
2886     option may be used to put all the translated materials into a separate
2887     RADIANCE file.
2888     This is not always advisable, as any given material name may be
2889     reused at different points in the MGF description, and writing them
2890     to a separate file loses the contextual association between
2891     materials and surfaces.
2892     As long as unique material names are used throughout the MGF
2893     description and material properties are not redefined, there
2894     will be no problem.
2895     Note that this is the only way to get all the translated materials
2896     into a single file, since no output is produced for unreferenced
2897     materials; i.e. translating just the MGF materials does not work.
2898     .LP
2899     The
2900     .I \-e
2901     option may be used to multiply all the emission values by the
2902     given
2903     .I mult
2904     factor.
2905     The
2906     .I \-g
2907     option may be used to establish a glow distance (in meters)
2908     for all emitting surfaces.
2909     These two options are employed principally by
2910     .I ies2rad,
2911     and are not generally useful to most users.
2912     .SH
2913     EXAMPLES
2914     .LP
2915     To translate two MGF files into one RADIANCE materials file and
2916     one geometry file:
2917     .IP
2918     mgf2rad -m materials.rad building1.mgf building2.mgf > building1+2.rad
2919     .LP
2920     To create an octree directly from two MGF files and one RADIANCE
2921     file:
2922     .IP
2923     oconv '\\!mgf2rad materials.mgf scene.mgf' source.rad > scene.oct
2924     .SH
2925     FILES
2926     .LP
2927     tmesh.cal Used to smooth polygonal geometry
2928     .br
2929     *.rad RADIANCE source descriptions created by ies2rad
2930     .br
2931     *.dat RADIANCE source data created by ies2rad
2932     .br
2933     source.cal Used for IES source coordinates
2934     .SH
2935     AUTHOR
2936     .LP
2937     Greg Ward
2938     .SH
2939     SEE ALSO
2940     .LP
2941     ies2rad(1), mgf2meta(1), obj2rad(1), oconv(1), rad2mgf(1), xform(1)
2942 greg 1.3 .ds RH RAD2MGF
2943 greg 1.1 .bp
2944     .SH
2945     NAME
2946     .LP
2947     rad2mgf - convert RADIANCE scene description to Materials and Geometry Format
2948     .SH
2949     SYNOPSIS
2950     .LP
2951     .B rad2mgf
2952     [
2953     .B \-dU
2954     ]
2955     [
2956     .B input ..
2957     ]
2958     .SH
2959     DESCRIPTION
2960     .LP
2961     .I Rad2mgf
2962     converts one or more RADIANCE scene files
2963     to the Materials and Geometry Format (MGF).
2964     Input units are specified with the
2965     .I \-mU
2966     option, where
2967     .I U
2968     is one of 'm' (meters), 'c' (centimeters), 'f' (feet) or 'i'
2969     (inches).
2970     The assumed unit is meters, which is the required output unit for
2971     MGF (thus the need to know).
2972     If the input dimensions are in none of these units, then the user
2973     should apply
2974     .I xform(1)
2975     with the
2976     .I \-s
2977     option to bring the units into line prior to translation.
2978     .LP
2979     The MGF material names and properties
2980     for the surfaces will be those assigned in RADIANCE.
2981     If a referenced material has not been defined, then its name will
2982     be invoked in the MGF output without definition, and the description
2983     will be incomplete.
2984     .SH
2985     LIMITATIONS
2986     .LP
2987     Although MGF supports all of the geometric types and the most
2988     common material types used in RADIANCE, there is currently no
2989     support for advanced BRDF materials, patterns, textures or mixtures.
2990     Also, the special types "source" and "antimatter" are not supported,
2991     and all light source materials are converted to simple diffuse emitters
2992     (except "illum" materials, which are converted to their alternates).
2993     These primitives are reproduced as comments in the output and
2994     must be replaced manually if necessary.
2995     .LP
2996     The RADIANCE "instance" type is treated specially.
2997     .I Rad2mgf
2998     converts each instance to an MGF include statement, using the corresponding
2999     transformation and a file name derived from the octree name.
3000     (The original octree suffix is replaced by ".mgf".)\0
3001     For this to work, the user must separately create the referenced
3002     MGF files from the original RADIANCE descriptions.
3003     The description file names can usually be determined using the
3004     .I getinfo(1)
3005     command run on the octrees in question.
3006     .SH
3007     EXAMPLES
3008     .LP
3009     To convert three RADIANCE files (in feet) to one MGF file:
3010     .IP
3011     mgf2rad -df file1.rad file2.rad file3.rad > scene.mgf
3012     .LP
3013     To translate a RADIANCE materials file to MGF:
3014     .IP
3015     mgf2rad materials.rad > materials.mgf
3016     .SH
3017     AUTHOR
3018     .LP
3019     Greg Ward
3020     .SH
3021     SEE ALSO
3022     .LP
3023     getinfo(1), ies2rad(1), mgf2meta(1), mgf2rad(1), obj2rad(1), oconv(1), xform(1)
3024     .ds RH MGF2META
3025     .bp
3026     .SH
3027     NAME
3028     .LP
3029     mgf2meta - convert Materials and Geometry Format file to Metafile graphics
3030     .SH
3031     SYNOPSIS
3032     .LP
3033     .B mgf2meta
3034     [
3035     .B "-t threshold"
3036     ]
3037     .B "{x|y|z} xmin xmax ymin ymax zmin zmax"
3038     [
3039     .B input ..
3040     ]
3041     .SH
3042     DESCRIPTION
3043     .LP
3044     .I Mgf2meta
3045     converts one or more Materials and Geometry Format (MGF)
3046     files to a 2-D orthographic projection along the selected axis in the
3047     .I metafile(1)
3048     graphics format.
3049     All geometry is clipped to the specified bounding box, and the
3050     resulting orientation is as follows:
3051     .sp .5
3052     .nf
3053     Projection Orientation
3054     ======= ========
3055     x Y-axis right, Z-axis up
3056     y Z-axis right, X-axis up
3057     z X-axis right, Z-axis up
3058     .fi
3059     .LP
3060     If multiple input files are given, the first file prints in black,
3061     the second prints in red, the third in green and the fourth in blue.
3062     If more than four input files are given, they cycle through the
3063     colors again in three other line types: dashed, dotted and
3064     dot-dashed.
3065     .LP
3066     The
3067     .I \-t
3068     option may be used to randomly throw out line segments that are
3069     shorter than the given
3070     .I threshold
3071     (given as a fraction of the plot width).
3072     Segments are included with a
3073     probability equal to the square of the line length over the square
3074     of the threshold.
3075     This can greatly reduce the number of lines in the drawing (and
3076     therefore improve the drawing speed) with only a modest loss in
3077     quality.
3078     A typical value for this parameter is 0.005.
3079     .LP
3080     All MGF material information is ignored on the input.
3081     .SH
3082     EXAMPLES
3083     .LP
3084     To project two MGF files along the Z-axis and display them under
3085     X11:
3086     .IP
3087     mgf2meta z 0 10 0 15 0 9 building1.mgf building2.mgf | x11meta
3088     .LP
3089     To convert a RADIANCE scene to a line drawing in RADIANCE picture
3090     format:
3091     .IP
3092     rad2mgf scene.rad | mgf2meta x `getbbox -h scene.rad` | meta2tga |
3093     ra_t8 -r > scene.pic
3094     .SH
3095     AUTHOR
3096     .LP
3097     Greg Ward
3098     .SH
3099     SEE ALSO
3100     .LP
3101     getbbox(1), meta2tga(1), metafile(5), mgf2rad(1), pflip(1),
3102     protate(1), psmeta(1), ra_t8(1), rad2mgf(1), t4014(1), x11meta(1)
3103     .ds RH
3104     .ds LH
3105     .bp
3106     .NH
3107     MGF Parser Library
3108     .LP
3109     The principal motivation for creating a standard parser library for
3110     MGF is to make it easy for software developers to offer some base
3111     level of compliance.
3112     The key to making MGF easy to support in fact is the parser, which
3113     has the ability to express higher order entities in terms of
3114     lower order ones.
3115     For example, tori are part of the MGF specification, but if a given
3116     program or translator does not support them, the parser will convert
3117     them to cones.
3118     If cones are not supported either, it will convert them further into
3119     smoothed polygons.
3120     If smoothing (vertex normal information) is not supported, it will
3121     be ignored and the program will just get flat polygons.
3122     This is done in such a way that future versions of the standard may
3123     include new entities that old software does not even have to know
3124     about, and they will be converted appropriately.
3125     Forward compatibility is thus built right into the parser loading
3126     mechanism itself -- the programmer simply links to the new code and
3127     the new standard is supported without any further changes.
3128     .SH
3129     Language
3130     .LP
3131     The provided MGF parser is written in ANSI-C.
3132     This language was chosen for reasons of portability and efficiency.
3133     Almost all systems support some form of ANSI-compatible C, and many
3134     languages can cross-link to C libraries without modification.
3135     Backward compatibility to Kernighan and Ritchie C is achieved by
3136     compiling with the -DNOPROTO flag.
3137     .LP
3138     All of the data structures and prototypes needed for the library
3139     are in the header file "parser.h".
3140     This file is the best resource for the parser and is updated with
3141     each MGF release.
3142     .SH
3143     Mechanism
3144     .LP
3145     The parser works by a simple callback mechanism to routines that
3146     actually interpret the individual entities.
3147     Some of these routines will belong to the calling program, and some
3148     will be entity support routines included in the library itself.
3149     There is a global array of function pointers, called
3150     .I mg_ehand.
3151     It is defined thus:
3152     .DS
3153     extern int (*mg_ehand[MG_NENTITIES])(int argc, char **argv);
3154     .DE
3155     Before parsing begins, this dispatch table is initialized to point to the
3156     routines that will handle each supported entity.
3157     Every entity handler has the same basic prototype, which is the
3158     same as the
3159     .I main
3160     function, i.e:
3161     .DS
3162     extern int \f2handler\f1(int argc, char **argv);
3163     .DE
3164     The first argument is the number of words in the MGF entity
3165     (counting the entity itself) and the second argument is an array of
3166     nul-terminated strings with the entity and its arguments.
3167     The function should return zero or one of the error
3168     codes defined in "parser.h".
3169     A non-zero return value causes the parser to abort, returning the
3170     error up through its call stack to the entry function, usually
3171     .I mg_load.
3172     .LP
3173     A special function pointer for undefined entities is
3174     defined as follows:
3175     .DS
3176     extern int (*mg_uhand)(int argc, char **argv);
3177     .DE
3178     By default, this points to the library function
3179     .I mg_defuhand,
3180     which prints an error message on the first unknown entity and keeps a
3181     count from then on, which is stored in the global unsigned integer
3182     .I mg_nunknown.
3183     If the
3184     .I mg_uhand
3185     pointer is assigned a value of NULL instead, parsing will abort at the
3186     first unrecognized entity.
3187     The reason this is not the default action is that ignoring unknown entities
3188     offers a certain base level of forward compatibility.
3189     Ignoring things one does not understand is not the best approach, but it
3190     is usually better than quitting with an error message if the input is
3191     in fact valid, but is a later version of the standard.
3192     The real solution is to update the interpreter by linking to a new version
3193     of the parser, or use a new version of the
3194     .I mgfilt
3195     command to convert the new MGF input to an older standard.
3196     .LP
3197     The
3198     .I mg_uhand
3199     pointer may also be used to customize the language for a particular
3200     application by adding entities, though this is discouraged because it
3201     tends to weaken the standard.
3202     .LP
3203     The skeletal framework for an MGF loader or translator is to assign
3204     function pointers to the
3205     .I mg_ehand
3206     array, call the parser initialization function
3207     .I mg_init,
3208     then call the file loader function
3209     .I mg_load
3210     once for each input file.
3211     This will in turn make calls back to the functions assigned to
3212     .I mg_ehand.
3213     To give a simple example, let us look at a
3214     translator that understands only flat polygonal faces, putting out
3215     vertex locations immediately after each "face" keyword:
3216     .DS
3217     #include <stdio.h>
3218     #include "parser.h"
3219    
3220     int
3221     myfaceh(ac, av) /* face handling routine */
3222     int ac;
3223     char **av;
3224     {
3225     C_VERTEX *vp; /* vertex structure pointer */
3226     FVECT vert; /* vertex point location */
3227     int i;
3228    
3229     if (ac < 4) /* check # arguments */
3230     return(MG_EARGC);
3231 greg 1.2 printf("face\\\\n"); /* begin face output */
3232 greg 1.1 for (i = 1; i < ac; i++) {
3233     if ((vp = c_getvert(av[i])) == NULL) /* vertex from name */
3234     return(MG_EUNDEF);
3235     xf_xfmpoint(vert, vp->p); /* apply transform */
3236 greg 1.2 printf("%15.9f %15.9f %15.9f\\\\n",
3237 greg 1.1 vert[0], vert[1], vert[2]); /* output vertex */
3238     }
3239 greg 1.2 printf(";\\\\n"); /* end of face output */
3240 greg 1.1 return(MG_OK); /* normal exit */
3241     }
3242    
3243     main(argc, argv) /* translate MGF file(s) */
3244     int argc;
3245     char **argv;
3246     {
3247     int i;
3248     /* initialize dispatch table */
3249     mg_ehand[MG_E_FACE] = myfaceh; /* ours */
3250     mg_ehand[MG_E_VERTEX] = c_hvertex; /* parser lib */
3251     mg_ehand[MG_E_POINT] = c_hvertex; /* parser lib */
3252     mg_ehand[MG_E_XF] = xf_handler; /* parser lib */
3253     mg_init(); /* initialize parser */
3254     for (i = 1; i < argc; i++) /* load each file argument */
3255     if (mg_load(argv[i]) != MG_OK) /* and check for error */
3256     exit(1);
3257     exit(0); /* all done! */
3258     }
3259     .DE
3260     Hopefully, this example demonstrates just how easy it is to
3261     write an MGF translator.
3262     Of course, translators get more complicated the more entity
3263     types they support, but the point is that one does not
3264     .I have
3265     to support every entity -- the parser handles what the translator
3266     does not.
3267     Also, the library includes many general entity handlers,
3268     further reducing the burden on the programmer.
3269     This same principle means that it is not necessary to modify an
3270     existing program to accommodate a new version of MGF -- one need only
3271     link to the new parser library to comply with the new standard.
3272     .SH
3273     Division of Labor
3274     .LP
3275     As seen in the previous example, there are two parser routines that
3276     are normally called directly in an MGF translator or loader program.
3277     The first is
3278     .I mg_init,
3279     which takes no arguments but relies on the program having
3280     initialized those parts of the global
3281     .I mg_ehand
3282     array it cares about.
3283     The second routine is
3284     .I mg_load,
3285     which is called once on each input file.
3286     (A third routine,
3287     .I mg_clear,
3288     may be called to free the parser data structures after each file or
3289     after all files, if the program plans to continue rather than
3290     exit.)\0
3291     .LP
3292     The rest of the routines in a translator or loader program are
3293     called indirectly through the
3294     .I mg_ehand
3295     dispatch table, and they are the ones that do the real work of
3296     supporting the MGF entities.
3297     In addition to converting or discarding entities that the calling
3298     program does not know or care about, the parser library includes a
3299     set of context handlers that greatly simplify the translation
3300     process.
3301     There are three handlers for each of the three named contexts and
3302     their constituents, and two handlers for the two hierarchical
3303     context entities.
3304     To use these handlers, one simply sets the appropriate positions in the
3305     .I mg_ehand
3306     dispatch table to point to these functions.
3307     Additional functions and global data structures provide convenient
3308     access to the relevant contexts, and all of these are detailed in
3309     the following manual pages.
3310     .ds LH Basic Parser Routines
3311     .ds RH MG_INIT
3312     .bp
3313     .SH
3314     NAME
3315     .LP
3316     mg_init, mg_ehand, mg_uhand - initialize MGF entity handlers
3317     .SH
3318     SYNOPSIS
3319     .LP
3320     #include "parser.h"
3321     .LP
3322     .B void
3323     mg_init(
3324     .B void
3325     )
3326     .LP
3327     .B int
3328     mg_defuhand(
3329     .B int
3330     argc,
3331     .B char
3332     **argv )
3333     .LP
3334     .B "extern int"
3335     (*mg_ehand[MG_NENTITIES])(
3336     .B int
3337     argc,
3338     .B char
3339     **argv )
3340     .LP
3341     .B "extern int"
3342     (*mg_uhand)(
3343     .B int
3344     argc,
3345     .B char
3346     **argv )
3347     .LP
3348     .B "extern unsigned"
3349     mg_nunknown
3350     .SH
3351     DESCRIPTION
3352     .LP
3353     The parser dispatch table,
3354     .I mg_ehand
3355     is initially set to all NULL pointers, and it
3356     is the duty of the calling program to assign entity handler functions to
3357     each of the supported entity positions in the array.
3358     The entities are given in the include file "parser.h" as the
3359     following:
3360     .DS
3361     #define MG_E_COMMENT 0 /* # */
3362     #define MG_E_COLOR 1 /* c */
3363     #define MG_E_CCT 2 /* cct */
3364     #define MG_E_CONE 3 /* cone */
3365     #define MG_E_CMIX 4 /* cmix */
3366     #define MG_E_CSPEC 5 /* cspec */
3367     #define MG_E_CXY 6 /* cxy */
3368 greg 1.4 #define MG_E_CYL 7 /* cyl */
3369 greg 1.1 #define MG_E_ED 8 /* ed */
3370     #define MG_E_FACE 9 /* f */
3371     #define MG_E_INCLUDE 10 /* i */
3372     #define MG_E_IES 11 /* ies */
3373 greg 1.2 #define MG_E_IR 12 /* ir */
3374 greg 1.1 #define MG_E_MATERIAL 13 /* m */
3375     #define MG_E_NORMAL 14 /* n */
3376     #define MG_E_OBJECT 15 /* o */
3377     #define MG_E_POINT 16 /* p */
3378     #define MG_E_PRISM 17 /* prism */
3379     #define MG_E_RD 18 /* rd */
3380     #define MG_E_RING 19 /* ring */
3381     #define MG_E_RS 20 /* rs */
3382     #define MG_E_SIDES 21 /* sides */
3383     #define MG_E_SPH 22 /* sph */
3384     #define MG_E_TD 23 /* td */
3385     #define MG_E_TORUS 24 /* torus */
3386     #define MG_E_TS 25 /* ts */
3387     #define MG_E_VERTEX 26 /* v */
3388     #define MG_E_XF 27 /* xf */
3389    
3390     #define MG_NENTITIES 28 /* total # entities */
3391     .DE
3392     .LP
3393     Once the
3394     .I mg_ehand
3395     array has been set by the program, the
3396     .I mg_init
3397     routine must be called to complete the initialization process.
3398     This should be done once and only once per invocation, before any other
3399     parser routines are called.
3400     .LP
3401     The
3402     .I mg_uhand
3403     variable points to the current handler for unknown entities
3404     encountered on the input.
3405     Its default value points to the
3406     .I mg_defuhand
3407     function, which simply increments the global variable
3408     .I mg_nunknown,
3409     printing a warning message on the standard error on the first
3410     offense.
3411     (This message may be avoided by incrementing
3412     .I mg_nunknown
3413     before processing begins.)\0
3414     If
3415     .I mg_uhand
3416     is assigned a value of NULL, then an unknown entity will return an
3417     .I MG_EUNK
3418     error, which will cause the parser to abort.
3419     (See the
3420     .I mg_load
3421     page for a list of errors.)\0
3422     If the
3423     .I mg_uhand
3424     pointer is assigned to another function, that function will receive
3425     any unknown entities and their arguments, and the parsing will
3426     abort if the new function returns a non-zero error value.
3427     This offers a convenient way to customize the language by adding
3428     non-standard entities.
3429     .SH
3430     DIAGNOSTICS
3431     .LP
3432     If an inconsistent set of entities has been set for support, the
3433     .I mg_init
3434     routine will print an informative message to standard error and abort
3435     the calling program with a call to
3436     .I exit.
3437     This is normally unacceptable behavior for a library routine, but since
3438     such an error indicates a fault with the calling program itself,
3439     recovery is impossible.
3440     .SH
3441     SEE ALSO
3442     .LP
3443     mg_load, mg_handle
3444     .ds RH MG_LOAD
3445     .bp
3446     .SH
3447     NAME
3448     .LP
3449     mg_load, mg_clear, mg_file, mg_err - load MGF file, clear data structures
3450     .SH
3451     SYNOPSIS
3452     .LP
3453     #include "parser.h"
3454     .LP
3455     .B int
3456     mg_load(
3457     .B char
3458     *filename )
3459     .LP
3460     .B void
3461     mg_clear(
3462     .B void
3463     )
3464     .LP
3465     .B extern
3466     MG_FCTXT *mg_file
3467     .LP
3468     .B "extern char"
3469     *mg_err[MG_NERRS]
3470     .SH
3471     DESCRIPTION
3472     .LP
3473     The
3474     .I mg_load
3475     function loads the named file, or standard input if
3476     .I filename
3477     is the NULL pointer.
3478     Calls back to the appropriate MGF handler routines are made through the
3479     .I mg_ehand
3480     dispatch table.
3481     .LP
3482     The global
3483     .I mg_file
3484     variable points to the current file context structure, which
3485     may be useful for the interpretation of certain entities, such as
3486     .UL ies,
3487     which must know the directory path of the enclosing file.
3488     This structure is of the defined type
3489     .I MG_FCTXT,
3490     given in "parser.h" as:
3491     .DS
3492     typedef struct mg_fctxt {
3493     char fname[96]; /* file name */
3494     FILE *fp; /* stream pointer */
3495     int fid; /* unique file context id */
3496     char inpline[4096]; /* input line */
3497     int lineno; /* line number */
3498     struct mg_fctxt *prev; /* previous context */
3499     } MG_FCTXT;
3500     .DE
3501     .SH
3502     DIAGNOSTICS
3503     .LP
3504     If an error is encountered during parsing,
3505     .I mg_load
3506     will print an appropriate error message to the standard error stream
3507     and return one of the non-zero values from "parser.h" listed below:
3508     .DS
3509     #define MG_OK 0 /* normal return value */
3510     #define MG_EUNK 1 /* unknown entity */
3511     #define MG_EARGC 2 /* wrong number of arguments */
3512     #define MG_ETYPE 3 /* argument type error */
3513 greg 1.14 #define MG_EILL 4 /* illegal argument value */
3514 greg 1.1 #define MG_EUNDEF 5 /* undefined reference */
3515     #define MG_ENOFILE 6 /* cannot open input file */
3516     #define MG_EINCL 7 /* error in included file */
3517     #define MG_EMEM 8 /* out of memory */
3518     #define MG_ESEEK 9 /* file seek error */
3519     #define MG_EBADMAT 10 /* bad material specification */
3520 greg 1.8 #define MG_ELINE 11 /* input line too long */
3521 greg 1.10 #define MG_ECNTXT 12 /* unmatched context close */
3522 greg 1.1
3523 greg 1.14 #define MG_NERRS 13
3524 greg 1.1 .DE
3525     If it is inappropriate to send output to standard error, the calling
3526     program should use the routines listed under
3527     .I mg_open
3528     for better control over the parsing process.
3529     .LP
3530     The
3531     .I mg_err
3532     array contains error messages corresponding to each of the values
3533     listed above in the native country's language.
3534     .SH
3535     SEE ALSO
3536     .LP
3537 greg 1.4 mg_fgetpos, mg_handle, mg_init, mg_open
3538 greg 1.1 .ds RH MG_OPEN
3539     .bp
3540     .SH
3541     NAME
3542     .LP
3543     mg_open, mg_read, mg_parse, mg_close - MGF file loading subroutines
3544     .SH
3545     SYNOPSIS
3546     .LP
3547     #include "parser.h"
3548     .LP
3549     .B int
3550     mg_open( MG_FCTXT *fcp,
3551     .B char
3552     *filename )
3553     .LP
3554     .B int
3555     mg_read(
3556     .B void
3557     )
3558     .LP
3559     .B int
3560     mg_parse(
3561     .B void
3562     )
3563     .LP
3564     .B void
3565     mg_close(
3566     .B void
3567     )
3568     .SH
3569     DESCRIPTION
3570     .LP
3571     Most loaders and translators will call the
3572     .I mg_load
3573     routine to handle the above operations, but some programs or
3574     entity handlers require tighter control over the loading process.
3575     .LP
3576     The
3577     .I mg_open
3578     routine takes an uninitialized
3579     .I MG_FCTXT
3580     structure and a file name as its arguments.
3581     If
3582     .I filename
3583     is the NULL pointer, the standard input is "opened."
3584     The
3585     .I fcp
3586     structure will be set by
3587     .I mg_open
3588     prior to its return, and the global
3589     .I mg_file
3590     pointer will be assigned to point to it.
3591     This variable must not be destroyed until after the file is closed
3592     with a call to
3593     .I mg_close.
3594     (See the
3595     .I mg_load
3596     page for a definition of
3597     .I mg_file
3598     and the
3599     .I MG_FCTXT
3600     type.)\0
3601     .LP
3602     The
3603     .I mg_read
3604     function reads the next input line from the current file,
3605     returning the number of characters in the line, or zero if the
3606     end of file is reached or there is a file error.
3607 greg 1.11 If the value returned equals MG_MAXLINE-1,
3608 greg 1.8 then the input line was too long, and you
3609     should return an MG_ELINE error.
3610 greg 1.11 The function keeps track of the
3611 greg 1.1 line number in the current file context
3612     .I mg_file,
3613     which also contains the line that was read.
3614     .LP
3615     The
3616     .I mg_parse
3617     function breaks the current line in the
3618     .I mg_file
3619     structure into words and calls the appropriate handler routine, if
3620     any.
3621     Blank lines and unsupported entities cause a quick return.
3622     .LP
3623     The
3624     .I mg_close
3625     routine closes the current input file (unless it is the standard
3626     input) and returns to the previous file context (if any).
3627     .SH
3628     DIAGNOSTICS
3629     .LP
3630     The
3631     .I mg_open
3632     function returns
3633     .I MG_OK
3634     (0) normally, or
3635     .I MG_ENOFILE
3636     if the open fails for some reason.
3637     .LP
3638     The
3639     .I mg_parse
3640     function returns
3641     .I MG_OK
3642     if the current line was successfully interpreted, or one of the
3643     defined error values if there is a problem.
3644     (See the
3645     .I mg_load
3646     page for the defined error values.)\0
3647     .SH
3648     SEE ALSO
3649     .LP
3650     mg_fgetpos, mg_handle, mg_init, mg_load
3651     .ds RH MG_FGETPOS
3652     .bp
3653     .SH
3654     NAME
3655     .LP
3656     mg_fgetpos, mg_fgoto - get current file position and seek to pointer
3657     .SH
3658     SYNOPSIS
3659     .LP
3660     #include "parser.h"
3661     .LP
3662     .B void
3663     mg_fgetpos( MG_FPOS *pos )
3664     .LP
3665     .B int
3666     mg_fgoto( MG_FPOS *pos )
3667     .SH
3668     DESCRIPTION
3669     .LP
3670     The
3671     .I mg_fgetpos
3672     gets the current MGF file position and loads it into the passed
3673     .I MG_FPOS
3674     structure,
3675     .I pos.
3676     .LP
3677     The
3678     .I mg_fgoto
3679     function seeks to the position
3680     .I pos,
3681     taken from a previous call to
3682     .I mg_fgetpos.
3683     .SH
3684     DIAGNOSTICS
3685     .LP
3686     If
3687     .I mg_fgoto
3688     is passed an illegal pointer or one that does not correspond to the
3689     current
3690     .I mg_file
3691     context, it will return the
3692     .I MG_ESEEK
3693     error value.
3694     Normally, it returns
3695     .I MG_OK
3696     (0).
3697     .SH
3698     SEE ALSO
3699     .LP
3700     mg_load, mg_open
3701     .ds RH MG_HANDLE
3702     .bp
3703     .SH
3704     NAME
3705     .LP
3706     mg_handle, mg_entity, mg_ename, mg_nqcdivs - entity assistance and control
3707     .SH
3708     SYNOPSIS
3709     .LP
3710     .B int
3711     mg_handle(
3712     .B int
3713     en,
3714     .B int
3715     ac,
3716     .B char
3717     *av )
3718     .LP
3719     .B int
3720     mg_entity(
3721     .B char
3722     *name )
3723     .LP
3724     .B "extern char"
3725     mg_ename[MG_NENTITIES][MG_MAXELEN]
3726     .LP
3727     .B "extern int"
3728     mg_nqcdivs
3729     .SH
3730     DESCRIPTION
3731     .LP
3732     The
3733     .I mg_handle
3734     routine may be used to pass entities back to the parser
3735     to be redirected through the
3736     .I mg_ehand
3737     dispatch table.
3738     This method is recommended rather than calling through
3739     .I mg_ehand
3740     directly, since the parser sometimes has its own support routines
3741     that it needs to call for specific entities.
3742     The first argument,
3743     .I en,
3744     is the corresponding entity number, or -1 if
3745     .I mg_handle
3746     should figure it out from the first
3747     .I av
3748     argument.
3749     .LP
3750     The
3751     .I mg_entity
3752     function gets an entity number from its name, using a hash
3753     table on the
3754     .I mg_ename
3755     list.
3756     .LP
3757     The
3758     .I mg_ename
3759     table contains the string names corresponding to each MGF entity in
3760     the designated order.
3761     (See the
3762     .I mg_init
3763     page for the list of MGF entities.)\0
3764     .LP
3765     The global integer variable
3766     .I mg_nqcdivs
3767     tells the parser how many subdivisions to use per quarter circle (90
3768     degrees) when tesselating curved geometry.
3769     The default value is 5, and it may be reset at any time by the
3770     calling program.
3771     .SH
3772     DIAGNOSTICS
3773     .LP
3774     The
3775     .I mg_handle
3776     function returns
3777     .I MG_OK
3778     if the entity is handled correctly, or one of the predefined error
3779     values if there is a problem.
3780     (See the
3781     .I mg_load
3782     page for a list of error values.)\0
3783     .LP
3784     The
3785     .I mg_entity
3786     function returns -1 if the passed name does not appear in the
3787     .I mg_ename
3788     list.
3789     .SH
3790     SEE ALSO
3791     .LP
3792     mg_init, mg_load, mg_open
3793     .ds RH ISINT, ISFLT, ISNAME
3794     .bp
3795     .SH
3796     NAME
3797     .LP
3798     isint, isflt, isname - determine if string fits integer or real format,
3799     or is legal identifier
3800     .SH
3801     SYNOPSIS
3802     .LP
3803     .B int
3804     isint(
3805     .B char
3806     *str )
3807     .LP
3808     .B int
3809     isflt(
3810     .B char
3811     *str )
3812     .LP
3813     .B int
3814     isname(
3815     .B char
3816     *str )
3817     .SH
3818     DESCRIPTION
3819     .LP
3820     The
3821     .I isint
3822     function checks to see if the passed string
3823     .I str
3824     matches a decimal integer format (positive or negative),
3825     and returns 1 or 0 based on whether it does or does not.
3826     .LP
3827     The
3828     .I isflt
3829     function checks to see if the passed string
3830     .I str
3831     matches a floating point format (positive or negative with optional
3832     exponent), and returns 1 or 0 based on whether it does or does not.
3833     .LP
3834     The
3835     .I isname
3836     function checks to see if the passed string
3837     .I str
3838     is a legal identifier name.
3839     In MGF, a legal identifier must begin with a letter and contain only
3840     visible ASCII characters (those between decimal 33 and 127 inclusive).
3841     The one caveat to this is that names may begin with one or more
3842     underscores ('_'), but this is a trick employed by the parser to
3843     maintain a separate name space from the user, and is not legal usage
3844     otherwise.
3845     .LP
3846     Note that a string that matches an integer format is also a valid
3847     floating point value.
3848     Conversely, a string that is not a floating point number cannot be a
3849     valid integer.
3850     .LP
3851     These routines are useful for checking arguments passed to entity
3852     handlers that certain types in certain positions.
3853     If an invalid argument is passed, the handler should return an
3854     .I MG_ETYPE
3855     error.
3856     .SH
3857     SEE ALSO
3858     .LP
3859     mg_init, mg_load
3860     .ds LH Entity Support Routines
3861     .ds RH C_HVERTEX
3862     .bp
3863     .SH
3864     NAME
3865     .LP
3866     c_hvertex, c_getvert, c_cvname, c_cvertex - vertex entity support
3867     .SH
3868     SYNOPSIS
3869     .LP
3870     #include "parser.h"
3871     .LP
3872     .B int
3873     c_hvertex(
3874     .B int
3875     argc,
3876     .B char
3877     **argv )
3878     .LP
3879     C_VERTEX *c_getvert(
3880     .B char
3881     *name )
3882     .LP
3883     .B "extern char"
3884     *c_vname
3885     .LP
3886     .B extern
3887     C_VERTEX *c_cvertex
3888     .SH
3889     DESCRIPTION
3890     .LP
3891     The
3892     .I c_hvertex
3893     function handles the MGF vertex entities,
3894     .UL v,
3895     .UL p
3896     and
3897     .UL n.
3898     If either
3899     .UL p
3900     or
3901     .UL n
3902     is supported, then
3903     .UL v
3904     must be also.
3905     The assignments are normally made to the
3906     .I mg_ehand
3907     array prior to parser initialization, like so:
3908     .DS
3909     mg_ehand[MG_E_VERTEX] = c_hvertex; /* support "v" entity */
3910     mg_ehand[MG_E_POINT] = c_hvertex; /* support "p" entity */
3911     mg_ehand[MG_E_NORMAL] = c_hvertex; /* support "n" entity */
3912     /* other entity handler assignments... */
3913     mg_init(); /* initialize parser */
3914     .DE
3915     If vertex normals are not understood by any of the program-supported
3916     entities, then the
3917     .I MG_E_NORMAL
3918     entry may be left with its original NULL assignment.
3919     .LP
3920     The
3921     .I c_getvert
3922     call takes the name of a defined vertex and returns a pointer to its
3923     .I C_VERTEX
3924     structure, defined in "parser.h" as:
3925     .DS
3926     typedef FLOAT FVECT[3]; /* a 3-d real vector */
3927    
3928     typedef struct {
3929     int clock; /* incremented each change -- resettable */
3930     FVECT p, n; /* point and normal */
3931     } C_VERTEX; /* vertex context */
3932     .DE
3933     The
3934     .I clock
3935     member will be incremented each time the value gets changed by a
3936     .UL p
3937     or
3938     .UL n
3939     entity, and may be reset by the controlling program if desired.
3940     This is a convenient way to keep track of whether or not a vertex has
3941     changed since its last use.
3942     To link identical vertices, one must also check that the current
3943     transform has not changed, which is uniquely identified by the
3944     global
3945     .I xf_context->xid
3946 greg 1.14 variable, but only if one is using the parser library's transform
3947 greg 1.1 handler.
3948     (See the
3949     .I xf_handler
3950     page.)\0
3951     .LP
3952     It is possible but not recommended to alter the contents of the
3953     vertex structure returned by
3954     .I c_getvert.
3955     Normally it is read during the
3956     interpretation of entities using named vertices.
3957     .LP
3958     The name of the current vertex is given by the global
3959     .I c_cvname
3960     variable, which is set to NULL if the unnamed vertex is current.
3961     The current vertex value is pointed to by the global variable
3962     .I c_cvertex,
3963     which should never be NULL.
3964     .SH
3965     DIAGNOSTICS
3966     .LP
3967     The
3968     .I c_hvertex
3969     function returns
3970     .I MG_OK
3971     (0) if the vertex is handled correctly, or one of the predefined
3972     error values if there is a problem.
3973     (See the
3974     .I mg_load
3975     page for a list of errors.)\0
3976     .LP
3977     The
3978     .I c_getvert
3979     function returns NULL if the specified vertex name is undefined, at
3980     which point the calling function should return an
3981     .I MG_EUNDEF
3982     error.
3983     .SH
3984     SEE ALSO
3985     .LP
3986     c_hcolor, c_hmaterial, mg_init, mg_load, xf_handler
3987     .ds RH C_HCOLOR
3988     .bp
3989     .SH
3990     NAME
3991     .LP
3992     c_hcolor, c_getcolor, c_ccname, c_ccolor, c_ccvt, c_isgrey -
3993     color entity support
3994     .SH
3995     SYNOPSIS
3996     .LP
3997     #include "parser.h"
3998     .LP
3999     .B int
4000     c_hcolor(
4001     .B int
4002     argc,
4003     .B char
4004     **argv )
4005     .LP
4006     C_COLOR *c_getcolor(
4007     .B char
4008     *name )
4009     .LP
4010     .B "extern char"
4011     *c_ccname
4012     .LP
4013     .B extern
4014     C_COLOR *c_ccolor
4015     .LP
4016     .B void
4017     c_ccvt( C_COLOR *cvp,
4018     .B int
4019     cflags )
4020     .LP
4021     .B int
4022     c_isgrey( C_COLOR *cvp )
4023     .SH
4024     DESCRIPTION
4025     .LP
4026     The
4027     .I c_hcolor
4028     function supports the MGF entities,
4029     .UL c,
4030     .UL cxy,
4031     .UL cspec,
4032     .UL cct
4033     and
4034     .UL cmix.
4035     It is an error to support any of the color field entities without
4036     supporting the
4037     .UL c
4038     entity itself.
4039     The assignments are normally made to the
4040     .I mg_ehand
4041     array prior to parser initialization, like so:
4042     .DS
4043     mg_ehand[MG_E_COLOR] = c_hcolor; /* support "c" entity */
4044     mg_ehand[MG_E_CXY] = c_hcolor; /* support "cxy" entity */
4045     mg_ehand[MG_E_CSPEC] = c_hcolor; /* support "cspec" entity */
4046     mg_ehand[MG_E_CCT] = c_hcolor; /* support "cct" entity */
4047     mg_ehand[MG_E_CMIX] = c_hcolor; /* support "cmix" entity */
4048     /* other entity handler assignments... */
4049     mg_init(); /* initialize parser */
4050     .DE
4051     If the loader/translator has no use for spectral data, the entries for
4052     .UL cspec
4053     and
4054     .UL cct
4055     may be left with their original NULL assignments and these entities will
4056     be re-expressed appropriately as tristimulus values.
4057     .LP
4058     The
4059     .I c_getcolor
4060     function takes the name of a defined color and returns a pointer to its
4061     .I C_COLOR
4062     structure, defined in "parser.h" as:
4063     .DS
4064     #define C_CMINWL 380 /* minimum wavelength */
4065     #define C_CMAXWL 780 /* maximum wavelength */
4066     #define C_CNSS 41 /* number of spectral samples */
4067     #define C_CWLI ((C_CMAXWL-C_CMINWL)/(C_CNSS-1))
4068     #define C_CMAXV 10000 /* nominal maximum sample value */
4069     #define C_CLPWM (683./C_CMAXV) /* peak lumens/watt multiplier */
4070    
4071     typedef struct {
4072     int clock; /* incremented each change */
4073     short flags; /* what's been set */
4074     short ssamp[C_CNSS]; /* spectral samples, min wl to max */
4075     long ssum; /* straight sum of spectral values */
4076     float cx, cy; /* xy chromaticity value */
4077     float eff; /* efficacy (lumens/watt) */
4078     } C_COLOR; /* color context */
4079     .DE
4080     The
4081     .I clock
4082     member will be incremented each time the value gets changed by a
4083     color field entity, and may be reset by the calling program if
4084     desired.
4085     This is a convenient way to keep track of whether or not a color has
4086     changed since its last use.
4087     The
4088     .I flags
4089     member indicates which color representations have been assigned,
4090     and is an inclusive OR of one or more of the following:
4091     .DS
4092     #define C_CSSPEC 01 /* flag if spectrum is set */
4093     #define C_CDSPEC 02 /* flag if defined w/ spectrum */
4094     #define C_CSXY 04 /* flag if xy is set */
4095     #define C_CDXY 010 /* flag if defined w/ xy */
4096     #define C_CSEFF 020 /* flag if efficacy set */
4097     .DE
4098     .LP
4099     It is possible but not recommended to alter the contents of the
4100     color structure returned by
4101     .I c_getcolor.
4102     Normally, this routine is never called directly, since there are no
4103     entities that access colors by name other than
4104     .UL c.
4105     .LP
4106     The global variable
4107     .I c_ccname
4108     points to the name of the current color, or NULL if it is unnamed.
4109     The variable
4110     .I c_ccolor
4111     points to the current color value, which should never be NULL.
4112     .LP
4113     The
4114     .I c_ccvt
4115     routine takes a
4116     .I C_COLOR
4117     structure and a set of desired flag settings and computes the
4118     missing color representation(s).
4119     .LP
4120     The
4121     .I c_isgrey
4122     function returns 1 if the passed color is very close to neutral
4123     grey, or 0 otherwise.
4124     .SH
4125     DIAGNOSTICS
4126     .LP
4127     The
4128     .I c_hcolor
4129     function returns
4130     .I MG_OK
4131     (0) if the color is handled correctly, or one of the predefined
4132     error values if there is a problem.
4133     (See the
4134     .I mg_load
4135     page for a list of errors.)\0
4136     .LP
4137     The
4138     .I c_getcolor
4139     function returns NULL if the specified color name is undefined, at
4140     which point the calling function should return an
4141     .I MG_EUNDEF
4142     error.
4143     .SH
4144     SEE ALSO
4145     .LP
4146     c_hmaterial, c_hvertex, mg_init, mg_load
4147     .ds RH C_HMATERIAL
4148     .bp
4149     .SH
4150     NAME
4151     .LP
4152     c_hmaterial, c_getmaterial, c_cmname, c_cmaterial -
4153     material entity support
4154     .SH
4155     SYNOPSIS
4156     .LP
4157     #include "parser.h"
4158     .LP
4159     .B int
4160     c_hmaterial(
4161     .B int
4162     argc,
4163     .B char
4164     **argv )
4165     .LP
4166     C_MATERIAL *c_getmaterial(
4167     .B char
4168     *name )
4169     .LP
4170     .B "extern char"
4171     *c_cmname
4172     .LP
4173     .B extern
4174     C_MATERIAL *c_cmaterial
4175     .SH
4176     DESCRIPTION
4177     .LP
4178     The
4179     .I c_hmaterial
4180     function supports the MGF entities,
4181     .UL m,
4182     .UL ed,
4183     .UL ir,
4184     .UL rd,
4185     .UL rs,
4186     .UL sides,
4187     .UL td,
4188     and
4189     .UL ts.
4190     It is an error to support any of the material field entities without
4191     supporting the
4192     .UL m
4193     entity itself.
4194     The assignments are normally made to the
4195     .I mg_ehand
4196     array prior to parser initialization, like so:
4197     .DS
4198     mg_ehand[MG_E_MATERIAL] = c_hmaterial; /* support "m" entity */
4199     mg_ehand[MG_E_ED] = c_hmaterial; /* support "ed" entity */
4200     mg_ehand[MG_E_IR] = c_hmaterial; /* support "ir" entity */
4201     mg_ehand[MG_E_RD] = c_hmaterial; /* support "rd" entity */
4202     mg_ehand[MG_E_RS] = c_hmaterial; /* support "rs" entity */
4203     mg_ehand[MG_E_SIDES] = c_hmaterial; /* support "sides" entity */
4204     mg_ehand[MG_E_TD] = c_hmaterial; /* support "td" entity */
4205     mg_ehand[MG_E_TS] = c_hmaterial; /* support "ts" entity */
4206     /* other entity handler assignments... */
4207     mg_init(); /* initialize parser */
4208     .DE
4209     Any of the above entities besides
4210     .UL m
4211     may be unsupported, but the parser will not attempt to include their
4212     effect into other members, e.g. an unsupported
4213     .UL rs
4214     component will not be added back into the
4215     .UL rd
4216     member.
4217     It is therefore safer to support all of the relevant material
4218     entities and make final approximations from the complete
4219     .I C_MATERIAL
4220     structure.
4221     .LP
4222     The
4223     .I c_getmaterial
4224     function takes the name of a defined material and returns a pointer to its
4225     .I C_MATERIAL
4226     structure, defined in "parser.h" as:
4227     .DS
4228     #define C_1SIDEDTHICK 0.005 /* assumed thickness of 1-sided mat. */
4229    
4230     typedef struct {
4231     int clock; /* incremented each change -- resettable */
4232     int sided; /* 1 if surface is 1-sided, 0 for 2-sided */
4233     float nr, ni; /* index of refraction, real and imaginary */
4234     float rd; /* diffuse reflectance */
4235     C_COLOR rd_c; /* diffuse reflectance color */
4236     float td; /* diffuse transmittance */
4237     C_COLOR td_c; /* diffuse transmittance color */
4238     float ed; /* diffuse emittance */
4239     C_COLOR ed_c; /* diffuse emittance color */
4240     float rs; /* specular reflectance */
4241     C_COLOR rs_c; /* specular reflectance color */
4242     float rs_a; /* specular reflectance roughness */
4243     float ts; /* specular transmittance */
4244     C_COLOR ts_c; /* specular transmittance color */
4245     float ts_a; /* specular transmittance roughness */
4246     } C_MATERIAL; /* material context */
4247     .DE
4248     The
4249     .I clock
4250     member will be incremented each time the value gets changed by a
4251     material field entity, and may be reset by the calling program if
4252     desired.
4253     This is a convenient way to keep track of whether or not a material has
4254     changed since its last use.
4255     .LP
4256     All reflectance and transmittance values correspond to normal
4257     incidence, and may vary as a function of angle depending on the
4258     index of refraction.
4259     A solid object is normally represented with a one-sided material.
4260     A two-sided material is most appropriate for thin surfaces, though
4261     it may be used also when the surface normal orientations in a model
4262     are unreliable.
4263     .LP
4264     If a transparent or translucent surface is one-sided, then the
4265     absorption will change as a function of distance through the
4266     material, and a single value for diffuse or specular transmittance is
4267     ambiguous.
4268     We therefore define a standard thickness,
4269     .I C_1SIDEDTHICK,
4270     which is the object thickness to which the given values correspond,
4271     so that one may compute the isotropic absorptance of the material.
4272     .LP
4273     It is possible but not recommended to alter the contents of the
4274     material structure returned by
4275     .I c_getmaterial.
4276     Normally, this routine is never called directly, since there are no
4277     entities that access materials by name other than
4278     .UL m.
4279     .LP
4280     The global variable
4281     .I c_cmname
4282     points to the name of the current material, or NULL if it is unnamed.
4283     The variable
4284     .I c_cmaterial
4285     points to the current material value, which should never be NULL.
4286     .SH
4287     DIAGNOSTICS
4288     .LP
4289     The
4290     .I c_hmaterial
4291     function returns
4292     .I MG_OK
4293     (0) if the color is handled correctly, or one of the predefined
4294     error values if there is a problem.
4295     (See the
4296     .I mg_load
4297     page for a list of errors.)\0
4298     .LP
4299     The
4300     .I c_getmaterial
4301     function returns NULL if the specified material name is undefined, at
4302     which point the calling function should return an
4303     .I MG_EUNDEF
4304     error.
4305     .SH
4306     SEE ALSO
4307     .LP
4308     c_hcolor, c_hvertex, mg_init, mg_load
4309     .ds RH OBJ_HANDLER
4310     .bp
4311     .SH
4312     NAME
4313     .LP
4314     obj_handler, obj_clear, obj_nnames, obj_name - object name support
4315     .SH
4316     SYNOPSIS
4317     .LP
4318     .B int
4319     obj_handler(
4320     .B int
4321     argc,
4322     .B char
4323     **argv )
4324     .LP
4325     .B void
4326     obj_clear(
4327     .B void
4328     )
4329     .LP
4330     .B "extern int"
4331     obj_nnames
4332     .LP
4333     .B "extern char"
4334     **obj_name
4335     .SH
4336     DESCRIPTION
4337     .LP
4338     The
4339     .I obj_handler
4340     routine should be assigned to the
4341     .I MG_E_OBJECT
4342     entry of the parser's
4343     .I mg_ehand
4344     array prior to calling
4345     .I mg_load
4346     if the loader/translator wishes to support hierarchical object
4347     names.
4348     .LP
4349     The
4350     .I obj_clear
4351     function may be used to clear the object name stack and free any
4352     associated memory, but this is usually not necessary since
4353     .UL o
4354     begin and end entities are normally balanced in the input.
4355     .LP
4356     The global
4357     .I obj_nnames
4358     variable indicates the number of names currently in the object
4359     stack, and the
4360     .I obj_name
4361     list contains the name strings in the same order as they were
4362     encountered on the input.
4363     (I.e. the most recently pushed name is last.)\0
4364     .SH
4365     DIAGNOSTICS
4366     .LP
4367     The
4368     .I obj_handler
4369     function returns
4370     .I MG_OK
4371     (0) if the color is handled correctly, or one of the predefined
4372     error values if there is a problem.
4373     (See the
4374     .I mg_load
4375     page for a list of errors.)\0
4376     .SH
4377     SEE ALSO
4378     .LP
4379     mg_init, mg_load, xf_handler
4380     .ds RH XF_HANDLER
4381     .bp
4382     .SH
4383     NAME
4384     .LP
4385     xf_handler, xf_clear, xf_context, xf_argend - transformation support
4386     .SH
4387     SYNOPSIS
4388     .LP
4389     .B int
4390     xf_handler(
4391     .B int
4392     argc,
4393     .B char
4394     **argv )
4395     .LP
4396     .B void
4397     xf_clear(
4398     .B void
4399     )
4400     .LP
4401     .B extern
4402     XF_SPEC *xf_context
4403     .LP
4404     .B "extern char"
4405     **xf_argend
4406     .SH
4407     DESCRIPTION
4408     .LP
4409     The
4410     .I xf_handler
4411     routine should be assigned to the
4412     .I MG_E_XF
4413     entry of the parser's
4414     .I mg_ehand
4415     array prior to calling
4416     .I mg_load
4417     if the loader/translator wishes to support hierarchical
4418     transformations.
4419     (Note that all MGF geometric entities require this support.)\0
4420     .LP
4421     The
4422     .I xf_clear
4423     function may be used to clear the transform stack and free any
4424     associated memory, but this is usually not necessary since
4425     .UL xf
4426     begin and end entities are normally balanced in the input.
4427     .LP
4428     The global
4429     .I xf_context
4430     variable points to the current transformation context, which is of
4431     the type
4432     .I XF_SPEC,
4433     described in "parser.h":
4434     .DS
4435     typedef struct xf_spec {
4436     long xid; /* unique transform id */
4437     short xac; /* context argument count */
4438     short rev; /* boolean true if vertices reversed */
4439     XF xf; /* cumulative transformation */
4440     struct xf_array *xarr; /* transformation array pointer */
4441     struct xf_spec *prev; /* previous transformation context */
4442     } XF_SPEC; /* followed by argument buffer */
4443     .DE
4444     The
4445     .I xid
4446     member is a identifier associated with this transformation,
4447     which should be the same for identical transformations, as an aid to
4448     vertex sharing.
4449     (See also the
4450     .I c_hvertex
4451     page.)\0
4452     The
4453     .I xac
4454     member indicates the total number of transform arguments, and is
4455     used to indicate the position of the first argument relative to the
4456     last one pointed to by the global
4457     .I xf_argend
4458     variable.
4459     .LP
4460     The first transform argument starts at
4461     .I xf_argv,
4462     which is a macro defined in "parser.h" as:
4463     .DS
4464     #define xf_argv (xf_argend - xf_context->xac)
4465     .DE
4466     Note that accessing this macro will result in a segmentation violation
4467     if the current context is NULL, so one should first test the second macro
4468     .I xf_argc
4469     against zero.
4470     This macro is defined as:
4471     .DS
4472     #define xf_argc (xf_context==NULL ? 0 : xf_context->xac)
4473     .DE
4474     .LP
4475     Normally, neither of these macros will be used, since there are
4476     routines for transforming points, vectors and scalars directly based
4477     on the current transformation context.
4478     (See the
4479     .I xf_xfmpoint
4480     page for details.)\0
4481     .LP
4482     The
4483     .I rev
4484     member of the
4485     .I XF_SPEC
4486     structure indicates whether or not this transform reverses the order
4487     of polygon vertices.
4488     This member will be 1 if the transformation mirrors about an odd
4489     number of coordinate axes, thus inverting faces.
4490     The usual thing to do in this circumstance is to interpret the
4491     vertex arguments in the reverse order, so as to bring the face back
4492     to its original orientation in the new position.
4493     .LP
4494     The
4495     .I xf
4496     member contains the transformation scalefactor (in xf.sca)
4497     and 4x4 homogeneous matrix (in xf.xfm), but these will usually not
4498     be accessed directly.
4499     Likewise, the
4500     .I xarr
4501     and
4502     .I prev
4503     members point to data that should not be needed by the calling
4504     program.
4505     .SH
4506     DIAGNOSTICS
4507     .LP
4508     The
4509     .I xf_handler
4510     function returns
4511     .I MG_OK
4512     (0) if the color is handled correctly, or one of the predefined
4513     error values if there is a problem.
4514     (See the
4515     .I mg_load
4516     page for a list of errors.)\0
4517     .SH
4518     SEE ALSO
4519     .LP
4520     mg_init, mg_load, obj_handler, xf_xfmpoint
4521     .ds RH XF_XFMPOINT
4522     .bp
4523     .SH
4524     NAME
4525     .LP
4526 greg 1.3 xf_xfmpoint, xf_xfmvect, xf_rotvect, xf_scale - apply current
4527 greg 1.1 transformation
4528     .SH
4529     SYNOPSIS
4530     .LP
4531     .B void
4532     xf_xfmpoint( FVECT pnew, FVECT pold )
4533     .LP
4534     .B void
4535     xf_xfmvect( FVECT vnew, FVECT vold )
4536     .LP
4537     .B void
4538     xf_rotvect( FVECT nnew, FVECT nold )
4539     .LP
4540     .B double
4541     xf_scale(
4542     .B double
4543     sold )
4544     .SH
4545     DESCRIPTION
4546     .LP
4547     The
4548     .I xf_xfmpoint
4549     routine applies the current transformation defined by
4550     .I xf_context
4551     to the point
4552     .I pold,
4553     scaling, rotating and moving it to its proper location, which is put in
4554     .I pnew.
4555 greg 1.2 (As for
4556     .I xf_xfmvect
4557     and
4558     .I xf_rotvect,
4559     the two arguments may point to the same vector.)\0
4560 greg 1.1 .LP
4561     The
4562     .I xf_xfmvect
4563     routine applies the current transformation to the vector
4564     .I vold,
4565     scaling and rotating it to its proper location, which is put in
4566     .I vnew.
4567     The only difference between
4568     .I xf_xfmpoint
4569     and
4570     .I xf_xfmvect
4571     is that in the latter, the final translation is not applied.
4572     .LP
4573     The
4574     .I xf_rotvect
4575     routine rotates the vector
4576     .I nold
4577     using the current transformation, and stores the result in
4578     .I nnew.
4579     No translation or scaling is applied, which is the appropriate
4580     action for surface normal vectors for example.
4581     .LP
4582     The
4583     .I xf_scale
4584     function takes a scalar argument
4585     .I sold
4586     and applies the current scale factor, returning the result.
4587     .SH
4588     SEE ALSO
4589     .LP
4590     xf_handler
4591     .ds LH
4592     .ds RH
4593     .bp
4594     .NH
4595     Application Notes
4596     .NH 2
4597     Relation to Standard Practices in Computer Graphics
4598     .LP
4599     For those coming from a computer graphics background, some of the
4600     choices in the material model may seem strange or even capricious.
4601     Why not simply stick with RGB colors and a Phong specular component
4602     like everyone else?
4603     What is the point in choosing the number of sides to a material?
4604     .LP
4605     In the real world, a surface can have only one side,
4606     defining the interface between one volume and another.
4607     Many object-space rendering packages (e.g. z-buffer algorithms) take
4608     advantage of this fact by culling back-facing polygons and thus saving
4609     as much as 50% of the preprocessing time.
4610     However, many models rely on an
4611     approximation whereby a single surface is used to represent a very thin
4612     volume, such as a pane of glass, and this also can provide significant
4613     calculational savings in an image-space algorithm (such as
4614     ray-tracing).
4615     Also, many models are created in such a way that the front vs. back
4616     information is lost or confused, so that the back side of one or
4617     more surfaces may have to serve as the front side during rendering.
4618     (AutoCAD is one easily identified culprit in this department.)\0
4619     Since both types of surface models are useful and any
4620     rendering algorithm may ultimately be applied, MGF provides a way
4621     to specify sidedness rather than picking one interpretation or the other.
4622     .LP
4623     The problem with RGB is that there is no accepted standard, and even
4624     if we were to set one it would either be impossible to realize (i.e.
4625     impossible to create phosphors with the chosen colors) or it would
4626     have a gamut that excludes many saturated colors.
4627     The CIE color system was very carefully conceived and developed,
4628     and is the standard to which all photometric measurements adhere.
4629     It is therefore the logical choice in any standard format, though it
4630     has been too often ignored by the computer graphics community.
4631     .LP
4632     Regarding Phong shading, this was never a physical model and making it
4633     behave basic laws of reciprocity and energy balance is difficult.
4634     More to the point, specular power has almost nothing to do with
4635     surface microstructure, and is difficult to set properly
4636     even if every physical characteristic of a material has
4637     been carefully measured.
4638     This is the ultimate indictment of any physical model -- that it
4639     is incapable of reproducing any measurement whatsoever.
4640     .LP
4641     Admittedly, the compliment of diffuse and specular component plus
4642     surface roughness and index of refraction used in MGF is less than a
4643     perfect model, but it is serviceable for most materials and
4644     relatively simple to incorporate into a rendering algorithm.
4645     In the long term, MGF shall probably include full spectral
4646     scattering functions, though the sheer quantity of data involved
4647     makes this burdensome from both the measurement side and the
4648     simulation side.
4649     .NH 3
4650     Converting between Phong Specular Power and Gaussian Roughness
4651     .LP
4652     So-called specular reflection and transmission are modeled using a
4653     Gaussian distribution of surface facets.
4654     The roughness parameters to the
4655     .UL rs
4656     and
4657     .UL ts
4658     entities specify
4659     the root-mean-squared (RMS) surface facet slope, which varies from 0
4660     for a perfectly smooth surface to around .2 for a fairly rough one.
4661     The effect this will have on the reflected component distribution is
4662     well-defined, but predicting the behavior of the transmitted
4663     component requires further assumptions.
4664     We assume that the surface
4665     scatters light passing through it just as much as it scatters
4666     reflected light.
4667     This assumption is approximately correct for a
4668     two-sided transparent material with an index of refraction of 1.5
4669     (like glass) and both sides having the given RMS facet slope.
4670     .LP
4671     Oftentimes, one is translating from a Phong exponent on the cosine
4672     of the half-vector-to-normal angle to the more physical but less
4673     familiar Gaussian model of MGF.
4674     The hardest part is translating the specular power to a roughness value.
4675     For this, we recommend the following approximation:
4676     .IP
4677 greg 1.15 roughness = sqrt(2/specular_power)
4678 greg 1.1 .LP
4679     It is not a perfect correlation, but it is about as close as one can get.
4680     .NH 3
4681     Converting between RGB and CIE Colors
4682     .LP
4683     Unlike most graphics languages, MGF does not use an RGB color model,
4684     simply because there is no recognized definition for this model.
4685     It is based on computer monitor phosphors, which vary from one
4686     CRT to the next.
4687     (There is an RGB standard defined in the TV
4688     industry, but this has a rather poor correlation to most computer
4689     monitors and it is impossible to express many real-world colors
4690     within its limited gamut.)\0
4691     .LP
4692     MGF uses two alternative, well-defined standards, spectral power
4693     distributions and the 1931 CIE 2 degree standard observer.
4694     With the CIE standard, any viewable
4695     color may be exactly represented as an (x,y) chromaticity value.
4696     Unfortunately, the interaction between
4697     colors (i.e. colored light sources and interreflections) cannot be
4698     specified exactly with any finite coordinate set, including CIE
4699     chromaticities.
4700     So, MGF offers the ability to give reflectance,
4701     transmittance or emittance as a function of wavelength over the visible
4702     spectrum.
4703     This function is still discretized, but at a user-selectable
4704     resolution.
4705     Furthermore, spectral colors may be mixed, providing (nearly)
4706     arbitrary basis functions, which can produce more accurate results in
4707     some cases and are merely a convenience for translation in others.
4708     .LP
4709     Conversion back and forth between CIE chromaticity coordinates and spectral
4710     samples is provided within the MGF parser.
4711     Unfortunately, conversion
4712     to and from RGB values depends on a particular RGB definition, and as we
4713     have said, there is no recognized standard.
4714     We therefore recommend that
4715     you decide yourself what chromaticity values to use for each RGB primary,
4716     and adopt the following code to convert between CIE and RGB coordinates.
4717     .LP
4718     .nf
4719     #ifdef NTSC
4720     #define CIE_x_r 0.670 /* standard NTSC primaries */
4721     #define CIE_y_r 0.330
4722     #define CIE_x_g 0.210
4723     #define CIE_y_g 0.710
4724     #define CIE_x_b 0.140
4725     #define CIE_y_b 0.080
4726     #define CIE_x_w 0.3333 /* monitor white point */
4727     #define CIE_y_w 0.3333
4728     #else
4729     #define CIE_x_r 0.640 /* nominal CRT primaries */
4730     #define CIE_y_r 0.330
4731     #define CIE_x_g 0.290
4732     #define CIE_y_g 0.600
4733     #define CIE_x_b 0.150
4734     #define CIE_y_b 0.060
4735     #define CIE_x_w 0.3333 /* monitor white point */
4736     #define CIE_y_w 0.3333
4737     #endif
4738    
4739 greg 1.4 #define CIE_D ( CIE_x_r*(CIE_y_g - CIE_y_b) + \\
4740     CIE_x_g*(CIE_y_b - CIE_y_r) + \\
4741 greg 1.1 CIE_x_b*(CIE_y_r - CIE_y_g) )
4742 greg 1.4 #define CIE_C_rD ( (1./CIE_y_w) * \\
4743     ( CIE_x_w*(CIE_y_g - CIE_y_b) - \\
4744     CIE_y_w*(CIE_x_g - CIE_x_b) + \\
4745 greg 1.1 CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g ) )
4746 greg 1.4 #define CIE_C_gD ( (1./CIE_y_w) * \\
4747     ( CIE_x_w*(CIE_y_b - CIE_y_r) - \\
4748     CIE_y_w*(CIE_x_b - CIE_x_r) - \\
4749 greg 1.1 CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r ) )
4750 greg 1.4 #define CIE_C_bD ( (1./CIE_y_w) * \\
4751     ( CIE_x_w*(CIE_y_r - CIE_y_g) - \\
4752     CIE_y_w*(CIE_x_r - CIE_x_g) + \\
4753 greg 1.1 CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r ) )
4754    
4755     #define CIE_rf (CIE_y_r*CIE_C_rD/CIE_D)
4756     #define CIE_gf (CIE_y_g*CIE_C_gD/CIE_D)
4757     #define CIE_bf (CIE_y_b*CIE_C_bD/CIE_D)
4758    
4759     float xyz2rgbmat[3][3] = { /* XYZ to RGB */
4760     {(CIE_y_g - CIE_y_b - CIE_x_b*CIE_y_g + CIE_y_b*CIE_x_g)/CIE_C_rD,
4761     (CIE_x_b - CIE_x_g - CIE_x_b*CIE_y_g + CIE_x_g*CIE_y_b)/CIE_C_rD,
4762     (CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g)/CIE_C_rD},
4763     {(CIE_y_b - CIE_y_r - CIE_y_b*CIE_x_r + CIE_y_r*CIE_x_b)/CIE_C_gD,
4764     (CIE_x_r - CIE_x_b - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r)/CIE_C_gD,
4765     (CIE_x_b*CIE_y_r - CIE_x_r*CIE_y_b)/CIE_C_gD},
4766     {(CIE_y_r - CIE_y_g - CIE_y_r*CIE_x_g + CIE_y_g*CIE_x_r)/CIE_C_bD,
4767     (CIE_x_g - CIE_x_r - CIE_x_g*CIE_y_r + CIE_x_r*CIE_y_g)/CIE_C_bD,
4768     (CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r)/CIE_C_bD}
4769     };
4770    
4771     float rgb2xyzmat[3][3] = { /* RGB to XYZ */
4772     {CIE_x_r*CIE_C_rD/CIE_D,CIE_x_g*CIE_C_gD/CIE_D,CIE_x_b*CIE_C_bD/CIE_D},
4773     {CIE_y_r*CIE_C_rD/CIE_D,CIE_y_g*CIE_C_gD/CIE_D,CIE_y_b*CIE_C_bD/CIE_D},
4774     {(1.-CIE_x_r-CIE_y_r)*CIE_C_rD/CIE_D,
4775     (1.-CIE_x_g-CIE_y_g)*CIE_C_gD/CIE_D,
4776     (1.-CIE_x_b-CIE_y_b)*CIE_C_bD/CIE_D}
4777     };
4778    
4779    
4780     cie_rgb(rgbcolor, ciecolor) /* convert CIE to RGB */
4781     register float *rgbcolor, *ciecolor;
4782     {
4783     register int i;
4784    
4785     for (i = 0; i < 3; i++) {
4786     rgbcolor[i] = xyz2rgbmat[i][0]*ciecolor[0] +
4787     xyz2rgbmat[i][1]*ciecolor[1] +
4788     xyz2rgbmat[i][2]*ciecolor[2] ;
4789     if (rgbcolor[i] < 0.0) /* watch for negative values */
4790     rgbcolor[i] = 0.0;
4791     }
4792     }
4793    
4794    
4795     rgb_cie(ciecolor, rgbcolor) /* convert RGB to CIE */
4796     register float *ciecolor, *rgbcolor;
4797     {
4798     register int i;
4799    
4800     for (i = 0; i < 3; i++)
4801     ciecolor[i] = rgb2xyzmat[i][0]*rgbcolor[0] +
4802     rgb2xyzmat[i][1]*rgbcolor[1] +
4803     rgb2xyzmat[i][2]*rgbcolor[2] ;
4804     }
4805     .fi
4806     .LP
4807     An alternative to adopting the above code is to use the MGF "cmix"
4808     entity to convert from RGB directly by naming the three primaries in
4809     terms of their chromaticities, e.g:
4810     .DS
4811     c R =
4812     cxy 0.640 0.330
4813     c G =
4814     cxy 0.290 0.600
4815     c B =
4816     cxy 0.150 0.060
4817     .DE
4818     .LP
4819     Then, converting from RGB to MGF colors is as simple as multiplying each
4820     component by its relative luminance in a cmix statement, for instance:
4821     .DS
4822     c white =
4823     cmix 0.265 R 0.670 G 0.065 B
4824     .DE
4825     .LP
4826     For the chosen RGB standard, the above specification would result a pure
4827     white.
4828     The reason the coefficients are not all 1 as you might expect is
4829     that cmix uses relative luminance as the standard for its weights.
4830     Since
4831     blue is less luminous for the same energy than red, which is in turn
4832     less luminous than green, the weights cannot be the same to achieve an
4833     even spectral balance.
4834     Unfortunately, computing these relative weights
4835     is not straightforward, though it is given in the above macros as CIE_rf,
4836     CIE_gf and CIE_bf.
4837     (The common factors in these macros may of course
4838     be removed since
4839     .UL cmix
4840     weights are all relative.)\0
4841     Alternatively, one could measure the actual full scale luminance of
4842     the phosphors with a luminance probe and get the same relative
4843     values.
4844     .NH 2
4845     Relation to IESNA LM-63 and Luminaire Catalogs
4846     .LP
4847     Recently, the Illuminating Engineering Society of North America
4848     (IESNA) adopted MGF as the official standard for
4849     representing luminaire geometry and materials.
4850     The way this works in an IES luminaire data file is through the
4851     addition of a keyword called LUMINOUSGEOMETRY, which is given on a
4852     line in the header portion of a file (before the TILT specification)
4853     like so:
4854     .LP
4855     .B [LUMINOUSGEOMETRY]
4856     .I mgf_file
4857     .LP
4858     The given MGF file must exist relative to the directory containing
4859     the IES file (i.e. the same stipulations and restrictions on pathnames
4860     apply as for the MGF
4861     .UL i
4862     entity).
4863     Furthermore, the position of the MGF geometry must be
4864     such that the gross geometric specification of emitting surfaces
4865     in the IES file completely
4866     blocks or encloses the luminous portions of the MGF description.
4867     Specifically, any ray traced towards the MGF geometry must strike
4868     the IES gross geometry before it strikes any luminous surface in the
4869     MGF description.
4870     This provides a convenient way of preventing overcounting in the
4871     illumination calculation, while still allowing for accurate fixture
4872     appearance.
4873     .LP
4874     To give two examples, let us consider first a recessed can, followed
4875     by a hanging direct/indirect fluorescent fixture.
4876     .LP
4877     The most appropriate IES geometric specification for the emitting
4878     area of a can light would be a circular disk.
4879     Since the IES gross geometry gives only the diameter of the disk, the
4880     actual 3-dimensional placement is implicitly defined as having a
4881     center at the origin, with the radiating disk facing in the
4882     negative Z direction (nadir, downwards).
4883     The MGF geometry would then be placed such that any luminous portion
4884     was above this disk, and no portion of it would obstruct the IES
4885     geometry.
4886     The most sensible position therefore has the IES disk flush with the
4887     MGF can opening, as shown in Figure 3.
4888     .bp
4889     Replace this page with the second page from "figures.ps".
4890     .bp
4891     .LP
4892     In the case of a direct/indirect fluorescent fixture, light will
4893     exit both the top and the bottom sides, and the IES geometry must
4894     enclose the radiating portion of the fixture entirely.
4895     It is acceptable to have additional MGF geometry above the
4896     fixture so long as it does not radiate, which is what we must do if
4897     we wish to include the support rods, as shown in Figure 4.
4898     .LP
4899     Note that the origin is always in the exact center of the IES
4900     geometry.
4901     .LP
4902     Not all fixtures will fit the simple IES geometry specification so
4903     nicely.
4904     For odd-shaped fixtures, it may be necessary to use an IES geometry
4905     that does not match the radiating area terribly well in order that
4906     it completely block or enclose the required MGF specification.
4907     .LP
4908     The unit of length in the MGF file is always meters, regardless of
4909     the units specified in the enclosing IES file.
4910     However, any and all multipliers applied to the candlepower data in the
4911     IES file will also be applied to the emittance of surfaces in the
4912     MGF specification, so that one MGF file may serve similar
4913     luminaires that differ in their total output.
4914     .NH
4915     Credits
4916     .LP
4917     The MGF language grew out of a joint investigation into physical
4918     representations for rendering undertaken by the author
4919     (Greg Ward of LBL) and Holly Rushmeier of the National
4920     Institute of Standards and Technology.
4921     After deciding that a complete and robust specification was
4922     an extreme challenge, we shelved the project for another time.
4923     A few months later, the author spoke with Ian Ashdown and Robert
4924     Shakespeare, who are both members of the IES Computing Committee,
4925     about the need for extending the existing data standard to
4926     include luminaire geometry and near-field photometry.
4927     We then moved forward as a team towards a somewhat less ambitious
4928     approach to physical materials and geometry that had the advantage
4929     of simplicity and the possibility of support with a standard parser
4930     library.
4931     The author went to work over the next two months
4932     on the detailed design of the language
4933     and an ANSI-C parser, with regular feedback from the other three
4934     team members.
4935     Several months and several versions later, we arrived at release
4936     1.0, which is the occasion of this document's creation.
4937     .LP
4938     Funding for this work... would be nice.