Files
XCEngine/engine/third_party/physx/source/simulationcontroller/src/ScVisualize.cpp

268 lines
10 KiB
C++
Raw Normal View History

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "ScScene.h"
#include "ScNPhaseCore.h"
#include "ScShapeInteraction.h"
#include "ScConstraintSim.h"
#include "ScConstraintCore.h"
#include "CmVisualization.h"
using namespace physx;
using namespace Sc;
// PT: Sc-level visualization code has been moved to this dedicated file (like we did in NpDebugViz.cpp)
static void visualize(const ConstraintSim& sim, Cm::ConstraintImmediateVisualizer& viz, PxU32 flags, const PxTransform& idt)
{
ConstraintCore& core = sim.getCore();
if(!(core.getFlags() & PxConstraintFlag::eVISUALIZATION))
return;
const Dy::Constraint& llc = sim.getLowLevelConstraint();
PxsRigidBody* b0 = llc.body0;
PxsRigidBody* b1 = llc.body1;
const PxTransform& t0 = b0 ? b0->getPose() : idt;
const PxTransform& t1 = b1 ? b1->getPose() : idt;
core.getVisualize()(viz, llc.constantBlock, t0, t1, flags);
}
void Sc::ShapeInteraction::visualize(PxRenderOutput& out, PxsContactManagerOutputIterator& outputs,
float scale, float contactImpulse, float contactNormal, float contactError, float contactPoint,
float frictionImpulse, float frictionNormal, float frictionPoint)
{
if(mManager) // sleeping pairs have no contact points -> do not visualize
{
Sc::ActorSim* actorSim0 = &getActor0();
Sc::ActorSim* actorSim1 = &getActor1();
if(!actorSim0->isNonRigid() && !actorSim1->isNonRigid())
{
PxU32 offset;
PxU32 nextOffset = 0;
do
{
const void* contactPatches;
const void* contactPoints;
PxU32 contactDataSize;
PxU32 contactPointCount;
PxU32 contactPatchCount;
const PxReal* impulses;
const void* frictionPatches;
offset = nextOffset;
nextOffset = getContactPointData(contactPatches, contactPoints, contactDataSize, contactPointCount, contactPatchCount, impulses, offset, outputs, frictionPatches);
const PxU32* faceIndices = reinterpret_cast<const PxU32*>(impulses + contactPointCount);
PxContactStreamIterator iter(reinterpret_cast<const PxU8*>(contactPatches), reinterpret_cast<const PxU8*>(contactPoints), faceIndices, contactPatchCount, contactPointCount);
PxFrictionAnchorStreamIterator fricIter(reinterpret_cast<const PxU8*>(contactPatches), reinterpret_cast<const PxU8*>(frictionPatches), contactPatchCount);
PxU32 i = 0;
while(iter.hasNextPatch())
{
iter.nextPatch();
while(iter.hasNextContact())
{
iter.nextContact();
if((contactImpulse != 0.0f) && impulses)
{
out << PxU32(PxDebugColor::eARGB_RED);
out.outputSegment(iter.getContactPoint(), iter.getContactPoint() + iter.getContactNormal() * (scale * contactImpulse * impulses[i]));
}
else if(contactNormal != 0.0f)
{
out << PxU32(PxDebugColor::eARGB_BLUE);
out.outputSegment(iter.getContactPoint(), iter.getContactPoint() + iter.getContactNormal() * (scale * contactNormal));
}
else if(contactError != 0.0f)
{
out << PxU32(PxDebugColor::eARGB_YELLOW);
out.outputSegment(iter.getContactPoint(), iter.getContactPoint() + iter.getContactNormal() * PxAbs(scale * contactError * PxMin(0.f, iter.getSeparation())));
}
if(contactPoint != 0.0f)
{
const PxReal s = scale * 0.1f;
const PxVec3& point = iter.getContactPoint();
//if (0) //temp debug to see identical contacts
// point.x += scale * 0.01f * (contactPointCount - i + 1);
out << PxU32(PxDebugColor::eARGB_RED);
out.outputSegment(point + PxVec3(-s, 0, 0), point + PxVec3(s, 0, 0));
out.outputSegment(point + PxVec3(0, -s, 0), point + PxVec3(0, s, 0));
out.outputSegment(point + PxVec3(0, 0, -s), point + PxVec3(0, 0, s));
}
i++;
}
if (fricIter.hasNextPatch())
{
fricIter.nextPatch();
while (fricIter.hasNextFrictionAnchor())
{
fricIter.nextFrictionAnchor();
if (frictionImpulse != 0.0f)
{
out << PxU32(PxDebugColor::eARGB_DARKRED);
out.outputSegment(fricIter.getPosition(), fricIter.getPosition() + fricIter.getImpulse() * (scale * frictionImpulse));
}
else if (frictionNormal != 0.0f)
{
out << PxU32(PxDebugColor::eARGB_BLUE);
out.outputSegment(fricIter.getPosition(), fricIter.getPosition() + fricIter.getNormal() * (scale * frictionNormal));
}
if (frictionPoint != 0.0f)
{
const PxReal s = scale * 0.1f;
const PxVec3& p = fricIter.getPosition();
out << PxU32(PxDebugColor::eARGB_DARKRED);
out.outputSegment(p + PxVec3(-s, 0, 0), p + PxVec3(s, 0, 0));
out.outputSegment(p + PxVec3(0, -s, 0), p + PxVec3(0, s, 0));
out.outputSegment(p + PxVec3(0, 0, -s), p + PxVec3(0, 0, s));
}
}
}
}
} while (nextOffset != offset);
}
}
}
// Render objects before simulation starts
void Sc::Scene::visualizeStartStep()
{
PX_PROFILE_ZONE("Sim.visualizeStartStep", mContextId);
// Update from visualization parameters
if(mVisualizationParameterChanged)
{
mVisualizationParameterChanged = false;
// Update SIPs if visualization is enabled
if( getVisualizationParameter(PxVisualizationParameter::eCONTACT_POINT) || getVisualizationParameter(PxVisualizationParameter::eCONTACT_NORMAL) ||
getVisualizationParameter(PxVisualizationParameter::eCONTACT_ERROR) || getVisualizationParameter(PxVisualizationParameter::eCONTACT_IMPULSE) ||
getVisualizationParameter(PxVisualizationParameter::eFRICTION_POINT) || getVisualizationParameter(PxVisualizationParameter::eFRICTION_NORMAL) ||
getVisualizationParameter(PxVisualizationParameter::eFRICTION_IMPULSE))
mInternalFlags |= SceneInternalFlag::eSCENE_SIP_STATES_DIRTY_VISUALIZATION;
}
#if PX_ENABLE_DEBUG_VISUALIZATION
const PxReal scale = getVisualizationScale();
if(scale==0.0f)
{
// make sure visualization inside simulate was skipped
PX_ASSERT(getRenderBuffer().empty());
return; // early out if visualization scale is 0
}
PxRenderOutput out(getRenderBuffer());
if(getVisualizationParameter(PxVisualizationParameter::eCOLLISION_COMPOUNDS))
mAABBManager->visualize(out);
// Visualize joints
{
const float frameScale = scale * getVisualizationParameter(PxVisualizationParameter::eJOINT_LOCAL_FRAMES);
const float limitScale = scale * getVisualizationParameter(PxVisualizationParameter::eJOINT_LIMITS);
if(frameScale!=0.0f || limitScale!=0.0f)
{
Cm::ConstraintImmediateVisualizer viz(frameScale, limitScale, out);
PxU32 flags = 0;
if(frameScale!=0.0f)
flags |= PxConstraintVisualizationFlag::eLOCAL_FRAMES;
if(limitScale!=0.0f)
flags |= PxConstraintVisualizationFlag::eLIMITS;
const PxTransform idt(PxIdentity);
Sc::ConstraintCore*const * constraints = mConstraints.getEntries();
for(PxU32 i=0, size = mConstraints.size();i<size; i++)
{
ConstraintSim* sim = constraints[i]->getSim();
if(sim)
visualize(*sim, viz, flags, idt);
}
}
}
#else
PX_CATCH_UNDEFINED_ENABLE_DEBUG_VISUALIZATION
#endif
}
// Render contacts at the simulation frame end
void Sc::Scene::visualizeContacts()
{
PX_PROFILE_ZONE("Sim.visualizeContacts", mContextId);
#if PX_ENABLE_DEBUG_VISUALIZATION
const PxReal scale = getVisualizationScale();
if (scale == 0.0f)
{
// make sure visualization inside simulate was skipped
PX_ASSERT(getRenderBuffer().empty());
return; // early out if visualization scale is 0
}
PxRenderOutput out(getRenderBuffer());
{
// PT: put common reads here to avoid doing them for each interaction
const PxReal contactImpulse = getVisualizationParameter(PxVisualizationParameter::eCONTACT_IMPULSE);
const PxReal contactNormal = getVisualizationParameter(PxVisualizationParameter::eCONTACT_NORMAL);
const PxReal contactError = getVisualizationParameter(PxVisualizationParameter::eCONTACT_ERROR);
const PxReal contactPoint = getVisualizationParameter(PxVisualizationParameter::eCONTACT_POINT);
const PxReal frictionImpulse = getVisualizationParameter(PxVisualizationParameter::eFRICTION_IMPULSE);
const PxReal frictionNormal = getVisualizationParameter(PxVisualizationParameter::eFRICTION_NORMAL);
const PxReal frictionPoint = getVisualizationParameter(PxVisualizationParameter::eFRICTION_POINT);
if(contactImpulse !=0.0f || contactNormal!=0.0f || contactError!=0.0f || contactPoint!=0.0f ||
frictionImpulse != 0.0f || frictionNormal != 0.0f || frictionPoint != 0.0f)
{
PxsContactManagerOutputIterator outputs = mLLContext->getNphaseImplementationContext()->getContactManagerOutputs();
ElementSimInteraction** interactions = getActiveInteractions(InteractionType::eOVERLAP);
PxU32 nbActiveInteractions = getNbActiveInteractions(InteractionType::eOVERLAP);
while(nbActiveInteractions--)
static_cast<ShapeInteraction*>(*interactions++)->visualize( out, outputs,
scale, contactImpulse, contactNormal, contactError, contactPoint,
frictionImpulse, frictionNormal, frictionPoint);
}
}
#else
PX_CATCH_UNDEFINED_ENABLE_DEBUG_VISUALIZATION
#endif
}