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 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 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); }