diff options
| author | Bryan Galdrikian <[email protected]> | 2017-02-24 09:32:20 -0800 |
|---|---|---|
| committer | Bryan Galdrikian <[email protected]> | 2017-02-24 09:32:20 -0800 |
| commit | e1bf674c16e3c8472b29574159c789cd3f0c64e0 (patch) | |
| tree | 9f0cfce09c71a2c27ff19589fcad6cd83504477c /samples/SampleBase/scene/SceneController.cpp | |
| parent | first commit (diff) | |
| download | blast-e1bf674c16e3c8472b29574159c789cd3f0c64e0.tar.xz blast-e1bf674c16e3c8472b29574159c789cd3f0c64e0.zip | |
Updating to [email protected] and [email protected] with a new directory structure.
NvBlast folder is gone, files have been moved to top level directory. README is changed to reflect this.
Diffstat (limited to 'samples/SampleBase/scene/SceneController.cpp')
| -rw-r--r-- | samples/SampleBase/scene/SceneController.cpp | 1363 |
1 files changed, 1363 insertions, 0 deletions
diff --git a/samples/SampleBase/scene/SceneController.cpp b/samples/SampleBase/scene/SceneController.cpp new file mode 100644 index 0000000..eeaca25 --- /dev/null +++ b/samples/SampleBase/scene/SceneController.cpp @@ -0,0 +1,1363 @@ +/* +* 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 "SceneController.h" +#include "RenderUtils.h" +#include "Utils.h" + +#include "BlastAssetBoxes.h" +#include "BlastAssetModelSimple.h" +#include "BlastAssetModelSkinned.h" +#include "NvBlastExtPxAsset.h" +#include "NvBlastExtPxFamily.h" +#include "NvBlastExtPxManager.h" + +#include "SampleAssetListParser.h" +#include "BlastReplay.h" +#include "Renderer.h" + +#include "BlastController.h" +#include "CommonUIController.h" +#include "PhysXController.h" + +#include "PxRigidDynamic.h" +#include <PsFastXml.h> +#include "PxInputDataFromPxFileBuf.h" + +#include <algorithm> +#include <imgui.h> +#include <sstream> +#include <tuple> + + + +//////// Simple hash function //////// +static NvBlastID generateIDFromString(const char* str) +{ + uint32_t h[4] = { 5381, 5381, 5381, 5381 }; + int i = 0; + for (const char* ptr = str; *ptr; i = ((i + 1) & 3), ++ptr) + { + h[i] = ((h[i] << 5) + h[i]) ^ static_cast<uint32_t>(*ptr); + } + return *reinterpret_cast<NvBlastID*>(h); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Scenes Setup +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const DirectX::XMFLOAT4 PICK_POINTER_ACTIVE_COLOR(1.0f, 0.f, 0.f, 0.6f); +const float RIGIDBODY_DENSITY = 2000.0f; + + +class SingleSceneAsset; + +class SceneAsset +{ +public: + SceneAsset() : spawnCount(0) {} + virtual ~SceneAsset() {} + + void initialize(Scene* scene) + { + m_scene = scene; + } + + virtual const char* getID() const = 0; + virtual const char* getName() const = 0; + + virtual void load() = 0; + virtual void unload() = 0; + virtual bool isLoaded() const = 0; + virtual void spawn(PxVec3 shift) = 0; + + virtual ImVec4 getUIColor() const + { + return ImGui::GetStyle().Colors[ImGuiCol_Text]; + } + + uint32_t spawnCount; +protected: + Scene* m_scene; +}; + + +class SceneActor +{ +public: + virtual ~SceneActor() {} + virtual const char* getName() const = 0; + virtual const char* getSubname(int subindex) const { return nullptr; } + virtual ImVec4 getUIColor() const = 0; + virtual void drawUI(int subindex) {} + virtual void drawStatsUI(int subindex) {} + virtual uint32_t getSubactorCount() const { return 0; } + virtual PxVec3 getSpawnShift() const { return PxVec3(PxZero); } + virtual void reload() {} + virtual void removeSubactor(int subindex) {} +}; + + +class Scene +{ +public: + struct ActorIndex + { + int index; + int subindex; + + ActorIndex() { reset(); } + ActorIndex(int i, int s) : index(i), subindex(s) {} + + bool operator==(const ActorIndex& other) const + { + return index == other.index && subindex == other.subindex; + } + + void reset() + { + index = -1; + subindex = -1; + } + }; + + Scene(Renderer& renderer, PhysXController& physXController, BlastController& blastController, CommonUIController& commonUIController) : + m_renderer(renderer), m_physXController(physXController), m_blastController(blastController), m_commonUIController(commonUIController) + { + } + + ~Scene() + { + removeAllSceneActors(); + + for (uint32_t i = 0; i < m_assets.size(); i++) + { + SAFE_DELETE(m_assets[i]); + } + m_assets.clear(); + m_assetsByID.clear(); + m_tkAssetMap.clear(); + } + + void addAsset(SceneAsset* asset) + { + m_assets.push_back(asset); + asset->initialize(this); + m_assetsByID[asset->getID()] = asset; + } + + void drawUI() + { + /////////////////////////////////////////////////////////////////////////////////////////// + // Assets Selection + /////////////////////////////////////////////////////////////////////////////////////////// + { + static int mode = 0; + ImGui::RadioButton("Replace", &mode, 0); ImGui::SameLine(); + ImGui::RadioButton("Append", &mode, 1); + + ImGui::ListBoxHeader("Assets", (int)m_assets.size()); + for (uint32_t i = 0; i < m_assets.size(); ++i) + { + ImVec4 color = m_assets[i]->getUIColor(); + color.w = color.w * (m_assets[i]->isLoaded() ? 1.0f : 0.5f); + ImGui::PushStyleColor(ImGuiCol_Text, color); + if (ImGui::Selectable(m_assets[i]->getName(), m_lastSpawnedAsset == i)) + { + m_lastSpawnedAsset = i; + if (mode == 0) + { + removeAllSceneActors(); + } + m_commonUIController.addDelayedCall([=]() { spawnAsset(m_lastSpawnedAsset); }, "Loading Asset"); + } + ImGui::PopStyleColor(); + } + ImGui::ListBoxFooter(); + } + + ImGui::Spacing(); + ImGui::Separator(); + + /////////////////////////////////////////////////////////////////////////////////////////// + // Actors Selection + /////////////////////////////////////////////////////////////////////////////////////////// + { + // actor's list + { + int itemCount = 0; + for (size_t i = 0; i < m_sceneActors.size(); ++i) + { + itemCount += 1 + m_sceneActors[i]->getSubactorCount(); + } + + ImGui::ListBoxHeader("Scene Actors", itemCount); + for (int i = 0; i < (int)m_sceneActors.size(); ++i) + { + ImVec4 color = m_sceneActors[i]->getUIColor(); + ImGui::PushStyleColor(ImGuiCol_Text, color); + + const bool isSelected = (m_selectedActor.index == i); + + ImGui::PushID(i); + if (ImGui::Selectable(m_sceneActors[i]->getName(), isSelected && m_selectedActor.subindex == -1)) + { + setSelectedActor(i); + } + + for (int s = 0; s < (int)m_sceneActors[i]->getSubactorCount(); ++s) + { + ImGui::PushID(s); + if (ImGui::Selectable(m_sceneActors[i]->getSubname(s), isSelected && m_selectedActor.subindex == s)) + { + setSelectedActor(i, s); + } + ImGui::PopID(); + } + + ImGui::PopID(); + ImGui::PopStyleColor(); + } + ImGui::ListBoxFooter(); + } + + SceneActor* selectedActor = getSelectedActor(); + if (selectedActor) + { + if (ImGui::Button("Remove")) + { + removeSceneActor(m_selectedActor); + } + + ImGui::SameLine(); + + if (ImGui::Button("Reload")) + { + selectedActor->reload(); + } + + ImGui::SameLine(); + } + + if (ImGui::Button("Remove All")) + { + removeAllSceneActors(); + } + ImGui::SameLine(); + if (ImGui::Button("Reload All (R)")) + { + reloadAllActors(); + } + } + + ImGui::Spacing(); + ImGui::Spacing(); + + /////////////////////////////////////////////////////////////////////////////////////////// + // Selected Actor + /////////////////////////////////////////////////////////////////////////////////////////// + { + SceneActor* selectedActor = getSelectedActor(); + if (selectedActor) + { + ImGui::Text("Selected Actor: "); + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text, ImColor(40, 200, 80, 255)); + ImGui::Text(m_selectedActor.subindex >= 0 ? selectedActor->getSubname(m_selectedActor.subindex) : selectedActor->getName()); + ImGui::PopStyleColor(); + + ImGui::Spacing(); + + selectedActor->drawUI(m_selectedActor.subindex); + } + else + { + ImGui::Text("No Selected Actor"); + } + } + } + + void drawStatsUI() + { + SceneActor* selectedActor = getSelectedActor(); + if (selectedActor) + { + selectedActor->drawStatsUI(m_selectedActor.subindex); + } + } + + void spawnAsset(int32_t num) + { + m_lastSpawnedAsset = physx::PxClamp<int32_t>(num, -1, (uint32_t)m_assets.size() - 1); + + if (m_lastSpawnedAsset < 0) + { + return; + } + + PxVec3 shift(PxZero); + for (SceneActor* a : m_sceneActors) + { + shift += a->getSpawnShift(); + } + + SceneAsset* asset = m_assets[m_lastSpawnedAsset]; + asset->spawn(shift); + } + + void addSceneActor(SceneActor* actor) + { + m_sceneActors.push_back(actor); + if (!getSelectedActor()) + { + setSelectedActor((uint32_t)m_sceneActors.size() - 1); + } + } + + void removeSceneActor(ActorIndex actorIndex) + { + SceneActor* actor = getActorByIndex(actorIndex.index); + if (actorIndex.subindex < 0) + { + delete actor; + m_sceneActors.erase(std::remove(m_sceneActors.begin(), m_sceneActors.end(), actor)); + } + else + { + actor->removeSubactor(actorIndex.subindex); + + if (actor->getSubactorCount() == 0) + { + removeSceneActor(ActorIndex(actorIndex.index, -1)); + return; + } + } + + SceneActor* selectedActor = getActorByIndex(m_selectedActor.index); + if (selectedActor == nullptr) + { + if (!m_sceneActors.empty()) + { + setSelectedActor((uint32_t)m_sceneActors.size() - 1); + } + } + else + { + int subactorCount = selectedActor->getSubactorCount(); + if (m_selectedActor.subindex >= subactorCount || (m_selectedActor.subindex < 0 && subactorCount > 0)) + { + setSelectedActor(m_selectedActor.index, subactorCount - 1); + } + } + } + + void removeAllSceneActors() + { + for (SceneActor* a : m_sceneActors) + { + delete a; + } + m_sceneActors.clear(); + setSelectedActor(-1); + } + + void setSelectedActor(int index, int subindex = -1) + { + m_selectedActor.index = physx::PxClamp<int32_t>(index, -1, (uint32_t)m_sceneActors.size() - 1); + m_selectedActor.subindex = subindex; + } + + SceneActor* getSelectedActor() const + { + return getActorByIndex(m_selectedActor.index); + } + + SceneActor* getActorByIndex(int index) const + { + return (index >= 0 && index < (int)m_sceneActors.size()) ? m_sceneActors[index] : nullptr; + } + + int releaseAll() + { + removeAllSceneActors(); + + for (size_t i = 0; i < m_assets.size(); ++i) + { + m_assets[i]->unload(); + } + + const int currentAsset = m_lastSpawnedAsset; + m_lastSpawnedAsset = -1; + return currentAsset; + } + + void reloadAllActors() + { + for (SceneActor* a : m_sceneActors) + { + a->reload(); + } + } + + void registerTkAsset(const TkAsset& tkAsset, SingleSceneAsset* asset) + { + m_tkAssetMap[&tkAsset] = asset; + } + + void unregisterTkAsset(const TkAsset& tkAsset) + { + m_tkAssetMap.erase(&tkAsset); + } + + SingleSceneAsset* findSingleSceneAsset(const TkAsset& tkAsset) + { + auto entry = m_tkAssetMap.find(&tkAsset); + return entry != m_tkAssetMap.end() ? entry->second : nullptr; + } + + SceneAsset* findSceneAsset(const std::string& id) + { + auto entry = m_assetsByID.find(id); + return entry != m_assetsByID.end() ? entry->second : nullptr; + } + + + //////// used controllers //////// + + Renderer& getRenderer() const + { + return m_renderer; + } + + PhysXController& getPhysXController() const + { + return m_physXController; + } + + BlastController& getBlastController() const + { + return m_blastController; + } + + CommonUIController& getCommonUIController() const + { + return m_commonUIController; + } + +private: + + Renderer& m_renderer; + PhysXController& m_physXController; + BlastController& m_blastController; + CommonUIController& m_commonUIController; + + std::vector<SceneAsset*> m_assets; + std::vector<SceneActor*> m_sceneActors; + std::map<const TkAsset*, SingleSceneAsset*> m_tkAssetMap; + std::map<std::string, SceneAsset*> m_assetsByID; + + int m_lastSpawnedAsset; + + ActorIndex m_selectedActor; +}; + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Assets +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +class SingleSceneActor; + +class SingleSceneAsset : public SceneAsset +{ +public: + SingleSceneAsset() : m_asset(nullptr) {} + virtual ~SingleSceneAsset() { unload(); } + + virtual void spawn(PxVec3 shift) override; + + virtual void load() override + { + if (!m_asset) + { + m_asset = createAsset(); + m_scene->registerTkAsset(m_asset->getPxAsset()->getTkAsset(), this); + } + } + + virtual void unload() override + { + if (m_asset) + { + m_scene->unregisterTkAsset(m_asset->getPxAsset()->getTkAsset()); + delete m_asset; + m_asset = nullptr; + } + } + + virtual bool isLoaded() const override + { + return m_asset != nullptr; + } + + BlastAsset* getAsset() const + { + return m_asset; + } + + virtual PxTransform getInitialTransform() = 0; + +protected: + virtual BlastAsset* createAsset() = 0; + +private: + BlastAsset* m_asset; +}; + + +class ModelSceneAsset : public SingleSceneAsset +{ +public: + ModelSceneAsset() {} + + virtual const char* getID() const override{ return desc.id.c_str(); } + virtual const char* getName() const override { return desc.name.c_str(); } + + AssetList::ModelAsset desc; + + virtual PxTransform getInitialTransform() { return desc.transform; } +}; + + +class SimpleModelSceneAsset : public ModelSceneAsset +{ +public: + virtual BlastAsset* createAsset() + { + return new BlastAssetModelSimple(m_scene->getBlastController().getTkFramework(), m_scene->getPhysXController().getPhysics(), + m_scene->getPhysXController().getCooking(), m_scene->getRenderer(), desc.file.c_str()); + } + + virtual ImVec4 getUIColor() const override + { + return ImColor(255, 255, 200, 255); + } +}; + + +class SkinnedModelSceneAsset : public ModelSceneAsset +{ +public: + virtual BlastAsset* createAsset() + { + return new BlastAssetModelSkinned(m_scene->getBlastController().getTkFramework(), m_scene->getPhysXController().getPhysics(), + m_scene->getPhysXController().getCooking(), m_scene->getRenderer(), desc.file.c_str()); + } + + virtual ImVec4 getUIColor() const override + { + return ImColor(255, 200, 255, 255); + } +}; + + +class BoxesSceneAsset : public SingleSceneAsset +{ +public: + BoxesSceneAsset(const AssetList::BoxAsset& d) : desc(d) + { + for (uint32_t lv = 0; lv < desc.levels.size(); ++lv) + { + const AssetList::BoxAsset::Level& level = desc.levels[lv]; + NvBlastChunkDesc::Flags fl = (level.isSupport) ? NvBlastChunkDesc::Flags::SupportFlag : NvBlastChunkDesc::Flags::NoFlags; + assetDesc.generatorSettings.depths.push_back({ GeneratorAsset::Vec3(level.x, level.y, level.z), fl }); + } + assetDesc.generatorSettings.extents = GeneratorAsset::Vec3(desc.extents.x, desc.extents.y, desc.extents.z); + assetDesc.staticHeight = desc.staticHeight; + assetDesc.jointAllBonds = desc.jointAllBonds; + } + + virtual ImVec4 getUIColor() const override + { + return ImColor(255, 200, 200, 255); + } + + virtual const char* getID() const override { return desc.id.c_str(); } + virtual const char* getName() const override { return desc.name.c_str(); } + + + AssetList::BoxAsset desc; + BlastAssetBoxes::Desc assetDesc; + + virtual BlastAsset* createAsset() + { + return new BlastAssetBoxes(m_scene->getBlastController().getTkFramework(), m_scene->getPhysXController().getPhysics(), + m_scene->getPhysXController().getCooking(), m_scene->getRenderer(), assetDesc); + } + + virtual PxTransform getInitialTransform() { return PxTransform(PxVec3(0, assetDesc.generatorSettings.extents.y / 2, 0)); } +}; + + +class CompositeSceneAsset : public SceneAsset +{ +public: + CompositeSceneAsset(const AssetList::CompositeAsset& desc) + : m_desc(desc) + { + } + + virtual ~CompositeSceneAsset() { unload(); } + + virtual ImVec4 getUIColor() const override + { + return ImColor(200, 255, 255, 255); + } + + virtual const char* getID() const override { return m_desc.id.c_str(); } + virtual const char* getName() const override { return m_desc.name.c_str(); } + + virtual void spawn(PxVec3 shift) override; + + virtual void load() override + { + if (!isLoaded()) + { + // load dependent assets + for (const auto& assetRef : m_desc.assetRefs) + { + SceneAsset* asset = m_scene->findSceneAsset(assetRef.id); + if (asset) + { + asset->load(); + m_sceneAssets.push_back(static_cast<SingleSceneAsset*>(asset)); + } + else + { + m_scene->getCommonUIController().addPopupMessage("Error", "Wrong asset dependency on composite"); + m_sceneAssets.clear(); + return; + } + } + + // check joints + for (const auto& joint : m_desc.joints) + { + bool ok = (joint.assetIndices[0] >= 0 || joint.assetIndices[1] >= 0); + for (char k = 0; k < 2 && ok; ++k) + { + if (joint.assetIndices[k] < 0) + continue; + ok &= (joint.assetIndices[k] < (int32_t)m_sceneAssets.size()); + if (!ok) + break; + ok &= joint.chunkIndices[k] < m_sceneAssets[joint.assetIndices[k]]->getAsset()->getPxAsset()->getTkAsset().getChunkCount(); + } + if (!ok) + { + m_scene->getCommonUIController().addPopupMessage("Error", "Wrong joint on composite"); + m_sceneAssets.clear(); + return; + } + } + } + } + + virtual void unload() override + { + m_sceneAssets.clear(); + } + + virtual bool isLoaded() const override + { + return !m_sceneAssets.empty(); + } + + virtual PxTransform getInitialTransform() + { + return m_desc.transform; + } + + const AssetList::CompositeAsset& getDesc() const + { + return m_desc; + } + + const std::vector<SingleSceneAsset*>& getSceneAssets() const + { + return m_sceneAssets; + } + +private: + AssetList::CompositeAsset m_desc; + std::vector<SingleSceneAsset*> m_sceneAssets; +}; + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Scene Actors +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +class SingleSceneActor : public SceneActor +{ +public: + SingleSceneActor(Scene& scene, SingleSceneAsset* asset, PxVec3 shift) + : m_scene(scene) + , m_asset(asset) + , m_shift(shift) + { + m_index = m_asset->spawnCount++; + spawn(); + } + + SingleSceneActor::~SingleSceneActor() + { + remove(); + } + + virtual const char* getName() const override + { + return m_name.c_str(); + } + + virtual const char* getSubname(int) const override + { + return nullptr; + } + + virtual ImVec4 getUIColor() const override + { + return m_asset->getUIColor(); + } + + virtual void drawUI(int) override + { + m_actor->drawUI(); + } + + virtual void drawStatsUI(int) override + { + m_actor->drawStatsUI(); + } + + virtual PxVec3 getSpawnShift() const override + { + return PxVec3(-20, 0, 0); + } + + virtual void reload() override + { + auto settings = m_actor->getSettings(); + remove(); + spawn(); + m_actor->setSettings(settings); + } + +private: + void remove() + { + m_scene.getBlastController().removeFamily(m_actor); + m_actor = nullptr; + } + + void spawn() + { + std::ostringstream str; + str << m_asset->getName(); + if (m_index) + str << " (" << m_index << ")"; + m_name = str.str(); + + PxTransform pose = m_asset->getInitialTransform(); + pose.p += m_shift; + + BlastAsset::ActorDesc actorDesc = { + actorDesc.id = generateIDFromString(m_name.c_str()), + pose, + m_scene.getBlastController().getTkGroup() + }; + + m_actor = m_scene.getBlastController().spawnFamily(m_asset->getAsset(), actorDesc); + } + + Scene& m_scene; + BlastFamilyPtr m_actor; + SingleSceneAsset* m_asset; + PxVec3 m_shift; + uint32_t m_index; + std::string m_name; +}; + +class CompositeSceneActor : public SceneActor +{ +public: + CompositeSceneActor(Scene& scene, CompositeSceneAsset* asset, PxVec3 shift) + : m_scene(scene) + , m_asset(asset) + , m_shift(shift) + { + m_index = m_asset->spawnCount++; + spawn(); + } + + CompositeSceneActor::~CompositeSceneActor() + { + remove(); + } + + virtual uint32_t getSubactorCount() const + { + return (uint32_t)m_actors.size(); + } + + virtual const char* getName() const override + { + return m_name.c_str(); + } + + virtual const char* getSubname(int subindex) const override + { + return m_actors[subindex].name.c_str(); + } + + virtual ImVec4 getUIColor() const override + { + return m_asset->getUIColor(); + } + + virtual void drawUI(int subindex) override + { + if (subindex >= 0) + { + m_actors[subindex].actor->drawUI(); + } + else + { + ImGui::Text("Select subactor to edit settings."); + } + } + + virtual void drawStatsUI(int subindex) override + { + if (subindex >= 0) + { + m_actors[subindex].actor->drawStatsUI(); + } + } + + virtual PxVec3 getSpawnShift() const override + { + return PxVec3(-20, 0, 0); + } + + virtual void reload() override + { + std::map<uint32_t, BlastFamily::Settings> settings; + for (uint32_t i = 0; i < m_actors.size(); ++i) + { + settings[m_actors[i].initialIndex] = m_actors[i].actor->getSettings(); + } + remove(); + spawn(); + for (uint32_t i = 0; i < m_actors.size(); ++i) + { + if (settings.find(i) != settings.end()) + { + m_actors[i].actor->setSettings(settings[i]); + } + } + } + + virtual void removeSubactor(int subindex) + { + if (subindex >= 0 && subindex < (int)m_actors.size()) + { + m_scene.getBlastController().removeFamily(m_actors[subindex].actor); + m_actors[subindex] = m_actors.back(); + m_actors.resize(m_actors.size() - 1); + } + } + +private: + void remove() + { + for (uint32_t i = 0; i < m_actors.size(); ++i) + { + m_scene.getBlastController().removeFamily(m_actors[i].actor); + } + m_actors.clear(); + } + + void spawn() + { + std::ostringstream str; + str << m_asset->getName(); + if (m_index) + str << " (" << m_index << ")"; + m_name = str.str(); + + const AssetList::CompositeAsset& assetDesc = m_asset->getDesc(); + const std::vector<SingleSceneAsset*>& sceneAssets = m_asset->getSceneAssets(); + + const uint32_t actorCount = (uint32_t)sceneAssets.size(); + m_actors.resize(actorCount); + + for (uint32_t i = 0; i < actorCount; ++i) + { + std::ostringstream str; + str << " -> " << i << "." << sceneAssets[i]->getName(); + m_actors[i].name = str.str(); + } + + ExtPxManager& pxManager = m_scene.getBlastController().getExtPxManager(); + for (uint32_t i = 0; i < actorCount; ++i) + { + PxTransform pose = m_asset->getInitialTransform(); + pose.p += m_shift; + pose = assetDesc.assetRefs[i].transform.transform(pose); + + BlastAsset::ActorDesc actorDesc = { + generateIDFromString(m_actors[i].name.c_str()), + pose, + m_scene.getBlastController().getTkGroup() + }; + m_actors[i].actor = m_scene.getBlastController().spawnFamily(sceneAssets[i]->getAsset(), actorDesc); + m_actors[i].initialIndex = i; + } + + for (const auto& joint : assetDesc.joints) + { + TkJointDesc jointDesc; + for (char k = 0; k < 2; ++k) + { + jointDesc.attachPositions[k] = joint.attachPositions[k]; + jointDesc.chunkIndices[k] = joint.chunkIndices[k]; + jointDesc.families[k] = (joint.assetIndices[k] < 0) ? nullptr : &m_actors[joint.assetIndices[k]].actor->getFamily()->getTkFamily(); + } + TkJoint* joint = pxManager.getFramework().createJoint(jointDesc); + if (joint) + { + pxManager.createJoint(*joint); + } + else + { + m_scene.getCommonUIController().addPopupMessage("Error", "Some joints can't be created"); + } + } + } + + struct Subactor + { + BlastFamilyPtr actor; + uint32_t initialIndex; + std::string name; + }; + + Scene& m_scene; + std::vector<Subactor> m_actors; + CompositeSceneAsset* m_asset; + PxVec3 m_shift; + uint32_t m_index; + std::string m_name; +}; + +class PhysXSceneActor : public SceneActor +{ +public: + PhysXSceneActor(PhysXController& physXController, PhysXController::Actor* actor, const char* name) + : m_physXController(physXController) + , m_actor(actor) + , m_name(name) + { + } + + PhysXSceneActor::~PhysXSceneActor() + { + m_physXController.removePhysXPrimitive(m_actor); + } + + virtual const char* getName() const override + { + return m_name; + } + + virtual ImVec4 getUIColor() const override + { + return ImColor(255, 100, 100, 255); + } + + +private: + PhysXController& m_physXController; + PhysXController::Actor* m_actor; + const char* m_name; + +}; + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Assets Implementation +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void SingleSceneAsset::spawn(PxVec3 shift) +{ + load(); + SingleSceneActor* actor = new SingleSceneActor(*m_scene, this, shift); + m_scene->addSceneActor(actor); +} + +void CompositeSceneAsset::spawn(PxVec3 shift) +{ + load(); + if (isLoaded()) + { + CompositeSceneActor* actor = new CompositeSceneActor(*m_scene, this, shift); + m_scene->addSceneActor(actor); + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// PackmanConfigParser +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +class PackmanConfigParser : public physx::shdfnd::FastXml::Callback +{ +public: + std::vector<std::pair<std::string, std::string>> dependencies; + +protected: + + // encountered a comment in the XML + virtual bool processComment(const char* /*comment*/) + { + return true; + } + + virtual bool processClose(const char* elementName, unsigned int /*depth*/, bool& /*isError*/) + { + return true; + } + + // return true to continue processing the XML document, false to skip. + virtual bool processElement(const char* elementName, // name of the element + const char* elementData, // element data, null if none + const physx::shdfnd::FastXml::AttributePairs& attr, + int /*lineno*/) // line number in the source XML file + { + if (::strcmp(elementName, "dependency") == 0) + { + dependencies.resize(dependencies.size() + 1); + for (int i = 0; i < attr.getNbAttr(); ++i) + { + if (::strcmp(attr.getKey(i), "name") == 0) + { + dependencies.back().first = std::string(attr.getValue(i)); + } + else if (::strcmp(attr.getKey(i), "version") == 0) + { + dependencies.back().second = std::string(attr.getValue(i)); + } + } + } + return true; + } +}; + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Controller +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +SceneController::SceneController() : m_cubeScale(1.0f) +{ + m_scene = NULL; +} + +SceneController::~SceneController() +{ +} + +void SceneController::onSampleStart() +{ + // setup camera + CFirstPersonCamera* camera = &getRenderer().getCamera(); + DirectX::XMVECTORF32 lookAtPt = { 0, 10, 0, 0 }; + DirectX::XMVECTORF32 eyePt = { 0, 20, 60, 0 }; + camera->SetViewParams(eyePt, lookAtPt); + camera->SetRotateButtons(false, false, true, false); + camera->SetEnablePositionMovement(true); + + // setup scene + m_scene = new Scene(getRenderer(), getPhysXController(), getBlastController(), getCommonUIController()); + + const SampleConfig& config = getManager()->getConfig(); + + // add packman repo to search dirs + bool packmanResourcesAdded = false; + if (const char* packmanPath = std::getenv("PM_PACKAGES_ROOT")) + { + const char* RESOURCES_CONFIG_FILE = "resources.xml"; + + std::string path; + if (getRenderer().getResourceManager().findFile(RESOURCES_CONFIG_FILE, path)) + { + physx::PsFileBuffer fileBuffer(path.c_str(), physx::general_PxIOStream2::PxFileBuf::OPEN_READ_ONLY); + if (fileBuffer.isOpen()) + { + PxInputDataFromPxFileBuf inputData(fileBuffer); + PackmanConfigParser parser; + physx::shdfnd::FastXml* xml = physx::shdfnd::createFastXml(&parser); + xml->processXml(inputData, false); + xml->release(); + for (auto& dep : parser.dependencies) + { + std::stringstream ss; + ss << packmanPath << "\\" << dep.first << "\\" << dep.second; + if (getRenderer().getResourceManager().addSearchDir(ss.str().c_str())) + { + packmanResourcesAdded = true; + } + } + } + } + } + if (!packmanResourcesAdded) + { + getManager()->getCommonUIController().addPopupMessage("Error", "BlastSampleResources package wasn't found. Consider running download_sample_resources.bat in root folder.", 5.0f); + } + + // parse asset file + AssetList assetList; + if (!config.assetsFile.empty()) + { + std::string path; + if (getRenderer().getResourceManager().findFile(config.assetsFile, path)) + { + parseAssetList(assetList, path); + } + } + + // add both asset file and asset list from config + addAssets(config.additionalAssetList, packmanResourcesAdded); + addAssets(assetList, packmanResourcesAdded); + + // prepare scene + spawnAsset(0); +} + +void SceneController::addAssets(const AssetList& assetList, bool loadModels) +{ + if (loadModels) + { + for (const auto& model : assetList.models) + { + ModelSceneAsset* asset; + if (!model.isSkinned) + { + asset = new SimpleModelSceneAsset(); + } + else + { + asset = new SkinnedModelSceneAsset(); + } + asset->desc = model; + m_scene->addAsset(asset); + } + + for (const auto& composite : assetList.composites) + { + m_scene->addAsset(new CompositeSceneAsset(composite)); + } + } + + for (const auto& box : assetList.boxes) + { + BoxesSceneAsset* asset = new BoxesSceneAsset(box); + m_scene->addAsset(asset); + } +} + +void SceneController::onInitialize() +{ + +} + +void SceneController::onSampleStop() +{ + if (NULL != m_scene) + { + delete m_scene; + m_scene = nullptr; + } +} + +void SceneController::onTerminate() +{ +} + +void SceneController::Animate(double dt) +{ +} + +LRESULT SceneController::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_KEYDOWN) + { + int iKeyPressed = static_cast<int>(wParam); + switch (iKeyPressed) + { + case 'R': + m_scene->reloadAllActors(); + return 0; + case 'F': + throwCube(); + return 0; + default: + break; + } + } + + return 1; +} + +void SceneController::drawUI() +{ + /////////////////////////////////////////////////////////////////////////////////////////// + // Scene UI + /////////////////////////////////////////////////////////////////////////////////////////// + + m_scene->drawUI(); + + + ImGui::Spacing(); + ImGui::Spacing(); + ImGui::Separator(); + ImGui::Spacing(); + ImGui::Spacing(); + + /////////////////////////////////////////////////////////////////////////////////////////// + // Replay + /////////////////////////////////////////////////////////////////////////////////////////// + { + ImGui::Text("Replay Control:"); + + BlastReplay* replay = getBlastController().getReplay(); + if (replay->isRecording()) + { + auto getAnimStr = []() + { + const uint32_t count = 5; + const uint64_t periodMS = 150; + static char str[count + 1] = ""; + for (uint32_t i = 0; i < count; i++) + { + uint64_t ts = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); + str[i] = (i == (ts % (periodMS * count)) / periodMS) ? '*' : ' '; + } + return str; + }; + ImGui::Text("State: Recording [%s] | Events: %d", getAnimStr(), replay->getEventCount()); + + if (ImGui::Button("Stop Recording")) + { + replay->stopRecording(); + } + } + else if (replay->isPlaying()) + { + ImGui::Text("State: Playing | Events: %d / %d", replay->getCurrentEventIndex(), replay->getEventCount()); + + if (ImGui::Button("Stop Playing")) + { + replay->stopPlayback(); + } + } + else + { + ImGui::Text("State: Idle | Events: %d", replay->getEventCount()); + + static bool syncFamilies = true; + static bool syncPhysics = true; + + ImGui::Checkbox("Sync Initial Actors", &syncFamilies); + if (ImGui::Checkbox("Sync Initial Transforms", &syncPhysics)) + { + syncFamilies = syncPhysics; + } + + if (ImGui::Button("Start Recording")) + { + replay->startRecording(getBlastController().getExtPxManager(), syncFamilies, syncPhysics); + } + + if (replay->hasRecord()) + { + static bool reload = false; + if (ImGui::Button("Start Playback")) + { + if (reload) + m_scene->reloadAllActors(); + replay->startPlayback(getBlastController().getExtPxManager(), getBlastController().getTkGroup()); + } + ImGui::SameLine(); + ImGui::Checkbox("Reload Scene On Playback", &reload); + } + } + } + + ImGui::Spacing(); + ImGui::Spacing(); + ImGui::Separator(); + + /////////////////////////////////////////////////////////////////////////////////////////// + // Cube + /////////////////////////////////////////////////////////////////////////////////////////// + { + ImGui::Text("Thrown Cube Params (F)"); + ImGui::DragFloat("Cube Size", &m_cubeScale, 1.0f, 0.0f, 100.0f); + } + +} + +void SceneController::drawStatsUI() +{ + m_scene->drawStatsUI(); +} + +void SceneController::throwCube() +{ + const float CUBE_VELOCITY = 100; + const float CUBE_DENSITY = 20000.0f; + + CFirstPersonCamera* camera = &getRenderer().getCamera(); + PxVec3 eyePos = XMVECTORToPxVec4(camera->GetEyePt()).getXYZ(); + PxVec3 lookAtPos = XMVECTORToPxVec4(camera->GetLookAtPt()).getXYZ(); + PhysXController::Actor* cube = getPhysXController().spawnPhysXPrimitiveBox(PxTransform(eyePos), PxVec3(m_cubeScale, m_cubeScale, m_cubeScale), CUBE_DENSITY); + PxRigidDynamic* rigidDynamic = cube->getActor()->is<PxRigidDynamic>(); + cube->setColor(DirectX::XMFLOAT4(1, 0, 0, 1)); + + PxVec3 dir = (lookAtPos - eyePos).getNormalized(); + rigidDynamic->setLinearVelocity(dir * CUBE_VELOCITY); + + m_scene->addSceneActor(new PhysXSceneActor(getPhysXController(), cube, "Cube")); +} + +void SceneController::spawnAsset(int32_t num) +{ + m_scene->spawnAsset(num); +} + +int SceneController::releaseAll() +{ + return m_scene->releaseAll(); +} |