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); }
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); OBBCollider& Collider = cData.gTrimesh->_OBBCollider; Point cCenter((float)cData.vCylinderPos[0],(float)cData.vCylinderPos[1],(float)cData.vCylinderPos[2]); Point cExtents((float)cData.fCylinderRadius,(float)cData.fCylinderRadius,(float)cData.fCylinderRadius); cExtents[nCYLINDER_AXIS] = (float)(cData.fCylinderSize * REAL(0.5)); Matrix3x3 obbRot; // It is a potential issue to explicitly cast to float // if custom width floating point type is introduced in OPCODE. // It is necessary to make a typedef and cast to it // (e.g. typedef float opc_float;) // However I'm not sure in what header it should be added. obbRot[0][0] = (float)cData.mCylinderRot[0]; obbRot[1][0] = (float)cData.mCylinderRot[1]; obbRot[2][0] = (float)cData.mCylinderRot[2]; obbRot[0][1] = (float)cData.mCylinderRot[4]; obbRot[1][1] = (float)cData.mCylinderRot[5]; obbRot[2][1] = (float)cData.mCylinderRot[6]; obbRot[0][2] = (float)cData.mCylinderRot[8]; obbRot[1][2] = (float)cData.mCylinderRot[9]; obbRot[2][2] = (float)cData.mCylinderRot[10]; OBB obbCapsule(cCenter,cExtents,obbRot); Matrix4x4 CapsuleMatrix; MakeMatrix(cData.vCylinderPos, cData.mCylinderRot, CapsuleMatrix); Matrix4x4 MeshMatrix; MakeMatrix(cData.vTrimeshPos, cData.mTrimeshRot, MeshMatrix); // TC results if (cData.gTrimesh->doBoxTC) { dxTriMesh::BoxTC* BoxTC = 0; for (int i = 0; i < cData.gTrimesh->BoxTCCache.size(); i++) { if (cData.gTrimesh->BoxTCCache[i].Geom == cData.gCylinder) { BoxTC = &cData.gTrimesh->BoxTCCache[i]; break; } } if (!BoxTC) { cData.gTrimesh->BoxTCCache.push(dxTriMesh::BoxTC()); BoxTC = &cData.gTrimesh->BoxTCCache[cData.gTrimesh->BoxTCCache.size() - 1]; BoxTC->Geom = cData.gCylinder; BoxTC->FatCoeff = REAL(1.0); } // Intersect Collider.SetTemporalCoherence(true); Collider.Collide(*BoxTC, obbCapsule, cData.gTrimesh->Data->BVTree, null, &MeshMatrix); } else { Collider.SetTemporalCoherence(false); Collider.Collide(dxTriMesh::defaultBoxCache, obbCapsule, cData.gTrimesh->Data->BVTree, null,&MeshMatrix); } // Retrieve data int TriCount = Collider.GetNbTouchedPrimitives(); const int* Triangles = (const int*)Collider.GetTouchedPrimitives(); if (TriCount != 0) { if (cData.gTrimesh->ArrayCallback != null) { cData.gTrimesh->ArrayCallback(cData.gTrimesh, cData.gCylinder, Triangles, TriCount); } // allocate buffer for local contacts on stack cData.gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(cData.iFlags & NUMC_MASK)); int ctContacts0 = 0; // loop through all intersecting triangles for (int i = 0; i < TriCount; i++) { const int Triint = Triangles[i]; if (!Callback(cData.gTrimesh, cData.gCylinder, Triint)) continue; dVector3 dv[3]; FetchTriangle(cData.gTrimesh, Triint, cData.vTrimeshPos, cData.mTrimeshRot, dv); // test this triangle TestOneTriangleVsCylinder(cData , dv[0],dv[1],dv[2], false); // fill-in tri 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; } } } return _ProcessLocalContacts(cData); }
// capsule - trimesh by CroTeam // Ported by Nguyem Binh int dCollideCCTL(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip) { dIASSERT (skip >= (int)sizeof(dContactGeom)); dIASSERT (o1->type == dTriMeshClass); dIASSERT (o2->type == dCapsuleClass); dIASSERT ((flags & NUMC_MASK) >= 1); int nContactCount = 0; dxTriMesh *TriMesh = (dxTriMesh*)o1; dxGeom *Capsule = o2; sTrimeshCapsuleColliderData cData; cData.SetupInitialContext(TriMesh, Capsule, flags, skip); const unsigned uiTLSKind = TriMesh->getParentSpaceTLSKind(); dIASSERT(uiTLSKind == Capsule->getParentSpaceTLSKind()); // The colliding spaces must use matching cleanup method TrimeshCollidersCache *pccColliderCache = GetTrimeshCollidersCache(uiTLSKind); OBBCollider& Collider = pccColliderCache->_OBBCollider; // Will it better to use LSS here? -> confirm Pierre. dQueryCCTLPotentialCollisionTriangles(Collider, cData, TriMesh, Capsule, pccColliderCache->defaultBoxCache); if (Collider.GetContactStatus()) { // Retrieve data int TriCount = Collider.GetNbTouchedPrimitives(); if (TriCount != 0) { const int* Triangles = (const int*)Collider.GetTouchedPrimitives(); if (TriMesh->ArrayCallback != null) { TriMesh->ArrayCallback(TriMesh, Capsule, Triangles, TriCount); } // allocate buffer for local contacts on stack cData.m_gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(cData.m_iFlags & NUMC_MASK)); unsigned int ctContacts0 = cData.m_ctContacts; uint8* UseFlags = TriMesh->Data->UseFlags; // loop through all intersecting triangles for (int i = 0; i < TriCount; i++) { const int Triint = Triangles[i]; if (!Callback(TriMesh, Capsule, Triint)) continue; dVector3 dv[3]; FetchTriangle(TriMesh, Triint, cData.m_mTriMeshPos, cData.m_mTriMeshRot, dv); uint8 flags = UseFlags ? UseFlags[Triint] : (uint8)dxTriMeshData::kUseAll; bool bFinishSearching; ctContacts0 = cData.TestCollisionForSingleTriangle(ctContacts0, Triint, dv, flags, bFinishSearching); if (bFinishSearching) { break; } } if (cData.m_ctContacts != 0) { nContactCount = cData._ProcessLocalContacts(contact, TriMesh, Capsule); } } } return nContactCount; }