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/scene/SceneController.cpp | 2845 +++++++++++++------------- 1 file changed, 1416 insertions(+), 1429 deletions(-) mode change 100644 => 100755 samples/SampleBase/scene/SceneController.cpp (limited to 'samples/SampleBase/scene/SceneController.cpp') diff --git a/samples/SampleBase/scene/SceneController.cpp b/samples/SampleBase/scene/SceneController.cpp old mode 100644 new mode 100755 index 47c8a6b..0b9b332 --- a/samples/SampleBase/scene/SceneController.cpp +++ b/samples/SampleBase/scene/SceneController.cpp @@ -1,1429 +1,1416 @@ -// 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 "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 -#include "PxInputDataFromPxFileBuf.h" - -#include -#include -#include -#include - - - -//////// 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(*ptr); - } - return *reinterpret_cast(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: - SceneActor() : removeOnReload(false) {} - - 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) {} - - bool removeOnReload; -}; - - -class Scene -{ -public: - struct ActorIndex - { - int index; - int subindex; - - ActorIndex() { reset(); } - ActorIndex(int i, int s = -1) : 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(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(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() - { - SceneActor* selectedActor = getSelectedActor(); - ActorIndex selectIndex(0); - - for (uint32_t i = 0; i < m_sceneActors.size(); i++) - { - if (m_sceneActors[i]->removeOnReload) - { - removeSceneActor(ActorIndex(i)); - i--; - } - } - - for (uint32_t i = 0; i < m_sceneActors.size(); i++) - { - if (m_sceneActors[i] == selectedActor) - { - selectIndex.index = i; - } - m_sceneActors[i]->reload(); - } - - setSelectedActor(selectIndex.index, selectIndex.subindex); - } - - 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 m_assets; - std::vector m_sceneActors; - std::map m_tkAssetMap; - std::map 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->getBlastController().getExtSerialization(), 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->getBlastController().getExtSerialization(), 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; - assetDesc.generatorSettings.bondFlags = (CubeAssetGenerator::BondFlags)desc.bondFlags; - } - - 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(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& getSceneAssets() const - { - return m_sceneAssets; - } - -private: - AssetList::CompositeAsset m_desc; - std::vector 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 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& 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 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> 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_cubeThrowDownTime(-1.f) -{ - 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, true); // only used for command line assets - 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(wParam); - switch (iKeyPressed) - { - case 'R': - m_scene->reloadAllActors(); - return 0; - case 'F': - if (m_cubeThrowDownTime == -1.f) - { - m_cubeThrowDownTime = ImGui::GetTime(); - } - return 0; - default: - break; - } - } - else if (uMsg == WM_KEYUP) - { - int iKeyPressed = static_cast(wParam); - switch (iKeyPressed) - { - case 'F': - throwCube(); - m_cubeThrowDownTime = -1.f; - 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::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); - ImGui::Text("Cube Speed (hold F): %1.f", getCubeSpeed()); - } - -} - -void SceneController::drawStatsUI() -{ - m_scene->drawStatsUI(); -} - -float SceneController::getCubeSpeed() -{ - const float CUBE_VELOCITY_SPEED_MIN = 70; - const float CUBE_VELOCITY_CHARGE_PER_SECOND = 300; - return m_cubeThrowDownTime > 0 ? CUBE_VELOCITY_SPEED_MIN + (ImGui::GetTime() - m_cubeThrowDownTime) * CUBE_VELOCITY_CHARGE_PER_SECOND : 0.f; -} - -void SceneController::throwCube() -{ - 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(); - cube->setColor(DirectX::XMFLOAT4(1, 0, 0, 1)); - - PxVec3 dir = (lookAtPos - eyePos).getNormalized(); - rigidDynamic->setLinearVelocity(dir * getCubeSpeed()); - - PhysXSceneActor* actor = new PhysXSceneActor(getPhysXController(), cube, "Cube"); - actor->removeOnReload = true; - m_scene->addSceneActor(actor); -} - -void SceneController::spawnAsset(int32_t num) -{ - m_scene->spawnAsset(num); -} - -int SceneController::releaseAll() -{ - return m_scene->releaseAll(); -} +// 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 "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 +#include "PxInputDataFromPxFileBuf.h" + +#include +#include +#include +#include + + + +//////// 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(*ptr); + } + return *reinterpret_cast(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: + SceneActor() : removeOnReload(false) {} + + 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) {} + + bool removeOnReload; +}; + + +class Scene +{ +public: + struct ActorIndex + { + int index; + int subindex; + + ActorIndex() { reset(); } + ActorIndex(int i, int s = -1) : 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(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(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() + { + SceneActor* selectedActor = getSelectedActor(); + ActorIndex selectIndex(0); + + for (uint32_t i = 0; i < m_sceneActors.size(); i++) + { + if (m_sceneActors[i]->removeOnReload) + { + removeSceneActor(ActorIndex(i)); + i--; + } + } + + for (uint32_t i = 0; i < m_sceneActors.size(); i++) + { + if (m_sceneActors[i] == selectedActor) + { + selectIndex.index = i; + } + m_sceneActors[i]->reload(); + } + + setSelectedActor(selectIndex.index, selectIndex.subindex); + } + + 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 m_assets; + std::vector m_sceneActors; + std::map m_tkAssetMap; + std::map 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->getBlastController().getExtSerialization(), 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->getBlastController().getExtSerialization(), 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; + assetDesc.generatorSettings.bondFlags = (CubeAssetGenerator::BondFlags)desc.bondFlags; + } + + 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(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& getSceneAssets() const + { + return m_sceneAssets; + } + +private: + AssetList::CompositeAsset m_desc; + std::vector 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 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& 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 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> 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_cubeThrowDownTime(-1.f) +{ + 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)) + { + if (getRenderer().getResourceManager().addSearchDir("..\\..\\samples\\resources\\BlastSampleResources\\") || + getRenderer().getResourceManager().addSearchDir("..\\..\\..\\samples\\resources\\BlastSampleResources\\")) + { + 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, true); // only used for command line assets + 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(wParam); + switch (iKeyPressed) + { + case 'R': + m_scene->reloadAllActors(); + return 0; + case 'F': + if (m_cubeThrowDownTime == -1.f) + { + m_cubeThrowDownTime = ImGui::GetTime(); + } + return 0; + default: + break; + } + } + else if (uMsg == WM_KEYUP) + { + int iKeyPressed = static_cast(wParam); + switch (iKeyPressed) + { + case 'F': + throwCube(); + m_cubeThrowDownTime = -1.f; + 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::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); + ImGui::Text("Cube Speed (hold F): %1.f", getCubeSpeed()); + } + +} + +void SceneController::drawStatsUI() +{ + m_scene->drawStatsUI(); +} + +float SceneController::getCubeSpeed() +{ + const float CUBE_VELOCITY_SPEED_MIN = 70; + const float CUBE_VELOCITY_CHARGE_PER_SECOND = 300; + return m_cubeThrowDownTime > 0 ? CUBE_VELOCITY_SPEED_MIN + (ImGui::GetTime() - m_cubeThrowDownTime) * CUBE_VELOCITY_CHARGE_PER_SECOND : 0.f; +} + +void SceneController::throwCube() +{ + 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(); + cube->setColor(DirectX::XMFLOAT4(1, 0, 0, 1)); + + PxVec3 dir = (lookAtPos - eyePos).getNormalized(); + rigidDynamic->setLinearVelocity(dir * getCubeSpeed()); + + PhysXSceneActor* actor = new PhysXSceneActor(getPhysXController(), cube, "Cube"); + actor->removeOnReload = true; + m_scene->addSceneActor(actor); +} + +void SceneController::spawnAsset(int32_t num) +{ + m_scene->spawnAsset(num); +} + +int SceneController::releaseAll() +{ + return m_scene->releaseAll(); +} -- cgit v1.2.3