1 |
greg |
1.1 |
MGF PACKAGE DESCRIPTION |
2 |
|
|
SCCSid "$SunId$ LBL" |
3 |
|
|
|
4 |
|
|
This package includes a description and parser for a new scene |
5 |
|
|
description standard, called for the lack of a better name, MGF |
6 |
|
|
for Materials and Geometry Format. It was developed by Greg |
7 |
|
|
Ward of the Lawrence Berkeley Laboratory <[email protected]> with |
8 |
|
|
help and advice from Rob Shakespeare of Indiana University |
9 |
|
|
<[email protected]>, Ian Ashdown of Ledalite Corporation |
10 |
|
|
<[email protected]> and Holly Rushmeier of the National |
11 |
|
|
Institute for Standards and Technology <[email protected]>. |
12 |
|
|
|
13 |
|
|
The language itself is described in the file "spec.txt", and |
14 |
|
|
the included Makefile should make building the parser library |
15 |
|
|
fairly straightforward on most systems. What's left then, is |
16 |
|
|
explaining the why and how of using this package. |
17 |
|
|
|
18 |
|
|
The initial purpose of developing a scene description standard |
19 |
|
|
was for inclusion in the Illumination Engineering Society's (IES) |
20 |
|
|
standard data representation for luminaires. It occurred to us |
21 |
|
|
early on that such a standard might have broader applications, |
22 |
|
|
so an effort was made to create a fairly general description |
23 |
|
|
language, while keeping it as simple as possible for the people |
24 |
|
|
who have to create descriptions with it as well as the programmers |
25 |
|
|
who have to support it. |
26 |
|
|
|
27 |
|
|
Why create a new standard rather than exploiting an existing one? |
28 |
|
|
Some of the rationale for our decision is explained at the end of |
29 |
|
|
the specification document, but it mostly boils down to materials. |
30 |
|
|
As easy as it is to describe physically valid materials, most |
31 |
|
|
scene description languages cannot do it. The material specification |
32 |
|
|
included in the MGF standard may not be perfect, but at least it's |
33 |
|
|
physically plausible. Furthermore, we are committed to making any |
34 |
|
|
future modifications to the standard backwards-compatible -- a rather |
35 |
|
|
tricky proposition. |
36 |
|
|
|
37 |
|
|
This takes us to the how of supporting this new standard. The basic |
38 |
|
|
approach is to use the standard parser, which does a lot of the work |
39 |
|
|
in supporting the language itself. The programmer tells the parser |
40 |
|
|
which entities it will support, and the parser does the rest. |
41 |
|
|
That way, it isn't necessary to modify the program when a new version |
42 |
|
|
of the standard comes out; all one has to do is link to the new |
43 |
|
|
standard's parser. (The include file will change as well, so it's |
44 |
|
|
not QUITE that simple, but close.) |
45 |
|
|
|
46 |
|
|
There are two ways to support the language, by linking the parser to |
47 |
|
|
the program itself, or by linking the parser to a translator program |
48 |
|
|
that expresses MGF entities in the native scene description format. |
49 |
greg |
1.3 |
The differences in the two approaches are slight, and we will mention |
50 |
greg |
1.1 |
them following a general explanation of the parser and support library. |
51 |
|
|
|
52 |
|
|
The Parser |
53 |
|
|
========== |
54 |
|
|
The MGF parser is written in ANSI-C (though the -DNOPROTO flag may be |
55 |
|
|
used to get back K&R compatibility). All of the declarations and |
56 |
|
|
definitions needed are in the single include file "parser.h". This |
57 |
|
|
file is a good place to look for details on using the various support |
58 |
|
|
routines as well. The parser itself is parser.c, though it relies for |
59 |
|
|
some translations on other C modules. These same support routines will |
60 |
|
|
no doubt be useful for applications programmers, and we will explain |
61 |
|
|
some of them in the following sections. |
62 |
|
|
|
63 |
|
|
Initializing the parser is the most important part of writing an MGF |
64 |
|
|
program, and it is done through the mg_ehand array and a call to mg_init. |
65 |
|
|
The global mg_ehand variable is an array of pointers to entity handler |
66 |
greg |
1.5 |
functions. The arguments to these functions are always the same, an |
67 |
greg |
1.1 |
argument count and an array of argument pointers (ala main). The return |
68 |
|
|
value for these integer functions is one of the error codes defined in |
69 |
|
|
parser.h, or MG_OK if the entity was handled correctly. You must |
70 |
|
|
set the appropriate entries for the entities you can support, then call |
71 |
|
|
mg_init to fill in the rest. Most of the entities you cannot support |
72 |
|
|
will be translated into (approximately) equivalent ones you can. |
73 |
|
|
Entities that have no equivalent (such as color), will be safely |
74 |
|
|
ignored on the input. If you have specified support for some entities |
75 |
|
|
without offering support to their prerequisites, mg_init will report an |
76 |
|
|
error and exit. |
77 |
|
|
|
78 |
|
|
Once the parser has been properly initialized, MGF input files may be |
79 |
|
|
loaded at will with the mg_load call. This function takes a single |
80 |
|
|
argument, which is the name of the MGF file. (The NULL pointer may be |
81 |
|
|
used to specify standard input.) The behavior of the parser in part |
82 |
|
|
depends on input history, so the mg_clear call should be used after |
83 |
|
|
each file if starting fresh is important. This also frees any data |
84 |
|
|
structures used by the parser, which may be desirable if the program |
85 |
|
|
is going to do something after loading besides exit. |
86 |
|
|
|
87 |
|
|
Support Functions |
88 |
|
|
================= |
89 |
|
|
In translating unsupported entities, the parser makes use of a number |
90 |
|
|
of support functions, contained in associated C modules. The most |
91 |
|
|
important of these are in context.c, which includes three handler |
92 |
|
|
functions that can support all color, material and vertex entities. |
93 |
|
|
To understand what these functions do, it is necessary to know a |
94 |
|
|
little about the MGF language itself, so please familiarize yourself |
95 |
|
|
with it now if you haven't already. (See the file "spec.txt".) |
96 |
|
|
|
97 |
|
|
Context Support |
98 |
|
|
=============== |
99 |
|
|
The MGF language defines three named contexts, the current vertex, |
100 |
|
|
the current color and the current material. (The current color is |
101 |
|
|
used mostly for setting parameters in the current material.) There |
102 |
|
|
are three handler routines defined in context.c, and they can handle |
103 |
|
|
all entities related to these three contexts. The simplest way to |
104 |
|
|
support materials, for example, is to initialize the mg_ehand array |
105 |
|
|
such that the MG_E_MATERIAL, MG_E_RD, MG_E_RS, etc. entries all point |
106 |
|
|
to c_hmaterial. Then, whenever a material is needed, the global |
107 |
|
|
c_cmaterial variable will be pointing to a structure with all the |
108 |
|
|
current settings. (Note that you would have to also set the color |
109 |
|
|
mg_ehand entries to c_hcolor if you intended to support color |
110 |
greg |
1.5 |
materials.) A list of related mg_ehand assignments is given below: |
111 |
greg |
1.1 |
|
112 |
greg |
1.5 |
mg_ehand[MG_E_COLOR] = c_hcolor; |
113 |
|
|
mg_ehand[MG_E_CMIX] = c_hcolor; |
114 |
|
|
mg_ehand[MG_E_CSPEC] = c_hcolor; |
115 |
|
|
mg_ehand[MG_E_CXY] = c_hcolor; |
116 |
|
|
mg_ehand[MG_E_ED] = c_hmaterial; |
117 |
|
|
mg_ehand[MG_E_MATERIAL] = c_hmaterial; |
118 |
|
|
mg_ehand[MG_E_NORMAL] = c_hvertex; |
119 |
|
|
mg_ehand[MG_E_POINT] = c_hvertex; |
120 |
|
|
mg_ehand[MG_E_RD] = c_hmaterial; |
121 |
|
|
mg_ehand[MG_E_RS] = c_hmaterial; |
122 |
|
|
mg_ehand[MG_E_SIDES] = c_hmaterial; |
123 |
|
|
mg_ehand[MG_E_TD] = c_hmaterial; |
124 |
|
|
mg_ehand[MG_E_TS] = c_hmaterial; |
125 |
|
|
mg_ehand[MG_E_VERTEX] = c_hvertex; |
126 |
|
|
|
127 |
greg |
1.1 |
In addition to the three handler functions, context.c contains a |
128 |
|
|
few support routines that make life simpler. For vertices, there |
129 |
|
|
is the c_getvertex call, which returns a pointer to a named vertex |
130 |
|
|
structure (or NULL if there is no corresponding definition for the |
131 |
|
|
given name). This function is needed for support of most surface |
132 |
|
|
entities. For color support, there is the analogous c_getcolor call, |
133 |
|
|
and the c_ccvt routine, which is used to convert from one color |
134 |
|
|
representation to another (e.g. spectral color to xy chromaticity |
135 |
|
|
coordinates). Also, there is a function called c_isgrey, which |
136 |
|
|
simply returns 1 or 0 based on whether the passed color structure |
137 |
|
|
is close to grey or not. Finally, there is the c_clearall routine, |
138 |
|
|
which clears and frees all context data structures, and is the |
139 |
greg |
1.5 |
principal action of the parser's mg_clear function. |
140 |
greg |
1.1 |
|
141 |
|
|
Transform Support |
142 |
|
|
================= |
143 |
|
|
If your program is supporting any geometry at all (and what would be |
144 |
|
|
the point if it wasn't?) you will need to support the transform |
145 |
|
|
entity (MG_E_XF). This would be tricky, if it weren't for the support |
146 |
|
|
routines provided, which make the task fairly painless. First, there |
147 |
|
|
is the transform handler itself, xf_handler. Just set the MG_E_XF |
148 |
|
|
entry of the mg_ehand array to this function. Then, anytime you want |
149 |
|
|
to transform something, call one of the associated functions, xf_xfmpoint, |
150 |
|
|
xf_xfmvect, xf_rotvect or xf_scale. These functions transform a 3-D |
151 |
|
|
point, 3-D vector (without translation), rotate a 3-D vector (without |
152 |
|
|
scaling) and scale a floating-point value, respectively. |
153 |
|
|
|
154 |
greg |
1.2 |
Object Support |
155 |
|
|
============== |
156 |
|
|
The MGF language includes a single entity for naming objects, MG_E_OBJECT. |
157 |
|
|
It is mostly provided as a convenience for the user, so that individual |
158 |
|
|
geometric parts may be easily identified. Although supporting this entity |
159 |
|
|
directly is possible, it's hierarchical nature requires maintaining a stack |
160 |
|
|
of object names. The object handler in object.c provides this functionality. |
161 |
|
|
Simply set the MG_E_OBJECT entry of the mg_ehand array to obj_handler, |
162 |
|
|
and the current object name list will be kept in the global array obj_name. |
163 |
|
|
The number of names is stored in the global obj_nnames variable. To clear |
164 |
|
|
this array (freeing any memory used in the process), call obj_clear. |
165 |
greg |
1.3 |
|
166 |
|
|
Loading vs. Translating |
167 |
|
|
======================= |
168 |
|
|
As mentioned in the introduction, the parser may be used either to load |
169 |
|
|
data into a rendering program directly, or to get MGF input for translation |
170 |
|
|
to another file format. In either case, the procedure is nearly identical. |
171 |
|
|
The only important difference is what you do with the parser data structures |
172 |
|
|
after loading. For a translator, this is not an issue, but rendering |
173 |
|
|
programs usually need all the memory they can get. Therefore, once the |
174 |
|
|
input process is complete, you should call the mg_clear function to free |
175 |
|
|
the parser data structures and return to an initialized state (i.e. it |
176 |
|
|
is never necessary to recall the mg_init routine). |
177 |
|
|
|
178 |
|
|
Also, if you use some of the support functions, you should call their |
179 |
|
|
specific clearing functions. For the transform module, the call is |
180 |
|
|
xf_clear. For the object support module, the call is obj_clear. The |
181 |
|
|
context routines use the c_clearall function, but this is actually |
182 |
|
|
called by mg_clear, so calling it again is unnecessary. |
183 |
|
|
|
184 |
|
|
Linking Vertices |
185 |
|
|
================ |
186 |
|
|
Although the MGF language was designed with linking vertices in mind, |
187 |
|
|
there are certain aspects which make this goal more challenging. |
188 |
|
|
Specifically, the ability to redefine values for a previously named |
189 |
|
|
vertex is troublesome for the programmer, since the same vertex can |
190 |
|
|
have different values at different points in the input. Likewise, the |
191 |
|
|
effect of the transform entity on surfaces rather than vertices means |
192 |
|
|
that the same named vertex can appear in many positions. |
193 |
|
|
|
194 |
|
|
It is not possible to use the parser data structures directly for |
195 |
|
|
linking vertices, but we've taken a couple of steps in the support |
196 |
|
|
routines to make the task of organizing your own data structures a |
197 |
|
|
little easier. First, there is a clock member in the C_VERTEX |
198 |
|
|
structure that is incremented on each change. (The same member is |
199 |
|
|
contained in the C_COLOR and C_MATERIAL structures.) Second, the |
200 |
|
|
current transform (pointed to by xf_context) contains a unique |
201 |
|
|
identifier, xf_context->xid. This is a long integer that will be |
202 |
|
|
different for each unique transform. (It is actually a hash key on the |
203 |
|
|
transformation matrix, and there is about 1 chance in 2 billion that |
204 |
|
|
two different matrices will hash to the same value. Is this a bug? |
205 |
|
|
I guess it depends on how long the programmer lives -- or vice versa.) |
206 |
|
|
|
207 |
|
|
There are two ways to use of this additional information. One |
208 |
|
|
is to record the vertex clock value along with it's id and the |
209 |
|
|
current xf_context->xid value. If another vertex comes along with |
210 |
|
|
the same name, but one of these two additional values fails to match, |
211 |
|
|
then it (probably) is a different vertex. Alternatively, one can reset |
212 |
|
|
the clock member every time a new vertex is stored. That way, it is |
213 |
|
|
only necessary to check the clock against zero rather than storing this |
214 |
|
|
value along with the vertex name and transform id. If the name and |
215 |
|
|
transform are the same and the clock is zero, then it's the same vertex |
216 |
|
|
as last time. |
217 |
|
|
|
218 |
|
|
Yet another approach is to ignore the parser structures entirely and |
219 |
|
|
focus on the actual vertex values. After all, the user is not compelled |
220 |
|
|
to reuse the same vertex names for the same points. It is just as likely |
221 |
|
|
that the same vertices will appear under different names, so that none |
222 |
|
|
of the above would help to merge them. The most sure-fire approach to |
223 |
|
|
linking identical vertices is therefore to hash the point and normal |
224 |
|
|
values directly and use the functions in lookup.c to associate them. |
225 |
greg |
1.4 |
You will have to write your own hash function, and we recommend making |
226 |
greg |
1.3 |
one that allows a little slop so that nearly identical points hash to |
227 |
|
|
the same value. |
228 |
greg |
1.2 |
|
229 |
greg |
1.1 |
Examples |
230 |
|
|
======== |
231 |
|
|
Two example translator programs are included with this package. |
232 |
|
|
|
233 |
|
|
The simplest is a translator from MGF to MGF called mgfilt.c, which |
234 |
|
|
produces on the standard output only those entities from the standard |
235 |
|
|
input that are supported according to the command line arguments. For |
236 |
|
|
example, one could remove everything but the raw, flat polygonal |
237 |
|
|
geometry with the following command: |
238 |
|
|
|
239 |
|
|
mgfilt v p f xf < any.mgf > faces.mgf |
240 |
|
|
|
241 |
|
|
Note that the xf entity must also be included, for its support is |
242 |
|
|
required by all geometric entities. |
243 |
|
|
|
244 |
|
|
The second translator converts from MGF to the Radiance scene description |
245 |
|
|
language, and is a more practical example of parser use. Unfortunately, |
246 |
|
|
we did not include all of the support functions required by this translator, |
247 |
|
|
so it serves as a source code example only. If you wish to get the rest |
248 |
|
|
of it because you intend to run it, contact Greg Ward <[email protected]> |
249 |
|
|
and he'll be happy to provide you with the missing pieces. |
250 |
|
|
|
251 |
|
|
Copyright |
252 |
|
|
========= |
253 |
|
|
At this point, the legal issues related to this parser have not been |
254 |
greg |
1.2 |
worked out. The intent is to offer it free of charge to all those who |
255 |
greg |
1.1 |
wish to use it (with no guarantees, of course). However, we may decide |
256 |
|
|
that copyright protections are necessary to prevent unauthorized versions |
257 |
greg |
1.4 |
of the parser, which do not properly support the MGF standard, from |
258 |
|
|
getting spread around. Since this is a pre-release, we trust that you |
259 |
|
|
will not share it with anyone without getting our permission first. |
260 |
greg |
1.1 |
|
261 |
|
|
Questions |
262 |
|
|
========= |
263 |
|
|
Questions should be directed to Greg Ward <[email protected]>, who will be |
264 |
|
|
happy to offer any reasonable assistance in using this standard. (Greg's |
265 |
|
|
telephone is 1-510-486-4757, fax 1-510-486-4089.) |