33 #include <libFreeWRL.h>
35 #include "../vrml_parser/Structs.h"
36 #include "../vrml_parser/CRoutes.h"
37 #include "../main/headers.h"
39 #include "../world_script/fieldSet.h"
40 #include "../x3d_parser/Bindable.h"
41 #include "Collision.h"
42 #include "quaternion.h"
44 #include "../opengl/Frustum.h"
45 #include "../opengl/Material.h"
46 #include "../opengl/OpenGL_Utils.h"
47 #include "../input/EAIHelpers.h"
50 #include "LinearAlgebra.h"
51 #include "Component_Picking.h"
53 #include "RenderFuncs.h"
62 Stack *stack_nodesdistance;
63 Stack *stack_intersections;
64 Stack *stack_pointsinside;
66 void *Component_Picking_constructor(){
71 void Component_Picking_init(
struct tComponent_Picking *t){
74 t->prv = Component_Picking_constructor();
88 void other_PickableGroup (
struct X3D_Group *node) {}
91 void prep_PickableGroup (
struct X3D_Group *node) {}
92 void add_picksensor(
struct X3D_Node * node) {}
93 void remove_picksensor(
struct X3D_Node * node) {}
95 void push_pickablegroupdata(
void *userdata);
96 void pop_pickablegroupdata();
97 void child_PickableGroup (
struct X3D_Group *node) {
99 RETURN_FROM_CHILD_IF_NOT_FOR_ME
102 prep_sibAffectors((
struct X3D_Node*)node,&node->__sibAffectors);
107 push_pickablegroupdata(node);
109 normalChildren(node->children);
113 pop_pickablegroupdata();
114 fin_sibAffectors((
struct X3D_Node*)node,&node->__sibAffectors);
119 int overlapMBBs(GLDOUBLE *MBBmin1, GLDOUBLE *MBBmax1, GLDOUBLE *MBBmin2, GLDOUBLE* MBBmax2);
120 void transformMBB(GLDOUBLE *rMBBmin, GLDOUBLE *rMBBmax, GLDOUBLE *matTransform, GLDOUBLE* inMBBmin, GLDOUBLE* inMBBmax);
178 int ntries, nmatches, iallsensor, ialltarget,inonetarget;
179 int i,j,iret = FALSE;
181 ntries = nmatches = iallsensor = ialltarget = inonetarget = 0;
182 for(j=0;j<list2->n;j++){
183 if(!strcmp(list2->p[j]->strptr,
"ALL")) ialltarget = TRUE;
184 if(!strcmp(list2->p[j]->strptr,
"NONE")) inonetarget = TRUE;
187 for(i=0;i<list1->n;i++){
188 if(!strcmp(list1->p[i]->strptr,
"ALL")) iallsensor = TRUE;
189 for(j=0;j<list2->n;j++){
191 if(!strcmp(list1->p[i]->strptr,list2->p[j]->strptr)) {
196 if(!strcmp(criterion->strptr,
"MATCH_ANY")){
197 if(nmatches) iret = TRUE;
198 }
else if(!strcmp(criterion->strptr,
"MATCH_ALL")){
199 if(nmatches == ntries) iret = TRUE;
200 }
else if(!strcmp(criterion->strptr,
"MATCH_ONE")){
201 if(nmatches == 1) iret = TRUE;
203 if(iallsensor || ialltarget) iret = TRUE;
204 if(inonetarget) iret = FALSE;
207 int isGeometryNode(
struct X3D_Node* node){
210 struct X3D_Virt *virt = virtTable[node->_nodeType];
211 if(virt->rend || virt->rendray) iret = TRUE;
223 int compare_nodedistance(
const void *elem1,
const void * elem2 )
227 return nd1->dist < nd2->dist ? -1 : nd1->dist > nd2->dist ? 1 : 0;
229 int compare_intersectiondistance(
const void *elem1,
const void * elem2){
232 return nd1->dist < nd2->dist ? -1 : nd1->dist > nd2->dist ? 1 : 0;
234 void do_PickSensorTick(
void *ptr){
238 struct X3D_Node *unode,*menode, *pnode;
245 switch(node->_nodeType){
246 case NODE_LinePickSensor:
247 case NODE_PointPickSensor:
248 case NODE_PrimitivePickSensor:
249 case NODE_VolumePickSensor:
257 if (node->__oldEnabled != node->enabled) {
258 node->__oldEnabled = node->enabled;
262 if (!node->enabled)
return;
265 printf (
"do_TransformSensorTick enabled\n");
271 unodes = &node->pickTarget;
273 pnode = node->pickingGeometry;
277 if(unodes->n && pnode){
280 while((mehit = usehit_next(menode,mehit))){
283 double meinv[16],memin[3],memax[3];
284 float emin[3], emax[3];
286 matinverseAFFINE(meinv,mehit->mvm);
293 matmultiplyAFFINE(ident,meinv,mehit->mvm);
295 printf(
"inverse check do_TransformSensor\n");
297 for(j=0;j<4;j++) printf(
"%lf ",ident[i*3+j]);
305 emin[i] = pnode->_extent[i*2 + 1];
306 emax[i] = pnode->_extent[i*2];
310 node->_extent[i*2 + 1] = emin[i];
311 node->_extent[i*2] = emax[i];
315 memin[i] = node->_extent[i*2 + 1];
316 memax[i] = node->_extent[i*2];
320 p->stack_intersections->n = 0;
321 p->stack_nodesdistance->n = 0;
322 p->stack_pointsinside->n = 0;
324 for(j=0;j<unodes->n;j++){
325 unode = unodes->p[j];
326 while((uhit = usehit_next(unode,uhit))){
329 int intypes,pickable;
330 double u2me[16], me2u[16], umin[3],umax[3],uumin[3],uumax[3];
337 pickable = pgroup->pickable;
338 intypes = objecttypes_overlap(&node->objectType,&pgroup->objectType,node->matchCriterion);
340 if(intypes && pickable){
341 matmultiplyAFFINE(u2me,uhit->mvm,meinv);
342 matinverseAFFINE(me2u,u2me);
350 umin[i] = unode->_extent[i*2 + 1];
351 umax[i] = unode->_extent[i*2];
353 transformMBB(uumin,uumax,u2me,umin,umax);
355 if( overlapMBBs(memin, memax, uumin, uumax) ){
361 if(!strcmp(node->intersectionType->strptr,
"BOUNDS") || unode->_nodeType == NODE_Inline){
363 double c1[3],c2[3],dd[3];
365 vecaddd(c1,memin,memax);
367 vecaddd(c2,umin,umax);
370 ndist.dist = (float)veclengthd(dd);
372 stack_push(
struct nodedistance,p->stack_nodesdistance,ndist);
374 }
else if(!strcmp(node->intersectionType->strptr,
"GEOMETRY")){
388 double viewMatrix[16];
393 if(isGeometryNode(unode)){
394 double matidentity[16];
395 loadIdentityMatrix(matidentity);
396 usehitB_add2(unode,matidentity,pgroup);
397 loadIdentityMatrix(viewMatrix);
401 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, viewMatrix);
402 render_hier(unode, VF_Geom | VF_Picking);
404 usehitB = getUseHitBStack();
405 for(m=0;m<vectorSize(usehitB);m++){
407 double u2meg[16], me2ug[16];
414 double viewinv[16], world2geom[16];
416 matinverseAFFINE(viewinv,viewMatrix);
418 matmultiply(world2geom,viewinv,ghit->mvm);
419 matmultiplyAFFINE(me2ug,world2geom,me2u);
420 matinverseAFFINE(u2meg,me2ug);
424 switch(node->_nodeType){
425 case NODE_LinePickSensor:
434 float *segments = NULL;
436 float cumdist = 0.0f;
437 int ik, cumcount = 0;
440 switch(pnode->_nodeType){
441 case NODE_IndexedLineSet:
446 segments = MALLOC(
float*,lnode->coordIndex.n * 2 * 3 *
sizeof(
float));
448 for(ik=0;ik<lnode->coordIndex.n;ik++){
449 if(lnode->coordIndex.p[ik] == -1)
continue;
450 if(lnode->coordIndex.p[ik+1] == -1)
continue;
451 veccopy3f(&segments[6*nseg +0],&points[3*lnode->coordIndex.p[ik]]);
452 veccopy3f(&segments[6*nseg +1],&points[3*lnode->coordIndex.p[ik+1]]);
461 int kk,ik,jk, nn = 0;
462 for(ik=0;ik<lnode->vertexCount.n;ik++)
463 nn += lnode->vertexCount.p[ik];
464 segments = MALLOC(
float*,nn * 2 * 3 *
sizeof(
float));
467 for(ik=0;ik<lnode->vertexCount.n;ik++){
468 for(jk=0;jk<lnode->vertexCount.p[ik]-1;jk++){
469 veccopy3f(&segments[6*nseg +0],&points[3*(kk+jk)]);
470 veccopy3f(&segments[6*nseg +3],&points[3*(kk+jk+1)]);
473 kk+= lnode->vertexCount.p[ik];
483 for(ik=0;ik<nseg;ik++){
486 veccopy3f(p1, &segments[6*ik]);
487 veccopy3f(p2,&segments[6*ik+3]);
488 float2double(dd,p1,3);
489 transformAFFINEd(dd,dd,me2ug);
490 double2float(p1,dd,3);
491 float2double(dd,p2,3);
492 transformAFFINEd(dd,dd,me2ug);
493 double2float(p2,dd,3);
496 if(intersect_polyrep2(ghit->node, p1, p2, p->stack_intersections )){
499 for(jk=cumcount;jk<p->stack_intersections->n;jk++){
501 iinfo->dist += cumdist;
502 float2double(dd,iinfo->p,3);
503 transformAFFINEd(dd,dd,u2meg);
506 double2float(iinfo->p,dd,3);
507 float2double(dd,iinfo->normal,3);
508 transformUPPER3X3d(dd,dd,u2meg);
509 double2float(iinfo->normal,dd,3);
511 cumdist += veclength3f(vecdif3f(delta,p2, p1));
512 cumcount = p->stack_intersections->n;
523 qsort(p->stack_intersections->data,p->stack_intersections->n,
sizeof(
struct intersection_info), compare_intersectiondistance );
525 ndist.dist = iinfo->dist;
527 stack_push(
struct nodedistance,p->stack_nodesdistance,ndist);
530 FREE_IF_NZ(segments);
533 case NODE_PointPickSensor:
541 int npoints,cumcount,ik;
544 points = (
float*)cc->point.p;
545 npoints = cc->point.n;
549 for(ik=0;ik<npoints;ik++){
554 veccopy3f(p1, &points[3*ik]);
555 float2double(dd,p1,3);
556 transformAFFINEd(dd,dd,me2ug);
557 double2float(p1,dd,3);
559 p2[3] = unode->_extent[4] - 1.0f;
563 if((ixcount = intersect_polyrep2(ghit->node, p1, p2, p->stack_intersections ))){
568 double c1[3], pointdist;
571 vecaddd(c1,memin,memax);
573 double2float(delta,c1,3);
574 pointdist = veclength3f(vecdif3f(delta,delta,p1));
575 iinfo.dist = (float)pointdist;
576 veccopy3f(iinfo.p,&points[3*ik]);
586 stack_push(
struct nodedistance,p->stack_nodesdistance,ndist);
591 case NODE_PrimitivePickSensor:
599 float *points = pr->actualCoord;
600 int ik, npts = pr->ntri;
603 for(ik=0;ik<npts;ik++){
606 float2double(dd,&points[ik*3],3);
607 transformAFFINEd(dd,dd,u2meg);
608 double2float(pp,dd,3);
609 switch(pnode->_nodeType){
615 R = cone->bottomRadius;
616 if(pp[1] >= -H/2.0f && pp[1] < H/2.0f){
618 h = pp[1] - (-H/2.0f);
622 rp = veclength2f(xz);
626 float apex[3], delta[3], conedist;
628 apex[0] = apex[2] = 0.0f;
629 conedist = veclength3f(vecdif3f(delta,pp,apex));
630 iinfo.dist = conedist;
631 veccopy3f(iinfo.p,pp);
645 if(pp[1] >= -H/2.0f && pp[1] < H/2.0f){
650 rp = veclength2f(xz);
654 iinfo.dist = veclength3f(pp);
655 veccopy3f(iinfo.p,pp);
666 rp = veclength3f(pp);
671 veccopy3f(iinfo.p,pp);
683 inside = inside && pp[im] >= -box->size.c[im] && pp[im] <= box->size.c[im];
686 iinfo.dist = veclength3f(pp);
687 veccopy3f(iinfo.p,pp);
696 cumcount = p->stack_pointsinside->n;
701 qsort(p->stack_intersections->data,p->stack_intersections->n,
sizeof(
struct intersection_info), compare_intersectiondistance );
704 ndist.dist = iinfo->dist;
706 stack_push(
struct nodedistance,p->stack_nodesdistance,ndist);
713 case NODE_VolumePickSensor:
723 float *points = pr->actualCoord;
727 for(ik=0;ik<npts;ik++){
730 float2double(dd,&points[ik*3],3);
731 transformAFFINEd(dd,dd,u2meg);
732 double2float(pp,dd,3);
739 p2[3] = menode->_extent[4] - 1.0f;
743 if((ixcount = intersect_polyrep2(pnode, p1, p2, p->stack_intersections ))){
748 double c1[3], pointdist;
751 vecaddd(c1,memin,memax);
753 double2float(delta,c1,3);
754 pointdist = veclength3f(vecdif3f(delta,delta,p1));
755 iinfo.dist = (float) pointdist;
756 veccopy3f(iinfo.p,&points[3*ik]);
763 cumcount = p->stack_pointsinside->n;
768 qsort(p->stack_intersections->data,p->stack_intersections->n,
sizeof(
struct intersection_info), compare_intersectiondistance );
771 ndist.dist = iinfo->dist;
773 stack_push(
struct nodedistance,p->stack_nodesdistance,ndist);
793 if (!node->isActive) {
795 printf (
"transformensor - now active\n");
802 if(!strcmp(node->sortOrder->strptr,
"ANY")){
804 node->pickedGeometry.p = realloc(node->pickedGeometry.p,1 *
sizeof(
struct X3D_Node*));
805 ndist = vector_get_ptr(
struct nodedistance,p->stack_nodesdistance,0);
806 node->pickedGeometry.p[0] = ndist->node;
807 }
else if(!strcmp(node->sortOrder->strptr,
"ALL")){
810 node->pickedGeometry.p = realloc(node->pickedGeometry.p,p->stack_nodesdistance->n *
sizeof(
struct X3D_Node*));
811 for(ii=0;ii<p->stack_nodesdistance->n;ii++){
812 ndist = vector_get_ptr(
struct nodedistance,p->stack_nodesdistance,0);
813 node->pickedGeometry.p[ii] = ndist->node;
816 }
else if(!strcmp(node->sortOrder->strptr,
"ALL_SORTED")){
829 qsort(p->stack_nodesdistance->data,p->stack_nodesdistance->n,
sizeof(
struct nodedistance), compare_nodedistance );
830 node->pickedGeometry.p = realloc(node->pickedGeometry.p,p->stack_nodesdistance->n *
sizeof(
struct X3D_Node*));
831 for(ii=0;ii<p->stack_nodesdistance->n;ii++){
832 ndist = vector_get_ptr(
struct nodedistance,p->stack_nodesdistance,0);
833 node->pickedGeometry.p[ii] = ndist->node;
835 }
else if(!strcmp(node->sortOrder->strptr,
"CLOSEST")){
838 qsort(p->stack_nodesdistance->data,p->stack_nodesdistance->n,
sizeof(
struct nodedistance), compare_nodedistance );
839 node->pickedGeometry.p = realloc(node->pickedGeometry.p,1 *
sizeof(
struct X3D_Node*));
840 ndist = vector_get_ptr(
struct nodedistance,p->stack_nodesdistance,0);
841 node->pickedGeometry.p[0] = ndist->node;
848 switch(node->_nodeType){
849 case NODE_LinePickSensor:
853 lnode->pickedPoint.n = p->stack_intersections->n;
854 lnode->pickedNormal.n = p->stack_intersections->n;
855 lnode->pickedTextureCoordinate.n = p->stack_intersections->n;
856 lnode->pickedPoint.p = realloc(lnode->pickedPoint.p,lnode->pickedPoint.n * 3 *
sizeof(
float));
857 lnode->pickedNormal.p = realloc(lnode->pickedNormal.p,lnode->pickedPoint.n * 3 *
sizeof(
float));
858 lnode->pickedTextureCoordinate.p = realloc(lnode->pickedTextureCoordinate.p,lnode->pickedPoint.n * 3 *
sizeof(
float));
859 for(ik=0;ik<p->stack_intersections->n;ik++){
861 veccopy3f(lnode->pickedPoint.p[ik].c,iinfo->p);
862 veccopy3f(lnode->pickedNormal.p[ik].c,iinfo->normal);
863 veccopy3f(lnode->pickedTextureCoordinate.p[ik].c,iinfo->texcoord);
870 case NODE_PointPickSensor:
875 lnode->pickedPoint.n = p->stack_pointsinside->n;
876 lnode->pickedPoint.p = realloc(lnode->pickedPoint.p,lnode->pickedPoint.n * 3 *
sizeof(
float));
877 for(ik=0;ik<p->stack_pointsinside->n;ik++){
879 veccopy3f(lnode->pickedPoint.p[ik].c,iinfo->p);
884 case NODE_PrimitivePickSensor:
886 case NODE_VolumePickSensor:
894 if (node->isActive) {
896 printf (
"transformsensor - going inactive\n");
906 for(i=0;i<unodes->n;i++)
907 unodes->p[i]->_renderFlags |= VF_USE;
909 node->_renderFlags |= VF_USE;