static void outputPlaneToStream(PxShape* planeShape, const PxRigidActor* actor, const PxTransform& globalPose, IntArray& geomStream, TriArray& worldTriangles, IntArray& triIndicesArray, const PxExtendedVec3& origin, const PxBounds3& tmpBounds, const CCTParams& params, Cm::RenderBuffer* renderBuffer) { PX_ASSERT(planeShape->getGeometryType() == PxGeometryType::ePLANE); const PxF32 length = (tmpBounds.maximum - tmpBounds.minimum).magnitude(); PxVec3 center = toVec3(origin); const PxPlane plane = PxPlaneEquationFromTransform(globalPose); PxVec3 right, up; Ps::computeBasis(plane.n, right, up); right *= length; up *= length; const PxVec3 p = plane.project(center); const PxVec3 p0 = p - right + up; const PxVec3 p1 = p - right - up; const PxVec3 p2 = p + right - up; const PxVec3 p3 = p + right + up; const PxU32 nbTouchedTris = 2; const PxVec3 offset(float(-origin.x), float(-origin.y), float(-origin.z)); TouchedMesh* touchedMesh = (TouchedMesh*)reserve(geomStream, sizeof(TouchedMesh)/sizeof(PxU32)); touchedMesh->mType = TouchedGeomType::eMESH; touchedMesh->mTGUserData = planeShape; touchedMesh->mActor = actor; touchedMesh->mOffset = origin; touchedMesh->mNbTris = nbTouchedTris; touchedMesh->mIndexWorldTriangles = worldTriangles.size(); // Reserve memory for incoming triangles PxTriangle* TouchedTriangles = reserve(worldTriangles, nbTouchedTris); triIndicesArray.pushBack(0); triIndicesArray.pushBack(1); TouchedTriangles[0].verts[0] = p0 + offset; TouchedTriangles[0].verts[1] = p1 + offset; TouchedTriangles[0].verts[2] = p2 + offset; TouchedTriangles[1].verts[0] = p0 + offset; TouchedTriangles[1].verts[1] = p2 + offset; TouchedTriangles[1].verts[2] = p3 + offset; if(gVisualizeTouchedTris) visualizeTouchedTriangles(touchedMesh->mNbTris, touchedMesh->mIndexWorldTriangles, &worldTriangles[0], renderBuffer, offset, params.mUpDirection); }
static void outputConvexToStream(PxShape* convexShape, const PxTransform& absPose, IntArray& geomStream, TriArray& worldTriangles, IntArray& triIndicesArray, const PxExtendedVec3& origin, const PxBounds3& tmpBounds) { PX_ASSERT(convexShape->getGeometryType() == PxGeometryType::eCONVEXMESH); PxConvexMeshGeometry cg; convexShape->getConvexMeshGeometry(cg); PX_ASSERT(cg.convexMesh); // Do AABB-mesh query PxU32* TF; // Collide AABB against current mesh // The overlap function doesn't exist for convexes so let's just dump all tris PxConvexMesh& cm = *cg.convexMesh; // PT: convex triangles are not exposed anymore so we need to access convex polygons & triangulate them // PT: TODO: this is copied from "DrawObjects", move this to a shared place. Actually a helper directly in PxConvexMesh would be useful. PxU32 Nb = 0; { const PxU32 nbPolys = cm.getNbPolygons(); const PxU8* polygons = cm.getIndexBuffer(); for(PxU32 i=0;i<nbPolys;i++) { PxHullPolygon data; cm.getPolygonData(i, data); Nb += data.mNbVerts - 2; } // PT: revisit this code. We don't use the polygon offset? TF = (PxU32*)PxAlloca(sizeof(PxU32)*Nb*3); PxU32* t = TF; for(PxU32 i=0;i<nbPolys;i++) { PxHullPolygon data; cm.getPolygonData(i, data); const PxU32 nbV = data.mNbVerts; const PxU32 nbTris = nbV - 2; const PxU8 vref0 = *polygons; for(PxU32 j=0;j<nbTris;j++) { const PxU32 vref1 = polygons[(j+1)%nbV]; const PxU32 vref2 = polygons[(j+2)%nbV]; *t++ = vref0; *t++ = vref1; *t++ = vref2; } polygons += nbV; } } const PxVec3* verts = cm.getVertices(); PxVec3 tmp = absPose.p; // LOSS OF ACCURACY PxVec3 MeshOffset; MeshOffset.x = float(tmp.x - origin.x); MeshOffset.y = float(tmp.y - origin.y); MeshOffset.z = float(tmp.z - origin.z); TouchedMesh* touchedMesh = (TouchedMesh*)reserve(geomStream, sizeof(TouchedMesh)/sizeof(PxU32)); touchedMesh->mType = TouchedGeomType::eMESH; touchedMesh->mUserData = convexShape; touchedMesh->mOffset = origin; touchedMesh->mNbTris = Nb; touchedMesh->mIndexWorldTriangles = worldTriangles.size(); // Reserve memory for incoming triangles PxTriangle* TouchedTriangles = reserve(worldTriangles, Nb); // Loop through touched triangles while(Nb--) { // Compute triangle in world space, add to array PxTriangle& CurrentTriangle = *TouchedTriangles++; const PxU32 vref0 = *TF++; const PxU32 vref1 = *TF++; const PxU32 vref2 = *TF++; PxVec3 v0 = verts[vref0]; PxVec3 v1 = verts[vref1]; PxVec3 v2 = verts[vref2]; v0 = absPose.q.rotate(v0); v1 = absPose.q.rotate(v1); v2 = absPose.q.rotate(v2); CurrentTriangle.verts[0] = v0; CurrentTriangle.verts[1] = v1; CurrentTriangle.verts[2] = v2; CurrentTriangle.verts[0] += MeshOffset; CurrentTriangle.verts[1] += MeshOffset; CurrentTriangle.verts[2] += MeshOffset; triIndicesArray.pushBack(PX_INVALID_U32); } }
static void outputHeightFieldToStream( PxShape* hfShape, const PxTransform& heightfieldPose, IntArray& geomStream, TriArray& worldTriangles, IntArray& triIndicesArray, const PxExtendedVec3& origin, const PxBounds3& tmpBounds, const CCTParams& params, Cm::RenderBuffer* renderBuffer) { PX_ASSERT(hfShape->getGeometryType() == PxGeometryType::eHEIGHTFIELD); // Do AABB-mesh query PxHeightFieldGeometry hfGeom; hfShape->getHeightFieldGeometry(hfGeom); PxBoxGeometry boxGeom(tmpBounds.getExtents()); PxTransform boxPose; boxPose.p = tmpBounds.getCenter(); boxPose.q = PxQuat::createIdentity(); // Collide AABB against current heightfield PxFindOverlapTriangleMeshUtil overlapUtil; const PxU32 nbTouchedTris = overlapUtil.findOverlap(boxGeom, boxPose, hfGeom, heightfieldPose); const PxVec3 offset(float(-origin.x), float(-origin.y), float(-origin.z)); TouchedMesh* touchedMesh = (TouchedMesh*)reserve(geomStream, sizeof(TouchedMesh)/sizeof(PxU32)); touchedMesh->mType = TouchedGeomType::eMESH; // ptchernev: seems to work touchedMesh->mUserData = hfShape; touchedMesh->mOffset = origin; touchedMesh->mNbTris = nbTouchedTris; touchedMesh->mIndexWorldTriangles = worldTriangles.size(); const PxU32* PX_RESTRICT indices = overlapUtil.getResults(); if(params.mSlopeLimit!=0.0f) { // Reserve memory for incoming triangles // PxTriangle* TouchedTriangles = reserve(worldTriangles, nbTouchedTris); // Loop through touched triangles PxU32 nbCreatedTris = 0; for(PxU32 i=0; i < nbTouchedTris; i++) { const PxU32 triangleIndex = indices[i]; // Compute triangle in world space, add to array PxTriangle currentTriangle; PxMeshQuery::getTriangle(hfGeom, heightfieldPose, triangleIndex, currentTriangle); currentTriangle.verts[0] += offset; currentTriangle.verts[1] += offset; currentTriangle.verts[2] += offset; const PxU32 nbNewTris = createInvisibleWalls(params, currentTriangle, worldTriangles, triIndicesArray); nbCreatedTris += nbNewTris; if(!nbNewTris) { worldTriangles.pushBack(currentTriangle); triIndicesArray.pushBack(triangleIndex); nbCreatedTris++; } } touchedMesh->mNbTris = nbCreatedTris; } else { // Reserve memory for incoming triangles PxTriangle* TouchedTriangles = reserve(worldTriangles, nbTouchedTris); // Loop through touched triangles for(PxU32 i=0; i < nbTouchedTris; i++) { const PxU32 triangleIndex = indices[i]; // Compute triangle in world space, add to array PxTriangle& currentTriangle = *TouchedTriangles++; PxMeshQuery::getTriangle(hfGeom, heightfieldPose, triangleIndex, currentTriangle); currentTriangle.verts[0] += offset; currentTriangle.verts[1] += offset; currentTriangle.verts[2] += offset; triIndicesArray.pushBack(triangleIndex); } } if(gVisualizeTouchedTris) visualizeTouchedTriangles(touchedMesh->mNbTris, touchedMesh->mIndexWorldTriangles, &worldTriangles[0], renderBuffer, offset, params.mUpDirection); }
static PxU32 createInvisibleWalls(const CCTParams& params, const PxTriangle& currentTriangle, TriArray& worldTriangles, IntArray& triIndicesArray) { const PxF32 wallHeight = params.mInvisibleWallHeight; if(wallHeight==0.0f) return 0; PxU32 nbNewTris = 0; // Number of newly created tris const PxVec3& upDirection = params.mUpDirection; PxVec3 normal; currentTriangle.normal(normal); if(testSlope(normal, upDirection, params.mSlopeLimit)) { const PxVec3 upWall = upDirection*wallHeight; PxVec3 v0p = currentTriangle.verts[0] + upWall; PxVec3 v1p = currentTriangle.verts[1] + upWall; PxVec3 v2p = currentTriangle.verts[2] + upWall; // Extrude edge 0-1 PxVec3 faceNormal01; { // 0-1-0p const PxTriangle tri0_1_0p(currentTriangle.verts[0], currentTriangle.verts[1], v0p); worldTriangles.pushBack(tri0_1_0p); // 0p-1-1p const PxTriangle tri0p_1_1p(v0p, currentTriangle.verts[1], v1p); worldTriangles.pushBack(tri0p_1_1p); tri0p_1_1p.normal(faceNormal01); } // Extrude edge 1-2 PxVec3 faceNormal12; { // 1p-1-2p const PxTriangle tri1p_1_2p(v1p, currentTriangle.verts[1], v2p); worldTriangles.pushBack(tri1p_1_2p); // 2p-1-2 const PxTriangle tri2p_1_2(v2p, currentTriangle.verts[1], currentTriangle.verts[2]); worldTriangles.pushBack(tri2p_1_2); tri2p_1_2.normal(faceNormal12); } // Extrude edge 2-0 PxVec3 faceNormal20; { // 0p-2-0 const PxTriangle tri0p_2_0(v0p, currentTriangle.verts[2], currentTriangle.verts[0]); worldTriangles.pushBack(tri0p_2_0); // 0p-2p-2 const PxTriangle tri0p_2p_2(v0p, v2p, currentTriangle.verts[2]); worldTriangles.pushBack(tri0p_2p_2); tri0p_2p_2.normal(faceNormal20); } const PxU32 triIndex = PX_INVALID_U32; for(PxU32 i=0;i<6;i++) triIndicesArray.pushBack(triIndex); nbNewTris += 6; } return nbNewTris; }
static void outputBoxToStream(PxShape* boxShape, const PxTransform& globalPose, IntArray& geomStream, TriArray& worldTriangles, IntArray& triIndicesArray, const PxExtendedVec3& origin, const PxBounds3& tmpBounds, const CCTParams& params, Cm::RenderBuffer* renderBuffer) { PX_ASSERT(boxShape->getGeometryType() == PxGeometryType::eBOX); PxBoxGeometry bg; boxShape->getBoxGeometry(bg); //8 verts in local space. const PxF32 dx = bg.halfExtents.x; const PxF32 dy = bg.halfExtents.y; const PxF32 dz = bg.halfExtents.z; PxVec3 boxVerts[8]= { PxVec3(-dx,-dy,-dz), PxVec3(+dx,-dy,-dz), PxVec3(+dx,+dy,-dz), PxVec3(-dx,+dy,-dz), PxVec3(-dx,-dy,+dz), PxVec3(+dx,-dy,+dz), PxVec3(+dx,+dy,+dz), PxVec3(-dx,+dy,+dz) }; //Transform verts into world space. PxVec3 pxOrigin = toVec3(origin); for(PxU32 i = 0; i < 8; i++) { boxVerts[i] = globalPose.transform(boxVerts[i]) - pxOrigin; } //Index of triangles. PxU32 boxTris[12][3]= { {0,2,1}, {2,0,3}, //0,1,2,3 {3,6,2}, {6,3,7}, //3,2,6,7 {7,5,6}, {5,7,4}, //7,6,5,4 {4,1,5}, {1,4,0}, //4,5,1,0 {0,7,3}, {7,0,4}, //0,3,7,4 {2,5,1}, {5,2,6} //2,1,5,6 }; TouchedMesh* touchedMesh = (TouchedMesh*)reserve(geomStream, sizeof(TouchedMesh)/sizeof(PxU32)); touchedMesh->mType = TouchedGeomType::eMESH; touchedMesh->mUserData = boxShape; touchedMesh->mOffset = origin; touchedMesh->mNbTris = 12; touchedMesh->mIndexWorldTriangles = worldTriangles.size(); // Reserve memory for incoming triangles PxTriangle* TouchedTriangles = reserve(worldTriangles, 12); for(PxU32 i = 0; i < 12; i++) { PxTriangle& CurrentTriangle = TouchedTriangles[i]; CurrentTriangle.verts[0] = boxVerts[boxTris[i][0]]; CurrentTriangle.verts[1] = boxVerts[boxTris[i][1]]; CurrentTriangle.verts[2] = boxVerts[boxTris[i][2]]; triIndicesArray.pushBack(PX_INVALID_U32); } }
static void outputConvexToStream( NxConvexShape* convexShape, NxShape* shape, IntArray& geom_stream, TriArray& world_triangles, TriArray* world_edge_normals, IntArray& edge_flags, const NxExtendedVec3& origin, const NxBounds3& tmpBounds ) { // Do AABB-mesh query NxU32 Nb; const NxU32* TF; // Collide AABB against current mesh // The overlap function doesn't exist for convexes so let's just dump all tris NxConvexMesh& cm = convexShape->getConvexMesh(); Nb = cm.getCount(0, NX_ARRAY_TRIANGLES); NX_ASSERT(cm.getFormat(0, NX_ARRAY_TRIANGLES)==NX_FORMAT_INT); TF = (const NxU32*)cm.getBase(0, NX_ARRAY_TRIANGLES); NX_ASSERT(cm.getFormat(0, NX_ARRAY_VERTICES)==NX_FORMAT_FLOAT); const NxVec3* verts = (const NxVec3*)cm.getBase(0, NX_ARRAY_VERTICES); NxMat34 absPose = shape->getGlobalPose(); NxVec3 tmp = shape->getGlobalPosition(); // LOSS OF ACCURACY NxVec3 MeshOffset; MeshOffset.x = float(tmp.x - origin.x); MeshOffset.y = float(tmp.y - origin.y); MeshOffset.z = float(tmp.z - origin.z); TouchedMesh* touchedMesh = (TouchedMesh*)reserve(geom_stream, sizeof(TouchedMesh)/sizeof(NxU32)); touchedMesh->mType = TOUCHED_MESH; touchedMesh->mUserData = shape; touchedMesh->mOffset = origin; touchedMesh->mNbTris = Nb; touchedMesh->mIndexWorldTriangles = world_triangles.size(); touchedMesh->mIndexWorldEdgeNormals = world_edge_normals ? world_edge_normals->size() : 0; touchedMesh->mIndexEdgeFlags = edge_flags.size(); // Reserve memory for incoming triangles NxTriangle* TouchedTriangles = reserve(world_triangles, Nb); NxTriangle* EdgeTriangles = world_edge_normals ? reserve(*world_edge_normals, Nb) : NULL; // Loop through touched triangles while(Nb--) { // Compute triangle in world space, add to array NxTriangle& CurrentTriangle = *TouchedTriangles++; NxU32 vref0 = *TF++; NxU32 vref1 = *TF++; NxU32 vref2 = *TF++; NxVec3 v0 = verts[vref0]; NxVec3 v1 = verts[vref1]; NxVec3 v2 = verts[vref2]; absPose.M.multiply(v0, v0); absPose.M.multiply(v1, v1); absPose.M.multiply(v2, v2); CurrentTriangle.verts[0] = v0; CurrentTriangle.verts[1] = v1; CurrentTriangle.verts[2] = v2; CurrentTriangle.verts[0] += MeshOffset; CurrentTriangle.verts[1] += MeshOffset; CurrentTriangle.verts[2] += MeshOffset; if(EdgeTriangles) { // #### hmmm NxTriangle edgeTri; edgeTri.verts[0].zero(); edgeTri.verts[1].zero(); edgeTri.verts[2].zero(); *EdgeTriangles++ = edgeTri; } // #### hmmm NxU32 edgeFlags = 7; edge_flags.pushBack(edgeFlags); } }
static void outputHeightFieldToStream( NxHeightFieldShape* hfShape, NxShape* shape, IntArray& geom_stream, TriArray& world_triangles, TriArray* world_edge_normals, IntArray& edge_flags, const NxExtendedVec3& origin, const NxBounds3& tmpBounds ) { // Do AABB-mesh query NxU32 Nb; const NxU32* TF; // Collide AABB against current mesh if(!hfShape->overlapAABBTriangles(tmpBounds, NX_QUERY_WORLD_SPACE, Nb, TF)) return; NxVec3 tmp = shape->getGlobalPosition(); // LOSS OF ACCURACY NxVec3 MeshOffset; MeshOffset.x = float(tmp.x - origin.x); MeshOffset.y = float(tmp.y - origin.y); MeshOffset.z = float(tmp.z - origin.z); TouchedMesh* touchedMesh = (TouchedMesh*)reserve(geom_stream, sizeof(TouchedMesh)/sizeof(NxU32)); touchedMesh->mType = TOUCHED_MESH; // ptchernev: seems to work touchedMesh->mUserData = shape; touchedMesh->mOffset = origin; touchedMesh->mNbTris = Nb; touchedMesh->mIndexWorldTriangles = world_triangles.size(); touchedMesh->mIndexWorldEdgeNormals = world_edge_normals ? world_edge_normals->size() : 0; touchedMesh->mIndexEdgeFlags = edge_flags.size(); // Reserve memory for incoming triangles NxTriangle* TouchedTriangles = reserve(world_triangles, Nb); NxTriangle* EdgeTriangles = world_edge_normals ? reserve(*world_edge_normals, Nb) : NULL; // Loop through touched triangles while(Nb--) { NxU32 Index = *TF++; // Compute triangle in world space, add to array NxTriangle& CurrentTriangle = *TouchedTriangles++; NxTriangle edgeTri; NxU32 edgeFlags; hfShape->getTriangle(CurrentTriangle, &edgeTri, &edgeFlags, Index, false); CurrentTriangle.verts[0] += MeshOffset; CurrentTriangle.verts[1] += MeshOffset; CurrentTriangle.verts[2] += MeshOffset; if(EdgeTriangles) { *EdgeTriangles++ = edgeTri; } edge_flags.pushBack(edgeFlags); #ifdef VISUALIZE_CCT_TRIS // Visualize debug triangles { // PhysicsSDK::getInstance().getDebugRenderable()->addTriangle((const NxVec3&)CurrentTriangle.mVerts[0], (const NxVec3&)CurrentTriangle.mVerts[1], (const NxVec3&)CurrentTriangle.mVerts[2], NX_ARGB_GREEN); NxGetPhysicsSDK()->getDebugRenderable()->addTriangle((const NxVec3&)CurrentTriangle.mVerts[0], (const NxVec3&)CurrentTriangle.mVerts[1], (const NxVec3&)CurrentTriangle.mVerts[2], NX_ARGB_GREEN); // PhysicsSDK::getInstance().getDebugRenderable()->addLine((const NxVec3&)CurrentTriangle.mVerts[0], (const NxVec3&)CurrentTriangle.mVerts[1], NX_ARGB_GREEN); // PhysicsSDK::getInstance().getDebugRenderable()->addLine((const NxVec3&)CurrentTriangle.mVerts[1], (const NxVec3&)CurrentTriangle.mVerts[2], NX_ARGB_GREEN); // PhysicsSDK::getInstance().getDebugRenderable()->addLine((const NxVec3&)CurrentTriangle.mVerts[2], (const NxVec3&)CurrentTriangle.mVerts[0], NX_ARGB_GREEN); } #endif } }
static void outputConvexToStream(PxShape* convexShape, const PxRigidActor* actor, const PxTransform& absPose_, IntArray& geomStream, TriArray& worldTriangles, IntArray& triIndicesArray, const PxExtendedVec3& origin, const PxBounds3& tmpBounds, const CCTParams& params, Cm::RenderBuffer* renderBuffer, PxU16& nbTessellation) { PX_ASSERT(convexShape->getGeometryType() == PxGeometryType::eCONVEXMESH); PxConvexMeshGeometry cg; convexShape->getConvexMeshGeometry(cg); PX_ASSERT(cg.convexMesh); // Do AABB-mesh query PxU32* TF; // Collide AABB against current mesh // The overlap function doesn't exist for convexes so let's just dump all tris PxConvexMesh& cm = *cg.convexMesh; // PT: convex triangles are not exposed anymore so we need to access convex polygons & triangulate them // PT: TODO: this is copied from "DrawObjects", move this to a shared place. Actually a helper directly in PxConvexMesh would be useful. PxU32 Nb = 0; { const PxU32 nbPolys = cm.getNbPolygons(); const PxU8* polygons = cm.getIndexBuffer(); for(PxU32 i=0;i<nbPolys;i++) { PxHullPolygon data; cm.getPolygonData(i, data); Nb += data.mNbVerts - 2; } // PT: revisit this code. We don't use the polygon offset? TF = (PxU32*)PxAlloca(sizeof(PxU32)*Nb*3); PxU32* t = TF; for(PxU32 i=0;i<nbPolys;i++) { PxHullPolygon data; cm.getPolygonData(i, data); const PxU32 nbV = data.mNbVerts; const PxU32 nbTris = nbV - 2; const PxU8 vref0 = *polygons; for(PxU32 j=0;j<nbTris;j++) { const PxU32 vref1 = polygons[(j+1)%nbV]; const PxU32 vref2 = polygons[(j+2)%nbV]; *t++ = vref0; *t++ = vref1; *t++ = vref2; } polygons += nbV; } } // PT: you can't use PxTransform with a non-uniform scaling const PxMat33 rot = PxMat33(absPose_.q) * cg.scale.toMat33(); const PxMat44 absPose(rot, absPose_.p); const PxVec3 p = absPose.getPosition(); const PxVec3 MeshOffset(float(p.x - origin.x), float(p.y - origin.y), float(p.z - origin.z)); // LOSS OF ACCURACY const PxVec3 offset(float(-origin.x), float(-origin.y), float(-origin.z)); TouchedMesh* touchedMesh = (TouchedMesh*)reserve(geomStream, sizeof(TouchedMesh)/sizeof(PxU32)); touchedMesh->mType = TouchedGeomType::eMESH; touchedMesh->mTGUserData = convexShape; touchedMesh->mActor = actor; touchedMesh->mOffset = origin; touchedMesh->mIndexWorldTriangles = worldTriangles.size(); const PxVec3* verts = cm.getVertices(); // Loop through touched triangles if(params.mTessellation) { const PxBoxGeometry boxGeom(tmpBounds.getExtents()); const PxBounds3 cullingBox = PxBounds3::centerExtents(tmpBounds.getCenter() + offset, boxGeom.halfExtents); PxU32 nbCreatedTris = 0; while(Nb--) { // Compute triangle in world space, add to array PxTriangle currentTriangle; const PxU32 vref0 = *TF++; const PxU32 vref1 = *TF++; const PxU32 vref2 = *TF++; currentTriangle.verts[0] = MeshOffset + absPose.rotate(verts[vref0]); currentTriangle.verts[1] = MeshOffset + absPose.rotate(verts[vref1]); currentTriangle.verts[2] = MeshOffset + absPose.rotate(verts[vref2]); PxU32 nbNewTris = 0; tessellateTriangle(nbNewTris, currentTriangle, PX_INVALID_U32, worldTriangles, triIndicesArray, cullingBox, params, nbTessellation); nbCreatedTris += nbNewTris; } touchedMesh->mNbTris = nbCreatedTris; } else { // Reserve memory for incoming triangles PxTriangle* TouchedTriangles = reserve(worldTriangles, Nb); touchedMesh->mNbTris = Nb; while(Nb--) { // Compute triangle in world space, add to array PxTriangle& currentTriangle = *TouchedTriangles++; const PxU32 vref0 = *TF++; const PxU32 vref1 = *TF++; const PxU32 vref2 = *TF++; currentTriangle.verts[0] = MeshOffset + absPose.rotate(verts[vref0]); currentTriangle.verts[1] = MeshOffset + absPose.rotate(verts[vref1]); currentTriangle.verts[2] = MeshOffset + absPose.rotate(verts[vref2]); triIndicesArray.pushBack(PX_INVALID_U32); } } if(gVisualizeTouchedTris) visualizeTouchedTriangles(touchedMesh->mNbTris, touchedMesh->mIndexWorldTriangles, &worldTriangles[0], renderBuffer, offset, params.mUpDirection); }
static void outputMeshToStream( PxShape* meshShape, const PxRigidActor* actor, const PxTransform& meshPose, IntArray& geomStream, TriArray& worldTriangles, IntArray& triIndicesArray, const PxExtendedVec3& origin, const PxBounds3& tmpBounds, const CCTParams& params, Cm::RenderBuffer* renderBuffer, PxU16& nbTessellation) { PX_ASSERT(meshShape->getGeometryType() == PxGeometryType::eTRIANGLEMESH); // Do AABB-mesh query PxTriangleMeshGeometry triGeom; meshShape->getTriangleMeshGeometry(triGeom); const PxBoxGeometry boxGeom(tmpBounds.getExtents()); const PxTransform boxPose(tmpBounds.getCenter(), PxQuat(PxIdentity)); // Collide AABB against current mesh PxMeshOverlapUtil overlapUtil; const PxU32 nbTouchedTris = overlapUtil.findOverlap(boxGeom, boxPose, triGeom, meshPose); const PxVec3 offset(float(-origin.x), float(-origin.y), float(-origin.z)); TouchedMesh* touchedMesh = (TouchedMesh*)reserve(geomStream, sizeof(TouchedMesh)/sizeof(PxU32)); touchedMesh->mType = TouchedGeomType::eMESH; touchedMesh->mTGUserData = meshShape; touchedMesh->mActor = actor; touchedMesh->mOffset = origin; touchedMesh->mNbTris = nbTouchedTris; touchedMesh->mIndexWorldTriangles = worldTriangles.size(); const PxU32* PX_RESTRICT indices = overlapUtil.getResults(); if(params.mSlopeLimit!=0.0f) { if(!params.mTessellation) { // Loop through touched triangles PxU32 nbCreatedTris = 0; for(PxU32 i=0; i < nbTouchedTris; i++) { const PxU32 triangleIndex = indices[i]; // Compute triangle in world space, add to array PxTriangle currentTriangle; PxMeshQuery::getTriangle(triGeom, meshPose, triangleIndex, currentTriangle); currentTriangle.verts[0] += offset; currentTriangle.verts[1] += offset; currentTriangle.verts[2] += offset; const PxU32 nbNewTris = createInvisibleWalls(params, currentTriangle, worldTriangles, triIndicesArray); nbCreatedTris += nbNewTris; if(!nbNewTris) { worldTriangles.pushBack(currentTriangle); triIndicesArray.pushBack(triangleIndex); nbCreatedTris++; } } touchedMesh->mNbTris = nbCreatedTris; } else { const PxBounds3 cullingBox = PxBounds3::centerExtents(boxPose.p + offset, boxGeom.halfExtents); // Loop through touched triangles PxU32 nbCreatedTris = 0; for(PxU32 i=0; i < nbTouchedTris; i++) { const PxU32 triangleIndex = indices[i]; // Compute triangle in world space, add to array PxTriangle currentTriangle; PxMeshQuery::getTriangle(triGeom, meshPose, triangleIndex, currentTriangle); currentTriangle.verts[0] += offset; currentTriangle.verts[1] += offset; currentTriangle.verts[2] += offset; PxU32 nbNewTris = createInvisibleWalls(params, currentTriangle, worldTriangles, triIndicesArray); nbCreatedTris += nbNewTris; if(!nbNewTris) { /* worldTriangles.pushBack(currentTriangle); triIndicesArray.pushBack(triangleIndex); nbCreatedTris++;*/ tessellateTriangle(nbNewTris, currentTriangle, triangleIndex, worldTriangles, triIndicesArray, cullingBox, params, nbTessellation); nbCreatedTris += nbNewTris; // printf("Tesselate: %d new tris\n", nbNewTris); } } touchedMesh->mNbTris = nbCreatedTris; } } else { if(!params.mTessellation) { // Reserve memory for incoming triangles PxTriangle* TouchedTriangles = reserve(worldTriangles, nbTouchedTris); // Loop through touched triangles for(PxU32 i=0; i < nbTouchedTris; i++) { const PxU32 triangleIndex = indices[i]; // Compute triangle in world space, add to array PxTriangle& currentTriangle = *TouchedTriangles++; PxMeshQuery::getTriangle(triGeom, meshPose, triangleIndex, currentTriangle); currentTriangle.verts[0] += offset; currentTriangle.verts[1] += offset; currentTriangle.verts[2] += offset; triIndicesArray.pushBack(triangleIndex); } } else { const PxBounds3 cullingBox = PxBounds3::centerExtents(boxPose.p + offset, boxGeom.halfExtents); PxU32 nbCreatedTris = 0; for(PxU32 i=0; i < nbTouchedTris; i++) { const PxU32 triangleIndex = indices[i]; // Compute triangle in world space, add to array PxTriangle currentTriangle; PxMeshQuery::getTriangle(triGeom, meshPose, triangleIndex, currentTriangle); currentTriangle.verts[0] += offset; currentTriangle.verts[1] += offset; currentTriangle.verts[2] += offset; PxU32 nbNewTris = 0; tessellateTriangle(nbNewTris, currentTriangle, triangleIndex, worldTriangles, triIndicesArray, cullingBox, params, nbTessellation); // printf("Tesselate: %d new tris\n", nbNewTris); nbCreatedTris += nbNewTris; } touchedMesh->mNbTris = nbCreatedTris; } } if(gVisualizeTouchedTris) visualizeTouchedTriangles(touchedMesh->mNbTris, touchedMesh->mIndexWorldTriangles, &worldTriangles[0], renderBuffer, offset, params.mUpDirection); }
static void outputBoxToStream( PxShape* boxShape, const PxRigidActor* actor, const PxTransform& globalPose, IntArray& geomStream, TriArray& worldTriangles, IntArray& triIndicesArray, const PxExtendedVec3& origin, const PxBounds3& tmpBounds, const CCTParams& params, PxU16& nbTessellation) { PX_ASSERT(boxShape->getGeometryType() == PxGeometryType::eBOX); PxBoxGeometry bg; boxShape->getBoxGeometry(bg); //8 verts in local space. const PxF32 dx = bg.halfExtents.x; const PxF32 dy = bg.halfExtents.y; const PxF32 dz = bg.halfExtents.z; PxVec3 boxVerts[8]= { PxVec3(-dx,-dy,-dz), PxVec3(+dx,-dy,-dz), PxVec3(+dx,+dy,-dz), PxVec3(-dx,+dy,-dz), PxVec3(-dx,-dy,+dz), PxVec3(+dx,-dy,+dz), PxVec3(+dx,+dy,+dz), PxVec3(-dx,+dy,+dz) }; //Transform verts into world space. const PxVec3 pxOrigin = toVec3(origin); for(PxU32 i = 0; i < 8; i++) { boxVerts[i] = globalPose.transform(boxVerts[i]) - pxOrigin; } //Index of triangles. const PxU32 boxTris[12][3]= { {0,2,1}, {2,0,3}, //0,1,2,3 {3,6,2}, {6,3,7}, //3,2,6,7 {7,5,6}, {5,7,4}, //7,6,5,4 {4,1,5}, {1,4,0}, //4,5,1,0 {0,7,3}, {7,0,4}, //0,3,7,4 {2,5,1}, {5,2,6} //2,1,5,6 }; TouchedMesh* touchedMesh = (TouchedMesh*)reserve(geomStream, sizeof(TouchedMesh)/sizeof(PxU32)); touchedMesh->mType = TouchedGeomType::eMESH; touchedMesh->mTGUserData = boxShape; touchedMesh->mActor = actor; touchedMesh->mOffset = origin; touchedMesh->mIndexWorldTriangles = worldTriangles.size(); if(params.mTessellation) { const PxBoxGeometry boxGeom(tmpBounds.getExtents()); const PxVec3 offset(float(-origin.x), float(-origin.y), float(-origin.z)); const PxBounds3 cullingBox = PxBounds3::centerExtents(tmpBounds.getCenter() + offset, boxGeom.halfExtents); PxU32 nbCreatedTris = 0; for(PxU32 i=0; i<12; i++) { // Compute triangle in world space, add to array const PxTriangle currentTriangle(boxVerts[boxTris[i][0]], boxVerts[boxTris[i][1]], boxVerts[boxTris[i][2]]); PxU32 nbNewTris = 0; tessellateTriangle(nbNewTris, currentTriangle, PX_INVALID_U32, worldTriangles, triIndicesArray, cullingBox, params, nbTessellation); nbCreatedTris += nbNewTris; } touchedMesh->mNbTris = nbCreatedTris; } else { touchedMesh->mNbTris = 12; // Reserve memory for incoming triangles PxTriangle* TouchedTriangles = reserve(worldTriangles, 12); for(PxU32 i=0; i<12; i++) { PxTriangle& currentTriangle = TouchedTriangles[i]; currentTriangle.verts[0] = boxVerts[boxTris[i][0]]; currentTriangle.verts[1] = boxVerts[boxTris[i][1]]; currentTriangle.verts[2] = boxVerts[boxTris[i][2]]; triIndicesArray.pushBack(PX_INVALID_U32); } } }