ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/mgfdoc.tr
Revision: 1.12
Committed: Mon Dec 4 12:27:04 1995 UTC (28 years, 5 months ago) by greg
Content type: application/x-troff
Branch: MAIN
Changes since 1.11: +59 -5 lines
Log Message:
added mgf2inv

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