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 |
< |
The differences in the two approaches are slight, and we will explain |
49 |
> |
The differences in the two approaches are slight, and we will mention |
50 |
|
them following a general explanation of the parser and support library. |
51 |
|
|
52 |
|
The Parser |
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 |
< |
functions. The arguments to these functions is always the same, an |
66 |
> |
functions. The arguments to these functions are always the same, an |
67 |
|
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 |
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 |
< |
materials.) |
110 |
> |
materials.) A list of related mg_ehand assignments is given below: |
111 |
|
|
112 |
+ |
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 |
|
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 |
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 |
< |
principle action of the parser's mg_clear function. |
139 |
> |
principal action of the parser's mg_clear function. |
140 |
|
|
141 |
|
Transform Support |
142 |
|
================= |
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 |
|
|
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 |
+ |
You will have to write your own hash function, and we recommend making |
226 |
+ |
one that allows a little slop so that nearly identical points hash to |
227 |
+ |
the same value. |
228 |
+ |
|
229 |
|
Examples |
230 |
|
======== |
231 |
|
Two example translator programs are included with this package. |
254 |
|
worked out. The intent is to offer it free of charge to all those who |
255 |
|
wish to use it (with no guarantees, of course). However, we may decide |
256 |
|
that copyright protections are necessary to prevent unauthorized versions |
257 |
< |
of the parser that do not properly support the MGF standard from getting |
258 |
< |
spread around. Since this is a pre-release, we trust that you will not |
259 |
< |
share it with anyone without getting our permission first. |
257 |
> |
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 |
|
|
261 |
|
Questions |
262 |
|
========= |