aboutsummaryrefslogtreecommitdiff
path: root/samples/SampleBase/blast/BlastFamilyModelSimple.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'samples/SampleBase/blast/BlastFamilyModelSimple.cpp')
-rwxr-xr-x[-rw-r--r--]samples/SampleBase/blast/BlastFamilyModelSimple.cpp708
1 files changed, 354 insertions, 354 deletions
diff --git a/samples/SampleBase/blast/BlastFamilyModelSimple.cpp b/samples/SampleBase/blast/BlastFamilyModelSimple.cpp
index 167ff36..61feec8 100644..100755
--- a/samples/SampleBase/blast/BlastFamilyModelSimple.cpp
+++ b/samples/SampleBase/blast/BlastFamilyModelSimple.cpp
@@ -1,354 +1,354 @@
-// 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 "BlastFamilyModelSimple.h"
-#include "RenderUtils.h"
-#include "DeviceManager.h"
-#include "Renderer.h"
-#include "NvBlastExtPxAsset.h"
-#include "NvBlastExtPxActor.h"
-#include "NvBlastTkActor.h"
-#include "NvBlastTkAsset.h"
-#include "PxRigidDynamic.h"
-
-using namespace physx;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// SimpleRenderMesh
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-class SimpleRenderMesh : public IRenderMesh
-{
-public:
- SimpleRenderMesh(const SimpleMesh* mesh) : m_mesh(mesh)
- {
- m_device = GetDeviceManager()->GetDevice();
-
- m_inputDesc.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
- m_inputDesc.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 });
- m_inputDesc.push_back({ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 });
- m_inputDesc.push_back({ "TEXCOORD", 1, DXGI_FORMAT_R32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
-
- m_numVertices = static_cast<uint32_t>(mesh->vertices.size());
- m_numFaces = static_cast<uint32_t>(mesh->indices.size());
-
- // VB
- {
- D3D11_SUBRESOURCE_DATA vertexBufferData;
- ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
- vertexBufferData.pSysMem = mesh->vertices.data();
-
- D3D11_BUFFER_DESC bufferDesc;
- memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
- bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
- bufferDesc.ByteWidth = sizeof(SimpleMesh::Vertex) * m_numVertices;
- bufferDesc.CPUAccessFlags = 0;
- bufferDesc.MiscFlags = 0;
- bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
-
- V(m_device->CreateBuffer(&bufferDesc, &vertexBufferData, &m_vertexBuffer));
- }
-
- // Health Buffer
- {
- // fill with 1.0f initially
- std::vector<float> healths(mesh->vertices.size());
- std::fill(healths.begin(), healths.end(), 1.0f);
-
- D3D11_SUBRESOURCE_DATA vertexBufferData;
- ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
- vertexBufferData.pSysMem = healths.data();
-
- D3D11_BUFFER_DESC bufferDesc;
- memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
- bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
- bufferDesc.ByteWidth = (uint32_t)(sizeof(float) * m_numVertices);
- bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- bufferDesc.MiscFlags = 0;
- bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
-
- V(m_device->CreateBuffer(&bufferDesc, &vertexBufferData, &m_healthBuffer));
- }
-
- // IB
- if (m_numFaces)
- {
- D3D11_SUBRESOURCE_DATA indexBufferData;
-
- ZeroMemory(&indexBufferData, sizeof(indexBufferData));
- indexBufferData.pSysMem = mesh->indices.data();
-
- D3D11_BUFFER_DESC bufferDesc;
-
- memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
- bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
- bufferDesc.ByteWidth = sizeof(uint32_t) * m_numFaces;
- bufferDesc.CPUAccessFlags = 0;
- bufferDesc.MiscFlags = 0;
- bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
-
- V(m_device->CreateBuffer(&bufferDesc, &indexBufferData, &m_indexBuffer));
- }
- }
-
- ~SimpleRenderMesh()
- {
- SAFE_RELEASE(m_healthBuffer);
- SAFE_RELEASE(m_vertexBuffer);
- SAFE_RELEASE(m_indexBuffer);
- }
-
-
- void render(ID3D11DeviceContext& context) const
- {
- context.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
-
- UINT strides[2] = { sizeof(SimpleMesh::Vertex), sizeof(uint32_t) };
- UINT offsets[2] = { 0 };
- ID3D11Buffer* buffers[2] = { m_vertexBuffer, m_healthBuffer };
- context.IASetVertexBuffers(0, 2, buffers, strides, offsets);
-
-
- context.IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
-
- if (m_indexBuffer)
- context.DrawIndexed(m_numFaces, 0, 0);
- else
- context.Draw(m_numVertices, 0);
- }
-
- const std::vector<D3D11_INPUT_ELEMENT_DESC>& getInputElementDesc() const { return m_inputDesc; }
-
- const SimpleMesh* getMesh() { return m_mesh; }
-
- void updateHealths(const std::vector<float>& healths)
- {
- ID3D11DeviceContext* context;
- m_device->GetImmediateContext(&context);
-
- // update buffer
- {
- D3D11_MAPPED_SUBRESOURCE mappedRead;
- V(context->Map(m_healthBuffer, 0, D3D11_MAP_WRITE_DISCARD, NULL, &mappedRead));
- memcpy(mappedRead.pData, healths.data(), sizeof(float) * healths.size());
- context->Unmap(m_healthBuffer, 0);
- }
-
- }
-
-
-private:
-
- ID3D11Device* m_device;
-
- ID3D11Buffer* m_vertexBuffer;
- ID3D11Buffer* m_healthBuffer;
- ID3D11Buffer* m_indexBuffer;
- uint32_t m_numFaces;
- uint32_t m_numVertices;
-
- std::vector<D3D11_INPUT_ELEMENT_DESC> m_inputDesc;
-
- const SimpleMesh* m_mesh;
-};
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// BlastFamilyModelSimple
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-BlastFamilyModelSimple::BlastFamilyModelSimple(PhysXController& physXController, ExtPxManager& pxManager, Renderer& renderer, const BlastAssetModelSimple& blastAsset, const BlastAsset::ActorDesc& desc)
- : BlastFamily(physXController, pxManager, blastAsset), m_renderer(renderer)
-{
- // materials
- auto materials = blastAsset.getRenderMaterials();
-
- // model
- const BlastModel& model = blastAsset.getModel();
-
- // create render mesh for every BlastModel::Chunk::Mesh and renderable with it
- const std::vector<BlastModel::Chunk>& modelChunks = model.chunks;
- m_chunks.resize(modelChunks.size());
- for (uint32_t chunkIndex = 0; chunkIndex < modelChunks.size(); chunkIndex++)
- {
- const std::vector<BlastModel::Chunk::Mesh>& meshes = modelChunks[chunkIndex].meshes;
- std::vector<SimpleRenderMesh*>& renderMeshes = m_chunks[chunkIndex].renderMeshes;
- std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
- renderMeshes.resize(meshes.size());
- renderables.resize(meshes.size());
- for (uint32_t i = 0; i < meshes.size(); i++)
- {
- renderMeshes[i] = new SimpleRenderMesh(&meshes[i].mesh);
-
- uint32_t materialIndex = model.chunks[chunkIndex].meshes[i].materialIndex;
- Renderable* renderable = renderer.createRenderable(*renderMeshes[i], *materials[materialIndex]);
- renderable->setHidden(true);
- renderables[i] = renderable;
-
- }
- }
-
- // initialize in position
- initialize(desc);
-}
-
-BlastFamilyModelSimple::~BlastFamilyModelSimple()
-{
- // release all chunks
- for (uint32_t chunkIndex = 0; chunkIndex < m_chunks.size(); chunkIndex++)
- {
- std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
- for (uint32_t i = 0; i < m_chunks[chunkIndex].renderables.size(); i++)
- {
- m_renderer.removeRenderable(m_chunks[chunkIndex].renderables[i]);
- SAFE_DELETE(m_chunks[chunkIndex].renderMeshes[i]);
- }
- }
-}
-
-void BlastFamilyModelSimple::onActorCreated(const ExtPxActor& actor)
-{
- // separate color for every material
- std::vector<DirectX::XMFLOAT4> colors;
-
- const uint32_t* chunkIndices = actor.getChunkIndices();
- uint32_t chunkCount = actor.getChunkCount();
- for (uint32_t i = 0; i < chunkCount; i++)
- {
- uint32_t chunkIndex = chunkIndices[i];
- std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
- for (uint32_t r = 0; r < renderables.size(); r++)
- {
- if (colors.size() <= r)
- colors.push_back(getRandomPastelColor());
-
- renderables[r]->setHidden(false);
- renderables[r]->setColor(colors[r]);
- }
- }
-}
-
-void BlastFamilyModelSimple::onActorUpdate(const ExtPxActor& actor)
-{
- const ExtPxChunk* chunks = m_blastAsset.getPxAsset()->getChunks();
- const ExtPxSubchunk* subChunks = m_blastAsset.getPxAsset()->getSubchunks();
- const uint32_t* chunkIndices = actor.getChunkIndices();
- uint32_t chunkCount = actor.getChunkCount();
- for (uint32_t i = 0; i < chunkCount; i++)
- {
- uint32_t chunkIndex = chunkIndices[i];
- std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
- for (Renderable* r : renderables)
- {
- r->setTransform(actor.getPhysXActor().getGlobalPose() * subChunks[chunks[chunkIndex].firstSubchunkIndex].transform);
- }
- }
-}
-
-void BlastFamilyModelSimple::onActorDestroyed(const ExtPxActor& actor)
-{
- const uint32_t* chunkIndices = actor.getChunkIndices();
- uint32_t chunkCount = actor.getChunkCount();
- for (uint32_t i = 0; i < chunkCount; i++)
- {
- uint32_t chunkIndex = chunkIndices[i];
- std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
- for (Renderable* r : renderables)
- {
- r->setHidden(true);
- }
- }
-}
-
-void BlastFamilyModelSimple::onActorHealthUpdate(const ExtPxActor& actor)
-{
- TkActor& tkActor = actor.getTkActor();
- const TkAsset* tkAsset = tkActor.getAsset();
-
- const float* bondHealths = tkActor.getBondHealths();
- uint32_t nodeCount = tkActor.getGraphNodeCount();
- if (nodeCount == 0) // subsupport chunks don't have graph nodes
- return;
-
- std::vector<uint32_t> nodes(tkActor.getGraphNodeCount());
- tkActor.getGraphNodeIndices(nodes.data(), static_cast<uint32_t>(nodes.size()));
-
- const NvBlastChunk* chunks = tkAsset->getChunks();
- const NvBlastBond* bonds = tkAsset->getBonds();
-
- const NvBlastSupportGraph graph = tkAsset->getGraph();
- const float bondHealthMax = m_blastAsset.getBondHealthMax();
-
- std::vector<float> healthBuffer;
-
- for (uint32_t node0 : nodes)
- {
- uint32_t chunkIndex = graph.chunkIndices[node0];
-
- if (chunkIndex >= m_chunks.size())
- continue;
-
- std::vector<SimpleRenderMesh*>& meshes = m_chunks[chunkIndex].renderMeshes;
- const auto& renderables = m_chunks[chunkIndex].renderables;
- for (uint32_t i = 0; i < meshes.size(); ++i)
- {
- if(renderables[i]->isHidden())
- continue;
-
- SimpleRenderMesh* renderMesh = meshes[i];
-
- const SimpleMesh* mesh = renderMesh->getMesh();
- healthBuffer.resize(mesh->vertices.size());
-
- for (uint32_t vertexIndex = 0; vertexIndex < mesh->vertices.size(); vertexIndex++)
- {
- PxVec3 position = mesh->vertices[vertexIndex].position;
- float health = 0.0f;
- float healthDenom = 0.0f;
-
- for (uint32_t adjacencyIndex = graph.adjacencyPartition[node0]; adjacencyIndex < graph.adjacencyPartition[node0 + 1]; adjacencyIndex++)
- {
- uint32_t node1 = graph.adjacentNodeIndices[adjacencyIndex];
- uint32_t bondIndex = graph.adjacentBondIndices[adjacencyIndex];
- float bondHealth = PxClamp(bondHealths[bondIndex] / bondHealthMax, 0.0f, 1.0f);
- const NvBlastBond& solverBond = bonds[bondIndex];
- const PxVec3& centroid = reinterpret_cast<const PxVec3&>(solverBond.centroid);
-
- float factor = 1.0f / (centroid - position).magnitudeSquared();
-
- health += bondHealth * factor;
- healthDenom += factor;
- }
-
- healthBuffer[vertexIndex] = healthDenom > 0.0f ? health / healthDenom : 1.0f;
- }
-
- renderMesh->updateHealths(healthBuffer);
- }
- }
-}
+// 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 "BlastFamilyModelSimple.h"
+#include "RenderUtils.h"
+#include "DeviceManager.h"
+#include "Renderer.h"
+#include "NvBlastExtPxAsset.h"
+#include "NvBlastExtPxActor.h"
+#include "NvBlastTkActor.h"
+#include "NvBlastTkAsset.h"
+#include "PxRigidDynamic.h"
+
+using namespace physx;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// SimpleRenderMesh
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SimpleRenderMesh : public IRenderMesh
+{
+public:
+ SimpleRenderMesh(const SimpleMesh* mesh) : m_mesh(mesh)
+ {
+ m_device = GetDeviceManager()->GetDevice();
+
+ m_inputDesc.push_back({ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ m_inputDesc.push_back({ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ m_inputDesc.push_back({ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+ m_inputDesc.push_back({ "TEXCOORD", 1, DXGI_FORMAT_R32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 });
+
+ m_numVertices = static_cast<uint32_t>(mesh->vertices.size());
+ m_numFaces = static_cast<uint32_t>(mesh->indices.size());
+
+ // VB
+ {
+ D3D11_SUBRESOURCE_DATA vertexBufferData;
+ ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
+ vertexBufferData.pSysMem = mesh->vertices.data();
+
+ D3D11_BUFFER_DESC bufferDesc;
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.ByteWidth = sizeof(SimpleMesh::Vertex) * m_numVertices;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+
+ V(m_device->CreateBuffer(&bufferDesc, &vertexBufferData, &m_vertexBuffer));
+ }
+
+ // Health Buffer
+ {
+ // fill with 1.0f initially
+ std::vector<float> healths(mesh->vertices.size());
+ std::fill(healths.begin(), healths.end(), 1.0f);
+
+ D3D11_SUBRESOURCE_DATA vertexBufferData;
+ ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
+ vertexBufferData.pSysMem = healths.data();
+
+ D3D11_BUFFER_DESC bufferDesc;
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.ByteWidth = (uint32_t)(sizeof(float) * m_numVertices);
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+
+ V(m_device->CreateBuffer(&bufferDesc, &vertexBufferData, &m_healthBuffer));
+ }
+
+ // IB
+ if (m_numFaces)
+ {
+ D3D11_SUBRESOURCE_DATA indexBufferData;
+
+ ZeroMemory(&indexBufferData, sizeof(indexBufferData));
+ indexBufferData.pSysMem = mesh->indices.data();
+
+ D3D11_BUFFER_DESC bufferDesc;
+
+ memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC));
+ bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ bufferDesc.ByteWidth = sizeof(uint32_t) * m_numFaces;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+
+ V(m_device->CreateBuffer(&bufferDesc, &indexBufferData, &m_indexBuffer));
+ }
+ }
+
+ ~SimpleRenderMesh()
+ {
+ SAFE_RELEASE(m_healthBuffer);
+ SAFE_RELEASE(m_vertexBuffer);
+ SAFE_RELEASE(m_indexBuffer);
+ }
+
+
+ void render(ID3D11DeviceContext& context) const
+ {
+ context.IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+
+ UINT strides[2] = { sizeof(SimpleMesh::Vertex), sizeof(uint32_t) };
+ UINT offsets[2] = { 0 };
+ ID3D11Buffer* buffers[2] = { m_vertexBuffer, m_healthBuffer };
+ context.IASetVertexBuffers(0, 2, buffers, strides, offsets);
+
+
+ context.IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
+
+ if (m_indexBuffer)
+ context.DrawIndexed(m_numFaces, 0, 0);
+ else
+ context.Draw(m_numVertices, 0);
+ }
+
+ const std::vector<D3D11_INPUT_ELEMENT_DESC>& getInputElementDesc() const { return m_inputDesc; }
+
+ const SimpleMesh* getMesh() { return m_mesh; }
+
+ void updateHealths(const std::vector<float>& healths)
+ {
+ ID3D11DeviceContext* context;
+ m_device->GetImmediateContext(&context);
+
+ // update buffer
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedRead;
+ V(context->Map(m_healthBuffer, 0, D3D11_MAP_WRITE_DISCARD, NULL, &mappedRead));
+ memcpy(mappedRead.pData, healths.data(), sizeof(float) * healths.size());
+ context->Unmap(m_healthBuffer, 0);
+ }
+
+ }
+
+
+private:
+
+ ID3D11Device* m_device;
+
+ ID3D11Buffer* m_vertexBuffer;
+ ID3D11Buffer* m_healthBuffer;
+ ID3D11Buffer* m_indexBuffer;
+ uint32_t m_numFaces;
+ uint32_t m_numVertices;
+
+ std::vector<D3D11_INPUT_ELEMENT_DESC> m_inputDesc;
+
+ const SimpleMesh* m_mesh;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// BlastFamilyModelSimple
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+BlastFamilyModelSimple::BlastFamilyModelSimple(PhysXController& physXController, ExtPxManager& pxManager, Renderer& renderer, const BlastAssetModelSimple& blastAsset, const BlastAsset::ActorDesc& desc)
+ : BlastFamily(physXController, pxManager, blastAsset), m_renderer(renderer)
+{
+ // materials
+ auto materials = blastAsset.getRenderMaterials();
+
+ // model
+ const BlastModel& model = blastAsset.getModel();
+
+ // create render mesh for every BlastModel::Chunk::Mesh and renderable with it
+ const std::vector<BlastModel::Chunk>& modelChunks = model.chunks;
+ m_chunks.resize(modelChunks.size());
+ for (uint32_t chunkIndex = 0; chunkIndex < modelChunks.size(); chunkIndex++)
+ {
+ const std::vector<BlastModel::Chunk::Mesh>& meshes = modelChunks[chunkIndex].meshes;
+ std::vector<SimpleRenderMesh*>& renderMeshes = m_chunks[chunkIndex].renderMeshes;
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ renderMeshes.resize(meshes.size());
+ renderables.resize(meshes.size());
+ for (uint32_t i = 0; i < meshes.size(); i++)
+ {
+ renderMeshes[i] = new SimpleRenderMesh(&meshes[i].mesh);
+
+ uint32_t materialIndex = model.chunks[chunkIndex].meshes[i].materialIndex;
+ Renderable* renderable = renderer.createRenderable(*renderMeshes[i], *materials[materialIndex]);
+ renderable->setHidden(true);
+ renderables[i] = renderable;
+
+ }
+ }
+
+ // initialize in position
+ initialize(desc);
+}
+
+BlastFamilyModelSimple::~BlastFamilyModelSimple()
+{
+ // release all chunks
+ for (uint32_t chunkIndex = 0; chunkIndex < m_chunks.size(); chunkIndex++)
+ {
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (uint32_t i = 0; i < m_chunks[chunkIndex].renderables.size(); i++)
+ {
+ m_renderer.removeRenderable(m_chunks[chunkIndex].renderables[i]);
+ SAFE_DELETE(m_chunks[chunkIndex].renderMeshes[i]);
+ }
+ }
+}
+
+void BlastFamilyModelSimple::onActorCreated(const ExtPxActor& actor)
+{
+ // separate color for every material
+ std::vector<DirectX::XMFLOAT4> colors;
+
+ const uint32_t* chunkIndices = actor.getChunkIndices();
+ uint32_t chunkCount = actor.getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (uint32_t r = 0; r < renderables.size(); r++)
+ {
+ if (colors.size() <= r)
+ colors.push_back(getRandomPastelColor());
+
+ renderables[r]->setHidden(false);
+ renderables[r]->setColor(colors[r]);
+ }
+ }
+}
+
+void BlastFamilyModelSimple::onActorUpdate(const ExtPxActor& actor)
+{
+ const ExtPxChunk* chunks = m_blastAsset.getPxAsset()->getChunks();
+ const ExtPxSubchunk* subChunks = m_blastAsset.getPxAsset()->getSubchunks();
+ const uint32_t* chunkIndices = actor.getChunkIndices();
+ uint32_t chunkCount = actor.getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (Renderable* r : renderables)
+ {
+ r->setTransform(actor.getPhysXActor().getGlobalPose() * subChunks[chunks[chunkIndex].firstSubchunkIndex].transform);
+ }
+ }
+}
+
+void BlastFamilyModelSimple::onActorDestroyed(const ExtPxActor& actor)
+{
+ const uint32_t* chunkIndices = actor.getChunkIndices();
+ uint32_t chunkCount = actor.getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; i++)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ std::vector<Renderable*>& renderables = m_chunks[chunkIndex].renderables;
+ for (Renderable* r : renderables)
+ {
+ r->setHidden(true);
+ }
+ }
+}
+
+void BlastFamilyModelSimple::onActorHealthUpdate(const ExtPxActor& actor)
+{
+ TkActor& tkActor = actor.getTkActor();
+ const TkAsset* tkAsset = tkActor.getAsset();
+
+ const float* bondHealths = tkActor.getBondHealths();
+ uint32_t nodeCount = tkActor.getGraphNodeCount();
+ if (nodeCount == 0) // subsupport chunks don't have graph nodes
+ return;
+
+ std::vector<uint32_t> nodes(tkActor.getGraphNodeCount());
+ tkActor.getGraphNodeIndices(nodes.data(), static_cast<uint32_t>(nodes.size()));
+
+ const NvBlastChunk* chunks = tkAsset->getChunks();
+ const NvBlastBond* bonds = tkAsset->getBonds();
+
+ const NvBlastSupportGraph graph = tkAsset->getGraph();
+ const float bondHealthMax = m_blastAsset.getBondHealthMax();
+
+ std::vector<float> healthBuffer;
+
+ for (uint32_t node0 : nodes)
+ {
+ uint32_t chunkIndex = graph.chunkIndices[node0];
+
+ if (chunkIndex >= m_chunks.size())
+ continue;
+
+ std::vector<SimpleRenderMesh*>& meshes = m_chunks[chunkIndex].renderMeshes;
+ const auto& renderables = m_chunks[chunkIndex].renderables;
+ for (uint32_t i = 0; i < meshes.size(); ++i)
+ {
+ if(renderables[i]->isHidden())
+ continue;
+
+ SimpleRenderMesh* renderMesh = meshes[i];
+
+ const SimpleMesh* mesh = renderMesh->getMesh();
+ healthBuffer.resize(mesh->vertices.size());
+
+ for (uint32_t vertexIndex = 0; vertexIndex < mesh->vertices.size(); vertexIndex++)
+ {
+ PxVec3 position = mesh->vertices[vertexIndex].position;
+ float health = 0.0f;
+ float healthDenom = 0.0f;
+
+ for (uint32_t adjacencyIndex = graph.adjacencyPartition[node0]; adjacencyIndex < graph.adjacencyPartition[node0 + 1]; adjacencyIndex++)
+ {
+ uint32_t node1 = graph.adjacentNodeIndices[adjacencyIndex];
+ uint32_t bondIndex = graph.adjacentBondIndices[adjacencyIndex];
+ float bondHealth = PxClamp(bondHealths[bondIndex] / bondHealthMax, 0.0f, 1.0f);
+ const NvBlastBond& solverBond = bonds[bondIndex];
+ const PxVec3& centroid = reinterpret_cast<const PxVec3&>(solverBond.centroid);
+
+ float factor = 1.0f / (centroid - position).magnitudeSquared();
+
+ health += bondHealth * factor;
+ healthDenom += factor;
+ }
+
+ healthBuffer[vertexIndex] = healthDenom > 0.0f ? health / healthDenom : 1.0f;
+ }
+
+ renderMesh->updateHealths(healthBuffer);
+ }
+ }
+}