1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #ifdef __MSW__
5 # include <windows.h>
6 #endif
7 #include <GL/gl.h>
8 #include "../include/string.h"
9 #include "x3d.h"
10
11
12 static const char *X3DGetValues1f(const char *arg, GLfloat *vf);
13 static const char *X3DGetValues2f(const char *arg, GLfloat *vf);
14 static const char *X3DGetValues3f(const char *arg, GLfloat *vf);
15 static const char *X3DGetValues4f(const char *arg, GLfloat *vf);
16 static GLuint X3DMatchTexture(
17 X3DTextureRef **texture, int total_textures,
18 const char *name
19 );
20
21 GLuint X3DOpenDataGLList(
22 char **data,
23 const X3DInterpValues *v,
24 X3DTextureRef **texture, int total_textures
25 );
26 void X3DOpenDataGLOutput(
27 char **data,
28 const X3DInterpValues *v,
29 X3DTextureRef **texture, int total_textures
30 );
31 X3DTextureRef *X3DTextureRefAppend(
32 X3DTextureRef ***texture, int *total_textures,
33 const char *name,
34 GLuint id
35 );
36 void X3DTextureDeleteAll(
37 X3DTextureRef ***texture, int *total_textures
38 );
39
40
41 #define ISBLANK(c) (((c) == ' ') || ((c) == '\t'))
42
43 #define ATOI(s) (((s) != NULL) ? atoi(s) : 0)
44 #define ATOL(s) (((s) != NULL) ? atol(s) : 0)
45 #define ATOF(s) (((s) != NULL) ? (float)atof(s) : 0.0f)
46 #define STRDUP(s) (((s) != NULL) ? strdup(s) : NULL)
47
48 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
49 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
50 #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h)))
51
52
53 /*
54 * Get 1 value from the argument string arg and seek arg to the
55 * 2nd argument (or returns NULL if end of string is reached).
56 */
X3DGetValues1f(const char * arg,GLfloat * vf)57 static const char *X3DGetValues1f(const char *arg, GLfloat *vf)
58 {
59 if((arg != NULL) ? (*arg == '\0') : GL_TRUE)
60 {
61 vf[0] = 0.0f;
62 return(NULL);
63 }
64
65 /* Seek to 1st argument and get argument. */
66 while(ISBLANK(*arg))
67 arg++;
68 vf[0] = ATOF(arg);
69
70 /* Seek to 2nd argument. */
71 while(!ISBLANK(*arg) && (*arg != '\0'))
72 arg++;
73 while(ISBLANK(*arg))
74 arg++;
75
76 /* Return new argument position or NULL if end of string. */
77 return((*arg != '\0') ? arg : NULL);
78 }
79
80 /*
81 * Get 2 values from the argument string arg and seek arg to the
82 * 3rd argument (or returns NULL if end of string is reached).
83 */
X3DGetValues2f(const char * arg,GLfloat * vf)84 static const char *X3DGetValues2f(const char *arg, GLfloat *vf)
85 {
86 if((arg != NULL) ? (*arg == '\0') : GL_TRUE)
87 {
88 vf[0] = 0.0f;
89 vf[1] = 0.0f;
90 return(NULL);
91 }
92
93 /* Seek to 1st argument and get argument. */
94 while(ISBLANK(*arg))
95 arg++;
96 vf[0] = ATOF(arg);
97
98 /* Seek to 2nd argument and get argument. */
99 while(!ISBLANK(*arg) && (*arg != '\0'))
100 arg++;
101 while(ISBLANK(*arg))
102 arg++;
103 vf[1] = ATOF(arg);
104
105 /* Seek to 3rd argument. */
106 while(!ISBLANK(*arg) && (*arg != '\0'))
107 arg++;
108 while(ISBLANK(*arg))
109 arg++;
110
111 /* Return new argument position or NULL if end of string. */
112 return((*arg != '\0') ? arg : NULL);
113 }
114
115
116 /*
117 * Get 3 values from the argument string arg and seek arg to the
118 * 4th argument (or returns NULL if end of string is reached).
119 */
X3DGetValues3f(const char * arg,GLfloat * vf)120 static const char *X3DGetValues3f(const char *arg, GLfloat *vf)
121 {
122 if((arg != NULL) ? (*arg == '\0') : GL_TRUE)
123 {
124 vf[0] = 0.0f;
125 vf[1] = 0.0f;
126 vf[2] = 0.0f;
127 return(NULL);
128 }
129
130 /* Seek to 1st argument and get argument. */
131 while(ISBLANK(*arg))
132 arg++;
133 vf[0] = ATOF(arg);
134
135 /* Seek to 2nd argument and get argument. */
136 while(!ISBLANK(*arg) && (*arg != '\0'))
137 arg++;
138 while(ISBLANK(*arg))
139 arg++;
140 vf[1] = ATOF(arg);
141
142 /* Seek to 3rd argument and get argument. */
143 while(!ISBLANK(*arg) && (*arg != '\0'))
144 arg++;
145 while(ISBLANK(*arg))
146 arg++;
147 vf[2] = ATOF(arg);
148
149 /* Seek to 4th argument. */
150 while(!ISBLANK(*arg) && (*arg != '\0'))
151 arg++;
152 while(ISBLANK(*arg))
153 arg++;
154
155 /* Return new argument position or NULL if end of string. */
156 return((*arg != '\0') ? arg : NULL);
157 }
158
159 /*
160 * Get 4 values from the argument string arg and seek arg to the
161 * 5th argument (or returns NULL if end of string is reached).
162 */
X3DGetValues4f(const char * arg,GLfloat * vf)163 static const char *X3DGetValues4f(const char *arg, GLfloat *vf)
164 {
165 if((arg != NULL) ? (*arg == '\0') : GL_TRUE)
166 {
167 vf[0] = 0.0f;
168 vf[1] = 0.0f;
169 vf[2] = 0.0f;
170 vf[3] = 0.0f;
171 return(NULL);
172 }
173
174 /* Seek to 1st argument and get argument. */
175 while(ISBLANK(*arg))
176 arg++;
177 vf[0] = ATOF(arg);
178
179 /* Seek to 2nd argument and get argument. */
180 while(!ISBLANK(*arg) && (*arg != '\0'))
181 arg++;
182 while(ISBLANK(*arg))
183 arg++;
184 vf[1] = ATOF(arg);
185
186 /* Seek to 3rd argument and get argument. */
187 while(!ISBLANK(*arg) && (*arg != '\0'))
188 arg++;
189 while(ISBLANK(*arg))
190 arg++;
191 vf[2] = ATOF(arg);
192
193 /* Seek to 4th argument and get argument. */
194 while(!ISBLANK(*arg) && (*arg != '\0'))
195 arg++;
196 while(ISBLANK(*arg))
197 arg++;
198 vf[3] = ATOF(arg);
199
200 /* Seek to 5th argument. */
201 while(!ISBLANK(*arg) && (*arg != '\0'))
202 arg++;
203 while(ISBLANK(*arg))
204 arg++;
205
206 /* Return new argument position or NULL if end of string. */
207 return((*arg != '\0') ? arg : NULL);
208 }
209
210 /*
211 * Returns a gl texture id that matches the given texture name in
212 * the list or returns 0 on failed match.
213 */
X3DMatchTexture(X3DTextureRef ** texture,int total_textures,const char * name)214 static GLuint X3DMatchTexture(
215 X3DTextureRef **texture, int total_textures,
216 const char *name
217 )
218 {
219 int i;
220 X3DTextureRef *t;
221
222 if(name == NULL)
223 return(0);
224
225 for(i = 0; i < total_textures; i++)
226 {
227 t = texture[i];
228 if(t == NULL)
229 continue;
230
231 if(t->name == NULL)
232 continue;
233
234 if(!strcasecmp(t->name, name))
235 return(t->id);
236 }
237
238 return(0);
239 }
240
241
242 /*
243 * Open the X3D data into a GL list.
244 */
X3DOpenDataGLList(char ** data,const X3DInterpValues * v,X3DTextureRef ** texture,int total_textures)245 GLuint X3DOpenDataGLList(
246 char **data,
247 const X3DInterpValues *v,
248 X3DTextureRef **texture, int total_textures
249 )
250 {
251 GLuint gllist = glGenLists(1);
252 glNewList(gllist, GL_COMPILE);
253 X3DOpenDataGLOutput(data, v, texture, total_textures);
254 glEndList();
255 return(gllist);
256 }
257
258 /*
259 * Open the X3D data and send it out as GL commands.
260 */
X3DOpenDataGLOutput(char ** data,const X3DInterpValues * v,X3DTextureRef ** texture,int total_textures)261 void X3DOpenDataGLOutput(
262 char **data,
263 const X3DInterpValues *v,
264 X3DTextureRef **texture, int total_textures
265 )
266 {
267 GLboolean texture_on = GL_FALSE;
268 unsigned long flags = X3D_DEFAULT_VALUE_FLAGS;
269 int coordinate_system = X3D_COORDINATE_SYSTEM_XYZ;
270 GLfloat scale_x = 1.0f,
271 scale_y = 1.0f,
272 scale_z = 1.0f;
273 GLfloat offset_x = 0.0f,
274 offset_y = 0.0f,
275 offset_z = 0.0f;
276 int i;
277 char *s, *s2, *s_end;
278 const char *arg;
279 char parm[X3D_PARM_MAX];
280
281
282 if(data == NULL)
283 return;
284
285 /* Get interpretation values. */
286 if(v != NULL)
287 {
288 flags = v->flags;
289 if(flags & X3D_VALUE_FLAG_COORDINATE_SYSTEM)
290 coordinate_system = v->coordinate_system;
291 if(flags & X3D_VALUE_FLAG_SCALE)
292 {
293 scale_x = v->scale_x;
294 scale_y = v->scale_y;
295 scale_z = v->scale_z;
296 }
297 if(flags & X3D_VALUE_FLAG_OFFSET)
298 {
299 offset_x = v->offset_x;
300 offset_y = v->offset_y;
301 offset_z = v->offset_z;
302 }
303 }
304
305 /* Iterate through each data line. */
306 for(i = 0; data[i] != NULL; i++)
307 {
308 /* Skip to line #4 (lines #0 to #3 are header and ignored). */
309 if(i < 4)
310 continue;
311
312 /* Get parameter. */
313 s = data[i];
314 s_end = s + X3D_PARM_MAX - 1;
315 s2 = parm;
316 while(!ISBLANK(*s) && (*s != '\0') && (s < s_end))
317 *s2++ = *s++;
318 *s2 = '\0';
319
320 /* Get argument. */
321 arg = s;
322 while(ISBLANK(*arg))
323 arg++;
324
325
326 /* Enable. */
327 if(!strcasecmp(parm, "enable"))
328 {
329 if(!(flags & X3D_VALUE_FLAG_SKIP_STATE_CHANGES))
330 {
331
332 }
333 }
334 /* Disable. */
335 else if(!strcasecmp(parm, "disable"))
336 {
337 if(!(flags & X3D_VALUE_FLAG_SKIP_STATE_CHANGES))
338 {
339
340 }
341 }
342 /* Points. */
343 else if(!strcasecmp(parm, "begin_points"))
344 {
345 glBegin(GL_POINTS);
346 }
347 else if(!strcasecmp(parm, "end_points"))
348 {
349 glEnd();
350 }
351 /* Lines. */
352 else if(!strcasecmp(parm, "begin_lines"))
353 {
354 glBegin(GL_LINES);
355 }
356 else if(!strcasecmp(parm, "end_lines"))
357 {
358 glEnd();
359 }
360 /* Line strip. */
361 else if(!strcasecmp(parm, "begin_line_strip"))
362 {
363 glBegin(GL_LINE_STRIP);
364 }
365 else if(!strcasecmp(parm, "end_line_strip"))
366 {
367 glEnd();
368 }
369 /* Line loop. */
370 if(!strcasecmp(parm, "begin_line_loop"))
371 {
372 glBegin(GL_LINE_LOOP);
373 }
374 else if(!strcasecmp(parm, "end_line_loop"))
375 {
376 glEnd();
377 }
378 /* Triangles. */
379 else if(!strcasecmp(parm, "begin_triangles"))
380 {
381 glBegin(GL_TRIANGLES);
382 }
383 else if(!strcasecmp(parm, "end_triangles"))
384 {
385 glEnd();
386 }
387 /* Triangle strip. */
388 else if(!strcasecmp(parm, "begin_triangle_strip"))
389 {
390 glBegin(GL_TRIANGLE_STRIP);
391 }
392 else if(!strcasecmp(parm, "end_triangle_strip"))
393 {
394 glEnd();
395 }
396 /* Triangle fan. */
397 else if(!strcasecmp(parm, "begin_triangle_fan"))
398 {
399 glBegin(GL_TRIANGLE_FAN);
400 }
401 else if(!strcasecmp(parm, "end_triangle_fan"))
402 {
403 glEnd();
404 }
405 /* Quads. */
406 else if(!strcasecmp(parm, "begin_quads"))
407 {
408 glBegin(GL_QUADS);
409 }
410 else if(!strcasecmp(parm, "end_quads"))
411 {
412 glEnd();
413 }
414 /* Quad strip. */
415 else if(!strcasecmp(parm, "begin_quad_strip"))
416 {
417 glBegin(GL_QUAD_STRIP);
418 }
419 else if(!strcasecmp(parm, "end_quad_strip"))
420 {
421 glEnd();
422 }
423 /* Polygon. */
424 else if(!strcasecmp(parm, "begin_polygon"))
425 {
426 glBegin(GL_POLYGON);
427 }
428 else if(!strcasecmp(parm, "end_polygon"))
429 {
430 glEnd();
431 }
432 /* Normal. */
433 else if(!strcasecmp(parm, "normal") ||
434 !strcasecmp(parm, "normal3") ||
435 !strcasecmp(parm, "normal3f")
436 )
437 {
438 GLfloat vf[3];
439
440 arg = X3DGetValues3f(arg, vf);
441 if(!(flags & X3D_VALUE_FLAG_SKIP_NORMALS))
442 {
443 if(coordinate_system == X3D_COORDINATE_SYSTEM_GL)
444 glNormal3f(vf[0], vf[1], vf[2]);
445 else
446 glNormal3f(vf[0], vf[2], -vf[1]);
447 }
448 }
449 /* Texcoord. */
450 else if(!strcasecmp(parm, "texcoord1f") ||
451 !strcasecmp(parm, "texcoord1")
452 )
453 {
454 GLfloat vf[1];
455
456 arg = X3DGetValues1f(arg, vf);
457 if(!(flags & X3D_VALUE_FLAG_SKIP_TEXCOORDS))
458 {
459 if(coordinate_system == X3D_COORDINATE_SYSTEM_GL)
460 glTexCoord1f(vf[0]);
461 else
462 glTexCoord1f(vf[0]);
463 }
464 }
465 else if(!strcasecmp(parm, "texcoord2f") ||
466 !strcasecmp(parm, "texcoord2") ||
467 !strcasecmp(parm, "texcoord")
468 )
469 {
470 GLfloat vf[2];
471
472 arg = X3DGetValues2f(arg, vf);
473 if(!(flags & X3D_VALUE_FLAG_SKIP_TEXCOORDS))
474 {
475 if(coordinate_system == X3D_COORDINATE_SYSTEM_GL)
476 glTexCoord2f(vf[0], vf[1]);
477 else
478 glTexCoord2f(vf[0], 1.0f - vf[1]);
479 }
480 }
481 else if(!strcasecmp(parm, "texcoord3f") ||
482 !strcasecmp(parm, "texcoord3")
483 )
484 {
485 GLfloat vf[3];
486
487 arg = X3DGetValues3f(arg, vf);
488 if(!(flags & X3D_VALUE_FLAG_SKIP_TEXCOORDS))
489 {
490 if(coordinate_system == X3D_COORDINATE_SYSTEM_GL)
491 glTexCoord3f(vf[0], vf[1], vf[2]);
492 else
493 glTexCoord3f(vf[0], 1.0f - vf[1], vf[2]);
494 }
495 }
496 /* Vertex. */
497 else if(!strcasecmp(parm, "vertex3f") ||
498 !strcasecmp(parm, "vertex3") ||
499 !strcasecmp(parm, "vertex")
500 )
501 {
502 GLfloat vf[3];
503
504 arg = X3DGetValues3f(arg, vf);
505 if(!(flags & X3D_VALUE_FLAG_SKIP_VERTICES))
506 {
507 if(coordinate_system == X3D_COORDINATE_SYSTEM_GL)
508 glVertex3f(
509 (vf[0] * scale_x) + offset_x,
510 (vf[1] * scale_y) + offset_y,
511 (vf[2] * scale_z) + offset_z
512 );
513 else
514 glVertex3f(
515 (vf[0] * scale_x) + offset_x,
516 (vf[2] * scale_z) + offset_z,
517 -((vf[1] * scale_y) + offset_y)
518 );
519 }
520 }
521 else if(!strcasecmp(parm, "vertex4f") ||
522 !strcasecmp(parm, "vertex4")
523 )
524 {
525 GLfloat vf[4];
526
527 arg = X3DGetValues4f(arg, vf);
528 if(!(flags & X3D_VALUE_FLAG_SKIP_VERTICES))
529 {
530 if(coordinate_system == X3D_COORDINATE_SYSTEM_GL)
531 glVertex4f(
532 (vf[0] * scale_x) + offset_x,
533 (vf[1] * scale_y) + offset_y,
534 (vf[2] * scale_z) + offset_z,
535 vf[3]
536 );
537 else
538 glVertex4f(
539 (vf[0] * scale_x) + offset_x,
540 (vf[2] * scale_z) + offset_z,
541 -((vf[1] * scale_y) + offset_y),
542 vf[3]
543 );
544 }
545 }
546 /* Color */
547 else if(!strcasecmp(parm, "color3f") ||
548 !strcasecmp(parm, "color3") ||
549 !strcasecmp(parm, "color")
550 )
551 {
552 GLfloat vf[3];
553
554 arg = X3DGetValues3f(arg, vf);
555 if(!(flags & X3D_VALUE_FLAG_SKIP_COLORS))
556 glColor3f(vf[0], vf[1], vf[2]);
557 }
558 else if(!strcasecmp(parm, "color4f") ||
559 !strcasecmp(parm, "color4")
560 )
561 {
562 GLfloat vf[4];
563
564 arg = X3DGetValues4f(arg, vf);
565 if(!(flags & X3D_VALUE_FLAG_SKIP_COLORS))
566 glColor4f(vf[0], vf[1], vf[2], vf[3]);
567 }
568 /* Bind Texture */
569 else if(!strcasecmp(parm, "bind_texture_1d"))
570 {
571 GLuint id = X3DMatchTexture(texture, total_textures, arg);
572 if(id != 0)
573 {
574 glBindTexture(GL_TEXTURE_1D, id);
575 texture_on = GL_TRUE;
576 }
577 else
578 {
579 glBindTexture(GL_TEXTURE_1D, 0);
580 texture_on = GL_FALSE;
581 }
582 }
583 else if(!strcasecmp(parm, "bind_texture_2d") ||
584 !strcasecmp(parm, "bind_texture")
585 )
586 {
587 GLuint id = X3DMatchTexture(texture, total_textures, arg);
588 if(id != 0)
589 {
590 glBindTexture(GL_TEXTURE_2D, id);
591 texture_on = GL_TRUE;
592 }
593 else
594 {
595 glBindTexture(GL_TEXTURE_2D, 0);
596 texture_on = GL_FALSE;
597 }
598 }
599 #ifdef GL_TEXTURE_3D
600 else if(!strcasecmp(parm, "bind_texture_3d"))
601 {
602 GLuint id = X3DMatchTexture(texture, total_textures, arg);
603 if(id != 0)
604 {
605 glBindTexture(GL_TEXTURE_3D, id);
606 texture_on = GL_TRUE;
607 }
608 else
609 {
610 glBindTexture(GL_TEXTURE_3D, 0);
611 texture_on = GL_FALSE;
612 }
613 }
614 #endif
615
616 }
617 }
618
619 /*
620 * Appends a texture reference to the list.
621 */
X3DTextureRefAppend(X3DTextureRef *** texture,int * total_textures,const char * name,GLuint id)622 X3DTextureRef *X3DTextureRefAppend(
623 X3DTextureRef ***texture, int *total_textures,
624 const char *name,
625 GLuint id
626 )
627 {
628 int i;
629 X3DTextureRef *t = NULL;
630
631 if((texture == NULL) || (total_textures == NULL))
632 return(t);
633
634 i = MAX(*total_textures, 0);
635 *total_textures = i + 1;
636 *texture = (X3DTextureRef **)realloc(
637 *texture,
638 (*total_textures) * sizeof(X3DTextureRef *)
639 );
640 if(*texture == NULL)
641 {
642 *total_textures = 0;
643 return(t);
644 }
645
646 *texture[i] = t = (X3DTextureRef *)calloc(
647 1, sizeof(X3DTextureRef)
648 );
649 if(t == NULL)
650 return(t);
651
652 t->name = STRDUP(name);
653 t->id = id;
654
655 return(t);
656 }
657
658 /*
659 * Delete all texture references.
660 */
X3DTextureDeleteAll(X3DTextureRef *** texture,int * total_textures)661 void X3DTextureDeleteAll(
662 X3DTextureRef ***texture, int *total_textures
663 )
664 {
665 int i;
666 X3DTextureRef *t;
667
668 if((texture == NULL) || (total_textures == NULL))
669 return;
670
671 for(i = 0; i < *total_textures; i++)
672 {
673 t = (*texture)[i];
674 if(t == NULL)
675 continue;
676
677 free(t->name);
678 free(t);
679 }
680
681 free(*texture);
682 *texture = NULL;
683 *total_textures = 0;
684 }
685