aboutsummaryrefslogtreecommitdiff
path: root/samples/SampleBase/ui/DamageToolController.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'samples/SampleBase/ui/DamageToolController.cpp')
-rw-r--r--samples/SampleBase/ui/DamageToolController.cpp337
1 files changed, 228 insertions, 109 deletions
diff --git a/samples/SampleBase/ui/DamageToolController.cpp b/samples/SampleBase/ui/DamageToolController.cpp
index 1850b26..2f8837c 100644
--- a/samples/SampleBase/ui/DamageToolController.cpp
+++ b/samples/SampleBase/ui/DamageToolController.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 "DamageToolController.h"
#include "RenderUtils.h"
@@ -18,6 +36,7 @@
#include <imgui.h>
#include "NvBlastTkActor.h"
+#include "NvBlastTkFamily.h"
#include "NvBlastExtDamageShaders.h"
#include "NvBlastExtPxActor.h"
@@ -32,44 +51,84 @@ 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_damageRadius(5.0f), m_compressiveDamage(1.0f), m_pickPointerColor(1.0f, 1.0f, 1.0f, 0.4f),
- m_pickPointerRenderMaterial(nullptr), m_pickPointerRenderable(nullptr), m_explosiveImpulse(100), m_damageProfile(0), m_stressForceFactor(1.0f)
+ : 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 void* material = actor->getTkActor().getFamily().getMaterial();
+ return material ? reinterpret_cast<const NvBlastExtMaterial*>(material)->getNormalizedDamage(damage) : 0.f;
+ };
+
// Damage functions
- auto radialDamageExecute = [&](const Damager* damager, ExtPxActor* actor, PxVec3 position, PxVec3 normal)
+ auto radialDamageExecute = [&](const Damager* damager, ExtPxActor* actor, PxVec3 origin, PxVec3 position, PxVec3 normal)
{
- NvBlastExtRadialDamageDesc desc =
+ const float damage = getDamageAmountFn(m_damage, actor);
+ if (damage > 0.f)
{
- m_compressiveDamage,
- { position.x, position.y, position.z },
- m_damageRadius,
- m_damageRadius + 2.0f
- };
+ NvBlastExtRadialDamageDesc desc =
+ {
+ damage,
+ { position.x, position.y, position.z },
+ damager->radius,
+ damager->radius * 1.6f
+ };
- actor->getTkActor().damage(damager->program, &desc, sizeof(desc));
+ actor->getTkActor().damage(damager->program, &desc, sizeof(desc));
+ }
};
- auto shearDamageExecute = [&](const Damager* damager, ExtPxActor* actor, PxVec3 position, PxVec3 normal)
+ auto lineSegmentDamageExecute = [&](const Damager* damager, ExtPxActor* actor, PxVec3 origin, PxVec3 position, PxVec3 normal)
{
- PxVec3 force = -2 * normal;
+ const float damage = getDamageAmountFn(m_damage, actor);
+ if (damage > 0.f)
+ {
+ PxVec3 dir = (position - origin).getNormalized();
+ PxVec3 farEnd = origin + dir * 10000.0f;
- NvBlastExtShearDamageDesc desc =
+ NvBlastExtSegmentRadialDamageDesc desc =
+ {
+ damage,
+ { origin.x, origin.y, origin.z },
+ { farEnd.x, farEnd.y, farEnd.z },
+ damager->radius,
+ damager->radius * 1.6f
+ };
+
+ actor->getTkActor().damage(damager->program, &desc, sizeof(desc));
+ }
+ };
+ auto shearDamageExecute = [&](const Damager* damager, ExtPxActor* actor, PxVec3 origin, PxVec3 position, PxVec3 normal)
+ {
+ const float damage = getDamageAmountFn(m_damage, actor);
+ if (damage > 0.f)
{
- { force.x, force.y, force.z },
- { position.x, position.y, position.z }
- };
+ PxVec3 impactNormal = -normal;
- actor->getTkActor().damage(damager->program, &desc, sizeof(desc));
+ NvBlastExtShearDamageDesc desc =
+ {
+ damage,
+ { impactNormal.x, impactNormal.y, impactNormal.z },
+ { position.x, position.y, position.z },
+ damager->radius,
+ damager->radius * 1.6f
+ };
+
+ actor->getTkActor().damage(damager->program, &desc, sizeof(desc));
+ }
};
- auto stressDamageExecute = [&](const Damager* damager, ExtPxActor* actor, PxVec3 position, PxVec3 normal)
+ auto stressDamageExecute = [&](const Damager* damager, ExtPxActor* actor, PxVec3 origin, PxVec3 position, PxVec3 normal)
{
PxVec3 force = -m_stressForceFactor * normal * actor->getPhysXActor().getMass();
@@ -81,40 +140,57 @@ DamageToolController::DamageToolController()
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_armory.push_back(dam);
+ 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_armory.push_back(dam);
+ m_damagers.push_back(dam);
+ }
+
+ {
+ Damager dam;
+ dam.uiName = "Segment Damage (Falloff)";
+ dam.program = NvBlastDamageProgram{ NvBlastExtSegmentFalloffGraphShader, NvBlastExtSegmentFalloffSubgraphShader };
+ dam.pointerType = Damager::PointerType::Line;
+ dam.pointerColor = DirectX::XMFLOAT4(0.1f, 1.0f, 0.1f, 0.4f);
+ dam.executeFunction = lineSegmentDamageExecute;
+ dam.damageWhilePressed = true;
+ dam.radius = .2f;
+ dam.radiusLimit = 20.0f;
+ 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_armory.push_back(dam);
+ 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_armory.push_back(dam);
+ m_damagers.push_back(dam);
}
- for (const Damager& d : m_armory)
+ for (const Damager& d : m_damagers)
{
- m_armoryNames.push_back(d.uiName);
+ m_damagerNames.push_back(d.uiName);
}
}
@@ -124,14 +200,19 @@ DamageToolController::~DamageToolController()
void DamageToolController::onSampleStart()
{
- // pick pointer
- m_pickPointerRenderMaterial = new RenderMaterial(getRenderer().getResourceManager(), "physx_primitive_transparent", "", RenderMaterial::BLEND_ALPHA_BLENDING);
- IRenderMesh* mesh = getRenderer().getPrimitiveRenderMesh(PrimitiveRenderMeshType::Sphere);
- m_pickPointerRenderable = getRenderer().createRenderable(*mesh, *m_pickPointerRenderMaterial);
- m_pickPointerRenderable->setScale(PxVec3(m_damageRadius));
+ // 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
- setDamageProfile(0);
+ m_damagerIndex = 0;
// start with damage mode by default
setDamageMode(true);
@@ -144,59 +225,124 @@ void DamageToolController::onInitialize()
void DamageToolController::onSampleStop()
{
- getRenderer().removeRenderable(m_pickPointerRenderable);
- SAFE_DELETE(m_pickPointerRenderMaterial);
+ getRenderer().removeRenderable(m_sphereToolRenderable);
+ getRenderer().removeRenderable(m_lineToolRenderable);
+ SAFE_DELETE(m_toolRenderMaterial);
}
+
void DamageToolController::Animate(double dt)
{
PROFILER_SCOPED_FUNCTION();
- m_pickPointerColor = XMFLOAT4Lerp(m_pickPointerColor, m_armory[m_damageProfile].pointerColor, dt * 5.0f);
- m_pickPointerRenderable->setColor(m_pickPointerColor);
-}
-
+ m_toolColor = XMFLOAT4Lerp(m_toolColor, m_damagers[m_damagerIndex].pointerColor, dt * 5.0f);
-LRESULT DamageToolController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- PROFILER_SCOPED_FUNCTION();
+ m_sphereToolRenderable->setHidden(true);
+ m_lineToolRenderable->setHidden(true);
- if (uMsg == WM_LBUTTONDOWN || uMsg == WM_MOUSEMOVE || uMsg == WM_LBUTTONUP)
+ // damage mode
+ if (m_damageMode)
{
- float mouseX = (short)LOWORD(lParam) / getRenderer().getScreenWidth();
- float mouseY = (short)HIWORD(lParam) / getRenderer().getScreenHeight();
- bool press = uMsg == WM_LBUTTONDOWN;
+ // ray cast according to camera + mouse ray
+ PxVec3 eyePos, pickDir;
+ getPhysXController().getEyePoseAndPickDir(m_lastMousePos.x, m_lastMousePos.y, eyePos, pickDir);
+ pickDir = pickDir.getNormalized();
- // damage mode
- if (m_damageMode && m_pickPointerRenderable)
+ 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)
{
- PxVec3 eyePos, pickDir;
- getPhysXController().getEyePoseAndPickDir(mouseX, mouseY, eyePos, pickDir);
- pickDir = pickDir.getNormalized();
+ PxMat44 cameraViewInv = XMMATRIXToPxMat44(getRenderer().getCamera().GetViewMatrix()).inverseRT();
+ PxVec3 weaponOrigin = eyePos + cameraViewInv.rotate(WEAPON_POSITION_IN_VIEW);
+
+ // damage function
+ const Damager& damager = m_damagers[m_damagerIndex];
+ auto damageFunction = [&](ExtPxActor* actor)
+ {
+ auto t0 = actor->getPhysXActor().getGlobalPose();
+ PxTransform t(t0.getInverse());
+ PxVec3 localNormal = t.rotate(hit.normal);
+ PxVec3 localPosition = t.transform(hit.position);
+ PxVec3 localOrigin = t.transform(weaponOrigin);
+ damager.executeFunction(&damager, actor, localOrigin, localPosition, localNormal);
+ };
+
+ // should damage?
+ bool shouldDamage = false;
+ if (m_isMousePressed)
+ {
+ shouldDamage = damager.damageWhilePressed || m_damageCountWhilePressed == 0;
+ m_damageCountWhilePressed++;
+ }
+ else
+ {
+ m_damageCountWhilePressed = 0;
+ }
- PxRaycastHit hit; hit.shape = NULL;
- PxRaycastBuffer hit1;
- getPhysXController().getPhysXScene().raycast(eyePos, pickDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL);
- hit = hit1.block;
+ // 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 (hit.shape)
+ 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)
{
- PxRigidActor* actor = hit.actor;
- m_pickPointerRenderable->setHidden(false);
- m_pickPointerRenderable->setTransform(PxTransform(hit.position));
+ 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 (press)
+ if (shouldDamage)
{
- damage(hit.position, hit.normal);
- m_pickPointerColor = PICK_POINTER_ACTIVE_COLOR;
+ if (this->getBlastController().overlap(PxBoxGeometry(scale), t, damageFunction))
+ {
+ m_toolColor = PICK_POINTER_ACTIVE_COLOR;
+ }
}
}
else
{
- m_pickPointerRenderable->setHidden(true);
+ PX_ASSERT(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)
{
@@ -217,14 +363,12 @@ LRESULT DamageToolController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
else if (iKeyPressed >= '1' && iKeyPressed <= '9')
{
- uint32_t num = PxClamp<uint32_t>(iKeyPressed - '1', 0, (uint32_t)m_armory.size() - 1);
- setDamageProfile(num);
+ m_damagerIndex = PxClamp<uint32_t>(iKeyPressed - '1', 0, (uint32_t)m_damagers.size() - 1);
}
else if (iKeyPressed == VK_SPACE)
{
setDamageMode(!isDamageMode());
}
-
}
return 1;
@@ -232,22 +376,20 @@ LRESULT DamageToolController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
void DamageToolController::drawUI()
{
- ImGui::DragFloat("Compressive Damage", &m_compressiveDamage, 0.05f);
+ ImGui::DragFloat("Damage Amount", &m_damage, 1.0f);
ImGui::DragFloat("Explosive Impulse", &m_explosiveImpulse);
- ImGui::DragFloat("Damage Radius (Mouse WH)", &m_damageRadius);
ImGui::DragFloat("Stress Damage Force", &m_stressForceFactor);
// - - - - - - - -
ImGui::Spacing();
// Armory
- if (ImGui::Combo("Damage Profile", (int*)&m_damageProfile, m_armoryNames.data(), (int)m_armoryNames.size(), -1))
- {
- setDamageProfile(m_damageProfile);
- }
+ 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;
@@ -256,37 +398,14 @@ void DamageToolController::setDamageMode(bool enabled)
if (!m_damageMode)
{
- m_pickPointerRenderable->setHidden(true);
+ m_sphereToolRenderable->setHidden(true);
+ m_lineToolRenderable->setHidden(true);
}
}
-
-void DamageToolController::setDamageProfile(uint32_t profile)
-{
- m_damageProfile = profile;
-}
-
-
void DamageToolController::changeDamageRadius(float dr)
{
- m_damageRadius += dr;
- m_damageRadius = PxMax(1.0f, m_damageRadius);
- m_pickPointerRenderable->setScale(PxVec3(m_damageRadius));
-}
-
-
-void DamageToolController::damage(physx::PxVec3 position, physx::PxVec3 normal)
-{
- auto damageFunction = [&](ExtPxActor* actor)
- {
- auto t0 = actor->getPhysXActor().getGlobalPose();
- PxTransform t(t0.getInverse());
- PxVec3 localNormal = t.rotate(normal);
- PxVec3 localPosition = t.transform(position);
- Damager& damager = m_armory[m_damageProfile];
- damager.execute(actor, localPosition, localNormal);
- };
-
- this->getBlastController().blast(position, m_damageRadius, m_explosiveImpulse, damageFunction);
-
+ Damager& damager = m_damagers[m_damagerIndex];
+ damager.radius += dr;
+ damager.radius = PxClamp<float>(damager.radius, 0.05f, damager.radiusLimit);
}