viewing source for "inputs/xml.c"

last commit

commit 2fcfc3b2e8e18bd4ab667b82d939cc2ba9b6a5d3 Author: Andrew Rader <andrew.r.rader@gmail.com> Date: Sun Jan 13 09:25:46 2008 -0800
Initial Commit

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: }