viewing source for "inputs/xml.c"
last commit
commit 2fcfc3b2e8e18bd4ab667b82d939cc2ba9b6a5d3
Date: Sun Jan 13 09:25:46 2008 -0800
source code
001: #include <stdio.h>
002: #include <stdlib.h>
003: #include <string.h>
004: #include <expat.h>
005:
006: #include "../objects.h"
007: #include "../vector.h"
008:
009: #define BUF_SIZE 4096
010:
011: typedef struct {
012: XML_Parser parser;
013: primitive *prim;
014: primitive *head;
015: } parse_data;
016:
017: static void parse_xyz( float*, const char** );
018: static void parse_light( primitive*, const char** );
019: static float parse_attrf( const char*, const char**, float );
020: static const char* parse_attrs( const char*, const char** );
021:
022: static void parse_xyz( float *xyz, const char **attr ) {
023: int i;
024:
025: for( i = 0; attr[i]; i += 2 ) {
026: if( strcmp( attr[i], "x" ) == 0 ) {
027: xyz[0] = (float)atof( attr[i+1] );
028: }
029: else if( strcmp( attr[i], "y" ) == 0 ) {
030: xyz[1] = (float)atof( attr[i+1] );
031: }
032: else if( strcmp( attr[i], "z" ) == 0 ) {
033: xyz[2] = (float)atof( attr[i+1] );
034: }
035: }
036: }
037:
038: static void parse_light( primitive *p, const char **attr ) {
039: const char *light = parse_attrs( "light", attr );
040: int i;
041: float y,z;
042:
043: if( light == NULL ) {
044: p->is_light = NOT_LIGHT;
045: }
046: else if( strcmp( light, "point" ) == 0 ) {
047: p->is_light = POINT_LIGHT;
048: }
049: else {
050: p->is_light = AREA_LIGHT;
051:
052: if( p->type == BOX ) {
053: p->grid = (float*)malloc( 192 * sizeof( float ) );
054:
055: p->dx = ((box_data*)p->data)->size.x * 0.25f;
056: p->dy = ((box_data*)p->data)->size.y * 0.25f;
057: p->dz = ((box_data*)p->data)->size.z * 0.25f;
058:
059: for( i = 0; i < 64; i++ ) {
060: p->grid[ i*3 ] = ((box_data*)p->data)->point.x + (i%4)*p->dx;
061:
062: if( i % 4 == 0 ) {
063: z = ((box_data*)p->data)->point.z + ((float)(i>=16?i%16:i)/4.0f)*p->dz;
064: if( i % 16 == 0 ) {
065: y = ((box_data*)p->data)->point.y + ((float)i/16.0f)*p->dy;
066: }
067: }
068:
069: p->grid[ i*3+1 ] = y;
070: p->grid[ i*3+2 ] = z;
071: }
072:
073: /*
074: for( i = 0; i < 16; i++ ) {
075: p->grid[i*2] = ((box_data*)p->data)->point.x + (i%4)*p->dx;
076: if( i % 4 == 0 ) {
077: z = ((box_data*)p->data)->point.z + ((float)i/4.0f)*p->dz;
078: }
079:
080: p->grid[i*2+1] = z;
081: }
082: */
083: }
084: }
085: }
086:
087:
088: static float parse_attrf( const char *name, const char **attr, float def ) {
089: int i;
090:
091: for( i = 0; attr[i]; i += 2 ) {
092: if( strcmp( attr[i], name ) == 0 ) {
093: return( (float)atof( attr[i+1] ) );
094: }
095: }
096:
097: return def;
098: }
099:
100: static const char* parse_attrs( const char *name, const char **attr ) {
101: int i;
102:
103: for( i = 0; attr[i]; i += 2 ) {
104: if( strcmp( attr[i], name ) == 0 ) {
105: return( attr[i+1] );
106: }
107: }
108:
109: return NULL;
110: }
111:
112: static char parse_attrb( const char *name, const char **attr, int def ) {
113: const char *truefalse = parse_attrs( name, attr );
114:
115: if( truefalse != NULL && strcmp( truefalse, "true" ) == 0 ) {
116: return 1;
117: }
118: else {
119: return 0;
120: }
121:
122: return def;
123: }
124:
125: void start( void *data, const char *el, const char **attr ) {
126: parse_data *pdata = (parse_data*)data;
127: float xyz[3];
128:
129: if( pdata == NULL ) {
130: fprintf( stderr, "*** xml: parse data is NULL\n" );
131: exit( 1 );
132: }
133:
134: if( strcmp( el, "scene" ) == 0 ) {
135: }
136: else if( pdata->prim == NULL ) {
137: pdata->prim = (primitive*)calloc( 1, sizeof( primitive ) );
138:
139: if( strcmp( el, "sphere" ) == 0 ) {
140: pdata->prim->type = SPHERE;
141:
142: pdata->prim->intersect = &sphere_isect;
143: pdata->prim->normal = &sphere_normal;
144:
145: pdata->prim->data = (sphere_data*)malloc( sizeof( sphere_data ) );
146:
147: parse_light( pdata->prim, attr );
148: parse_xyz( xyz, attr );
149: ((sphere_data*)pdata->prim->data)->radius = parse_attrf(
150: "radius", attr, 0.0f );
151:
152: ((sphere_data*)pdata->prim->data)->center.x = xyz[0];
153: ((sphere_data*)pdata->prim->data)->center.y = xyz[1];
154: ((sphere_data*)pdata->prim->data)->center.z = xyz[2];
155:
156: vect_copy( &pdata->prim->center,
157: &((sphere_data*)pdata->prim->data)->center );
158:
159: /* set some defaults */
160: pdata->prim->mat.col.x = 1.0f;
161: pdata->prim->mat.col.y = 1.0f;
162: pdata->prim->mat.col.z = 1.0f;
163:
164: pdata->prim->mat.diffuse = 1.0f;
165: pdata->prim->mat.specular = 0.0f;
166: pdata->prim->mat.refl = 0.0f;
167: pdata->prim->mat.is_refr = 0;
168: }
169: else if( strcmp( el, "plane" ) == 0 ) {
170: pdata->prim->type = PLANE;
171:
172: pdata->prim->intersect = &plane_isect;
173: pdata->prim->normal = &plane_normal;
174:
175: pdata->prim->data = (plane_data*)malloc( sizeof( plane_data ) );
176:
177: parse_light( pdata->prim, attr );
178: parse_xyz( xyz, attr );
179:
180: ((plane_data*)pdata->prim->data)->normal.x = xyz[0];
181: ((plane_data*)pdata->prim->data)->normal.y = xyz[1];
182: ((plane_data*)pdata->prim->data)->normal.z = xyz[2];
183: ((plane_data*)pdata->prim->data)->dist = parse_attrf(
184: "distance", attr, 0.0f );
185:
186: vect_copy( &pdata->prim->center,
187: &((plane_data*)pdata->prim->data)->normal );
188:
189: /* set some defaults */
190: pdata->prim->mat.col.x = 1.0f;
191: pdata->prim->mat.col.y = 1.0f;
192: pdata->prim->mat.col.z = 1.0f;
193:
194: pdata->prim->mat.diffuse = 1.0f;
195: pdata->prim->mat.specular = 0.0f;
196: pdata->prim->mat.refl = 0.0f;
197: pdata->prim->mat.is_refr = 0;
198: }
199: else if( strcmp( el, "box" ) == 0 ) {
200: pdata->prim->type = BOX;
201:
202: pdata->prim->intersect = &box_isect;
203: pdata->prim->normal = &box_normal;
204:
205: pdata->prim->data = (box_data*)malloc( sizeof( box_data ) );
206:
207: parse_xyz( xyz, attr );
208:
209: ((box_data*)pdata->prim->data)->point.x = xyz[0];
210: ((box_data*)pdata->prim->data)->point.y = xyz[1];
211: ((box_data*)pdata->prim->data)->point.z = xyz[2];
212: ((box_data*)pdata->prim->data)->size.x = parse_attrf(
213: "width", attr, 0.0f );
214: ((box_data*)pdata->prim->data)->size.y = parse_attrf(
215: "height", attr, 0.0f );
216: ((box_data*)pdata->prim->data)->size.z = parse_attrf(
217: "depth", attr, 0.0f );
218:
219: pdata->prim->center.x = xyz[0] +
220: (0.5f * ((box_data*)pdata->prim->data)->size.x);
221: pdata->prim->center.y = xyz[1] +
222: (0.5f * ((box_data*)pdata->prim->data)->size.y);
223: pdata->prim->center.z = xyz[2] +
224: (0.5f * ((box_data*)pdata->prim->data)->size.z);
225:
226: parse_light( pdata->prim, attr );
227:
228: /* set some defaults */
229: pdata->prim->mat.col.x = 1.0f;
230: pdata->prim->mat.col.y = 1.0f;
231: pdata->prim->mat.col.z = 1.0f;
232:
233: pdata->prim->mat.diffuse = 1.0f;
234: pdata->prim->mat.specular = 0.0f;
235: pdata->prim->mat.refl = 0.0f;
236: pdata->prim->mat.is_refr = 0;
237: }
238: else {
239: fprintf( stderr,
240: "*** xml: unknown primitive type \"%s\" at line %d\n",
241: el, XML_GetCurrentLineNumber( pdata->parser ) );
242: exit( 1 );
243: }
244:
245: pdata->prim->next = pdata->head;
246: pdata->head = pdata->prim;
247: }
248: else if( strcmp( el, "material" ) == 0 ) {
249: pdata->prim->mat.col.x = parse_attrf( "r", attr, 1.0f );
250: pdata->prim->mat.col.y = parse_attrf( "g", attr, 1.0f );
251: pdata->prim->mat.col.z = parse_attrf( "b", attr, 1.0f );
252:
253: pdata->prim->mat.diffuse = parse_attrf( "diffuse", attr, 1.0f );
254: pdata->prim->mat.specular = parse_attrf( "specular", attr, 0.0f );
255: pdata->prim->mat.refl = parse_attrf( "reflectivity", attr, 0.0f );
256: pdata->prim->mat.is_refr = parse_attrb( "refractive", attr, 0 );
257: if( pdata->prim->mat.is_refr ) {
258: pdata->prim->mat.refr = parse_attrf( "refractivity", attr, 1.0f );
259: }
260: }
261: else if( strcmp( el, "light" ) == 0 ) {
262: }
263: }
264:
265: void end( void *data, const char *el ) {
266: parse_data *pdata = (parse_data*)data;
267: if( strcmp( el, "scene" ) == 0 ) {
268: }
269: else {
270: pdata->prim = NULL;
271: }
272: }
273:
274: primitive* load_scene( char *file ) {
275: primitive *head = NULL;
276: char buff[BUF_SIZE];
277: FILE *ffile;
278: parse_data *pdata = (parse_data*)calloc( 1, sizeof( parse_data ) );
279:
280: if( pdata == NULL ) {
281: fprintf( stderr, "*** xml: could not allocate memory for parsing\n" );
282: exit( 1 );
283: }
284:
285: pdata->parser = XML_ParserCreate( NULL );
286:
287: if( pdata->parser == NULL ) {
288: fprintf( stderr, "*** xml: could not allocate memory for parser\n" );
289: exit( 1 );
290: }
291:
292: ffile = fopen( file, "r" );
293: if( ffile == NULL ) {
294: fprintf( stderr, "*** xml: could not open %s for reading\n", file );
295: exit( 1 );
296: }
297:
298: XML_SetElementHandler( pdata->parser, start, end );
299: XML_SetUserData( pdata->parser, pdata );
300:
301: for( ;; ) {
302: int done;
303: int len;
304:
305: len = fread( buff, 1, BUF_SIZE, ffile );
306: if( ferror( ffile ) ) {
307: fprintf( stderr, "*** xml: read error\n" );
308: exit( 1 );
309: }
310:
311: done = feof( ffile );
312:
313: if( ! XML_Parse( pdata->parser, buff, len, done ) ) {
314: fprintf( stderr, "*** xml: parse error at line %d:\n%s\n",
315: XML_GetCurrentLineNumber( pdata->parser ),
316: XML_ErrorString( XML_GetErrorCode( pdata->parser ) ) );
317: exit( 1 );
318: }
319:
320: if( done ) break;
321: }
322:
323: #if 0
324: p = (primitive*)malloc( sizeof( primitive ) );
325:
326: p->type = PLANE;
327: p->is_light = NOT_LIGHT;
328:
329: p->intersect = &plane_isect;
330: p->normal = &plane_normal;
331:
332: p->data = (plane_data*)malloc( sizeof( plane_data ) );
333:
334: ((plane_data*)p->data)->normal.x = 0.0f;
335: ((plane_data*)p->data)->normal.y = 1.0f;
336: ((plane_data*)p->data)->normal.z = 0.0f;
337: ((plane_data*)p->data)->dist = 2.0f;
338:
339: p->center.x = 0.0f;
340: p->center.y = 0.0f;
341: p->center.z = 0.0f;
342:
343: p->mat.diffuse = 1.0f;
344: p->mat.specular = 0.0f;
345: p->mat.refl = 0.0f;
346: p->mat.is_refr = 0;
347:
348: p->mat.col.x = 0.46667f;
349: p->mat.col.y = 0.52941f;
350: p->mat.col.z = 0.60784f;
351:
352: p->next = head;
353: head = p;
354: #endif
355:
356: fclose( ffile );
357: XML_ParserFree( pdata->parser );
358:
359: head = pdata->head;
360: free( pdata );
361:
362: return head;
363: }