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"
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;
65}* ppComponent_Picking;
66void *Component_Picking_constructor(){
71void Component_Picking_init(
struct tComponent_Picking *t){
74 t->prv = Component_Picking_constructor();
76 ppComponent_Picking p = (ppComponent_Picking)t->prv;
88void other_PickableGroup (
struct X3D_Group *node) {}
91void prep_PickableGroup (
struct X3D_Group *node) {}
92void add_picksensor(
struct X3D_Node * node) {}
93void remove_picksensor(
struct X3D_Node * node) {}
95void push_pickablegroupdata(
void *userdata);
96void pop_pickablegroupdata();
99 int nc = node->children.n;
100 RETURN_FROM_CHILD_IF_NOT_FOR_ME
102 prep_sibAffectors((
struct X3D_Node*)node,&node->__sibAffectors);
103 prep_BBox((
struct BBoxFields*)&node->bboxCenter);
107 push_pickablegroupdata(node);
109 normalChildren(node->children);
113 pop_pickablegroupdata();
116 fin_sibAffectors((
struct X3D_Node*)node,&node->__sibAffectors);
121int overlapMBBs(GLDOUBLE *MBBmin1, GLDOUBLE *MBBmax1, GLDOUBLE *MBBmin2, GLDOUBLE* MBBmax2);
122void transformMBB(GLDOUBLE *rMBBmin, GLDOUBLE *rMBBmax, GLDOUBLE *matTransform, GLDOUBLE* inMBBmin, GLDOUBLE* inMBBmax);
180 int ntries, nmatches, iallsensor, ialltarget,inonetarget;
181 int i,j,iret = FALSE;
183 ntries = nmatches = iallsensor = ialltarget = inonetarget = 0;
184 for(j=0;j<list2->n;j++){
185 if(!strcmp(list2->p[j]->strptr,
"ALL")) ialltarget = TRUE;
186 if(!strcmp(list2->p[j]->strptr,
"NONE")) inonetarget = TRUE;
189 for(i=0;i<list1->n;i++){
190 if(!strcmp(list1->p[i]->strptr,
"ALL")) iallsensor = TRUE;
191 for(j=0;j<list2->n;j++){
193 if(!strcmp(list1->p[i]->strptr,list2->p[j]->strptr)) {
198 if(!strcmp(criterion->strptr,
"MATCH_ANY")){
199 if(nmatches) iret = TRUE;
200 }
else if(!strcmp(criterion->strptr,
"MATCH_ALL")){
201 if(nmatches == ntries) iret = TRUE;
202 }
else if(!strcmp(criterion->strptr,
"MATCH_ONE")){
203 if(nmatches == 1) iret = TRUE;
205 if(iallsensor || ialltarget) iret = TRUE;
206 if(inonetarget) iret = FALSE;
209int isGeometryNode(
struct X3D_Node* node){
212 struct X3D_Virt *virt = virtTable[node->_nodeType];
213 if(virt->rend || virt->rendray) iret = TRUE;
225int compare_nodedistance(
const void *elem1,
const void * elem2 )
229 return nd1->dist < nd2->dist ? -1 : nd1->dist > nd2->dist ? 1 : 0;
231int compare_intersectiondistance(
const void *elem1,
const void * elem2){
234 return nd1->dist < nd2->dist ? -1 : nd1->dist > nd2->dist ? 1 : 0;
236void do_PickSensorTick(
void *ptr){
240 struct X3D_Node *unode,*menode, *pnode;
245 ppComponent_Picking p = (ppComponent_Picking)gglobal()->Component_Picking.prv;
247 switch(node->_nodeType){
248 case NODE_LinePickSensor:
249 case NODE_PointPickSensor:
250 case NODE_PrimitivePickSensor:
251 case NODE_VolumePickSensor:
259 if (node->__oldEnabled != node->enabled) {
260 node->__oldEnabled = node->enabled;
264 if (!node->enabled)
return;
267 printf (
"do_TransformSensorTick enabled\n");
273 unodes = &node->pickTarget;
275 pnode = node->pickingGeometry;
279 if(unodes->n && pnode){
282 while((mehit = usehit_next(menode,mehit))){
285 double meinv[16],memin[3],memax[3];
286 float emin[3], emax[3];
288 matinverseAFFINE(meinv,mehit->mvm);
295 matmultiplyAFFINE(ident,meinv,mehit->mvm);
297 printf(
"inverse check do_TransformSensor\n");
299 for(j=0;j<4;j++) printf(
"%lf ",ident[i*3+j]);
307 emin[i] = pnode->_extent[i*2 + 1];
308 emax[i] = pnode->_extent[i*2];
312 node->_extent[i*2 + 1] = emin[i];
313 node->_extent[i*2] = emax[i];
317 memin[i] = node->_extent[i*2 + 1];
318 memax[i] = node->_extent[i*2];
322 p->stack_intersections->n = 0;
323 p->stack_nodesdistance->n = 0;
324 p->stack_pointsinside->n = 0;
326 for(j=0;j<unodes->n;j++){
327 unode = unodes->p[j];
328 while((uhit = usehit_next(unode,uhit))){
331 int intypes,pickable;
332 double u2me[16], me2u[16], umin[3],umax[3],uumin[3],uumax[3];
339 pickable = pgroup->pickable;
340 intypes = objecttypes_overlap(&node->objectType,&pgroup->objectType,node->matchCriterion);
342 if(intypes && pickable){
343 matmultiplyAFFINE(u2me,uhit->mvm,meinv);
344 matinverseAFFINE(me2u,u2me);
352 umin[i] = unode->_extent[i*2 + 1];
353 umax[i] = unode->_extent[i*2];
355 transformMBB(uumin,uumax,u2me,umin,umax);
357 if( overlapMBBs(memin, memax, uumin, uumax) ){
363 if(!strcmp(node->intersectionType->strptr,
"BOUNDS") || unode->_nodeType == NODE_Inline){
365 double c1[3],c2[3],dd[3];
367 vecaddd(c1,memin,memax);
369 vecaddd(c2,umin,umax);
372 ndist.dist = (float)veclengthd(dd);
374 stack_push(
struct nodedistance,p->stack_nodesdistance,ndist);
376 }
else if(!strcmp(node->intersectionType->strptr,
"GEOMETRY")){
390 double viewMatrix[16];
395 if(isGeometryNode(unode)){
396 double matidentity[16];
397 loadIdentityMatrix(matidentity);
398 usehitB_add2(unode,matidentity,pgroup);
399 loadIdentityMatrix(viewMatrix);
403 FW_GL_GETDOUBLEV(GL_MODELVIEW_MATRIX, viewMatrix);
404 render_hier(unode, VF_Geom | VF_Picking);
406 usehitB = getUseHitBStack();
407 for(m=0;m<vectorSize(usehitB);m++){
409 double u2meg[16], me2ug[16];
416 double viewinv[16], world2geom[16];
418 matinverseAFFINE(viewinv,viewMatrix);
420 matmultiply(world2geom,viewinv,ghit->mvm);
421 matmultiplyAFFINE(me2ug,world2geom,me2u);
422 matinverseAFFINE(u2meg,me2ug);
426 switch(node->_nodeType){
427 case NODE_LinePickSensor:
436 float *segments = NULL;
438 float cumdist = 0.0f;
439 int ik, cumcount = 0;
442 switch(pnode->_nodeType){
443 case NODE_IndexedLineSet:
448 segments = MALLOC(
float*,lnode->coordIndex.n * 2 * 3 *
sizeof(
float));
450 for(ik=0;ik<lnode->coordIndex.n;ik++){
451 if(lnode->coordIndex.p[ik] == -1)
continue;
452 if(lnode->coordIndex.p[ik+1] == -1)
continue;
453 veccopy3f(&segments[6*nseg +0],&points[3*lnode->coordIndex.p[ik]]);
454 veccopy3f(&segments[6*nseg +1],&points[3*lnode->coordIndex.p[ik+1]]);
463 int kk,ik,jk, nn = 0;
464 for(ik=0;ik<lnode->vertexCount.n;ik++)
465 nn += lnode->vertexCount.p[ik];
466 segments = MALLOC(
float*,nn * 2 * 3 *
sizeof(
float));
469 for(ik=0;ik<lnode->vertexCount.n;ik++){
470 for(jk=0;jk<lnode->vertexCount.p[ik]-1;jk++){
471 veccopy3f(&segments[6*nseg +0],&points[3*(kk+jk)]);
472 veccopy3f(&segments[6*nseg +3],&points[3*(kk+jk+1)]);
475 kk+= lnode->vertexCount.p[ik];
485 for(ik=0;ik<nseg;ik++){
488 veccopy3f(p1, &segments[6*ik]);
489 veccopy3f(p2,&segments[6*ik+3]);
490 float2double(dd,p1,3);
491 transformAFFINEd(dd,dd,me2ug);
492 double2float(p1,dd,3);
493 float2double(dd,p2,3);
494 transformAFFINEd(dd,dd,me2ug);
495 double2float(p2,dd,3);
498 if(intersect_polyrep2(ghit->node, p1, p2, p->stack_intersections )){
501 for(jk=cumcount;jk<p->stack_intersections->n;jk++){
503 iinfo->dist += cumdist;
504 float2double(dd,iinfo->p,3);
505 transformAFFINEd(dd,dd,u2meg);
508 double2float(iinfo->p,dd,3);
509 float2double(dd,iinfo->normal,3);
510 transformUPPER3X3d(dd,dd,u2meg);
511 double2float(iinfo->normal,dd,3);
513 cumdist += veclength3f(vecdif3f(delta,p2, p1));
514 cumcount = p->stack_intersections->n;
525 qsort(p->stack_intersections->data,p->stack_intersections->n,
sizeof(
struct intersection_info), compare_intersectiondistance );
527 ndist.dist = iinfo->dist;
529 stack_push(
struct nodedistance,p->stack_nodesdistance,ndist);
532 FREE_IF_NZ(segments);
535 case NODE_PointPickSensor:
543 int npoints,cumcount,ik;
546 points = (
float*)cc->point.p;
547 npoints = cc->point.n;
551 for(ik=0;ik<npoints;ik++){
556 veccopy3f(p1, &points[3*ik]);
557 float2double(dd,p1,3);
558 transformAFFINEd(dd,dd,me2ug);
559 double2float(p1,dd,3);
561 p2[3] = unode->_extent[4] - 1.0f;
565 if((ixcount = intersect_polyrep2(ghit->node, p1, p2, p->stack_intersections ))){
570 double c1[3], pointdist;
573 vecaddd(c1,memin,memax);
575 double2float(delta,c1,3);
576 pointdist = veclength3f(vecdif3f(delta,delta,p1));
577 iinfo.dist = (float)pointdist;
578 veccopy3f(iinfo.p,&points[3*ik]);
588 stack_push(
struct nodedistance,p->stack_nodesdistance,ndist);
593 case NODE_PrimitivePickSensor:
601 float *points = pr->actualCoord;
602 int ik, npts = pr->ntri;
605 for(ik=0;ik<npts;ik++){
608 float2double(dd,&points[ik*3],3);
609 transformAFFINEd(dd,dd,u2meg);
610 double2float(pp,dd,3);
611 switch(pnode->_nodeType){
617 R = cone->bottomRadius;
618 if(pp[1] >= -H/2.0f && pp[1] < H/2.0f){
620 h = pp[1] - (-H/2.0f);
624 rp = veclength2f(xz);
628 float apex[3], delta[3], conedist;
630 apex[0] = apex[2] = 0.0f;
631 conedist = veclength3f(vecdif3f(delta,pp,apex));
632 iinfo.dist = conedist;
633 veccopy3f(iinfo.p,pp);
647 if(pp[1] >= -H/2.0f && pp[1] < H/2.0f){
652 rp = veclength2f(xz);
656 iinfo.dist = veclength3f(pp);
657 veccopy3f(iinfo.p,pp);
668 rp = veclength3f(pp);
673 veccopy3f(iinfo.p,pp);
685 inside = inside && pp[im] >= -box->size.c[im] && pp[im] <= box->size.c[im];
688 iinfo.dist = veclength3f(pp);
689 veccopy3f(iinfo.p,pp);
698 cumcount = p->stack_pointsinside->n;
703 qsort(p->stack_intersections->data,p->stack_intersections->n,
sizeof(
struct intersection_info), compare_intersectiondistance );
706 ndist.dist = iinfo->dist;
708 stack_push(
struct nodedistance,p->stack_nodesdistance,ndist);
715 case NODE_VolumePickSensor:
725 float *points = pr->actualCoord;
729 for(ik=0;ik<npts;ik++){
732 float2double(dd,&points[ik*3],3);
733 transformAFFINEd(dd,dd,u2meg);
734 double2float(pp,dd,3);
741 p2[3] = menode->_extent[4] - 1.0f;
745 if((ixcount = intersect_polyrep2(pnode, p1, p2, p->stack_intersections ))){
750 double c1[3], pointdist;
753 vecaddd(c1,memin,memax);
755 double2float(delta,c1,3);
756 pointdist = veclength3f(vecdif3f(delta,delta,p1));
757 iinfo.dist = (float) pointdist;
758 veccopy3f(iinfo.p,&points[3*ik]);
765 cumcount = p->stack_pointsinside->n;
770 qsort(p->stack_intersections->data,p->stack_intersections->n,
sizeof(
struct intersection_info), compare_intersectiondistance );
773 ndist.dist = iinfo->dist;
775 stack_push(
struct nodedistance,p->stack_nodesdistance,ndist);
795 if (!node->isActive) {
797 printf (
"transformensor - now active\n");
804 if(!strcmp(node->sortOrder->strptr,
"ANY")){
806 node->pickedGeometry.p = realloc(node->pickedGeometry.p,1 *
sizeof(
struct X3D_Node*));
807 ndist = vector_get_ptr(
struct nodedistance,p->stack_nodesdistance,0);
808 node->pickedGeometry.p[0] = ndist->node;
809 }
else if(!strcmp(node->sortOrder->strptr,
"ALL")){
812 node->pickedGeometry.p = realloc(node->pickedGeometry.p,p->stack_nodesdistance->n *
sizeof(
struct X3D_Node*));
813 for(ii=0;ii<p->stack_nodesdistance->n;ii++){
814 ndist = vector_get_ptr(
struct nodedistance,p->stack_nodesdistance,0);
815 node->pickedGeometry.p[ii] = ndist->node;
818 }
else if(!strcmp(node->sortOrder->strptr,
"ALL_SORTED")){
831 qsort(p->stack_nodesdistance->data,p->stack_nodesdistance->n,
sizeof(
struct nodedistance), compare_nodedistance );
832 node->pickedGeometry.p = realloc(node->pickedGeometry.p,p->stack_nodesdistance->n *
sizeof(
struct X3D_Node*));
833 for(ii=0;ii<p->stack_nodesdistance->n;ii++){
834 ndist = vector_get_ptr(
struct nodedistance,p->stack_nodesdistance,0);
835 node->pickedGeometry.p[ii] = ndist->node;
837 }
else if(!strcmp(node->sortOrder->strptr,
"CLOSEST")){
840 qsort(p->stack_nodesdistance->data,p->stack_nodesdistance->n,
sizeof(
struct nodedistance), compare_nodedistance );
841 node->pickedGeometry.p = realloc(node->pickedGeometry.p,1 *
sizeof(
struct X3D_Node*));
842 ndist = vector_get_ptr(
struct nodedistance,p->stack_nodesdistance,0);
843 node->pickedGeometry.p[0] = ndist->node;
850 switch(node->_nodeType){
851 case NODE_LinePickSensor:
855 lnode->pickedPoint.n = p->stack_intersections->n;
856 lnode->pickedNormal.n = p->stack_intersections->n;
857 lnode->pickedTextureCoordinate.n = p->stack_intersections->n;
858 lnode->pickedPoint.p = realloc(lnode->pickedPoint.p,lnode->pickedPoint.n * 3 *
sizeof(
float));
859 lnode->pickedNormal.p = realloc(lnode->pickedNormal.p,lnode->pickedPoint.n * 3 *
sizeof(
float));
860 lnode->pickedTextureCoordinate.p = realloc(lnode->pickedTextureCoordinate.p,lnode->pickedPoint.n * 3 *
sizeof(
float));
861 for(ik=0;ik<p->stack_intersections->n;ik++){
863 veccopy3f(lnode->pickedPoint.p[ik].c,iinfo->p);
864 veccopy3f(lnode->pickedNormal.p[ik].c,iinfo->normal);
865 veccopy3f(lnode->pickedTextureCoordinate.p[ik].c,iinfo->texcoord);
872 case NODE_PointPickSensor:
877 lnode->pickedPoint.n = p->stack_pointsinside->n;
878 lnode->pickedPoint.p = realloc(lnode->pickedPoint.p,lnode->pickedPoint.n * 3 *
sizeof(
float));
879 for(ik=0;ik<p->stack_pointsinside->n;ik++){
881 veccopy3f(lnode->pickedPoint.p[ik].c,iinfo->p);
886 case NODE_PrimitivePickSensor:
888 case NODE_VolumePickSensor:
896 if (node->isActive) {
898 printf (
"transformsensor - going inactive\n");
908 for(i=0;i<unodes->n;i++)
909 unodes->p[i]->_renderFlags |= VF_USE;
911 node->_renderFlags |= VF_USE;