#ifndef B3_CONTACT_SPHERE_SPHERE_H #define B3_CONTACT_SPHERE_SPHERE_H void computeContactSphereConvex(int pairIndex, int bodyIndexA, int bodyIndexB, int collidableIndexA, int collidableIndexB, const b3RigidBodyData* rigidBodies, const b3Collidable* collidables, const b3ConvexPolyhedronData* convexShapes, const b3Vector3* convexVertices, const int* convexIndices, const b3GpuFace* faces, b3Contact4* globalContactsOut, int& nGlobalContactsOut, int maxContactCapacity) { float radius = collidables[collidableIndexA].m_radius; float4 spherePos1 = rigidBodies[bodyIndexA].m_pos; b3Quaternion sphereOrn = rigidBodies[bodyIndexA].m_quat; float4 pos = rigidBodies[bodyIndexB].m_pos; b3Quaternion quat = rigidBodies[bodyIndexB].m_quat; b3Transform tr; tr.setIdentity(); tr.setOrigin(pos); tr.setRotation(quat); b3Transform trInv = tr.inverse(); float4 spherePos = trInv(spherePos1); int collidableIndex = rigidBodies[bodyIndexB].m_collidableIdx; int shapeIndex = collidables[collidableIndex].m_shapeIndex; int numFaces = convexShapes[shapeIndex].m_numFaces; float4 closestPnt = b3MakeVector3(0, 0, 0, 0); float4 hitNormalWorld = b3MakeVector3(0, 0, 0, 0); float minDist = -1000000.f; // TODO: What is the largest/smallest float? bool bCollide = true; int region = -1; float4 localHitNormal; for ( int f = 0; f < numFaces; f++ ) { b3GpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f]; float4 planeEqn; float4 localPlaneNormal = b3MakeVector3(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f); float4 n1 = localPlaneNormal;//quatRotate(quat,localPlaneNormal); planeEqn = n1; planeEqn[3] = face.m_plane.w; float4 pntReturn; float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn); if ( dist > radius) { bCollide = false; break; } if ( dist > 0 ) { //might hit an edge or vertex b3Vector3 out; bool isInPoly = IsPointInPolygon(spherePos, &face, &convexVertices[convexShapes[shapeIndex].m_vertexOffset], convexIndices, &out); if (isInPoly) { if (dist>minDist) { minDist = dist; closestPnt = pntReturn; localHitNormal = planeEqn; region=1; } } else { b3Vector3 tmp = spherePos-out; b3Scalar l2 = tmp.length2(); if (l2minDist) { minDist = dist; closestPnt = out; localHitNormal = tmp/dist; region=2; } } else { bCollide = false; break; } } } else { if ( dist > minDist ) { minDist = dist; closestPnt = pntReturn; localHitNormal = planeEqn; region=3; } } } static int numChecks = 0; numChecks++; if (bCollide && minDist > -10000) { float4 normalOnSurfaceB1 = tr.getBasis()*localHitNormal;//-hitNormalWorld; float4 pOnB1 = tr(closestPnt); //printf("dist ,%f,",minDist); float actualDepth = minDist-radius; if (actualDepth<0) { //printf("actualDepth = ,%f,", actualDepth); //printf("normalOnSurfaceB1 = ,%f,%f,%f,", normalOnSurfaceB1.x,normalOnSurfaceB1.y,normalOnSurfaceB1.z); //printf("region=,%d,\n", region); pOnB1[3] = actualDepth; int dstIdx; // dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx ); if (nGlobalContactsOut < maxContactCapacity) { dstIdx=nGlobalContactsOut; nGlobalContactsOut++; b3Contact4* c = &globalContactsOut[dstIdx]; c->m_worldNormalOnB = normalOnSurfaceB1; c->setFrictionCoeff(0.7); c->setRestituitionCoeff(0.f); c->m_batchIdx = pairIndex; c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA; c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB; c->m_worldPosB[0] = pOnB1; int numPoints = 1; c->m_worldNormalOnB.w = (b3Scalar)numPoints; }//if (dstIdx < numPairs) } }//if (hasCollision) } #endif //B3_CONTACT_SPHERE_SPHERE_H