diff options
| author | sschirm <[email protected]> | 2016-12-23 14:20:36 +0100 |
|---|---|---|
| committer | sschirm <[email protected]> | 2016-12-23 14:56:17 +0100 |
| commit | ef6937e69e8ee3f409cf9d460d5ad300a65d5924 (patch) | |
| tree | 710426e8daa605551ce3f34b581897011101c30f /PhysX_3.4/Source/PhysX/src/NpShapeManager.cpp | |
| parent | Initial commit: (diff) | |
| download | physx-3.4-ef6937e69e8ee3f409cf9d460d5ad300a65d5924.tar.xz physx-3.4-ef6937e69e8ee3f409cf9d460d5ad300a65d5924.zip | |
PhysX 3.4 / APEX 1.4 release candidate @21506124
Diffstat (limited to 'PhysX_3.4/Source/PhysX/src/NpShapeManager.cpp')
| -rw-r--r-- | PhysX_3.4/Source/PhysX/src/NpShapeManager.cpp | 460 |
1 files changed, 444 insertions, 16 deletions
diff --git a/PhysX_3.4/Source/PhysX/src/NpShapeManager.cpp b/PhysX_3.4/Source/PhysX/src/NpShapeManager.cpp index ab2d6d8b..55eceec6 100644 --- a/PhysX_3.4/Source/PhysX/src/NpShapeManager.cpp +++ b/PhysX_3.4/Source/PhysX/src/NpShapeManager.cpp @@ -31,7 +31,6 @@ #include "NpFactory.h" #include "ScbRigidObject.h" #include "NpActor.h" -#include "SqSceneQueryManager.h" #include "SqPruningStructure.h" #include "NpScene.h" #include "NpPtrTableStorageManager.h" @@ -40,6 +39,8 @@ using namespace physx; using namespace Sq; +using namespace Gu; +using namespace Cm; namespace physx { @@ -63,7 +64,7 @@ NpShapeManager::NpShapeManager(const PxEMPTY) : NpShapeManager::~NpShapeManager() { PX_ASSERT(!mPruningStructure); - Cm::PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager(); + PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager(); mShapes.clear(sm); mSceneQueryData.clear(sm); } @@ -85,7 +86,7 @@ void NpShapeManager::attachShape(NpShape& shape, PxRigidActor& actor) { PX_ASSERT(!mPruningStructure); - Cm::PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager(); + PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager(); const PxU32 index = getNbShapes(); mShapes.add(&shape, sm); @@ -106,7 +107,7 @@ void NpShapeManager::detachShape(NpShape& s, PxRigidActor& actor, bool wakeOnLos { PX_ASSERT(!mPruningStructure); - Cm::PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager(); + PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager(); const PxU32 index = mShapes.find(&s); PX_ASSERT(index!=0xffffffff); @@ -143,7 +144,7 @@ void NpShapeManager::detachAll(NpScene* scene) for(PxU32 i=0;i<nbShapes;i++) shapes[i]->onActorDetach(); - Cm::PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager(); + PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager(); mShapes.clear(sm); mSceneQueryData.clear(sm); @@ -151,7 +152,7 @@ void NpShapeManager::detachAll(NpScene* scene) PxU32 NpShapeManager::getShapes(PxShape** buffer, PxU32 bufferSize, PxU32 startIndex) const { - return Cm::getArrayOfPointers(buffer, bufferSize, startIndex, getShapes(), getNbShapes()); + return getArrayOfPointers(buffer, bufferSize, startIndex, getShapes(), getNbShapes()); } PxBounds3 NpShapeManager::getWorldBounds(const PxRigidActor& actor) const @@ -159,11 +160,11 @@ PxBounds3 NpShapeManager::getWorldBounds(const PxRigidActor& actor) const PxBounds3 bounds(PxBounds3::empty()); const PxU32 nbShapes = getNbShapes(); - PxTransform actorPose = actor.getGlobalPose(); + const PxTransform actorPose = actor.getGlobalPose(); NpShape*const* PX_RESTRICT shapes = getShapes(); for(PxU32 i=0;i<nbShapes;i++) - bounds.include(Gu::computeBounds(shapes[i]->getScbShape().getGeometry(), actorPose * shapes[i]->getLocalPoseFast(), !physx::gUnifiedHeightfieldCollision)); + bounds.include(Gu::computeBounds(shapes[i]->getScbShape().getGeometry(), actorPose * shapes[i]->getLocalPoseFast(), !gUnifiedHeightfieldCollision)); return bounds; } @@ -284,26 +285,453 @@ void NpShapeManager::teardownSceneQuery(SceneQueryManager& sqManager, PxU32 inde } #if PX_ENABLE_DEBUG_VISUALIZATION -void NpShapeManager::visualize(Cm::RenderOutput& out, NpScene* scene, const PxRigidActor& actor) +#include "GuHeightFieldUtil.h" +#include "PxGeometryQuery.h" +#include "PxMeshQuery.h" +#include "GuConvexEdgeFlags.h" +#include "GuMidphaseInterface.h" + +static const PxDebugColor::Enum gColors[] = +{ + PxDebugColor::eARGB_BLACK, + PxDebugColor::eARGB_RED, + PxDebugColor::eARGB_GREEN, + PxDebugColor::eARGB_BLUE, + PxDebugColor::eARGB_YELLOW, + PxDebugColor::eARGB_MAGENTA, + PxDebugColor::eARGB_CYAN, + PxDebugColor::eARGB_WHITE, + PxDebugColor::eARGB_GREY, + PxDebugColor::eARGB_DARKRED, + PxDebugColor::eARGB_DARKGREEN, + PxDebugColor::eARGB_DARKBLUE, +}; + +static const PxU32 gColorCount = sizeof(gColors)/sizeof(PxDebugColor::Enum); + +static const PxU32 gCollisionShapeColor = PxU32(PxDebugColor::eARGB_MAGENTA); + +static void visualizeSphere(const PxSphereGeometry& geometry, RenderOutput& out, const PxTransform& absPose) +{ + out << gCollisionShapeColor; // PT: no need to output this for each segment! + + out << absPose << DebugCircle(100, geometry.radius); + + PxMat44 rotPose(absPose); + Ps::swap(rotPose.column1, rotPose.column2); + rotPose.column1 = -rotPose.column1; + out << rotPose << DebugCircle(100, geometry.radius); + + Ps::swap(rotPose.column0, rotPose.column2); + rotPose.column0 = -rotPose.column0; + out << rotPose << DebugCircle(100, geometry.radius); +} + +static void visualizePlane(const PxPlaneGeometry& /*geometry*/, RenderOutput& out, const PxTransform& absPose) +{ + PxMat44 rotPose(absPose); + Ps::swap(rotPose.column1, rotPose.column2); + rotPose.column1 = -rotPose.column1; + + Ps::swap(rotPose.column0, rotPose.column2); + rotPose.column0 = -rotPose.column0; + + out << rotPose << gCollisionShapeColor; // PT: no need to output this for each segment! + for(PxReal radius = 2.0f; radius < 20.0f ; radius += 2.0f) + out << DebugCircle(100, radius*radius); +} + +static void visualizeCapsule(const PxCapsuleGeometry& geometry, RenderOutput& out, const PxTransform& absPose) +{ + out << gCollisionShapeColor; + out.outputCapsule(geometry.radius, geometry.halfHeight, absPose); +} + +static void visualizeBox(const PxBoxGeometry& geometry, RenderOutput& out, const PxTransform& absPose) +{ + out << gCollisionShapeColor; + out << absPose << DebugBox(geometry.halfExtents); +} + +static void visualizeConvexMesh(const PxConvexMeshGeometry& geometry, RenderOutput& out, const PxTransform& absPose) +{ + const ConvexMesh* convexMesh = static_cast<const ConvexMesh*>(geometry.convexMesh); + const ConvexHullData& hullData = convexMesh->getHull(); + + const PxVec3* vertices = hullData.getHullVertices(); + const PxU8* indexBuffer = hullData.getVertexData8(); + const PxU32 nbPolygons = convexMesh->getNbPolygonsFast(); + + const PxMat44 m44(PxMat33(absPose.q) * geometry.scale.toMat33(), absPose.p); + + out << m44 << gCollisionShapeColor; // PT: no need to output this for each segment! + + for(PxU32 i=0; i<nbPolygons; i++) + { + const PxU32 pnbVertices = hullData.mPolygons[i].mNbVerts; + + PxVec3 begin = m44.transform(vertices[indexBuffer[0]]); // PT: transform it only once before the loop starts + for(PxU32 j=1; j<pnbVertices; j++) + { + const PxVec3 end = m44.transform(vertices[indexBuffer[j]]); + out.outputSegment(begin, end); + begin = end; + } + out.outputSegment(begin, m44.transform(vertices[indexBuffer[0]])); + + indexBuffer += pnbVertices; + } +} + +static void getTriangle(const Gu::TriangleMesh&, PxU32 i, PxVec3* wp, const PxVec3* vertices, const void* indices, bool has16BitIndices) +{ + PxU32 ref0, ref1, ref2; + + if(!has16BitIndices) + { + const PxU32* dtriangles = reinterpret_cast<const PxU32*>(indices); + ref0 = dtriangles[i*3+0]; + ref1 = dtriangles[i*3+1]; + ref2 = dtriangles[i*3+2]; + } + else + { + const PxU16* wtriangles = reinterpret_cast<const PxU16*>(indices); + ref0 = wtriangles[i*3+0]; + ref1 = wtriangles[i*3+1]; + ref2 = wtriangles[i*3+2]; + } + + wp[0] = vertices[ref0]; + wp[1] = vertices[ref1]; + wp[2] = vertices[ref2]; +} + +static void getTriangle(const Gu::TriangleMesh& mesh, PxU32 i, PxVec3* wp, const PxVec3* vertices, const void* indices, const Matrix34& absPose, bool has16BitIndices) +{ + PxVec3 localVerts[3]; + getTriangle(mesh, i, localVerts, vertices, indices, has16BitIndices); + + wp[0] = absPose.transform(localVerts[0]); + wp[1] = absPose.transform(localVerts[1]); + wp[2] = absPose.transform(localVerts[2]); +} + +static void visualizeActiveEdges(RenderOutput& out, const Gu::TriangleMesh& mesh, PxU32 nbTriangles, const PxU32* results, const Matrix34& absPose) +{ + const PxU8* extraTrigData = mesh.getExtraTrigData(); + PX_ASSERT(extraTrigData); + + const PxVec3* vertices = mesh.getVerticesFast(); + const void* indices = mesh.getTrianglesFast(); + + out << PxU32(PxDebugColor::eARGB_YELLOW); // PT: no need to output this for each segment! + + const bool has16Bit = mesh.has16BitIndices(); + for(PxU32 i=0; i<nbTriangles; i++) + { + const PxU32 index = results ? results[i] : i; + + PxVec3 wp[3]; + getTriangle(mesh, index, wp, vertices, indices, absPose, has16Bit); + + const PxU32 flags = extraTrigData[index]; + + if(flags & Gu::ETD_CONVEX_EDGE_01) + out.outputSegment(wp[0], wp[1]); + + if(flags & Gu::ETD_CONVEX_EDGE_12) + out.outputSegment(wp[1], wp[2]); + + if(flags & Gu::ETD_CONVEX_EDGE_20) + out.outputSegment(wp[0], wp[2]); + } +} + +static void visualizeFaceNormals( PxReal fscale, RenderOutput& out, const TriangleMesh& mesh, PxU32 nbTriangles, const PxVec3* vertices, + const void* indices, bool has16Bit, const PxU32* results, const Matrix34& absPose, const PxMat44& midt) +{ + if(fscale==0.0f) + return; + + out << midt << PxU32(PxDebugColor::eARGB_DARKRED); // PT: no need to output this for each segment! + + for(PxU32 i=0; i<nbTriangles; i++) + { + const PxU32 index = results ? results[i] : i; + PxVec3 wp[3]; + getTriangle(mesh, index, wp, vertices, indices, absPose, has16Bit); + + const PxVec3 center = (wp[0] + wp[1] + wp[2]) / 3.0f; + PxVec3 normal = (wp[0] - wp[1]).cross(wp[0] - wp[2]); + PX_ASSERT(!normal.isZero()); + normal = normal.getNormalized(); + + out << DebugArrow(center, normal * fscale); + } +} + +static PX_FORCE_INLINE void outputTriangle(PxDebugLine* segments, const PxVec3& v0, const PxVec3& v1, const PxVec3& v2, PxU32 color) +{ + // PT: TODO: use SIMD + segments[0] = PxDebugLine(v0, v1, color); + segments[1] = PxDebugLine(v1, v2, color); + segments[2] = PxDebugLine(v2, v0, color); +} + +static void visualizeTriangleMesh(const PxTriangleMeshGeometry& geometry, RenderOutput& out, const PxTransform& pose, const PxBounds3& cullbox, const PxReal fscale, bool visualizeShapes, bool visualizeEdges, bool useCullBox) +{ + const TriangleMesh* triangleMesh = static_cast<const TriangleMesh*>(geometry.triangleMesh); + + const PxMat44 midt(PxIdentity); + const Matrix34 absPose(PxMat33(pose.q) * geometry.scale.toMat33(), pose.p); + + PxU32 nbTriangles = triangleMesh->getNbTrianglesFast(); + const PxU32 nbVertices = triangleMesh->getNbVerticesFast(); + const PxVec3* vertices = triangleMesh->getVerticesFast(); + const void* indices = triangleMesh->getTrianglesFast(); + const bool has16Bit = triangleMesh->has16BitIndices(); + + // PT: TODO: don't render the same edge multiple times + + PxU32* results = NULL; + if(useCullBox) + { + const Gu::Box worldBox( + (cullbox.maximum + cullbox.minimum)*0.5f, + (cullbox.maximum - cullbox.minimum)*0.5f, + PxMat33(PxIdentity)); + + // PT: TODO: use the callback version here to avoid allocating this huge array + results = reinterpret_cast<PxU32*>(PX_ALLOC_TEMP(sizeof(PxU32)*nbTriangles, "tmp triangle indices")); + LimitedResults limitedResults(results, nbTriangles, 0); + Midphase::intersectBoxVsMesh(worldBox, *triangleMesh, pose, geometry.scale, &limitedResults); + nbTriangles = limitedResults.mNbResults; + + if(visualizeShapes) + { + const PxU32 scolor = gCollisionShapeColor; + + out << midt << scolor; // PT: no need to output this for each segment! + + PxDebugLine* segments = out.reserveSegments(nbTriangles*3); + for(PxU32 i=0; i<nbTriangles; i++) + { + PxVec3 wp[3]; + getTriangle(*triangleMesh, results[i], wp, vertices, indices, absPose, has16Bit); + outputTriangle(segments, wp[0], wp[1], wp[2], scolor); + segments+=3; + } + } + } + else + { + if(visualizeShapes) + { + PxU32 scolor = gCollisionShapeColor; + + out << midt << scolor; // PT: no need to output this for each segment! + + // PT: TODO: use SIMD + PxVec3* transformed = reinterpret_cast<PxVec3*>(PX_ALLOC(sizeof(PxVec3)*nbVertices, "PxVec3")); + for(PxU32 i=0;i<nbVertices;i++) + transformed[i] = absPose.transform(vertices[i]); + + PxDebugLine* segments = out.reserveSegments(nbTriangles*3); + for(PxU32 i=0; i<nbTriangles; i++) + { + PxVec3 wp[3]; + getTriangle(*triangleMesh, i, wp, transformed, indices, has16Bit); + const PxU32 localMaterialIndex = triangleMesh->getTriangleMaterialIndex(i); + // PT: TODO: I doubt this is correct. "localMaterialIndex" will be 0xffff for most meshes so + // the color we pick is basically random. Also, get rid of these modulos (==divisions) + scolor = gColors[localMaterialIndex % gColorCount]; + + outputTriangle(segments, wp[0], wp[1], wp[2], scolor); + segments+=3; + } + + PX_FREE(transformed); + } + } + + visualizeFaceNormals(fscale, out, *triangleMesh, nbTriangles, vertices, indices, has16Bit, results, absPose, midt); + + if(visualizeEdges && triangleMesh->getExtraTrigData()) + visualizeActiveEdges(out, *triangleMesh, nbTriangles, results, absPose); + + if(results) + PX_FREE(results); +} + +static void visualizeHeightField(const PxHeightFieldGeometry& hfGeometry, RenderOutput& out, const PxTransform& absPose, const PxBounds3& cullbox, bool useCullBox) { + const HeightField* heightfield = static_cast<const HeightField*>(hfGeometry.heightField); + + // PT: TODO: the debug viz for HFs is minimal at the moment... + // PT: TODO: REALLY? all shapes use magenta but HFs use yellow? + PxU32 scolor = PxU32(PxDebugColor::eARGB_YELLOW); + const PxMat44 midt = PxMat44(PxIdentity); + + HeightFieldUtil hfUtil(hfGeometry); + + const PxU32 nbRows = heightfield->getNbRowsFast(); + const PxU32 nbColumns = heightfield->getNbColumnsFast(); + const PxU32 nbVerts = nbRows * nbColumns; + const PxU32 nbTriangles = 2 * nbVerts; + + out << midt << scolor; // PT: no need to output the same matrix/color for each triangle + + if(useCullBox) + { + const PxTransform pose0((cullbox.maximum + cullbox.minimum)*0.5f); + const PxBoxGeometry boxGeometry((cullbox.maximum - cullbox.minimum)*0.5f); + + PxU32* results = reinterpret_cast<PxU32*>(PX_ALLOC(sizeof(PxU32)*nbTriangles, "tmp triangle indices")); + + bool overflow = false; + PxU32 nbTouchedTris = PxMeshQuery::findOverlapHeightField(boxGeometry, pose0, hfGeometry, absPose, results, nbTriangles, 0, overflow); + + PxDebugLine* segments = out.reserveSegments(nbTouchedTris*3); + + for(PxU32 i=0; i<nbTouchedTris; i++) + { + const PxU32 index = results[i]; + PxTriangle currentTriangle; + PxMeshQuery::getTriangle(hfGeometry, absPose, index, currentTriangle); + + //The check has been done in the findOverlapHeightField + //if(heightfield->isValidTriangle(index) && heightfield->getTriangleMaterial(index) != PxHeightFieldMaterial::eHOLE) + { + const PxU16 localMaterialIndex = heightfield->getTriangleMaterialIndex(index); + // PT: TODO: optimize away modulos/divisions + scolor = gColors[localMaterialIndex % gColorCount]; + + outputTriangle(segments, currentTriangle.verts[0], currentTriangle.verts[1], currentTriangle.verts[2], scolor); + segments+=3; + } + } + PX_FREE(results); + } + else + { + // PT: transform vertices only once + PxVec3* tmpVerts = reinterpret_cast<PxVec3*>(PX_ALLOC(sizeof(PxVec3)*nbVerts, "PxVec3")); + // PT: TODO: optimize the following line + for(PxU32 i=0;i<nbVerts;i++) + tmpVerts[i] = absPose.transform(hfUtil.hf2shapep(heightfield->getVertex(i))); + + for(PxU32 i=0; i<nbTriangles; i++) + { + // PT: TODO: optimize away the useless divisions/modulos in the lines below + if(heightfield->isValidTriangle(i) && heightfield->getTriangleMaterial(i) != PxHeightFieldMaterial::eHOLE) + { + PxU32 vi0, vi1, vi2; + heightfield->getTriangleVertexIndices(i, vi0, vi1, vi2); + const PxU16 localMaterialIndex = heightfield->getTriangleMaterialIndex(i); + + PxDebugLine* segments = out.reserveSegments(3); + outputTriangle(segments, tmpVerts[vi0], tmpVerts[vi1], tmpVerts[vi2], gColors[localMaterialIndex % gColorCount]); + } + } + PX_FREE(tmpVerts); + } +} + +static void visualize(const PxGeometry& geometry, RenderOutput& out, const PxTransform& absPose, const PxBounds3& cullbox, const PxReal fscale, bool visualizeShapes, bool visualizeEdges, bool useCullBox) +{ + // triangle meshes can render active edges or face normals, but for other types we can just early out if there are no collision shapes + if(!visualizeShapes && geometry.getType() != PxGeometryType::eTRIANGLEMESH) + return; + + switch(geometry.getType()) + { + case PxGeometryType::eSPHERE: + visualizeSphere(static_cast<const PxSphereGeometry&>(geometry), out, absPose); + break; + case PxGeometryType::eBOX: + visualizeBox(static_cast<const PxBoxGeometry&>(geometry), out, absPose); + break; + case PxGeometryType::ePLANE: + visualizePlane(static_cast<const PxPlaneGeometry&>(geometry), out, absPose); + break; + case PxGeometryType::eCAPSULE: + visualizeCapsule(static_cast<const PxCapsuleGeometry&>(geometry), out, absPose); + break; + case PxGeometryType::eCONVEXMESH: + visualizeConvexMesh(static_cast<const PxConvexMeshGeometry&>(geometry), out, absPose); + break; + case PxGeometryType::eTRIANGLEMESH: + visualizeTriangleMesh(static_cast<const PxTriangleMeshGeometry&>(geometry), out, absPose, cullbox, fscale, visualizeShapes, visualizeEdges, useCullBox); + break; + case PxGeometryType::eHEIGHTFIELD: + visualizeHeightField(static_cast<const PxHeightFieldGeometry&>(geometry), out, absPose, cullbox, useCullBox); + break; + case PxGeometryType::eINVALID: + break; + case PxGeometryType::eGEOMETRY_COUNT: + break; + } +} + +void NpShapeManager::visualize(RenderOutput& out, NpScene* scene, const PxRigidActor& actor) +{ + const PxReal scale = scene->getVisualizationParameter(PxVisualizationParameter::eSCALE); + if(!scale) + return; + const PxU32 nbShapes = getNbShapes(); NpShape*const* PX_RESTRICT shapes = getShapes(); - PxTransform actorPose = actor.getGlobalPose(); const bool visualizeCompounds = (nbShapes>1) && scene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_COMPOUNDS)!=0.0f; + // PT: moved all these out of the loop, no need to grab them once per shape + const bool visualizeAABBs = scene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_AABBS)!=0.0f; + const bool visualizeShapes = scene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_SHAPES)!=0.0f; + const bool visualizeEdges = scene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_EDGES)!=0.0f; + const float fNormals = scene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_FNORMALS); + const bool visualizeFNormals = fNormals!=0.0f; + const bool visualizeCollision = visualizeShapes || visualizeFNormals || visualizeEdges; + const bool useCullBox = scene->getVisualizationParameter(PxVisualizationParameter::eCULL_BOX)!=0.0f; + const bool needsShapeBounds0 = visualizeCompounds || (visualizeCollision && useCullBox); + const PxReal collisionAxes = scale * scene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_AXES); + const PxReal fscale = scale * fNormals; + const PxBounds3& cullbox = scene->getScene().getVisualizationCullingBox(); + + const PxTransform actorPose = actor.getGlobalPose(); + PxBounds3 compoundBounds(PxBounds3::empty()); for(PxU32 i=0;i<nbShapes;i++) { - Scb::Shape& shape = shapes[i]->getScbShape(); - if(shape.getFlags() & PxShapeFlag::eVISUALIZATION) + const Scb::Shape& scbShape = shapes[i]->getScbShape(); + + const PxTransform absPose = actorPose * scbShape.getShape2Actor(); + const PxGeometry& geom = scbShape.getGeometry(); + + const bool shapeDebugVizEnabled = scbShape.getFlags() & PxShapeFlag::eVISUALIZATION; + + const bool needsShapeBounds = needsShapeBounds0 || (visualizeAABBs && shapeDebugVizEnabled); + const PxBounds3 currentShapeBounds = needsShapeBounds ? Gu::computeBounds(geom, absPose, !gUnifiedHeightfieldCollision) : PxBounds3::empty(); + + if(shapeDebugVizEnabled) { - shapes[i]->visualize(out, actor); - if(visualizeCompounds) - compoundBounds.include(Gu::computeBounds(shape.getGeometry(), actorPose*shapes[i]->getLocalPose(), !physx::gUnifiedHeightfieldCollision)); + if(visualizeAABBs) + out << PxU32(PxDebugColor::eARGB_YELLOW) << PxMat44(PxIdentity) << DebugBox(currentShapeBounds); + + if(collisionAxes != 0.0f) + out << PxMat44(absPose) << DebugBasis(PxVec3(collisionAxes), 0xcf0000, 0x00cf00, 0x0000cf); + + if(visualizeCollision) + { + if(!useCullBox || cullbox.intersects(currentShapeBounds)) + ::visualize(geom, out, absPose, cullbox, fscale, visualizeShapes, visualizeEdges, useCullBox); + } } + + if(visualizeCompounds) + compoundBounds.include(currentShapeBounds); } if(visualizeCompounds && !compoundBounds.isEmpty()) - out << PxU32(PxDebugColor::eARGB_MAGENTA) << PxMat44(PxIdentity) << Cm::DebugBox(compoundBounds); + out << gCollisionShapeColor << PxMat44(PxIdentity) << DebugBox(compoundBounds); } #endif // PX_ENABLE_DEBUG_VISUALIZATION |