/*! In each contact <ul> <li> m_handle1 points to trimesh. <li> m_handle2 points to NULL. <li> m_feature1 Is a triangle index of trimesh. </ul> \param trimesh \param center \param radius \param contacts A GIM_CONTACT array. Must be initialized */ void gim_trimesh_sphere_collision(GIM_TRIMESH * trimesh,vec3f center,GREAL radius, GDYNAMIC_ARRAY * contacts) { contacts->m_size = 0; aabb3f test_aabb; test_aabb.minX = center[0]-radius; test_aabb.maxX = center[0]+radius; test_aabb.minY = center[1]-radius; test_aabb.maxY = center[1]+radius; test_aabb.minZ = center[2]-radius; test_aabb.maxZ = center[2]+radius; GDYNAMIC_ARRAY collision_result; GIM_CREATE_BOXQUERY_LIST(collision_result); gim_aabbset_box_collision(&test_aabb, &trimesh->m_aabbset , &collision_result); if(collision_result.m_size==0) { GIM_DYNARRAY_DESTROY(collision_result); } //collide triangles //Locks trimesh gim_trimesh_locks_work_data(trimesh); //dummy contacts GDYNAMIC_ARRAY dummycontacts; GIM_CREATE_CONTACT_LIST(dummycontacts); int cresult; unsigned int i; GUINT32 * boxesresult = GIM_DYNARRAY_POINTER(GUINT32,collision_result); GIM_TRIANGLE_CONTACT_DATA tri_contact_data; GIM_TRIANGLE_DATA tri_data; for(i=0;i<collision_result.m_size;i++) { gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tri_data); cresult = gim_triangle_sphere_collision(&tri_data,center,radius,&tri_contact_data); if(cresult!=0) { GIM_PUSH_CONTACT(dummycontacts, tri_contact_data.m_points[0],tri_contact_data.m_separating_normal ,tri_contact_data.m_penetration_depth,trimesh, 0, boxesresult[i],0); } } ///unlocks gim_trimesh_unlocks_work_data(trimesh); ///Destroy box result GIM_DYNARRAY_DESTROY(collision_result); //merge contacts gim_merge_contacts(&dummycontacts,contacts); //Destroy dummy GIM_DYNARRAY_DESTROY(dummycontacts); }
/*! \param trimesh \param contact \return 1 if the ray collides, else 0 */ int gim_trimesh_ray_collision(GIM_TRIMESH * trimesh,vec3f origin,vec3f dir, GREAL tmax, GIM_TRIANGLE_RAY_CONTACT_DATA * contact) { GDYNAMIC_ARRAY collision_result; GIM_CREATE_BOXQUERY_LIST(collision_result); gim_aabbset_ray_collision(origin,dir,tmax,&trimesh->m_aabbset,&collision_result); if(collision_result.m_size==0) { GIM_DYNARRAY_DESTROY(collision_result); return 0; } //collide triangles GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result); GIM_TRIANGLE_DATA tridata; vec3f pout; GREAL tparam,u,v; char does_intersect; gim_trimesh_locks_work_data(trimesh); for(unsigned int i=0;i<collision_result.m_size;i++) { gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tridata); RAY_TRIANGLE_INTERSECTION(origin,dir,tridata.m_vertices[0],tridata.m_vertices[1],tridata.m_vertices[2],tridata.m_planes.m_planes[0],pout,u,v,tparam,tmax,does_intersect); if(does_intersect) { contact->tparam = tparam; contact->u = u; contact->v = v; contact->m_face_id = boxesresult[i]; VEC_COPY(contact->m_point,pout); VEC_COPY(contact->m_normal,tridata.m_planes.m_planes[0]); gim_trimesh_unlocks_work_data(trimesh); GIM_DYNARRAY_DESTROY(collision_result); return 1; } } gim_trimesh_unlocks_work_data(trimesh); GIM_DYNARRAY_DESTROY(collision_result); return 0;//no collisiion }
int dCollideCylinderTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT( skip >= (int)sizeof( dContactGeom ) ); dIASSERT( o1->type == dCylinderClass ); dIASSERT( o2->type == dTriMeshClass ); dIASSERT ((flags & NUMC_MASK) >= 1); // Main data holder sData cData; // Assign ODE stuff cData.gCylinder = o1; cData.gTrimesh = (dxTriMesh*)o2; cData.iFlags = flags; cData.iSkip = skip; cData.gContact = contact; cData.nContacts = 0; _InitCylinderTrimeshData(cData); //*****at first , collide box aabb******// aabb3f test_aabb; test_aabb.minX = o1->aabb[0]; test_aabb.maxX = o1->aabb[1]; test_aabb.minY = o1->aabb[2]; test_aabb.maxY = o1->aabb[3]; test_aabb.minZ = o1->aabb[4]; test_aabb.maxZ = o1->aabb[5]; GDYNAMIC_ARRAY collision_result; GIM_CREATE_BOXQUERY_LIST(collision_result); gim_aabbset_box_collision(&test_aabb, &cData.gTrimesh->m_collision_trimesh.m_aabbset , &collision_result); if(collision_result.m_size==0) { GIM_DYNARRAY_DESTROY(collision_result); return 0; } //*****Set globals for box collision******// int ctContacts0 = 0; cData.gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(cData.iFlags & NUMC_MASK)); GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result); GIM_TRIMESH * ptrimesh = &cData.gTrimesh->m_collision_trimesh; gim_trimesh_locks_work_data(ptrimesh); for(unsigned int i=0; i<collision_result.m_size; i++) { const int Triint = boxesresult[i]; dVector3 dv[3]; gim_trimesh_get_triangle_vertices(ptrimesh, Triint,dv[0],dv[1],dv[2]); // test this triangle TestOneTriangleVsCylinder(cData , dv[0],dv[1],dv[2], false); // fill-in triangle index for generated contacts for (; ctContacts0<cData.nContacts; ctContacts0++) cData.gLocalContacts[ctContacts0].triIndex = Triint; // Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue" if(cData.nContacts >= (cData.iFlags & NUMC_MASK)) { break; } } gim_trimesh_unlocks_work_data(ptrimesh); GIM_DYNARRAY_DESTROY(collision_result); return _ProcessLocalContacts(cData); }
/*! Find the closest primitive collided by the ray \param trimesh \param capsule \param contact \param contacts A GIM_CONTACT array. Must be initialized */ void gim_trimesh_capsule_collision(GIM_TRIMESH * trimesh, GIM_CAPSULE_DATA * capsule, GDYNAMIC_ARRAY * contacts) { contacts->m_size = 0; aabb3f test_aabb; CALC_CAPSULE_AABB((*capsule),test_aabb); GDYNAMIC_ARRAY collision_result; GIM_CREATE_BOXQUERY_LIST(collision_result); gim_aabbset_box_collision(&test_aabb, &trimesh->m_aabbset , &collision_result); if(collision_result.m_size==0) { GIM_DYNARRAY_DESTROY(collision_result); } //collide triangles //Locks trimesh gim_trimesh_locks_work_data(trimesh); //dummy contacts GDYNAMIC_ARRAY dummycontacts; GIM_CREATE_CONTACT_LIST(dummycontacts); int cresult; unsigned int i; GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result); GIM_TRIANGLE_DATA tri_data; GUINT old_contact_size; GIM_CONTACT * pcontact; for(i=0;i<collision_result.m_size;i++) { old_contact_size = dummycontacts.m_size; gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tri_data); cresult = gim_triangle_capsule_collision(&tri_data, capsule, &dummycontacts); if(cresult!=0) { pcontact = GIM_DYNARRAY_POINTER(GIM_CONTACT ,dummycontacts); pcontact+= old_contact_size; while(old_contact_size<dummycontacts.m_size) { pcontact->m_handle1 = trimesh; pcontact->m_handle2 = capsule; pcontact->m_feature1 = boxesresult[i]; pcontact->m_feature2 = 0; pcontact++; old_contact_size++; } } } ///unlocks gim_trimesh_unlocks_work_data(trimesh); ///Destroy box result GIM_DYNARRAY_DESTROY(collision_result); //merge contacts gim_merge_contacts(&dummycontacts,contacts); //Destroy dummy GIM_DYNARRAY_DESTROY(dummycontacts); }