FreeWRL / FreeX3D 4.3.0
Component_Geometry2D.c
1/*
2
3
4X3D Geometry2D Component
5
6*/
7
8
9/****************************************************************************
10 This file is part of the FreeWRL/FreeX3D Distribution.
11
12 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
13
14 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
15 it under the terms of the GNU Lesser Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
26****************************************************************************/
27
28
29
30#include <config.h>
31#include <system.h>
32#include <display.h>
33#include <internal.h>
34
35#include <libFreeWRL.h>
36
37#include "../vrml_parser/Structs.h"
38#include "../main/headers.h"
39
40#include "Collision.h"
41#include "LinearAlgebra.h"
42#include "../opengl/Frustum.h"
43#include "../opengl/Material.h"
44#include "Component_Geometry3D.h"
45#include "../opengl/OpenGL_Utils.h"
46#include "../opengl/Textures.h"
47
48#include "Component_Shape.h"
49#include "../scenegraph/RenderFuncs.h"
50#include "../x3d_parser/Bindable.h"
51
52#include <float.h>
53#if defined(_MSC_VER) && _MSC_VER < 1500
54#define cosf cos
55#define sinf sin
56#endif
57#define SEGMENTS_PER_CIRCLE 36
58#define PIE 10
59#define CHORD 20
60#define NONE 30
61
62static void *createLines (float start, float end, float radius, int closed, int *size,float *_extent);
63
64#define COMPILE_AND_GET_BOUNDS(myType,myField) \
65void compile_##myType (struct X3D_##myType *node){ \
66 float myminx = FLT_MAX; \
67 float mymaxx = -FLT_MAX; \
68 float myminy = FLT_MAX; \
69 float mymaxy = -FLT_MAX; \
70 int count; \
71 \
72 if (node->myField.n<=0) { \
73 node->EXTENT_MIN_X = 0.0f; \
74 node->EXTENT_MAX_X = 0.0f; \
75 node->EXTENT_MIN_Y = 0.0f; \
76 node->EXTENT_MAX_Y = 0.0f; \
77 } else { \
78 for (count = 0; count < node->myField.n; count++) { \
79 if (node->myField.p[count].c[0] > mymaxx) mymaxx = node->myField.p[count].c[0]; \
80 if (node->myField.p[count].c[0] < myminx) myminx = node->myField.p[count].c[0]; \
81 if (node->myField.p[count].c[1] > mymaxy) mymaxy = node->myField.p[count].c[1]; \
82 if (node->myField.p[count].c[1] < myminy) myminy = node->myField.p[count].c[1]; \
83 } \
84 node->EXTENT_MAX_X = mymaxx; \
85 node->EXTENT_MIN_X = myminx; \
86 node->EXTENT_MAX_Y = mymaxy; \
87 node->EXTENT_MIN_Y = myminy; \
88 } \
89 \
90 MARK_NODE_COMPILED \
91}
92/***********************************************************************************/
93
94void compile_Arc2D (struct X3D_Arc2D *node) {
95 /* have to regen the shape*/
96 struct SFVec2f *tmpptr_a, *tmpptr_b;
97 int tmpint;
98
99 MARK_NODE_COMPILED
100
101 tmpint = 0;
102 tmpptr_a = createLines (node->startAngle, node->endAngle, node->radius, NONE, &tmpint, node->_extent);
103
104 /* perform the switch - worry about threading here without locking */
105 node->__numPoints = 0; /* tell us that it has zero points */
106 tmpptr_b = node->__points.p; /* old set of points, for freeing later */
107 node->__points.p = tmpptr_a; /* new points */
108 node->__numPoints = tmpint;
109 FREE_IF_NZ (tmpptr_b);
110 /* switch completed */
111
112}
113
114void render_Arc2D (struct X3D_Arc2D *node) {
115 ttglobal tg = gglobal();
116 COMPILE_IF_REQUIRED
117 if (node->__numPoints>0) {
118 /* for BoundingBox calculations */
119 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
120 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
121
122 LIGHTING_OFF
123 DISABLE_CULL_FACE
124
125 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
126 sendArraysToGPU (GL_LINE_STRIP, 0, node->__numPoints);
127 tg->Mainloop.trisThisLoop += node->__numPoints;
128 }
129}
130
131/***********************************************************************************/
132void compile_ArcClose2D (struct X3D_ArcClose2D *node){
133 /* have to regen the shape*/
134 char *ct;
135 struct SFVec2f *fp, *tp;
136 //GLfloat *tp;
137 struct SFVec2f *sfp, *stp;
138 //GLfloat *stp;
139 struct SFVec2f *ofp, *otp;
140 //GLfloat *otp;
141 int i,j,k;
142 GLfloat id;
143 GLfloat od;
144 int tmpint;
145 int simpleDisc;
146 int closure;
147 ushort *lindex;
148 float start, end, radius, angle, angle_increment;
149 int numPoints, arcpoints;
150
151 MARK_NODE_COMPILED
152
153
154 ct = node->closureType->strptr;
155 //xx = node->closureType->len;
156 tmpint = 0;
157
158 if (strcmp(ct,"PIE") == 0) {
159 closure = PIE;
160 } else if (strcmp(ct,"CHORD") == 0) {
161 closure = CHORD;
162 } else {
163 printf ("ArcClose2D, closureType %s invalid\n",node->closureType->strptr);
164 }
165 start = node->startAngle;
166 end = node->endAngle;
167 radius = node->radius;
168 /* is this a circle? */
169 simpleDisc = APPROX(start,end);
170
171 /* bounds check, and sort values */
172 if(end < start)
173 end += 2.0*PI;
174
175 if (radius < 0.0) radius = 1.0f;
176
177 if(0) if (start > end) {
178 float tmp = start;
179 start = end;
180 end = tmp;
181 }
182
183 if (simpleDisc) {
184 numPoints = SEGMENTS_PER_CIRCLE;
185 } else {
186 numPoints = (int) ((float)(SEGMENTS_PER_CIRCLE * (end - start))/(PI*2.0f));
187 numPoints++; //one more point than segments
188 if (numPoints>SEGMENTS_PER_CIRCLE) numPoints=SEGMENTS_PER_CIRCLE;
189 }
190 arcpoints = numPoints;
191 //add one point for pie center or half-chord - we'll fan from this point.
192 numPoints ++;
193
194 tmpint = SEGMENTS_PER_CIRCLE+2;
195 fp = sfp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * (numPoints));
196 tp = stp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * (numPoints));
197 lindex = MALLOC (ushort *, sizeof(ushort) * (numPoints*2)*2); //over malloc by a few. should be nsegs * 2 lines/seg * 2 lineEnds/line
198 //if(!node->_gc) node->_gc = newVector(void *,4); H: FreeWRLPTR gets freed, no need for _gc
199 //vector_pushBack(void*,node->_gc,lindex);
200
201 /* initial TriangleFan point */
202 (*fp).c[0] = 0.0f; (*fp).c[1] = 0.0f; fp++;
203 (*tp).c[0] = 0.5f; (*tp).c[1] = 0.5f; tp++;
204
205 angle = start;
206 angle_increment = (end - start)/(float)(arcpoints -1);
207 for (i=0,k=0,j=1;i<arcpoints;i++,k+=4,j++) {
208 float x,y;
209 x = cosf(angle);
210 y = sinf(angle);
211 (*fp).c[0] = node->radius * x;
212 (*fp).c[1] = node->radius * y;
213 fp++;
214
215 lindex[k + 0] = 0;
216 lindex[k + 1] = j;
217 lindex[k + 2] = j;
218 lindex[k + 3] = j+1;
219
220 (*tp).c[0] = 0.5f + x*.5f; //center 0,0 in middle of texture
221 (*tp).c[1] = 0.5f + y*.5f;
222 tp++;
223 angle += angle_increment;
224 angle = max(angle, start);
225 }
226 if(closure == CHORD){
227 sfp[0].c[0] = .5f * (sfp[1].c[0] + sfp[arcpoints].c[0]);
228 sfp[0].c[1] = .5f * (sfp[1].c[1] + sfp[arcpoints].c[1]);
229 stp[0].c[0] = .5f * (stp[1].c[0] + stp[arcpoints].c[0]);
230 stp[0].c[1] = .5f * (stp[1].c[1] + stp[arcpoints].c[1]);
231 }
232 node->__wireindices = lindex;
233
234
235 /* compiling done, set up for rendering. thread safe */
236 node->__numPoints = 0;
237 ofp = node->__points.p;
238 otp = node->__texCoords.p;
239 node->__points.p = sfp;
240 node->__texCoords.p = stp;
241 node->__simpleDisk = simpleDisc;
242 node->__numPoints = numPoints;
243 FREE_IF_NZ (ofp);
244 FREE_IF_NZ (otp);
245
246 /* we can set the extents here... */
247 {
248 float myminx = FLT_MAX;
249 float mymaxx = -FLT_MAX;
250 float myminy = FLT_MAX;
251 float mymaxy = -FLT_MAX;
252 for (i=0; i<numPoints; i++) {
253 /* do X first */
254 if (sfp[i].c[0] > mymaxx) mymaxx = sfp[i].c[0];
255 if (sfp[i].c[0] < myminx) myminx = sfp[i].c[0];
256 fp++;
257 /* do Y second */
258 if (sfp[i].c[1] > mymaxy) mymaxy = sfp[i].c[1];
259 if (sfp[i].c[1] < myminy) myminy = sfp[i].c[1];
260 }
261
262 node->EXTENT_MAX_X = myminx; //node->radius;
263 node->EXTENT_MIN_X = mymaxx; // -node->radius;
264 node->EXTENT_MAX_Y = myminy; //node->radius;
265 node->EXTENT_MIN_Y = mymaxy; //-node->radius;
266 }
267}
268#define DESIRE(whichOne,zzz) ((whichOne & zzz)==zzz)
269void render_ArcClose2D (struct X3D_ArcClose2D *node){
270 COMPILE_IF_REQUIRED
271 if (node->__numPoints>0) {
272 struct textureVertexInfo mtf = {(GLfloat *)node->__texCoords.p,2,GL_FLOAT,0,NULL,NULL};
273 /* for BoundingBox calculations */
274 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
275 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
276
277 CULL_FACE(node->solid)
278
279 textureCoord_send(&mtf);
280 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
281
282
283 /* do the array drawing; sides are simple 0-1-2-3, 4-5-6-7, etc quads */
284 if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
285 //wireframe triangles
286 sendElementsToGPU(GL_LINES,((node->__numPoints-1)*4 -1 ),node->__wireindices); //should be segs x 2 lines/seg = (pts-1) x 2 lines / pt
287 }else{
288 sendArraysToGPU (GL_TRIANGLE_FAN, 0, node->__numPoints);
289 }
290
291 gglobal()->Mainloop.trisThisLoop += node->__numPoints;
292 }
293}
294
295void compile_ArcClose2D_LINE (struct X3D_ArcClose2D *node) {
296 //int xx;
297 char *ct;
298 struct SFVec2f *tmpptr_a, *tmpptr_b;
299 int tmpint;
300
301 /* have to regen the shape*/
302 MARK_NODE_COMPILED
303
304 ct = node->closureType->strptr;
305 //xx = node->closureType->len;
306 tmpint = 0;
307 tmpptr_a = NULL;
308
309 if (strcmp(ct,"PIE") == 0) {
310 tmpptr_a = createLines (node->startAngle,
311 node->endAngle, node->radius, PIE, &tmpint,node->_extent);
312 } else if (strcmp(ct,"CHORD") == 0) {
313 tmpptr_a = createLines (node->startAngle,
314 node->endAngle, node->radius, CHORD, &tmpint,node->_extent);
315 } else {
316 printf ("ArcClose2D, closureType %s invalid\n",node->closureType->strptr);
317 }
318
319 /* perform the switch - worry about threading here without locking */
320 node->__numPoints = 0; /* tell us that it has zero points */
321 tmpptr_b = node->__points.p; /* old set of points, for freeing later */
322 node->__points.p = tmpptr_a; /* new points */
323 node->__numPoints = tmpint;
324 FREE_IF_NZ (tmpptr_b);
325 /* switch completed */
326}
327
328
329void render_ArcClose2D_LINE (struct X3D_ArcClose2D *node) {
330 ttglobal tg = gglobal();
331 COMPILE_IF_REQUIRED
332 if (node->__numPoints>0) {
333 /* for BoundingBox calculations */
334 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
335 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
336
337 LIGHTING_OFF
338 DISABLE_CULL_FACE
339
340
341 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
342 sendArraysToGPU (GL_LINE_STRIP, 0, node->__numPoints);
343
344 gglobal()->Mainloop.trisThisLoop += node->__numPoints;
345 }
346}
347// rendray_ArcClose2D
348
349/***********************************************************************************/
350
351void compile_Circle2D (struct X3D_Circle2D *node) {
352 struct SFVec2f *tmpptr_a, *tmpptr_b;
353 int tmpint;
354
355 /* have to regen the shape*/
356 MARK_NODE_COMPILED
357
358 tmpptr_a = createLines (0.0f, 0.0f, node->radius, NONE, &tmpint,node->_extent);
359
360 /* perform the switch - worry about threading here without locking */
361 node->__numPoints = 0; /* tell us that it has zero points */
362 tmpptr_b = node->__points.p; /* old set of points, for freeing later */
363 node->__points.p = tmpptr_a; /* new points */
364 node->__numPoints = tmpint;
365 FREE_IF_NZ (tmpptr_b);
366 /* switch completed */
367}
368
369void render_Circle2D (struct X3D_Circle2D *node) {
370 ttglobal tg = gglobal();
371 COMPILE_IF_REQUIRED
372 if (node->__numPoints>0) {
373 /* for BoundingBox calculations */
374 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
375 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
376
377 LIGHTING_OFF
378 DISABLE_CULL_FACE
379
380 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
381 sendArraysToGPU (GL_LINE_STRIP, 0, node->__numPoints);
382 gglobal()->Mainloop.trisThisLoop += node->__numPoints;
383 }
384}
385
386/***********************************************************************************/
387
388
389COMPILE_AND_GET_BOUNDS(Polyline2D,lineSegments)
390
391void render_Polyline2D (struct X3D_Polyline2D *node){
392 ttglobal tg = gglobal();
393
394 COMPILE_IF_REQUIRED
395 if (node->lineSegments.n>0) {
396 /* for BoundingBox calculations */
397 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
398 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
399
400 LIGHTING_OFF
401 DISABLE_CULL_FACE
402
403
404 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->lineSegments.p);
405 sendArraysToGPU (GL_LINE_STRIP, 0, node->lineSegments.n);
406 gglobal()->Mainloop.trisThisLoop += node->lineSegments.n;
407 }
408}
409
410/***********************************************************************************/
411
412COMPILE_AND_GET_BOUNDS(Polypoint2D,point)
413
414void render_Polypoint2D (struct X3D_Polypoint2D *node){
415 ttglobal tg = gglobal();
416
417 COMPILE_IF_REQUIRED
418 if (node->point.n>0) {
419 /* for BoundingBox calculations */
420 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
421 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
422
423 LIGHTING_OFF
424 DISABLE_CULL_FACE
425
426
427 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->point.p);
428 sendArraysToGPU (GL_POINTS, 0, node->point.n);
429 gglobal()->Mainloop.trisThisLoop += node->point.n;
430 }
431}
432
433/***********************************************************************************/
434
435void compile_Disk2D (struct X3D_Disk2D *node){
436 /* have to regen the shape*/
437 struct SFVec2f *fp, *tp;
438 //GLfloat *tp;
439 struct SFVec2f *sfp, *stp;
440 //GLfloat *stp;
441 struct SFVec2f *ofp, *otp;
442 //GLfloat *otp;
443 int i,j,k;
444 GLfloat id;
445 GLfloat od;
446 int tmpint;
447 int simpleDisc;
448 ushort *lindex;
449
450 MARK_NODE_COMPILED
451
452
453 /* bounds checking */
454 if (node->innerRadius<0) {node->__numPoints = 0; return;}
455 if (node->outerRadius<0) {node->__numPoints = 0; return;}
456
457 /* is this a simple disc ? */
458 if ((APPROX (node->innerRadius, 0.0)) ||
459 (APPROX(node->innerRadius,node->outerRadius))) simpleDisc = TRUE;
460 else simpleDisc = FALSE;
461
462 /* is this a simple disk, or one with an inner circle cut out? */
463 if (simpleDisc) {
464 tmpint = SEGMENTS_PER_CIRCLE+2;
465 fp = sfp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * (tmpint));
466 tp = stp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * (tmpint)); //(GLfloat *, sizeof(GLfloat) * 2 * (tmpint));
467 lindex = MALLOC (ushort *, sizeof(ushort) * (tmpint*2)*2); //over malloc by a few. should be nsegs * 2 lines/seg * 2 lineEnds/line
468 //if(!node->_gc) node->_gc = newVector(void *,4); H: FreeWRLPTR gets freed, no need for _gc
469 //vector_pushBack(void*,node->_gc,lindex);
470
471 /* initial TriangleFan point */
472 (*fp).c[0] = 0.0f; (*fp).c[1] = 0.0f; fp++;
473 (*tp).c[0] = 0.5f; (*tp).c[1] = 0.5f; tp++;
474 id = 2.0f;
475
476 for (i=SEGMENTS_PER_CIRCLE,j=1,k=0; i >= 0; i--,j++,k+=4) {
477 (*fp).c[0] = node->outerRadius * sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
478 (*fp).c[1] = node->outerRadius * cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
479 fp++;
480
481 lindex[k + 0] = 0;
482 lindex[k + 1] = j;
483 lindex[k + 2] = j;
484 lindex[k + 3] = j+1;
485
486 (*tp).c[0] = 0.5f + (sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/id);
487 (*tp).c[1] = 0.5f + (cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/id);
488 tp++;
489 }
490 node->__wireindices = lindex;
491 } else {
492 tmpint = (SEGMENTS_PER_CIRCLE+1) * 2;
493 fp = sfp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * 2 * tmpint);
494 tp = stp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * (tmpint)); //MALLOC (GLfloat *, sizeof(GLfloat) * 2 * tmpint);
495 lindex = MALLOC (ushort *, sizeof(ushort) * (tmpint*2) *2); //over malloc by a few, should be (nseg-1)*4 lines/seg * 2 lineEnds per line
496 //if(!node->_gc) node->_gc = newVector(void *,4);
497 //vector_pushBack(void*,node->_gc,lindex);
498
499 /* texture scaling params */
500 od = 2.0f;
501 id = node->outerRadius * 2.0f / node->innerRadius;
502
503 for (i=SEGMENTS_PER_CIRCLE,j=0,k=0; i >= 0; i--,j+=2,k+=8) {
504 (*fp).c[0] = node->innerRadius * (float) sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
505 (*fp).c[1] = node->innerRadius * (float) cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
506 fp++;
507 (*fp).c[0] = node->outerRadius * (float) sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
508 (*fp).c[1] = node->outerRadius * (float) cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
509 fp++;
510
511 lindex[k + 0] = j;
512 lindex[k + 1] = j+1;
513 lindex[k + 2] = j+1;
514 lindex[k + 3] = j+2;
515 lindex[k + 4] = j+2;
516 lindex[k + 5] = j;
517 lindex[k + 6] = j+1;
518 lindex[k + 7] = j+3;
519
520 (*tp).c[0] = 0.5f + ((float)sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/id);
521 (*tp).c[1] = 0.5f + ((float)cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/id);
522 tp++;
523 (*tp).c[0] = 0.5f + ((float)sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/od);
524 (*tp).c[1] = 0.5f + ((float)cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/od);
525 tp++;
526 }
527 node->__wireindices = lindex;
528 }
529
530
531 /* compiling done, set up for rendering. thread safe */
532 node->__numPoints = 0;
533 ofp = node->__points.p;
534 otp = node->__texCoords.p;
535 node->__points.p = sfp;
536 node->__texCoords.p = stp;
537 node->__simpleDisk = simpleDisc;
538 node->__numPoints = tmpint;
539 FREE_IF_NZ (ofp);
540 FREE_IF_NZ (otp);
541
542 /* we can set the extents here... */
543 node->EXTENT_MAX_X = node->outerRadius;
544 node->EXTENT_MIN_X = -node->outerRadius;
545 node->EXTENT_MAX_Y = node->outerRadius;
546 node->EXTENT_MIN_Y = -node->outerRadius;
547}
548
549void render_Disk2D (struct X3D_Disk2D *node){
550 COMPILE_IF_REQUIRED
551 if (node->__numPoints>0) {
552 struct textureVertexInfo mtf = {(GLfloat *)node->__texCoords.p,2,GL_FLOAT,0,NULL,NULL};
553 /* for BoundingBox calculations */
554 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
555 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
556
557 CULL_FACE(node->solid)
558
559 textureCoord_send(&mtf);
560 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
561
562
563 /* do the array drawing; sides are simple 0-1-2-3, 4-5-6-7, etc quads */
564 if (node->__simpleDisk) {
565 if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
566 //wireframe triangles
567 sendElementsToGPU(GL_LINES,((node->__numPoints-1)*4 -1 ),node->__wireindices); //should be segs x 2 lines/seg = (pts-1) x 2 lines / pt
568 }else{
569 sendArraysToGPU (GL_TRIANGLE_FAN, 0, node->__numPoints);
570 }
571 }
572 else{
573 if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
574 //wireframe triangles
575 sendElementsToGPU(GL_LINES,(node->__numPoints*4 -4 -1),node->__wireindices); //(nseg -1)*4 = (npts-2)*2 = npts*2 -4
576 }else{
577 sendArraysToGPU (GL_TRIANGLE_STRIP, 0, node->__numPoints);
578 }
579 }
580
581 gglobal()->Mainloop.trisThisLoop += node->__numPoints;
582 }
583}
584//rendray_Disk2D
585
586/***********************************************************************************/
587
588void compile_TriangleSet2D (struct X3D_TriangleSet2D *node){
589 /* have to regen the shape*/
590 GLfloat maxX, minX;
591 GLfloat maxY, minY;
592 GLfloat Ssize, Tsize;
593 int i,j;
594 ushort *lindex;
595 struct SFVec2f *fp; //GLfloat *fp;
596 int tmpint;
597
598 MARK_NODE_COMPILED
599
600 /* do we have vertex counts in sets of 3? */
601 if ((node->vertices.n %3) != 0) {
602 printf ("TriangleSet2D, have incorrect vertex count, %d\n",node->vertices.n);
603 node->vertices.n -= node->vertices.n % 3;
604 }
605
606 /* save this, and tell renderer that this has 0 vertices (threading stuff) */
607 tmpint = node->vertices.n;
608 node->vertices.n = 0;
609
610 /* ok, now if renderer renders (threading) it'll see zero, so we are safe */
611 FREE_IF_NZ (node->__texCoords.p);
612 node->__texCoords.p = fp = MALLOC (struct SFVec2f *, sizeof(struct SFVec2f) * (tmpint)); //MALLOC (GLfloat *, sizeof (GLfloat) * tmpint * 2);
613 node->__texCoords.n = tmpint;
614 node->__wireindices = lindex = MALLOC (ushort *, sizeof(ushort)*(tmpint+1)*2); //over malloc a bit, should be: pts = lines, lines * 2 ends/line
615 /* find min/max values for X and Y axes */
616 minY = minX = FLT_MAX;
617 maxY = maxX = -FLT_MAX;
618 for (i=0; i<tmpint; i++) {
619 if (node->vertices.p[i].c[0] < minX) minX = node->vertices.p[i].c[0];
620 if (node->vertices.p[i].c[1] < minY) minY = node->vertices.p[i].c[1];
621 if (node->vertices.p[i].c[0] > maxX) maxX = node->vertices.p[i].c[0];
622 if (node->vertices.p[i].c[1] > maxY) maxY = node->vertices.p[i].c[1];
623 }
624
625 /* save these numbers for extents */
626 node->EXTENT_MAX_X = maxX;
627 node->EXTENT_MIN_X = minX;
628 node->EXTENT_MAX_Y = maxY;
629 node->EXTENT_MIN_Y = minY;
630
631 /* printf ("minX %f maxX %f minY %f maxY %f\n",minX, maxX, minY, maxY); */
632 Ssize = maxX - minX;
633 Tsize = maxY - minY;
634 /* printf ("ssize %f tsize %f\n",Ssize, Tsize); */
635
636 for (i=0,j=0; i<tmpint/3; i++,j+=6) {
637 //wireframe indices
638 int i3 = i*3;
639 lindex[j + 0] = i3;
640 lindex[j + 1] = i3+1;
641 lindex[j + 2] = i3+1;
642 lindex[j + 3] = i3+2;
643 lindex[j + 4] = i3+2;
644 lindex[j + 5] = i3;
645 }
646
647 for (i=0; i<tmpint; i++) {
648 (*fp).c[0] = (node->vertices.p[i].c[0] - minX) / Ssize;
649 (*fp).c[1] = (node->vertices.p[i].c[1] - minY) / Tsize;
650 fp++;
651 }
652
653 /* restore, so we know how many tris there are */
654 node->vertices.n = tmpint;
655}
656
657void render_TriangleSet2D (struct X3D_TriangleSet2D *node){
658 COMPILE_IF_REQUIRED
659 if (node->vertices.n>0) {
660 struct textureVertexInfo mtf = {(GLfloat *)node->__texCoords.p,2,GL_FLOAT,0,NULL,NULL};
661 /* for BoundingBox calculations */
662 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
663 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
664
665 CULL_FACE(node->solid)
666
667 textureCoord_send(&mtf);
668 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->vertices.p);
669
670
671 if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
672 //wireframe triangles
673 sendElementsToGPU(GL_LINES,(node->vertices.n*2),node->__wireindices); //(nseg -1)*4 = (npts-2)*2 = npts*2 -4
674 }else{
675 sendArraysToGPU (GL_TRIANGLES, 0, node->vertices.n);
676 }
677
678 gglobal()->Mainloop.trisThisLoop += node->vertices.n;
679 }
680}
681//rendray_TriangleSet2D
682
683
684/***********************************************************************************/
685
686
687/* this code is remarkably like Box, but with a zero z axis. */
688void compile_Rectangle2D (struct X3D_Rectangle2D *node) {
689 float *pt;
690 struct SFVec3f *ptr;
691 float x = ((node->size).c[0])/2;
692 float y = ((node->size).c[1])/2;
693
694 MARK_NODE_COMPILED
695
696 /* MALLOC memory (if possible)*/
697 if (!node->__points.p) ptr = MALLOC (struct SFVec3f *,sizeof(struct SFVec3f)*(6));
698 else ptr = node->__points.p;
699
700 /* now, create points; 6 points per face.*/
701 pt = (float *) ptr;
702 #define PTF0 *pt++ = x; *pt++ = y; *pt++ = 0.0f;
703 #define PTF1 *pt++ = -x; *pt++ = y; *pt++ = 0.0f;
704 #define PTF2 *pt++ = -x; *pt++ = -y; *pt++ = 0.0f;
705 #define PTF3 *pt++ = x; *pt++ = -y; *pt++ = 0.0f;
706
707 PTF0 PTF1 PTF2 PTF0 PTF2 PTF3 /* front */
708 /* finished, and have good data */
709 node->__points.p = (struct SFVec3f*) ptr;
710
711 #undef PTF0
712 #undef PTF1
713 #undef PTF2
714 #undef PTF3
715}
716
717
718void render_Rectangle2D (struct X3D_Rectangle2D *node) {
719 extern GLfloat boxtex[]; /* in CFuncs/statics.c*/
720 extern GLfloat boxnorms[]; /* in CFuncs/statics.c*/
721 struct textureVertexInfo mtf = {boxtex,2,GL_FLOAT,0,NULL,NULL};
722
723 float x = ((node->size).c[0])/2;
724 float y = ((node->size).c[1])/2;
725
726 /* test for <0 of sides */
727 if ((x < 0) || (y < 0)) return;
728
729 COMPILE_IF_REQUIRED
730 if (!node->__points.p) return; /* still compiling */
731
732 /* for BoundingBox calculations */
733 setExtent(x,-x,y,-y,0.0f,0.0f,X3D_NODE(node));
734
735 CULL_FACE(node->solid)
736
737 /* Draw it; assume VERTEX and NORMALS already defined.*/
738 textureCoord_send(&mtf);
739 FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,(GLfloat *)node->__points.p);
740 FW_GL_NORMAL_POINTER (GL_FLOAT,0,boxnorms);
741
742 /* do the array drawing; sides are simple 0-1-2-3, 4-5-6-7, etc quads */
743 if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
744 //wireframe triangles
745 static ushort wireindices [] = { 0, 1, 1, 2, 2, 0, 3, 4, 4, 5, 5, 3 };
746 sendElementsToGPU(GL_LINES,6*2,wireindices); //(nseg -1)*4 = (npts-2)*2 = npts*2 -4
747 }else{
748 sendArraysToGPU (GL_TRIANGLES, 0, 6);
749 }
750 gglobal()->Mainloop.trisThisLoop += 2;
751}
752// rendray_Rectangle2D
753
754/***********************************************************************************/
755//http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/geometry2D.html#ArcClose2D
756// "the angle starts at +x and goes toward +y"
757// y^
758// | /
759// | / ) angle
760// |_____> x
761static void *createLines (float start, float end, float radius, int closed, int *size, float *_extent) {
762 int i;
763 int isCircle;
764 int numPoints;
765 GLfloat tmp;
766 GLfloat *points;
767 GLfloat *fp;
768 int arcpoints;
769
770 float myminx = FLT_MAX;
771 float mymaxx = -FLT_MAX;
772 float myminy = FLT_MAX;
773 float mymaxy = -FLT_MAX;
774
775 *size = 0;
776
777 /* is this a circle? */
778 isCircle = APPROX(start,end);
779
780 /* bounds check, and sort values */
781 if ((start < PI*2.0) || (start > PI*2.0)) start = 0.0f;
782 if ((end < PI*2.0) || (end > PI*2.0)) end = (float) (PI/2.0);
783 if (radius<0.0) radius = 1.0f;
784
785 if (end > start) {
786 tmp = start;
787 start = end;
788 end = tmp;
789 }
790
791
792 if (isCircle) {
793 numPoints = SEGMENTS_PER_CIRCLE;
794 closed = NONE; /* this is a circle, CHORD, PIE dont mean anything now */
795 } else {
796 numPoints = (int) ((float)(SEGMENTS_PER_CIRCLE * (start-end))/(PI*2.0f));
797 if (numPoints>SEGMENTS_PER_CIRCLE) numPoints=SEGMENTS_PER_CIRCLE;
798 }
799
800 /* we always have to draw the line - we have a line strip, and we calculate
801 the beginning points; we have also to calculate the ending point. */
802 numPoints++;
803 arcpoints = numPoints;
804
805 /* closure type */
806 if (closed == CHORD) numPoints+=2;
807 if (closed == PIE) numPoints+=2;
808
809 points = MALLOC (float *, sizeof(float)*numPoints*2);
810 fp = points;
811
812 for (i=0; i<arcpoints; i++) {
813 *fp = radius * cosf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
814 fp++;
815 *fp = radius * sinf(((float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
816 fp++;
817 }
818
819 /* do we have to draw any pies, cords, etc, etc? */
820 if (closed == CHORD) {
821 /* go to mid-chord */
822 *fp = .5f*(points[0] + points[(arcpoints-1)*2]);
823 fp++;
824 *fp = .5f*(points[1] + points[(arcpoints-1)*2 +1]);
825 fp++;
826
827 /* loop back to first point */
828 *fp = radius * cosf(0.0f/((float)SEGMENTS_PER_CIRCLE));
829 fp++;
830 *fp = radius * sinf(0.0f/((float)SEGMENTS_PER_CIRCLE));
831 fp++;
832 } else if (closed == PIE) {
833 /* go to origin */
834 *fp = 0.0f; fp++; *fp=0.0f; fp++;
835 /* go back to first point */
836 *fp = radius * cosf(0.0f/((float)SEGMENTS_PER_CIRCLE));
837 fp++;
838 *fp = radius * sinf(0.0f/((float)SEGMENTS_PER_CIRCLE));
839 fp++;
840 }
841
842
843 /* find extents */
844 *size = numPoints;
845 if (numPoints==0) {
846 EXTENT_MAX_X = 0.0f;
847 EXTENT_MIN_X = 0.0f;
848 EXTENT_MAX_Y = 0.0f;
849 EXTENT_MIN_Y = 0.0f;
850 } else {
851 /* find min/max for setExtent for these points */
852 fp = points;
853 for (i=0; i<numPoints; i++) {
854 /* do X first */
855 if (*fp > mymaxx) mymaxx = *fp;
856 if (*fp < myminx) myminx = *fp;
857 fp++;
858 /* do Y second */
859 if (*fp > mymaxy) mymaxy = *fp;
860 if (*fp < myminy) myminy = *fp;
861 fp++;
862 }
863 EXTENT_MIN_X = myminx;
864 EXTENT_MAX_X = mymaxx;
865 EXTENT_MIN_Y = myminy;
866 EXTENT_MAX_Y = mymaxy;
867 }
868
869 return (void *)points;
870}
871
872
873
874
875void collide_TriangleSet2D (struct X3D_TriangleSet2D *node) {
876 UNUSED (node);
877}
878
879void collide_Disk2D (struct X3D_Disk2D *node) {
880 UNUSED (node);
881}
882
883void collide_Rectangle2D (struct X3D_Rectangle2D *node) {
884 /* Modified Box code. */
885 struct sNaviInfo *naviinfo;
886 GLDOUBLE awidth, atop, abottom, astep, modelMatrix[16];
887 struct point_XYZ iv = {0,0,0};
888 struct point_XYZ jv = {0,0,0};
889 struct point_XYZ kv = {0,0,0};
890 struct point_XYZ ov = {0,0,0};
891 struct point_XYZ delta;
892
893 ttglobal tg = gglobal();
894 /*easy access, naviinfo.step unused for sphere collisions */
895 naviinfo = (struct sNaviInfo*)tg->Bindable.naviinfo;
896 awidth = naviinfo->width; /*avatar width*/
897 atop = naviinfo->width; /*top of avatar (relative to eyepoint)*/
898 abottom = -naviinfo->height; /*bottom of avatar (relative to eyepoint)*/
899 astep = -naviinfo->height+naviinfo->step;
900
901
902 iv.x = node->size.c[0];
903 jv.y = node->size.c[1];
904 kv.z = 0.0;
905 ov.x = -(node->size.c[0])/2; ov.y = -(node->size.c[1])/2; ov.z = 0.0;
906
907 /* get the transformed position of the Box, and the scale-corrected radius. */
908 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelMatrix);
909
910 matmultiplyAFFINE(modelMatrix,modelMatrix,FallInfo()->avatar2collision);
911 //dug9july2011 matmultiply(modelMatrix,FallInfo()->avatar2collision,modelMatrix);
912
913 {
914 /* minimum bounding box MBB test in avatar/collision space */
915 double shapeMBBmin[3], shapeMBBmax[3], dsize[3];
916 //int i;
917 float2double(dsize,node->size.c,3);
918 vecscaled(shapeMBBmax,dsize,.5);
919 vecscaled(shapeMBBmax,dsize,-.5);
920 //for(i=0;i<3;i++)
921 //{
922 // shapeMBBmin[i] = DOUBLE_MIN(-(node->size.c[i])*.5,node->size.c[i]*.5);
923 // shapeMBBmax[i] = DOUBLE_MAX(-(node->size.c[i])*.5,node->size.c[i]*.5);
924 //}
925 if(!avatarCollisionVolumeIntersectMBB(modelMatrix, shapeMBBmin, shapeMBBmax))return;
926 }
927 /* get transformed box edges and position */
928 transform(&ov,&ov,modelMatrix);
929 transform3x3(&iv,&iv,modelMatrix);
930 transform3x3(&jv,&jv,modelMatrix);
931 transform3x3(&kv,&kv,modelMatrix);
932
933 delta = box_disp(abottom,atop,astep,awidth,ov,iv,jv,kv);
934
935 vecscale(&delta,&delta,-1);
936
937 accumulate_disp(CollisionInfo(),delta);
938
939
940 #ifdef COLLISIONVERBOSE
941 if((fabs(delta.x) != 0. || fabs(delta.y) != 0. || fabs(delta.z) != 0.))
942 printf("COLLISION_BOX: (%f %f %f) (%f %f %f)\n",
943 ov.x, ov.y, ov.z,
944 delta.x, delta.y, delta.z
945 );
946 if((fabs(delta.x != 0.) || fabs(delta.y != 0.) || fabs(delta.z) != 0.))
947 printf("iv=(%f %f %f) jv=(%f %f %f) kv=(%f %f %f)\n",
948 iv.x, iv.y, iv.z,
949 jv.x, jv.y, jv.z,
950 kv.x, kv.y, kv.z
951 );
952 #endif
953}