aboutsummaryrefslogtreecommitdiff
path: root/samples/SampleBase/physx/PhysXController.cpp
diff options
context:
space:
mode:
authorAnton Novoselov <[email protected]>2017-08-01 12:53:38 +0300
committerAnton Novoselov <[email protected]>2017-08-01 12:53:38 +0300
commit236f03c0b9a4982328ed1201978f7f69d192d9b2 (patch)
treee486f2fa39dba203563895541e92c60ed3e25759 /samples/SampleBase/physx/PhysXController.cpp
parentAdded screens to welcome page (diff)
downloadblast-236f03c0b9a4982328ed1201978f7f69d192d9b2.tar.xz
blast-236f03c0b9a4982328ed1201978f7f69d192d9b2.zip
Blast 1.1 release (windows / linux)
see docs/release_notes.txt for details
Diffstat (limited to 'samples/SampleBase/physx/PhysXController.cpp')
-rw-r--r--samples/SampleBase/physx/PhysXController.cpp196
1 files changed, 156 insertions, 40 deletions
diff --git a/samples/SampleBase/physx/PhysXController.cpp b/samples/SampleBase/physx/PhysXController.cpp
index 1df06be..b473c8e 100644
--- a/samples/SampleBase/physx/PhysXController.cpp
+++ b/samples/SampleBase/physx/PhysXController.cpp
@@ -1,12 +1,30 @@
-/*
- * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved.
- *
- * NVIDIA CORPORATION and its licensors retain all intellectual property
- * and proprietary rights in and to this software, related documentation
- * and any modifications thereto. Any use, reproduction, disclosure or
- * distribution of this software and related documentation without an express
- * license agreement from NVIDIA CORPORATION is strictly prohibited.
- */
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2017 NVIDIA Corporation. All rights reserved.
+
#include "PhysXController.h"
#include "RenderMaterial.h"
@@ -19,7 +37,8 @@
#include "ConvexRenderMesh.h"
#include "RenderUtils.h"
#include "SampleProfiler.h"
-#include "NvBlastProfiler.h"
+#include "NvBlastExtCustomProfiler.h"
+#include "NvBlastPxCallbacks.h"
#include "PxPhysicsVersion.h"
#include "PxPvdTransport.h"
@@ -47,9 +66,12 @@ const DirectX::XMFLOAT4 PLANE_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
const DirectX::XMFLOAT4 HOOK_LINE_COLOR(1.0f, 1.0f, 1.0f, 1.0f);
const float DEFAULT_FIXED_TIMESTEP = 1.0f / 60.0f;
+static Nv::Blast::ExtCustomProfiler gBlastProfiler;
+
PhysXController::PhysXController(PxSimulationFilterShader filterShader)
: m_filterShader(filterShader)
, m_gpuPhysicsAvailable(true)
+, m_isSimulating(false)
, m_useGPUPhysics(true)
, m_lastSimulationTime(0)
, m_paused(false)
@@ -77,6 +99,7 @@ void PhysXController::onInitialize()
void PhysXController::onTerminate()
{
+ simualtionSyncEnd();
releasePhysXPrimitives();
releasePhysX();
}
@@ -88,13 +111,13 @@ void PhysXController::onTerminate()
void PhysXController::initPhysX()
{
- m_foundation = PxCreateFoundation(PX_FOUNDATION_VERSION, m_allocator, m_errorCallback);
+ m_foundation = PxCreateFoundation(PX_FOUNDATION_VERSION, NvBlastGetPxAllocatorCallback(), NvBlastGetPxErrorCallback());
m_pvd = PxCreatePvd(*m_foundation);
- NvBlastProfilerSetCallback(m_pvd);
- NvBlastProfilerEnablePlatform(false);
- NvBlastProfilerSetDetail(NvBlastProfilerDetail::LOW);
+ NvBlastProfilerSetCallback(&gBlastProfiler);
+ NvBlastProfilerSetDetail(Nv::Blast::ProfilerDetail::LOW);
+ gBlastProfiler.setPlatformEnabled(false);
PxTolerancesScale scale;
@@ -237,54 +260,77 @@ void PhysXController::notifyRigidDynamicDestroyed(PxRigidDynamic* rigidDynamic)
}
-
-
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Controller events
+// Simulation control
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-void PhysXController::Animate(double dt)
+void PhysXController::simulationBegin(float dt)
{
PROFILER_SCOPED_FUNCTION();
if (m_paused)
return;
- // slower physics if fps is too low
- dt = PxClamp(dt, 0.0, 0.033333);
-
updateDragging(dt);
+ processExplosionQueue();
+
+ // slower physics if fps is too low
+ dt = PxClamp(dt, 0.0f, 0.0333f);
{
- PROFILER_SCOPED("PhysX simulate");
- steady_clock::time_point start = steady_clock::now();
+ PROFILER_SCOPED("PhysX simulate call");
if (m_useFixedTimeStep)
{
m_timeAccumulator += dt;
m_substepCount = (uint32_t)std::floor(m_timeAccumulator / m_fixedTimeStep);
m_timeAccumulator -= m_fixedTimeStep * m_substepCount;
m_substepCount = m_maxSubstepCount > 0 ? physx::PxClamp<uint32_t>(m_substepCount, 0, m_maxSubstepCount) : m_substepCount;
- for (uint32_t i = 0; i < m_substepCount; ++i)
+ if (m_substepCount > 0)
{
- PROFILER_SCOPED("PhysX simulate (substep)");
m_physicsScene->simulate(m_fixedTimeStep);
- m_physicsScene->fetchResults(true);
+ m_isSimulating = true;
}
}
else
{
m_substepCount = 1;
+ PX_ASSERT(!m_isSimulating);
m_physicsScene->simulate(dt);
- m_physicsScene->fetchResults(true);
+ m_isSimulating = true;
+
}
- m_lastSimulationTime = duration_cast<microseconds>(steady_clock::now() - start).count() * 0.000001;
}
+}
+
+void PhysXController::simualtionSyncEnd()
+{
+ PROFILER_SCOPED_FUNCTION();
- PROFILER_BEGIN("Debug Render Buffer");
- getRenderer().queueRenderBuffer(&m_physicsScene->getRenderBuffer());
- PROFILER_END();
+ if (m_isSimulating)
+ {
+ steady_clock::time_point start = steady_clock::now();
+ m_physicsScene->fetchResults(true);
- updateActorTransforms();
+ // For fixed time step case it could be that we need more then one step (m_maxSubstepCount > 1). We will run leftover steps synchronously right there.
+ // Ideally is to make them overlap with other logic too, but it's much harder and requires more synchronization logic. Don't want to obfuscate sample code.
+ if (m_useFixedTimeStep && m_substepCount > 1)
+ {
+ for (uint32_t i = 0; i < m_substepCount - 1; i++)
+ {
+ m_physicsScene->simulate(m_fixedTimeStep);
+ m_physicsScene->fetchResults(true);
+ }
+ }
+ m_lastSimulationTime = duration_cast<microseconds>(steady_clock::now() - start).count() * 0.000001;
+
+ m_isSimulating = false;
+
+ updateActorTransforms();
+
+ PROFILER_BEGIN("Debug Render Buffer");
+ getRenderer().queueRenderBuffer(&m_physicsScene->getRenderBuffer());
+ PROFILER_END();
+ }
}
@@ -352,8 +398,11 @@ void PhysXController::updateDragging(double dt)
PxVec3 hookPoint = m_draggingActor->getGlobalPose().transform(m_draggingActorHookLocalPoint);
m_draggingActorLastHookWorldPoint = hookPoint;
m_dragVector = (m_dragAttractionPoint - hookPoint);
- PxVec3 dragVeloctiy = (m_dragVector * DRAGGING_FORCE_FACTOR - DRAGGING_VELOCITY_FACTOR * m_draggingActor->getLinearVelocity()) * dt;
- PxRigidBodyExt::addForceAtLocalPos(*m_draggingActor, dragVeloctiy * m_draggingActor->getMass(), m_draggingActorHookLocalPoint, PxForceMode::eIMPULSE, true);
+ if (!m_draggingActor->getRigidBodyFlags().isSet(PxRigidBodyFlag::eKINEMATIC))
+ {
+ PxVec3 dragVeloctiy = (m_dragVector * DRAGGING_FORCE_FACTOR - DRAGGING_VELOCITY_FACTOR * m_draggingActor->getLinearVelocity()) * dt;
+ PxRigidBodyExt::addForceAtLocalPos(*m_draggingActor, dragVeloctiy * m_draggingActor->getMass(), m_draggingActorHookLocalPoint, PxForceMode::eIMPULSE, true);
+ }
// debug render line
m_dragDebugRenderBuffer.clear();
@@ -393,9 +442,12 @@ LRESULT PhysXController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
m_dragDistance = (eyePos - hit.position).magnitude();
m_draggingActor = hit.actor->is<PxRigidDynamic>();
m_draggingActorHookLocalPoint = m_draggingActor->getGlobalPose().getInverse().transform(hit.position);
- m_draggingActor->setLinearVelocity(PxVec3(0, 0, 0));
- m_draggingActor->setAngularVelocity(PxVec3(0, 0, 0));
m_dragAttractionPoint = hit.position;
+ if (!m_draggingActor->getRigidBodyFlags().isSet(PxRigidBodyFlag::eKINEMATIC))
+ {
+ m_draggingActor->setLinearVelocity(PxVec3(0, 0, 0));
+ m_draggingActor->setAngularVelocity(PxVec3(0, 0, 0));
+ }
}
}
}
@@ -422,6 +474,71 @@ LRESULT PhysXController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Explosion
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class ExplodeOverlapCallback : public PxOverlapCallback
+{
+public:
+ ExplodeOverlapCallback(PxVec3 worldPos, float radius, float explosiveImpulse)
+ : m_worldPos(worldPos)
+ , m_radius(radius)
+ , m_explosiveImpulse(explosiveImpulse)
+ , PxOverlapCallback(m_hitBuffer, sizeof(m_hitBuffer) / sizeof(m_hitBuffer[0])) {}
+
+ PxAgain processTouches(const PxOverlapHit* buffer, PxU32 nbHits)
+ {
+ for (PxU32 i = 0; i < nbHits; ++i)
+ {
+ PxRigidActor* actor = buffer[i].actor;
+ PxRigidDynamic* rigidDynamic = actor->is<PxRigidDynamic>();
+ if (rigidDynamic && !(rigidDynamic->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC))
+ {
+ if (m_actorBuffer.find(rigidDynamic) == m_actorBuffer.end())
+ {
+ m_actorBuffer.insert(rigidDynamic);
+ PxVec3 dr = rigidDynamic->getGlobalPose().transform(rigidDynamic->getCMassLocalPose()).p - m_worldPos;
+ float distance = dr.magnitude();
+ float factor = PxClamp(1.0f - (distance * distance) / (m_radius * m_radius), 0.0f, 1.0f);
+ float impulse = factor * m_explosiveImpulse * 1000.0f;
+ PxVec3 vel = dr.getNormalized() * impulse / rigidDynamic->getMass();
+ rigidDynamic->setLinearVelocity(rigidDynamic->getLinearVelocity() + vel);
+ }
+ }
+ }
+ return true;
+ }
+
+private:
+ PxOverlapHit m_hitBuffer[1000];
+ float m_explosiveImpulse;
+ std::set<PxRigidDynamic*> m_actorBuffer;
+ PxVec3 m_worldPos;
+ float m_radius;
+};
+
+void PhysXController::explode(PxVec3 worldPos, float damageRadius, float explosiveImpulse)
+{
+ ExplodeOverlapCallback overlapCallback(worldPos, damageRadius, explosiveImpulse);
+ m_physicsScene->overlap(PxSphereGeometry(damageRadius), PxTransform(worldPos), overlapCallback);
+}
+
+void PhysXController::explodeDelayed(PxVec3 worldPos, float damageRadius, float explosiveImpulse)
+{
+ m_explosionQueue.push_back({ worldPos, damageRadius, explosiveImpulse });
+}
+
+void PhysXController::processExplosionQueue()
+{
+ for (auto& e : m_explosionQueue)
+ {
+ explode(e.worldPos, e.damageRadius, e.explosiveImpulse);
+ }
+ m_explosionQueue.clear();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// UI
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -435,8 +552,7 @@ void PhysXController::drawUI()
}
ImGui::Text("Substep Count: %d", m_substepCount);
- ImGui::Text("Simulation Time (total): %4.2f ms", getLastSimulationTime() * 1000);
- ImGui::Text("Simulation Time (substep): %4.2f ms", m_substepCount > 0 ? (getLastSimulationTime() / m_substepCount) * 1000 : 0.0);
+ ImGui::Text("Sync Simulation Time (total): %4.2f ms", getLastSimulationTime() * 1000);
}
@@ -544,7 +660,7 @@ void PhysXController::removeUnownedPhysXActors()
{
if (m_physXActorsToRemove.size())
{
- m_physicsScene->removeActors(&m_physXActorsToRemove[0], (PxU32)m_physXActorsToRemove.size());
+ m_physicsScene->removeActors(m_physXActorsToRemove.data(), (PxU32)m_physXActorsToRemove.size());
for (size_t i = 0; i < m_physXActorsToRemove.size(); ++i)
{
m_physXActorsToRemove[i]->release();
@@ -567,7 +683,7 @@ PhysXController::Actor::Actor(PhysXController* controller, PxRigidActor* actor,
uint32_t shapesCount = actor->getNbShapes();
m_shapes.resize(shapesCount);
- actor->getShapes(&m_shapes[0], shapesCount);
+ actor->getShapes(m_shapes.data(), shapesCount);
m_renderables.resize(m_shapes.size());
for (uint32_t i = 0; i < m_shapes.size(); i++)