ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/mgfdoc.tr
Revision: 1.16
Committed: Tue Mar 18 11:43:22 1997 UTC (27 years, 1 month ago) by greg
Content type: application/x-troff
Branch: MAIN
Changes since 1.15: +64 -4 lines
Log Message:
added fh entity and general cleanup

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