ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/mgfdoc.tr
Revision: 1.15
Committed: Fri Apr 5 16:35:25 1996 UTC (28 years, 1 month ago) by greg
Content type: application/x-troff
Branch: MAIN
Changes since 1.14: +1 -1 lines
Log Message:
corrected specular power conversion

File Contents

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