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