diff options
| author | Anton Novoselov <[email protected]> | 2017-08-01 12:53:38 +0300 |
|---|---|---|
| committer | Anton Novoselov <[email protected]> | 2017-08-01 12:53:38 +0300 |
| commit | 236f03c0b9a4982328ed1201978f7f69d192d9b2 (patch) | |
| tree | e486f2fa39dba203563895541e92c60ed3e25759 /samples/SampleBase/ui/DamageToolController.cpp | |
| parent | Added screens to welcome page (diff) | |
| download | blast-236f03c0b9a4982328ed1201978f7f69d192d9b2.tar.xz blast-236f03c0b9a4982328ed1201978f7f69d192d9b2.zip | |
Blast 1.1 release (windows / linux)
see docs/release_notes.txt for details
Diffstat (limited to 'samples/SampleBase/ui/DamageToolController.cpp')
| -rw-r--r-- | samples/SampleBase/ui/DamageToolController.cpp | 337 |
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); } |