aboutsummaryrefslogtreecommitdiff
path: root/samples/SampleBase/ui/DamageToolController.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'samples/SampleBase/ui/DamageToolController.cpp')
-rwxr-xr-x[-rw-r--r--]samples/SampleBase/ui/DamageToolController.cpp968
1 files changed, 484 insertions, 484 deletions
diff --git a/samples/SampleBase/ui/DamageToolController.cpp b/samples/SampleBase/ui/DamageToolController.cpp
index 1fc0817..b634c7d 100644..100755
--- a/samples/SampleBase/ui/DamageToolController.cpp
+++ b/samples/SampleBase/ui/DamageToolController.cpp
@@ -1,484 +1,484 @@
-// 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-2018 NVIDIA Corporation. All rights reserved.
-
-
-#include "DamageToolController.h"
-#include "RenderUtils.h"
-#include "BlastController.h"
-#include "Renderer.h"
-#include "PhysXController.h"
-#include "SampleProfiler.h"
-
-#include <imgui.h>
-
-#include "NvBlastTkActor.h"
-#include "NvBlastTkFamily.h"
-#include "NvBlastExtDamageShaders.h"
-#include "NvBlastExtPxActor.h"
-#include "NvBlastExtPxFamily.h"
-
-#include "PxRigidDynamic.h"
-#include "PxScene.h"
-
-
-using namespace Nv::Blast;
-using namespace physx;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Setup
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-const DirectX::XMFLOAT4 PICK_POINTER_ACTIVE_COLOR(1.0f, 0.f, 0.f, 0.6f);
-static const PxVec3 WEAPON_POSITION_IN_VIEW(0, -7, 23);
-static const float SEGMENT_DAMAGE_MAX_DISTANCE = 100.0f;
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-DamageToolController::DamageToolController()
- : m_damage(100.0f), m_toolColor(1.0f, 1.0f, 1.0f, 0.4f),
- m_toolRenderMaterial(nullptr), m_sphereToolRenderable(nullptr), m_lineToolRenderable(nullptr),
- m_explosiveImpulse(100), m_damagerIndex(0), m_stressForceFactor(1.0f), m_isMousePressed(false), m_damageCountWhilePressed(0)
-{
- // damage amount calc using NvBlastExtMaterial
- auto getDamageAmountFn = [](const float damage, ExtPxActor* actor)
- {
- const NvBlastExtMaterial* material = actor->getFamily().getMaterial();
- return material ? material->getNormalizedDamage(damage) : 0.f;
- };
-
- // Damage functions
- auto radialDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
- {
- const float damage = getDamageAmountFn(m_damage, actor);
- if (damage > 0.f)
- {
- NvBlastExtRadialDamageDesc desc =
- {
- damage,
- { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z },
- damager->radius,
- damager->radius * 1.6f
- };
-
- getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc));
- }
- };
- auto sliceDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
- {
- const float damage = getDamageAmountFn(m_damage, actor);
- if (damage > 0.f)
- {
- PxVec3 farEnd = data.origin + data.weaponDir * 1000.0f;
- PxVec3 farEndPrev = data.origin + data.previousWeaponDir * 1000.0f;
-
- NvBlastExtTriangleIntersectionDamageDesc desc =
- {
- damage,
- { data.origin.x, data.origin.y, data.origin.z },
- { farEnd.x, farEnd.y, farEnd.z },
- { farEndPrev.x, farEndPrev.y, farEndPrev.z },
- };
-
- getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc));
- }
- };
- auto capsuleDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
- {
- const float damage = getDamageAmountFn(m_damage, actor);
- if (damage > 0.f)
- {
- PxVec3 dir = (data.hitPosition - data.origin).getNormalized();
- PxVec3 farEnd = data.origin + dir * 10000.0f;
-
- NvBlastExtCapsuleRadialDamageDesc desc =
- {
- damage,
- { data.origin.x, data.origin.y, data.origin.z },
- { farEnd.x, farEnd.y, farEnd.z },
- damager->radius,
- damager->radius * 1.6f
- };
-
- getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc));
- }
- };
- auto impulseSpreadDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
- {
- const float damage = m_damage;
- if (damage > 0.f)
- {
- PxVec3 impactNormal = -data.hitNormal;
-
- NvBlastExtImpactSpreadDamageDesc desc =
- {
- damage,
- { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z },
- damager->radius,
- damager->radius * 1.6f
- };
-
- getBlastController().immediateDamage(actor, family, damager->program, &desc);
- }
- };
- auto shearDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
- {
- const float damage = getDamageAmountFn(m_damage, actor);
- if (damage > 0.f)
- {
- PxVec3 impactNormal = -data.hitNormal;
-
- NvBlastExtShearDamageDesc desc =
- {
- damage,
- { impactNormal.x, impactNormal.y, impactNormal.z },
- { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z },
- damager->radius,
- damager->radius * 1.6f
- };
-
- getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc));
- }
- };
- auto stressDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
- {
- PxVec3 force = -m_stressForceFactor * data.hitNormal * actor->getPhysXActor().getMass();
-
- getBlastController().stressDamage(actor, data.hitPosition, force);
- };
-
- // Damage Tools:
- {
- Damager dam;
- dam.uiName = "Radial Damage (Falloff)";
- dam.program = NvBlastDamageProgram { NvBlastExtFalloffGraphShader, NvBlastExtFalloffSubgraphShader };
- dam.pointerType = Damager::PointerType::Sphere;
- dam.pointerColor = DirectX::XMFLOAT4(1.0f, 1.0f, 1.0f, 0.4f);
- dam.executeFunction = radialDamageExecute;
- m_damagers.push_back(dam);
- }
- {
- Damager dam;
- dam.uiName = "Radial Damage (Cutter)";
- dam.program = NvBlastDamageProgram { NvBlastExtCutterGraphShader, NvBlastExtCutterSubgraphShader };
- dam.pointerType = Damager::PointerType::Sphere;
- dam.pointerColor = DirectX::XMFLOAT4(0.5f, 0.5f, 1.0f, 0.4f);
- dam.executeFunction = radialDamageExecute;
- m_damagers.push_back(dam);
- }
-
- {
- Damager dam;
- dam.uiName = "Slice Damage";
- dam.program = NvBlastDamageProgram{ NvBlastExtTriangleIntersectionGraphShader, NvBlastExtTriangleIntersectionSubgraphShader };
- dam.pointerType = Damager::PointerType::Line;
- dam.pointerColor = DirectX::XMFLOAT4(0.1f, 1.0f, 0.1f, 0.4f);
- dam.executeFunction = sliceDamageExecute;
- dam.damageWhilePressed = true;
- dam.radius = .2f;
- dam.radiusLimit = .2f;
- m_damagers.push_back(dam);
- }
-
- {
- Damager dam;
- dam.uiName = "Capsule Damage (Falloff)";
- dam.program = NvBlastDamageProgram{ NvBlastExtCapsuleFalloffGraphShader, NvBlastExtCapsuleFalloffSubgraphShader };
- dam.pointerType = Damager::PointerType::Line;
- dam.pointerColor = DirectX::XMFLOAT4(0.1f, 1.0f, 0.1f, 0.4f);
- dam.executeFunction = capsuleDamageExecute;
- dam.damageWhilePressed = true;
- dam.radius = .2f;
- dam.radiusLimit = 20.0f;
- m_damagers.push_back(dam);
- }
-
- {
- Damager dam;
- dam.uiName = "Impact Spread Damage";
- dam.program = NvBlastDamageProgram { NvBlastExtImpactSpreadGraphShader, NvBlastExtImpactSpreadSubgraphShader };
- dam.pointerType = Damager::PointerType::Sphere;
- dam.pointerColor = DirectX::XMFLOAT4(0.5f, 1.0f, 0.5f, 0.4f);
- dam.executeFunction = impulseSpreadDamageExecute;
- m_damagers.push_back(dam);
- }
-
- {
- Damager dam;
- dam.uiName = "Shear Damage";
- dam.program = NvBlastDamageProgram{ NvBlastExtShearGraphShader, NvBlastExtShearSubgraphShader };
- dam.pointerType = Damager::PointerType::Sphere;
- dam.pointerColor = DirectX::XMFLOAT4(0.5f, 1.0f, 0.5f, 0.4f);
- dam.executeFunction = shearDamageExecute;
- m_damagers.push_back(dam);
- }
-
- {
- Damager dam;
- dam.uiName = "Stress Damage";
- dam.program = { nullptr, nullptr };
- dam.pointerType = Damager::PointerType::Sphere;
- dam.pointerColor = DirectX::XMFLOAT4(0.5f, 0.5f, 1.0f, 0.4f);
- dam.executeFunction = stressDamageExecute;
- m_damagers.push_back(dam);
- }
-
- for (const Damager& d : m_damagers)
- {
- m_damagerNames.push_back(d.uiName);
- }
-}
-
-DamageToolController::~DamageToolController()
-{
-}
-
-void DamageToolController::onSampleStart()
-{
- // damage tool pointer
- m_toolRenderMaterial = new RenderMaterial(getRenderer().getResourceManager(), "physx_primitive_transparent", "", RenderMaterial::BLEND_ALPHA_BLENDING);
- {
- IRenderMesh* mesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Sphere);
- m_sphereToolRenderable = getRenderer().createRenderable(*mesh, *m_toolRenderMaterial);
- }
- {
- IRenderMesh* mesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Box);
- m_lineToolRenderable = getRenderer().createRenderable(*mesh, *m_toolRenderMaterial);
- }
-
- // default tool
- m_damagerIndex = 0;
-
- // start with damage mode by default
- setDamageMode(true);
-}
-
-void DamageToolController::onInitialize()
-{
-}
-
-
-void DamageToolController::onSampleStop()
-{
- getRenderer().removeRenderable(m_sphereToolRenderable);
- getRenderer().removeRenderable(m_lineToolRenderable);
- SAFE_DELETE(m_toolRenderMaterial);
-}
-
-
-void DamageToolController::Animate(double dt)
-{
- PROFILER_SCOPED_FUNCTION();
-
- m_toolColor = XMFLOAT4Lerp(m_toolColor, m_damagers[m_damagerIndex].pointerColor, dt * 5.0f);
-
- m_sphereToolRenderable->setHidden(true);
- m_lineToolRenderable->setHidden(true);
-
- // damage mode
- if (m_damageMode)
- {
- const Damager& damager = m_damagers[m_damagerIndex];
-
- // ray cast according to camera + mouse ray
- PxVec3 eyePos, pickDir;
- getPhysXController().getEyePoseAndPickDir(m_lastMousePos.x, m_lastMousePos.y, eyePos, pickDir);
- pickDir = pickDir.getNormalized();
-
- PxRaycastHit hit; hit.shape = NULL;
- PxRaycastBuffer hit1;
- getPhysXController().getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL);
- hit = hit1.block;
-
- if (hit.shape || (m_prevWasHit && damager.pointerType == Damager::Line))
- {
- PxMat44 cameraViewInv = XMMATRIXToPxMat44(getRenderer().getCamera().GetViewMatrix()).inverseRT();
- PxVec3 weaponOrigin = eyePos + cameraViewInv.rotate(WEAPON_POSITION_IN_VIEW);
- PxVec3 weaponDir = (hit.position - weaponOrigin).getNormalized();
-
- // damage function
- auto damageFunction = [&](ExtPxActor* actor, BlastFamily& family)
- {
- auto t0 = actor->getPhysXActor().getGlobalPose();
- PxTransform t(t0.getInverse());
- Damager::DamageData data;
- data.hitNormal = t.rotate(hit.normal);
- data.hitPosition = t.transform(hit.position);
- data.origin = t.transform(weaponOrigin);
- data.weaponDir = t.rotate(weaponDir);
- data.previousWeaponDir = t.rotate(m_previousPickDir);
- damager.executeFunction(&damager, actor, family, data);
- };
-
- // should damage?
- bool shouldDamage = false;
- if (m_isMousePressed)
- {
- shouldDamage = damager.damageWhilePressed || m_damageCountWhilePressed == 0;
- m_damageCountWhilePressed++;
- }
- else
- {
- m_damageCountWhilePressed = 0;
- }
-
- // Update tool pointer and do damage with specific overlap
- if (damager.pointerType == Damager::Sphere)
- {
- m_sphereToolRenderable->setHidden(false);
- m_sphereToolRenderable->setColor(m_toolColor);
- m_sphereToolRenderable->setScale(PxVec3(damager.radius));
- m_sphereToolRenderable->setTransform(PxTransform(hit.position));
-
- if (shouldDamage)
- {
- if (getBlastController().overlap(PxSphereGeometry(damager.radius), PxTransform(hit.position), damageFunction))
- {
- m_toolColor = PICK_POINTER_ACTIVE_COLOR;
- }
- getPhysXController().explodeDelayed(hit.position, damager.radius, m_explosiveImpulse);
- }
- }
- else if (damager.pointerType == Damager::Line)
- {
- m_lineToolRenderable->setHidden(false);
- m_lineToolRenderable->setColor(m_toolColor);
-
- PxVec3 scale(damager.radius, damager.radius, SEGMENT_DAMAGE_MAX_DISTANCE);
- PxVec3 direction = (hit.position - weaponOrigin).getNormalized();
- PxVec3 position = weaponOrigin + direction * SEGMENT_DAMAGE_MAX_DISTANCE;
-
- m_lineToolRenderable->setScale(scale);
- PxTransform t(position, quatLookAt(direction));
- m_lineToolRenderable->setTransform(t);
-
- if (shouldDamage)
- {
- if (this->getBlastController().overlap(PxBoxGeometry(scale), t, damageFunction))
- {
- m_toolColor = PICK_POINTER_ACTIVE_COLOR;
- }
- }
- }
- else
- {
- PX_ASSERT(false);
- }
-
- m_previousPickDir = weaponDir;
- m_prevWasHit = true;
- }
- else
- {
- m_prevWasHit = false;
- }
- }
-}
-
-
-LRESULT DamageToolController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- PROFILER_SCOPED_FUNCTION();
-
- if (uMsg == WM_LBUTTONDOWN || uMsg == WM_MOUSEMOVE || uMsg == WM_LBUTTONUP)
- {
- m_lastMousePos.x = (short)LOWORD(lParam) / getRenderer().getScreenWidth();
- m_lastMousePos.y = (short)HIWORD(lParam) / getRenderer().getScreenHeight();
- }
-
- if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
- {
- m_isMousePressed = (uMsg == WM_LBUTTONDOWN);
- }
-
- if (uMsg == WM_MOUSEWHEEL)
- {
- int delta = int((short)HIWORD(wParam)) / WHEEL_DELTA;
- changeDamageRadius(delta * 0.3f);
- }
-
- if (uMsg == WM_KEYDOWN)
- {
- int iKeyPressed = static_cast<int>(wParam);
- if (iKeyPressed == VK_OEM_PLUS)
- {
- changeDamageRadius(0.2f);
- }
- else if (iKeyPressed == VK_OEM_MINUS)
- {
- changeDamageRadius(-0.2f);
- }
- else if (iKeyPressed >= '1' && iKeyPressed <= '9')
- {
- m_damagerIndex = PxClamp<uint32_t>(iKeyPressed - '1', 0, (uint32_t)m_damagers.size() - 1);
- }
- else if (iKeyPressed == VK_SPACE)
- {
- setDamageMode(!isDamageMode());
- }
- }
-
- return 1;
-}
-
-void DamageToolController::drawUI()
-{
- ImGui::DragFloat("Damage Amount", &m_damage, 1.0f);
- ImGui::DragFloat("Explosive Impulse", &m_explosiveImpulse);
- ImGui::DragFloat("Stress Damage Force", &m_stressForceFactor);
-
- // - - - - - - - -
- ImGui::Spacing();
-
- // Armory
- ImGui::Combo("Damage Profile", (int*)&m_damagerIndex, m_damagerNames.data(), (int)m_damagerNames.size(), -1);
- Damager& damager = m_damagers[m_damagerIndex];
- ImGui::DragFloat("Damage Radius (Mouse WH)", &damager.radius);
- ImGui::Checkbox("Damage Continuously", &damager.damageWhilePressed);
-}
-
-void DamageToolController::setDamageMode(bool enabled)
-{
- m_damageMode = enabled;
-
- getPhysXController().setDraggingEnabled(!m_damageMode);
-
- if (!m_damageMode)
- {
- m_sphereToolRenderable->setHidden(true);
- m_lineToolRenderable->setHidden(true);
- }
-}
-
-void DamageToolController::changeDamageRadius(float dr)
-{
- Damager& damager = m_damagers[m_damagerIndex];
- damager.radius += dr;
- damager.radius = PxClamp<float>(damager.radius, 0.05f, damager.radiusLimit);
-}
+// 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-2018 NVIDIA Corporation. All rights reserved.
+
+
+#include "DamageToolController.h"
+#include "RenderUtils.h"
+#include "BlastController.h"
+#include "Renderer.h"
+#include "PhysXController.h"
+#include "SampleProfiler.h"
+
+#include <imgui.h>
+
+#include "NvBlastTkActor.h"
+#include "NvBlastTkFamily.h"
+#include "NvBlastExtDamageShaders.h"
+#include "NvBlastExtPxActor.h"
+#include "NvBlastExtPxFamily.h"
+
+#include "PxRigidDynamic.h"
+#include "PxScene.h"
+
+
+using namespace Nv::Blast;
+using namespace physx;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Setup
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+const DirectX::XMFLOAT4 PICK_POINTER_ACTIVE_COLOR(1.0f, 0.f, 0.f, 0.6f);
+static const PxVec3 WEAPON_POSITION_IN_VIEW(0, -7, 23);
+static const float SEGMENT_DAMAGE_MAX_DISTANCE = 100.0f;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+DamageToolController::DamageToolController()
+ : m_damage(100.0f), m_toolColor(1.0f, 1.0f, 1.0f, 0.4f),
+ m_toolRenderMaterial(nullptr), m_sphereToolRenderable(nullptr), m_lineToolRenderable(nullptr),
+ m_explosiveImpulse(100), m_damagerIndex(0), m_stressForceFactor(1.0f), m_isMousePressed(false), m_damageCountWhilePressed(0)
+{
+ // damage amount calc using NvBlastExtMaterial
+ auto getDamageAmountFn = [](const float damage, ExtPxActor* actor)
+ {
+ const NvBlastExtMaterial* material = actor->getFamily().getMaterial();
+ return material ? material->getNormalizedDamage(damage) : 0.f;
+ };
+
+ // Damage functions
+ auto radialDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
+ {
+ const float damage = getDamageAmountFn(m_damage, actor);
+ if (damage > 0.f)
+ {
+ NvBlastExtRadialDamageDesc desc =
+ {
+ damage,
+ { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z },
+ damager->radius,
+ damager->radius * 1.6f
+ };
+
+ getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc));
+ }
+ };
+ auto sliceDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
+ {
+ const float damage = getDamageAmountFn(m_damage, actor);
+ if (damage > 0.f)
+ {
+ PxVec3 farEnd = data.origin + data.weaponDir * 1000.0f;
+ PxVec3 farEndPrev = data.origin + data.previousWeaponDir * 1000.0f;
+
+ NvBlastExtTriangleIntersectionDamageDesc desc =
+ {
+ damage,
+ { data.origin.x, data.origin.y, data.origin.z },
+ { farEnd.x, farEnd.y, farEnd.z },
+ { farEndPrev.x, farEndPrev.y, farEndPrev.z },
+ };
+
+ getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc));
+ }
+ };
+ auto capsuleDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
+ {
+ const float damage = getDamageAmountFn(m_damage, actor);
+ if (damage > 0.f)
+ {
+ PxVec3 dir = (data.hitPosition - data.origin).getNormalized();
+ PxVec3 farEnd = data.origin + dir * 10000.0f;
+
+ NvBlastExtCapsuleRadialDamageDesc desc =
+ {
+ damage,
+ { data.origin.x, data.origin.y, data.origin.z },
+ { farEnd.x, farEnd.y, farEnd.z },
+ damager->radius,
+ damager->radius * 1.6f
+ };
+
+ getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc));
+ }
+ };
+ auto impulseSpreadDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
+ {
+ const float damage = m_damage;
+ if (damage > 0.f)
+ {
+ PxVec3 impactNormal = -data.hitNormal;
+
+ NvBlastExtImpactSpreadDamageDesc desc =
+ {
+ damage,
+ { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z },
+ damager->radius,
+ damager->radius * 1.6f
+ };
+
+ getBlastController().immediateDamage(actor, family, damager->program, &desc);
+ }
+ };
+ auto shearDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
+ {
+ const float damage = getDamageAmountFn(m_damage, actor);
+ if (damage > 0.f)
+ {
+ PxVec3 impactNormal = -data.hitNormal;
+
+ NvBlastExtShearDamageDesc desc =
+ {
+ damage,
+ { impactNormal.x, impactNormal.y, impactNormal.z },
+ { data.hitPosition.x, data.hitPosition.y, data.hitPosition.z },
+ damager->radius,
+ damager->radius * 1.6f
+ };
+
+ getBlastController().deferDamage(actor, family, damager->program, &desc, sizeof(desc));
+ }
+ };
+ auto stressDamageExecute = [&](const Damager* damager, ExtPxActor* actor, BlastFamily& family, const Damager::DamageData& data)
+ {
+ PxVec3 force = -m_stressForceFactor * data.hitNormal * actor->getPhysXActor().getMass();
+
+ getBlastController().stressDamage(actor, data.hitPosition, force);
+ };
+
+ // Damage Tools:
+ {
+ Damager dam;
+ dam.uiName = "Radial Damage (Falloff)";
+ dam.program = NvBlastDamageProgram { NvBlastExtFalloffGraphShader, NvBlastExtFalloffSubgraphShader };
+ dam.pointerType = Damager::PointerType::Sphere;
+ dam.pointerColor = DirectX::XMFLOAT4(1.0f, 1.0f, 1.0f, 0.4f);
+ dam.executeFunction = radialDamageExecute;
+ m_damagers.push_back(dam);
+ }
+ {
+ Damager dam;
+ dam.uiName = "Radial Damage (Cutter)";
+ dam.program = NvBlastDamageProgram { NvBlastExtCutterGraphShader, NvBlastExtCutterSubgraphShader };
+ dam.pointerType = Damager::PointerType::Sphere;
+ dam.pointerColor = DirectX::XMFLOAT4(0.5f, 0.5f, 1.0f, 0.4f);
+ dam.executeFunction = radialDamageExecute;
+ m_damagers.push_back(dam);
+ }
+
+ {
+ Damager dam;
+ dam.uiName = "Slice Damage";
+ dam.program = NvBlastDamageProgram{ NvBlastExtTriangleIntersectionGraphShader, NvBlastExtTriangleIntersectionSubgraphShader };
+ dam.pointerType = Damager::PointerType::Line;
+ dam.pointerColor = DirectX::XMFLOAT4(0.1f, 1.0f, 0.1f, 0.4f);
+ dam.executeFunction = sliceDamageExecute;
+ dam.damageWhilePressed = true;
+ dam.radius = .2f;
+ dam.radiusLimit = .2f;
+ m_damagers.push_back(dam);
+ }
+
+ {
+ Damager dam;
+ dam.uiName = "Capsule Damage (Falloff)";
+ dam.program = NvBlastDamageProgram{ NvBlastExtCapsuleFalloffGraphShader, NvBlastExtCapsuleFalloffSubgraphShader };
+ dam.pointerType = Damager::PointerType::Line;
+ dam.pointerColor = DirectX::XMFLOAT4(0.1f, 1.0f, 0.1f, 0.4f);
+ dam.executeFunction = capsuleDamageExecute;
+ dam.damageWhilePressed = true;
+ dam.radius = .2f;
+ dam.radiusLimit = 20.0f;
+ m_damagers.push_back(dam);
+ }
+
+ {
+ Damager dam;
+ dam.uiName = "Impact Spread Damage";
+ dam.program = NvBlastDamageProgram { NvBlastExtImpactSpreadGraphShader, NvBlastExtImpactSpreadSubgraphShader };
+ dam.pointerType = Damager::PointerType::Sphere;
+ dam.pointerColor = DirectX::XMFLOAT4(0.5f, 1.0f, 0.5f, 0.4f);
+ dam.executeFunction = impulseSpreadDamageExecute;
+ m_damagers.push_back(dam);
+ }
+
+ {
+ Damager dam;
+ dam.uiName = "Shear Damage";
+ dam.program = NvBlastDamageProgram{ NvBlastExtShearGraphShader, NvBlastExtShearSubgraphShader };
+ dam.pointerType = Damager::PointerType::Sphere;
+ dam.pointerColor = DirectX::XMFLOAT4(0.5f, 1.0f, 0.5f, 0.4f);
+ dam.executeFunction = shearDamageExecute;
+ m_damagers.push_back(dam);
+ }
+
+ {
+ Damager dam;
+ dam.uiName = "Stress Damage";
+ dam.program = { nullptr, nullptr };
+ dam.pointerType = Damager::PointerType::Sphere;
+ dam.pointerColor = DirectX::XMFLOAT4(0.5f, 0.5f, 1.0f, 0.4f);
+ dam.executeFunction = stressDamageExecute;
+ m_damagers.push_back(dam);
+ }
+
+ for (const Damager& d : m_damagers)
+ {
+ m_damagerNames.push_back(d.uiName);
+ }
+}
+
+DamageToolController::~DamageToolController()
+{
+}
+
+void DamageToolController::onSampleStart()
+{
+ // damage tool pointer
+ m_toolRenderMaterial = new RenderMaterial(getRenderer().getResourceManager(), "physx_primitive_transparent", "", RenderMaterial::BLEND_ALPHA_BLENDING);
+ {
+ IRenderMesh* mesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Sphere);
+ m_sphereToolRenderable = getRenderer().createRenderable(*mesh, *m_toolRenderMaterial);
+ }
+ {
+ IRenderMesh* mesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Box);
+ m_lineToolRenderable = getRenderer().createRenderable(*mesh, *m_toolRenderMaterial);
+ }
+
+ // default tool
+ m_damagerIndex = 0;
+
+ // start with damage mode by default
+ setDamageMode(true);
+}
+
+void DamageToolController::onInitialize()
+{
+}
+
+
+void DamageToolController::onSampleStop()
+{
+ getRenderer().removeRenderable(m_sphereToolRenderable);
+ getRenderer().removeRenderable(m_lineToolRenderable);
+ SAFE_DELETE(m_toolRenderMaterial);
+}
+
+
+void DamageToolController::Animate(double dt)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ m_toolColor = XMFLOAT4Lerp(m_toolColor, m_damagers[m_damagerIndex].pointerColor, dt * 5.0f);
+
+ m_sphereToolRenderable->setHidden(true);
+ m_lineToolRenderable->setHidden(true);
+
+ // damage mode
+ if (m_damageMode)
+ {
+ const Damager& damager = m_damagers[m_damagerIndex];
+
+ // ray cast according to camera + mouse ray
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(m_lastMousePos.x, m_lastMousePos.y, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
+
+ PxRaycastHit hit; hit.shape = NULL;
+ PxRaycastBuffer hit1;
+ getPhysXController().getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL);
+ hit = hit1.block;
+
+ if (hit.shape || (m_prevWasHit && damager.pointerType == Damager::Line))
+ {
+ PxMat44 cameraViewInv = XMMATRIXToPxMat44(getRenderer().getCamera().GetViewMatrix()).inverseRT();
+ PxVec3 weaponOrigin = eyePos + cameraViewInv.rotate(WEAPON_POSITION_IN_VIEW);
+ PxVec3 weaponDir = (hit.position - weaponOrigin).getNormalized();
+
+ // damage function
+ auto damageFunction = [&](ExtPxActor* actor, BlastFamily& family)
+ {
+ auto t0 = actor->getPhysXActor().getGlobalPose();
+ PxTransform t(t0.getInverse());
+ Damager::DamageData data;
+ data.hitNormal = t.rotate(hit.normal);
+ data.hitPosition = t.transform(hit.position);
+ data.origin = t.transform(weaponOrigin);
+ data.weaponDir = t.rotate(weaponDir);
+ data.previousWeaponDir = t.rotate(m_previousPickDir);
+ damager.executeFunction(&damager, actor, family, data);
+ };
+
+ // should damage?
+ bool shouldDamage = false;
+ if (m_isMousePressed)
+ {
+ shouldDamage = damager.damageWhilePressed || m_damageCountWhilePressed == 0;
+ m_damageCountWhilePressed++;
+ }
+ else
+ {
+ m_damageCountWhilePressed = 0;
+ }
+
+ // Update tool pointer and do damage with specific overlap
+ if (damager.pointerType == Damager::Sphere)
+ {
+ m_sphereToolRenderable->setHidden(false);
+ m_sphereToolRenderable->setColor(m_toolColor);
+ m_sphereToolRenderable->setScale(PxVec3(damager.radius));
+ m_sphereToolRenderable->setTransform(PxTransform(hit.position));
+
+ if (shouldDamage)
+ {
+ if (getBlastController().overlap(PxSphereGeometry(damager.radius), PxTransform(hit.position), damageFunction))
+ {
+ m_toolColor = PICK_POINTER_ACTIVE_COLOR;
+ }
+ getPhysXController().explodeDelayed(hit.position, damager.radius, m_explosiveImpulse);
+ }
+ }
+ else if (damager.pointerType == Damager::Line)
+ {
+ m_lineToolRenderable->setHidden(false);
+ m_lineToolRenderable->setColor(m_toolColor);
+
+ PxVec3 scale(damager.radius, damager.radius, SEGMENT_DAMAGE_MAX_DISTANCE);
+ PxVec3 direction = (hit.position - weaponOrigin).getNormalized();
+ PxVec3 position = weaponOrigin + direction * SEGMENT_DAMAGE_MAX_DISTANCE;
+
+ m_lineToolRenderable->setScale(scale);
+ PxTransform t(position, quatLookAt(direction));
+ m_lineToolRenderable->setTransform(t);
+
+ if (shouldDamage)
+ {
+ if (this->getBlastController().overlap(PxBoxGeometry(scale), t, damageFunction))
+ {
+ m_toolColor = PICK_POINTER_ACTIVE_COLOR;
+ }
+ }
+ }
+ else
+ {
+ PX_ASSERT(false);
+ }
+
+ m_previousPickDir = weaponDir;
+ m_prevWasHit = true;
+ }
+ else
+ {
+ m_prevWasHit = false;
+ }
+ }
+}
+
+
+LRESULT DamageToolController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ PROFILER_SCOPED_FUNCTION();
+
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_MOUSEMOVE || uMsg == WM_LBUTTONUP)
+ {
+ m_lastMousePos.x = (short)LOWORD(lParam) / getRenderer().getScreenWidth();
+ m_lastMousePos.y = (short)HIWORD(lParam) / getRenderer().getScreenHeight();
+ }
+
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
+ {
+ m_isMousePressed = (uMsg == WM_LBUTTONDOWN);
+ }
+
+ if (uMsg == WM_MOUSEWHEEL)
+ {
+ int delta = int((short)HIWORD(wParam)) / WHEEL_DELTA;
+ changeDamageRadius(delta * 0.3f);
+ }
+
+ if (uMsg == WM_KEYDOWN)
+ {
+ int iKeyPressed = static_cast<int>(wParam);
+ if (iKeyPressed == VK_OEM_PLUS)
+ {
+ changeDamageRadius(0.2f);
+ }
+ else if (iKeyPressed == VK_OEM_MINUS)
+ {
+ changeDamageRadius(-0.2f);
+ }
+ else if (iKeyPressed >= '1' && iKeyPressed <= '9')
+ {
+ m_damagerIndex = PxClamp<uint32_t>(iKeyPressed - '1', 0, (uint32_t)m_damagers.size() - 1);
+ }
+ else if (iKeyPressed == VK_SPACE)
+ {
+ setDamageMode(!isDamageMode());
+ }
+ }
+
+ return 1;
+}
+
+void DamageToolController::drawUI()
+{
+ ImGui::DragFloat("Damage Amount", &m_damage, 1.0f);
+ ImGui::DragFloat("Explosive Impulse", &m_explosiveImpulse);
+ ImGui::DragFloat("Stress Damage Force", &m_stressForceFactor);
+
+ // - - - - - - - -
+ ImGui::Spacing();
+
+ // Armory
+ ImGui::Combo("Damage Profile", (int*)&m_damagerIndex, m_damagerNames.data(), (int)m_damagerNames.size(), -1);
+ Damager& damager = m_damagers[m_damagerIndex];
+ ImGui::DragFloat("Damage Radius (Mouse WH)", &damager.radius);
+ ImGui::Checkbox("Damage Continuously", &damager.damageWhilePressed);
+}
+
+void DamageToolController::setDamageMode(bool enabled)
+{
+ m_damageMode = enabled;
+
+ getPhysXController().setDraggingEnabled(!m_damageMode);
+
+ if (!m_damageMode)
+ {
+ m_sphereToolRenderable->setHidden(true);
+ m_lineToolRenderable->setHidden(true);
+ }
+}
+
+void DamageToolController::changeDamageRadius(float dr)
+{
+ Damager& damager = m_damagers[m_damagerIndex];
+ damager.radius += dr;
+ damager.radius = PxClamp<float>(damager.radius, 0.05f, damager.radiusLimit);
+}