From 7115f60b91b5717d90f643fd692010905c7004db Mon Sep 17 00:00:00 2001 From: Bryan Galdrikian Date: Thu, 31 May 2018 11:36:08 -0700 Subject: Blast 1.1.3. See docs/release_notes.txt. --- samples/SampleBase/ui/DamageToolController.cpp | 968 ++++++++++++------------- 1 file changed, 484 insertions(+), 484 deletions(-) mode change 100644 => 100755 samples/SampleBase/ui/DamageToolController.cpp (limited to 'samples/SampleBase/ui/DamageToolController.cpp') diff --git a/samples/SampleBase/ui/DamageToolController.cpp b/samples/SampleBase/ui/DamageToolController.cpp old mode 100644 new mode 100755 index 1fc0817..b634c7d --- 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 - -#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(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(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(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 + +#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(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(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(damager.radius, 0.05f, damager.radiusLimit); +} -- cgit v1.2.3