From 236f03c0b9a4982328ed1201978f7f69d192d9b2 Mon Sep 17 00:00:00 2001 From: Anton Novoselov Date: Tue, 1 Aug 2017 12:53:38 +0300 Subject: Blast 1.1 release (windows / linux) see docs/release_notes.txt for details --- samples/SampleBase/physx/PhysXController.cpp | 196 +++++++++++++++++++++------ 1 file changed, 156 insertions(+), 40 deletions(-) (limited to 'samples/SampleBase/physx/PhysXController.cpp') 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(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(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(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(); 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)); + } } } } @@ -421,6 +473,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(); + 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 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++) -- cgit v1.2.3