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