35 #include <libFreeWRL.h>
37 #include "../vrml_parser/Structs.h"
38 #include "../main/headers.h"
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"
48 #include "Component_Shape.h"
49 #include "../scenegraph/RenderFuncs.h"
52 #if defined(_MSC_VER) && _MSC_VER < 1500
56 #define SEGMENTS_PER_CIRCLE 36
61 static void *createLines (
float start,
float end,
float radius,
int closed,
int *size,
float *_extent);
63 #define COMPILE_AND_GET_BOUNDS(myType,myField) \
64 void compile_##myType (struct X3D_##myType *node){ \
65 float myminx = FLT_MAX; \
66 float mymaxx = -FLT_MAX; \
67 float myminy = FLT_MAX; \
68 float mymaxy = -FLT_MAX; \
71 if (node->myField.n<=0) { \
72 node->EXTENT_MIN_X = 0.0f; \
73 node->EXTENT_MAX_X = 0.0f; \
74 node->EXTENT_MIN_Y = 0.0f; \
75 node->EXTENT_MAX_Y = 0.0f; \
77 for (count = 0; count < node->myField.n; count++) { \
78 if (node->myField.p[count].c[0] > mymaxx) mymaxx = node->myField.p[count].c[0]; \
79 if (node->myField.p[count].c[0] < myminx) myminx = node->myField.p[count].c[0]; \
80 if (node->myField.p[count].c[1] > mymaxy) mymaxy = node->myField.p[count].c[1]; \
81 if (node->myField.p[count].c[1] < myminy) myminy = node->myField.p[count].c[1]; \
83 node->EXTENT_MAX_X = mymaxx; \
84 node->EXTENT_MIN_X = myminx; \
85 node->EXTENT_MAX_Y = mymaxy; \
86 node->EXTENT_MIN_Y = myminy; \
93 void compile_Arc2D (
struct X3D_Arc2D *node) {
95 struct SFVec2f *tmpptr_a, *tmpptr_b;
101 tmpptr_a = createLines (node->startAngle, node->endAngle, node->radius, NONE, &tmpint, node->_extent);
104 node->__numPoints = 0;
105 tmpptr_b = node->__points.p;
106 node->__points.p = tmpptr_a;
107 node->__numPoints = tmpint;
108 FREE_IF_NZ (tmpptr_b);
113 void render_Arc2D (
struct X3D_Arc2D *node) {
116 if (node->__numPoints>0) {
118 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
119 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
124 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
125 sendArraysToGPU (GL_LINE_STRIP, 0, node->__numPoints);
126 tg->Mainloop.trisThisLoop += node->__numPoints;
135 struct SFVec2f *tmpptr_a, *tmpptr_b;
141 ct = node->closureType->strptr;
146 if (strcmp(ct,
"PIE") == 0) {
147 tmpptr_a = createLines (node->startAngle,
148 node->endAngle, node->radius, PIE, &tmpint,node->_extent);
149 }
else if (strcmp(ct,
"CHORD") == 0) {
150 tmpptr_a = createLines (node->startAngle,
151 node->endAngle, node->radius, CHORD, &tmpint,node->_extent);
153 printf (
"ArcClose2D, closureType %s invalid\n",node->closureType->strptr);
157 node->__numPoints = 0;
158 tmpptr_b = node->__points.p;
159 node->__points.p = tmpptr_a;
160 node->__numPoints = tmpint;
161 FREE_IF_NZ (tmpptr_b);
169 if (node->__numPoints>0) {
171 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
172 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
178 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
179 sendArraysToGPU (GL_LINE_STRIP, 0, node->__numPoints);
181 gglobal()->Mainloop.trisThisLoop += node->__numPoints;
189 struct SFVec2f *tmpptr_a, *tmpptr_b;
195 tmpptr_a = createLines (0.0f, 0.0f, node->radius, NONE, &tmpint,node->_extent);
198 node->__numPoints = 0;
199 tmpptr_b = node->__points.p;
200 node->__points.p = tmpptr_a;
201 node->__numPoints = tmpint;
202 FREE_IF_NZ (tmpptr_b);
209 if (node->__numPoints>0) {
211 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
212 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
217 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
218 sendArraysToGPU (GL_LINE_STRIP, 0, node->__numPoints);
219 gglobal()->Mainloop.trisThisLoop += node->__numPoints;
226 COMPILE_AND_GET_BOUNDS(Polyline2D,lineSegments)
232 if (node->lineSegments.n>0) {
234 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
235 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
241 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->lineSegments.p);
242 sendArraysToGPU (GL_LINE_STRIP, 0, node->lineSegments.n);
243 gglobal()->Mainloop.trisThisLoop += node->lineSegments.n;
249 COMPILE_AND_GET_BOUNDS(Polypoint2D,point)
255 if (node->point.n>0) {
257 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
258 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
264 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->point.p);
265 sendArraysToGPU (GL_POINTS, 0, node->point.n);
266 gglobal()->Mainloop.trisThisLoop += node->point.n;
271 #define DESIRE(whichOne,zzz) ((whichOne & zzz)==zzz)
272 void compile_Disk2D (
struct X3D_Disk2D *node){
291 if (node->innerRadius<0) {node->__numPoints = 0;
return;}
292 if (node->outerRadius<0) {node->__numPoints = 0;
return;}
295 if ((APPROX (node->innerRadius, 0.0)) ||
296 (APPROX(node->innerRadius,node->outerRadius))) simpleDisc = TRUE;
297 else simpleDisc = FALSE;
301 tmpint = SEGMENTS_PER_CIRCLE+2;
302 fp = sfp = MALLOC (
struct SFVec2f *,
sizeof(
struct SFVec2f) * (tmpint));
303 tp = stp = MALLOC (
struct SFVec2f *,
sizeof(
struct SFVec2f) * (tmpint));
304 lindex = MALLOC (ushort *,
sizeof(ushort) * (tmpint*2)*2);
309 (*fp).c[0] = 0.0f; (*fp).c[1] = 0.0f; fp++;
310 (*tp).c[0] = 0.5f; (*tp).c[1] = 0.5f; tp++;
313 for (i=SEGMENTS_PER_CIRCLE,j=1,k=0; i >= 0; i--,j++,k+=4) {
314 (*fp).c[0] = node->outerRadius * sinf(((
float)PI * 2.0f * (
float)i)/((
float)SEGMENTS_PER_CIRCLE));
315 (*fp).c[1] = node->outerRadius * cosf(((
float)PI * 2.0f * (
float)i)/((
float)SEGMENTS_PER_CIRCLE));
323 (*tp).c[0] = 0.5f + (sinf(((
float)PI * 2.0f * (
float)i)/((
float)SEGMENTS_PER_CIRCLE))/id);
324 (*tp).c[1] = 0.5f + (cosf(((
float)PI * 2.0f * (
float)i)/((
float)SEGMENTS_PER_CIRCLE))/id);
327 node->__wireindices = lindex;
329 tmpint = (SEGMENTS_PER_CIRCLE+1) * 2;
330 fp = sfp = MALLOC (
struct SFVec2f *,
sizeof(
struct SFVec2f) * 2 * tmpint);
331 tp = stp = MALLOC (
struct SFVec2f *,
sizeof(
struct SFVec2f) * (tmpint));
332 lindex = MALLOC (ushort *,
sizeof(ushort) * (tmpint*2) *2);
338 id = node->outerRadius * 2.0f / node->innerRadius;
340 for (i=SEGMENTS_PER_CIRCLE,j=0,k=0; i >= 0; i--,j+=2,k+=8) {
341 (*fp).c[0] = node->innerRadius * (float) sinf(((
float)PI * 2.0f * (
float)i)/((float)SEGMENTS_PER_CIRCLE));
342 (*fp).c[1] = node->innerRadius * (float) cosf(((
float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
344 (*fp).c[0] = node->outerRadius * (float) sinf(((
float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
345 (*fp).c[1] = node->outerRadius * (float) cosf(((
float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE));
357 (*tp).c[0] = 0.5f + ((float)sinf(((
float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/
id);
358 (*tp).c[1] = 0.5f + ((float)cosf(((
float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/
id);
360 (*tp).c[0] = 0.5f + ((float)sinf(((
float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/od);
361 (*tp).c[1] = 0.5f + ((float)cosf(((
float)PI * 2.0f * (float)i)/((float)SEGMENTS_PER_CIRCLE))/od);
364 node->__wireindices = lindex;
369 node->__numPoints = 0;
370 ofp = node->__points.p;
371 otp = node->__texCoords.p;
372 node->__points.p = sfp;
373 node->__texCoords.p = stp;
374 node->__simpleDisk = simpleDisc;
375 node->__numPoints = tmpint;
380 node->EXTENT_MAX_X = node->outerRadius;
381 node->EXTENT_MIN_X = -node->outerRadius;
382 node->EXTENT_MAX_Y = node->outerRadius;
383 node->EXTENT_MIN_Y = -node->outerRadius;
388 if (node->__numPoints>0) {
389 struct textureVertexInfo mtf = {(GLfloat *)node->__texCoords.p,2,GL_FLOAT,0,NULL,NULL};
391 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
392 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
394 CULL_FACE(node->solid)
396 textureCoord_send(&mtf);
397 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->__points.p);
401 if (node->__simpleDisk) {
402 if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
404 sendElementsToGPU(GL_LINES,((node->__numPoints-1)*4 -1 ),node->__wireindices);
406 sendArraysToGPU (GL_TRIANGLE_FAN, 0, node->__numPoints);
410 if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
412 sendElementsToGPU(GL_LINES,(node->__numPoints*4 -4 -1),node->__wireindices);
414 sendArraysToGPU (GL_TRIANGLE_STRIP, 0, node->__numPoints);
418 gglobal()->Mainloop.trisThisLoop += node->__numPoints;
429 GLfloat Ssize, Tsize;
438 if ((node->vertices.n %3) != 0) {
439 printf (
"TriangleSet2D, have incorrect vertex count, %d\n",node->vertices.n);
440 node->vertices.n -= node->vertices.n % 3;
444 tmpint = node->vertices.n;
445 node->vertices.n = 0;
448 FREE_IF_NZ (node->__texCoords.p);
449 node->__texCoords.p = fp = MALLOC (
struct SFVec2f *,
sizeof(
struct SFVec2f) * (tmpint));
450 node->__texCoords.n = tmpint;
451 node->__wireindices = lindex = MALLOC (ushort *,
sizeof(ushort)*(tmpint+1)*2);
453 minY = minX = FLT_MAX;
454 maxY = maxX = -FLT_MAX;
455 for (i=0; i<tmpint; i++) {
456 if (node->vertices.p[i].c[0] < minX) minX = node->vertices.p[i].c[0];
457 if (node->vertices.p[i].c[1] < minY) minY = node->vertices.p[i].c[1];
458 if (node->vertices.p[i].c[0] > maxX) maxX = node->vertices.p[i].c[0];
459 if (node->vertices.p[i].c[1] > maxY) maxY = node->vertices.p[i].c[1];
463 node->EXTENT_MAX_X = maxX;
464 node->EXTENT_MIN_X = minX;
465 node->EXTENT_MAX_Y = maxY;
466 node->EXTENT_MIN_Y = minY;
473 for (i=0,j=0; i<tmpint/3; i++,j+=6) {
477 lindex[j + 1] = i3+1;
478 lindex[j + 2] = i3+1;
479 lindex[j + 3] = i3+2;
480 lindex[j + 4] = i3+2;
484 for (i=0; i<tmpint; i++) {
485 (*fp).c[0] = (node->vertices.p[i].c[0] - minX) / Ssize;
486 (*fp).c[1] = (node->vertices.p[i].c[1] - minY) / Tsize;
491 node->vertices.n = tmpint;
496 if (node->vertices.n>0) {
497 struct textureVertexInfo mtf = {(GLfloat *)node->__texCoords.p,2,GL_FLOAT,0,NULL,NULL};
499 setExtent( node->EXTENT_MAX_X, node->EXTENT_MIN_X,
500 node->EXTENT_MAX_Y, node->EXTENT_MIN_Y, 0.0f,0.0f,X3D_NODE(node));
502 CULL_FACE(node->solid)
504 textureCoord_send(&mtf);
505 FW_GL_VERTEX_POINTER (2,GL_FLOAT,0,(GLfloat *)node->vertices.p);
508 if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
510 sendElementsToGPU(GL_LINES,(node->vertices.n*2),node->__wireindices);
512 sendArraysToGPU (GL_TRIANGLES, 0, node->vertices.n);
515 gglobal()->Mainloop.trisThisLoop += node->vertices.n;
528 float x = ((node->size).c[0])/2;
529 float y = ((node->size).c[1])/2;
534 if (!node->__points.p) ptr = MALLOC (
struct SFVec3f *,
sizeof(
struct SFVec3f)*(6));
535 else ptr = node->__points.p;
539 #define PTF0 *pt++ = x; *pt++ = y; *pt++ = 0.0f;
540 #define PTF1 *pt++ = -x; *pt++ = y; *pt++ = 0.0f;
541 #define PTF2 *pt++ = -x; *pt++ = -y; *pt++ = 0.0f;
542 #define PTF3 *pt++ = x; *pt++ = -y; *pt++ = 0.0f;
544 PTF0 PTF1 PTF2 PTF0 PTF2 PTF3
546 node->__points.p = (
struct SFVec3f*) ptr;
556 extern GLfloat boxtex[];
557 extern GLfloat boxnorms[];
560 float x = ((node->size).c[0])/2;
561 float y = ((node->size).c[1])/2;
564 if ((x < 0) || (y < 0))
return;
567 if (!node->__points.p)
return;
570 setExtent(x,-x,y,-y,0.0f,0.0f,X3D_NODE(node));
572 CULL_FACE(node->solid)
575 textureCoord_send(&mtf);
576 FW_GL_VERTEX_POINTER (3,GL_FLOAT,0,(GLfloat *)node->__points.p);
577 FW_GL_NORMAL_POINTER (GL_FLOAT,0,boxnorms);
580 if(DESIRE(getShaderFlags().base,SHADINGSTYLE_WIRE)){
582 static ushort wireindices [] = { 0, 1, 1, 2, 2, 0, 3, 4, 4, 5, 5, 3 };
583 sendElementsToGPU(GL_LINES,6*2,wireindices);
585 sendArraysToGPU (GL_TRIANGLES, 0, 6);
587 gglobal()->Mainloop.trisThisLoop += 2;
598 static void *createLines (
float start,
float end,
float radius,
int closed,
int *size,
float *_extent) {
607 float myminx = FLT_MAX;
608 float mymaxx = -FLT_MAX;
609 float myminy = FLT_MAX;
610 float mymaxy = -FLT_MAX;
615 isCircle = APPROX(start,end);
618 if ((start < PI*2.0) || (start > PI*2.0)) start = 0.0f;
619 if ((end < PI*2.0) || (end > PI*2.0)) end = (float) (PI/2.0);
620 if (radius<0.0) radius = 1.0f;
630 numPoints = SEGMENTS_PER_CIRCLE;
633 numPoints = (int) ((
float)(SEGMENTS_PER_CIRCLE * (start-end))/(PI*2.0f));
634 if (numPoints>SEGMENTS_PER_CIRCLE) numPoints=SEGMENTS_PER_CIRCLE;
640 arcpoints = numPoints;
643 if (closed == CHORD) numPoints++;
644 if (closed == PIE) numPoints+=2;
646 points = MALLOC (
float *,
sizeof(
float)*numPoints*2);
649 for (i=0; i<arcpoints; i++) {
650 *fp = radius * cosf(((
float)PI * 2.0f * (
float)i)/((
float)SEGMENTS_PER_CIRCLE));
652 *fp = radius * sinf(((
float)PI * 2.0f * (
float)i)/((
float)SEGMENTS_PER_CIRCLE));
657 if (closed == CHORD) {
659 *fp = radius * cosf(0.0f/((
float)SEGMENTS_PER_CIRCLE));
661 *fp = radius * sinf(0.0f/((
float)SEGMENTS_PER_CIRCLE));
663 }
else if (closed == PIE) {
665 *fp = 0.0f; fp++; *fp=0.0f; fp++;
666 *fp = radius * cosf(0.0f/((
float)SEGMENTS_PER_CIRCLE));
668 *fp = radius * sinf(0.0f/((
float)SEGMENTS_PER_CIRCLE));
683 for (i=0; i<numPoints; i++) {
685 if (*fp > mymaxx) mymaxx = *fp;
686 if (*fp < myminx) myminx = *fp;
689 if (*fp > mymaxy) mymaxy = *fp;
690 if (*fp < myminy) myminy = *fp;
693 EXTENT_MIN_X = myminx;
694 EXTENT_MAX_X = mymaxx;
695 EXTENT_MIN_Y = myminy;
696 EXTENT_MAX_Y = mymaxy;
699 return (
void *)points;
709 void collide_Disk2D (
struct X3D_Disk2D *node) {
716 GLDOUBLE awidth, atop, abottom, astep, modelMatrix[16];
725 naviinfo = (
struct sNaviInfo*)tg->Bindable.naviinfo;
726 awidth = naviinfo->width;
727 atop = naviinfo->width;
728 abottom = -naviinfo->height;
729 astep = -naviinfo->height+naviinfo->step;
732 iv.x = node->size.c[0];
733 jv.y = node->size.c[1];
735 ov.x = -((node->size).c[0])/2; ov.y = -((node->size).c[1])/2; ov.z = 0.0;
738 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, modelMatrix);
740 matmultiplyAFFINE(modelMatrix,modelMatrix,FallInfo()->avatar2collision);
745 GLDOUBLE shapeMBBmin[3], shapeMBBmax[3];
749 shapeMBBmin[i] = DOUBLE_MIN(-(node->size).c[i]*.5,(node->size).c[i]*.5);
750 shapeMBBmax[i] = DOUBLE_MAX(-(node->size).c[i]*.5,(node->size).c[i]*.5);
752 if(!avatarCollisionVolumeIntersectMBB(modelMatrix, shapeMBBmin, shapeMBBmax))
return;
755 transform(&ov,&ov,modelMatrix);
756 transform3x3(&iv,&iv,modelMatrix);
757 transform3x3(&jv,&jv,modelMatrix);
758 transform3x3(&kv,&kv,modelMatrix);
760 delta = box_disp(abottom,atop,astep,awidth,ov,iv,jv,kv);
762 vecscale(&delta,&delta,-1);
764 accumulate_disp(CollisionInfo(),delta);
767 #ifdef COLLISIONVERBOSE
768 if((fabs(delta.x) != 0. || fabs(delta.y) != 0. || fabs(delta.z) != 0.))
769 printf(
"COLLISION_BOX: (%f %f %f) (%f %f %f)\n",
771 delta.x, delta.y, delta.z
773 if((fabs(delta.x != 0.) || fabs(delta.y != 0.) || fabs(delta.z) != 0.))
774 printf(
"iv=(%f %f %f) jv=(%f %f %f) kv=(%f %f %f)\n",