aboutsummaryrefslogtreecommitdiff
path: root/samples/SampleBase/blast/BlastFamilyModelSkinned.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'samples/SampleBase/blast/BlastFamilyModelSkinned.cpp')
-rw-r--r--samples/SampleBase/blast/BlastFamilyModelSkinned.cpp167
1 files changed, 167 insertions, 0 deletions
diff --git a/samples/SampleBase/blast/BlastFamilyModelSkinned.cpp b/samples/SampleBase/blast/BlastFamilyModelSkinned.cpp
new file mode 100644
index 0000000..c0731d5
--- /dev/null
+++ b/samples/SampleBase/blast/BlastFamilyModelSkinned.cpp
@@ -0,0 +1,167 @@
+/*
+* 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.
+*/
+
+#include "BlastFamilyModelSkinned.h"
+#include "RenderUtils.h"
+#include "Renderer.h"
+#include "SkinnedRenderMesh.h"
+#include "NvBlastExtPxAsset.h"
+#include "NvBlastExtPxActor.h"
+#include "NvBlastTkActor.h"
+#include "PxRigidDynamic.h"
+
+using namespace physx;
+
+BlastFamilyModelSkinned::BlastFamilyModelSkinned(PhysXController& physXController, ExtPxManager& pxManager, Renderer& renderer, const BlastAssetModelSkinned& blastAsset, const BlastAsset::ActorDesc& desc)
+ : BlastFamily(physXController, pxManager, blastAsset), m_renderer(renderer), m_visibleActorsDirty(true)
+{
+ // materials
+ auto materials = blastAsset.getRenderMaterials();
+
+ const BlastModel& model = blastAsset.getModel();
+
+ // finalize (create) sub model
+ auto finalizeSubModelFunction = [&](SubModel* subModel, std::vector<const SimpleMesh*>& subModelMeshes, RenderMaterial& renderMaterial)
+ {
+ subModel->skinnedRenderMesh = new SkinnedRenderMesh(subModelMeshes);
+ subModel->renderable = renderer.createRenderable(*subModel->skinnedRenderMesh, renderMaterial);
+ subModel->renderable->setColor(getRandomPastelColor());
+ };
+
+ // create at least one submodel per every material (if mesh count is too high, more then one sub model per material to be created)
+ SubModel* subModel = nullptr;
+ std::vector<const SimpleMesh*> subModelMeshes;
+ subModelMeshes.reserve(model.chunks.size());
+ for (uint32_t materialIndex = 0; materialIndex < model.materials.size(); materialIndex++)
+ {
+ for (uint32_t chunkIndex = 0; chunkIndex < model.chunks.size(); chunkIndex++)
+ {
+ const BlastModel::Chunk& chunk = model.chunks[chunkIndex];
+ for (const BlastModel::Chunk::Mesh& mesh : chunk.meshes)
+ {
+ if (mesh.materialIndex == materialIndex)
+ {
+ // init new submodel?
+ if (subModel == nullptr)
+ {
+ m_subModels.push_back(SubModel());
+ subModel = &m_subModels.back();
+ subModel->chunkIdToBoneMap.resize(model.chunks.size());
+ std::fill(subModel->chunkIdToBoneMap.begin(), subModel->chunkIdToBoneMap.end(), SubModel::INVALID_BONE_ID);
+ subModelMeshes.clear();
+ }
+
+ // add mesh to map and list
+ subModel->chunkIdToBoneMap[chunkIndex] = (uint32_t)subModelMeshes.size();
+ subModelMeshes.push_back(&(mesh.mesh));
+
+ // mesh reached limit?
+ if (subModelMeshes.size() == SkinnedRenderMesh::MeshesCountMax)
+ {
+ finalizeSubModelFunction(subModel, subModelMeshes, *materials[materialIndex]);
+ subModel = nullptr;
+ }
+ }
+ }
+ }
+
+ // finalize subModel for this material
+ if (subModel && subModelMeshes.size() > 0)
+ {
+ finalizeSubModelFunction(subModel, subModelMeshes, *materials[materialIndex]);
+ subModel = nullptr;
+ }
+ }
+
+ // reserve for scratch
+ m_visibleBones.reserve(model.chunks.size());
+ m_visibleBoneTransforms.reserve(model.chunks.size());
+
+ // initialize in position
+ initialize(desc);
+}
+
+BlastFamilyModelSkinned::~BlastFamilyModelSkinned()
+{
+ for (uint32_t subModelIndex = 0; subModelIndex < m_subModels.size(); subModelIndex++)
+ {
+ m_renderer.removeRenderable(m_subModels[subModelIndex].renderable);
+ SAFE_DELETE(m_subModels[subModelIndex].skinnedRenderMesh);
+ }
+}
+
+void BlastFamilyModelSkinned::onActorCreated(const ExtPxActor& actor)
+{
+ m_visibleActors.insert(&actor);
+ m_visibleActorsDirty = true;
+}
+
+void BlastFamilyModelSkinned::onActorUpdate(const ExtPxActor& actor)
+{
+}
+
+void BlastFamilyModelSkinned::onActorDestroyed(const ExtPxActor& actor)
+{
+ m_visibleActors.erase(&actor);
+ m_visibleActorsDirty = true;
+}
+
+void BlastFamilyModelSkinned::onUpdate()
+{
+ // visible actors changed this frame?
+ if (m_visibleActorsDirty)
+ {
+ for (const SubModel& model : m_subModels)
+ {
+ // pass visible chunks list to render mesh
+ m_visibleBones.clear();
+ for (const ExtPxActor* actor : m_visibleActors)
+ {
+ const uint32_t* chunkIndices = actor->getChunkIndices();
+ uint32_t chunkCount = actor->getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; ++i)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ uint32_t boneIndex = model.chunkIdToBoneMap[chunkIndex];
+ if (boneIndex != SubModel::INVALID_BONE_ID)
+ {
+ m_visibleBones.push_back(boneIndex);
+ }
+ }
+ }
+ model.skinnedRenderMesh->updateVisibleMeshes(m_visibleBones);
+ }
+
+ m_visibleActorsDirty = false;
+ }
+
+ // update and pass chunk transforms
+ const ExtPxChunk* chunks = m_blastAsset.getPxAsset()->getChunks();
+ const ExtPxSubchunk* subChunks = m_blastAsset.getPxAsset()->getSubchunks();
+ for (const SubModel& model : m_subModels)
+ {
+ m_visibleBoneTransforms.clear();
+ for (const ExtPxActor* actor : m_visibleActors)
+ {
+ const uint32_t* chunkIndices = actor->getChunkIndices();
+ uint32_t chunkCount = actor->getChunkCount();
+ for (uint32_t i = 0; i < chunkCount; ++i)
+ {
+ uint32_t chunkIndex = chunkIndices[i];
+ uint32_t boneIndex = model.chunkIdToBoneMap[chunkIndex];
+ if (boneIndex != SubModel::INVALID_BONE_ID)
+ {
+ m_visibleBoneTransforms.push_back(PxMat44(actor->getPhysXActor().getGlobalPose() * subChunks[chunks[chunkIndex].firstSubchunkIndex].transform));
+ }
+ }
+ }
+ model.skinnedRenderMesh->updateVisibleMeshTransforms(m_visibleBoneTransforms);
+ }
+}