ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/mgfdoc.tr
Revision: 1.3
Committed: Mon May 15 14:42:30 1995 UTC (28 years, 11 months ago) by greg
Content type: application/x-troff
Branch: MAIN
Changes since 1.2: +3 -4 lines
Log Message:
minor formatting fixes

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