From 0e518c52a953da2023a4fef789ff175ea89dd565 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sun, 2 Oct 2022 04:22:32 +0800 Subject: [PATCH 01/28] Fixed bug when SceneGraph is destroyed --- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index da2dcffd..60f0794d 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -312,6 +312,11 @@ namespace SHADE if (parentNode == nullptr) { SHLOG_WARNING("Removing Entity {}'s parent", entityID) + + if (parent) + parent->RemoveChild(this); + + return; } // Handle self assignment From 51eba31ad4d5a5ea6a9ca3a6637c0e5de41a57a4 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Wed, 19 Oct 2022 18:38:11 +0800 Subject: [PATCH 02/28] Added animation asset class Added animation reading from assimp scene Separated assimp loading from mesh loader in preparation for exe use --- SHADE_Engine/SHAnimationAsset.h | 30 ++++ .../src/Assets/Asset Types/SHAnimationAsset.h | 30 ++++ .../src/Assets/Libraries/SHAssimpLibrary.cpp | 143 ++++++++++++++++ .../src/Assets/Libraries/SHAssimpLibrary.h | 36 ++++ .../src/Assets/Libraries/SHMeshLoader.cpp | 162 ------------------ .../src/Assets/Libraries/SHMeshLoader.h | 16 +- SHADE_Engine/src/Assets/SHAssetManager.cpp | 77 +++++---- SHADE_Engine/src/Assets/SHAssetManager.h | 9 +- 8 files changed, 287 insertions(+), 216 deletions(-) create mode 100644 SHADE_Engine/SHAnimationAsset.h create mode 100644 SHADE_Engine/src/Assets/Asset Types/SHAnimationAsset.h create mode 100644 SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.cpp create mode 100644 SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.h diff --git a/SHADE_Engine/SHAnimationAsset.h b/SHADE_Engine/SHAnimationAsset.h new file mode 100644 index 00000000..d8d0ffb1 --- /dev/null +++ b/SHADE_Engine/SHAnimationAsset.h @@ -0,0 +1,30 @@ +/*************************************************************************//** + * \file SHAnimationAsset.h + * \author Loh Xiao Qi + * \date October 2022 + * \brief + * + * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. + *****************************************************************************/ +#pragma once + +#include +#include +#include "SH_API.power h" + +namespace SHADE +{ + struct SH_API SHAnimationAsset + { + std::string name; + + std::vector nodeChannels; + std::vector meshChannels; + std::vector morphMeshChannels; + + double duration; + double ticksPerSecond; + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAnimationAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHAnimationAsset.h new file mode 100644 index 00000000..76f4c0ac --- /dev/null +++ b/SHADE_Engine/src/Assets/Asset Types/SHAnimationAsset.h @@ -0,0 +1,30 @@ +/*************************************************************************//** + * \file SHAnimationAsset.h + * \author Loh Xiao Qi + * \date October 2022 + * \brief + * + * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. + *****************************************************************************/ +#pragma once + +#include +#include +#include "SH_API.h" + +namespace SHADE +{ + struct SH_API SHAnimationAsset + { + std::string name; + + std::vector nodeChannels; + std::vector meshChannels; + std::vector morphMeshChannels; + + double duration; + double ticksPerSecond; + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.cpp b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.cpp new file mode 100644 index 00000000..feea9f35 --- /dev/null +++ b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.cpp @@ -0,0 +1,143 @@ +/*************************************************************************//** + * \file SHAssimpLibrary.cpp + * \author Loh Xiao Qi + * \date October 2022 + * \brief + * + * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. + *****************************************************************************/ +#include "SHpch.h" +#include "SHAssimpLibrary.h" +#include + +namespace SHADE +{ + Assimp::Importer SHAssimpLibrary::aiImporter; + + void SHAssimpLibrary::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept + { + for (size_t i {0}; i < node.mNumMeshes; ++i) + { + aiMesh* mesh = scene.mMeshes[node.mMeshes[i]]; + meshes.push_back(ProcessMesh(*mesh)); + } + + for (size_t i{ 0 }; i < node.mNumChildren; ++i) + { + ProcessNode(*node.mChildren[i], scene, meshes); + } + } + + void SHAssimpLibrary::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept + { + if (scene.HasAnimations()) + { + std::vector anims(scene.mNumAnimations); + for (auto i{0}; i < scene.mNumAnimations; ++i) + { + auto const& anim {*scene.mAnimations[i]}; + + anims[i].name = anim.mName.C_Str(); + + anims[i].duration = anim.mDuration; + anims[i].ticksPerSecond = anim.mTicksPerSecond; + + std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data()); + std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data()); + std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data()); + } + } + } + + SHMeshAsset SHAssimpLibrary::ProcessMesh(aiMesh const& mesh) noexcept + { + SHMeshAsset result + { + .compiled { false}, + .changed { false } + }; + + for (size_t i{0}; i < mesh.mNumVertices; ++i) + { + // Vertex position + SHVec3 vertex; + vertex.x = mesh.mVertices[i].x; + vertex.y = mesh.mVertices[i].y; + vertex.z = mesh.mVertices[i].z; + result.vertexPosition.push_back(vertex); + + // Tex coords + SHVec2 texCoord{0.f, 0.f}; + if (mesh.mTextureCoords[0]) + { + texCoord.x = mesh.mTextureCoords[0][i].x; + texCoord.y = mesh.mTextureCoords[0][i].y; + } + result.texCoords.push_back(texCoord); + + // Normals + SHVec3 normal{0.f, 0.f, 0.f}; + if (mesh.mNormals) + { + normal.x = mesh.mNormals[i].x; + normal.y = mesh.mNormals[i].y; + normal.z = mesh.mNormals[i].z; + } + result.vertexNormal.push_back(normal); + + // Tangent + SHVec3 tangent{0.f, 0.f, 0.f}; + if (mesh.mTangents) + { + tangent.x = mesh.mTangents[i].x; + tangent.y = mesh.mTangents[i].y; + tangent.z = mesh.mTangents[i].z; + } + result.vertexTangent.push_back(tangent); + } + + for (size_t i {0}; i < mesh.mNumFaces; ++i) + { + aiFace face = mesh.mFaces[i]; + for (size_t j{0}; j < face.mNumIndices; ++j) + { + result.indices.push_back(face.mIndices[j]); + } + } + + result.header.vertexCount = static_cast(result.vertexPosition.size()); + result.header.indexCount = static_cast(result.indices.size()); + result.header.meshName = mesh.mName.C_Str(); + + return result; + } + + void SHAssimpLibrary::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept + { + const aiScene* scene = aiImporter.ReadFile(path.string().c_str(), + aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons + | aiProcess_GenUVCoords // Convert any type of mapping to uv mapping + | aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...) + | aiProcess_FindInstances // search for instanced meshes and remove them by references to one master + | aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible + | aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing + | aiProcess_RemoveRedundantMaterials // remove redundant materials + | aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors + | aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs + ); + + if (!scene || !scene->HasMeshes()) + { + SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string()); + return; + } + + ExtractAnimations(*scene, anims); + + ProcessNode(*scene->mRootNode, *scene, meshes); + + aiImporter.FreeScene(); + } +} diff --git a/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.h b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.h new file mode 100644 index 00000000..a4a0447a --- /dev/null +++ b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.h @@ -0,0 +1,36 @@ +/*************************************************************************//** + * \file SHAssimpLibrary.h + * \author Loh Xiao Qi + * \date October 2022 + * \brief + * + * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. + *****************************************************************************/ + +#pragma once +#include +#include +#include +#include "../SHAssetMacros.h" +#include "../Asset Types/SHMeshAsset.h" +#include "../Asset Types/SHAnimationAsset.h" + +namespace SHADE +{ + class SHAssimpLibrary + { + private: + using MeshVectorRef = std::vector&; + using AnimVectorRef = std::vector&; + + static Assimp::Importer aiImporter; + static void ProcessNode(aiNode const& node, aiScene const& scene,MeshVectorRef meshes) noexcept; + static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept; + static SHMeshAsset ProcessMesh(aiMesh const& mesh) noexcept; + + public: + static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept; + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp index 4bfa2d9b..73fed1fb 100644 --- a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp +++ b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp @@ -12,128 +12,10 @@ *****************************************************************************/ #include "SHpch.h" #include "SHMeshLoader.h" -#include #include namespace SHADE { - Assimp::Importer SHMeshLoader::aiImporter; - - void SHMeshLoader::ProcessNode(aiNode const& node, aiScene const& scene, std::vector& meshes) noexcept - { - for (size_t i {0}; i < node.mNumMeshes; ++i) - { - aiMesh* mesh = scene.mMeshes[node.mMeshes[i]]; - meshes.push_back(ProcessMesh(*mesh, scene)); - } - - for (size_t i{ 0 }; i < node.mNumChildren; ++i) - { - ProcessNode(*node.mChildren[i], scene, meshes); - } - } - - SHMeshAsset SHMeshLoader::ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept - { - (void)scene; - - SHMeshAsset result - { - .compiled { false}, - .changed { false } - }; - - for (size_t i{0}; i < mesh.mNumVertices; ++i) - { - // Vertex position - SHVec3 vertex; - vertex.x = mesh.mVertices[i].x; - vertex.y = mesh.mVertices[i].y; - vertex.z = mesh.mVertices[i].z; - result.vertexPosition.push_back(vertex); - - // Tex coords - SHVec2 texCoord{0.f, 0.f}; - if (mesh.mTextureCoords[0]) - { - texCoord.x = mesh.mTextureCoords[0][i].x; - texCoord.y = mesh.mTextureCoords[0][i].y; - } - result.texCoords.push_back(texCoord); - - // Normals - SHVec3 normal{0.f, 0.f, 0.f}; - if (mesh.mNormals) - { - normal.x = mesh.mNormals[i].x; - normal.y = mesh.mNormals[i].y; - normal.z = mesh.mNormals[i].z; - } - result.vertexNormal.push_back(normal); - - // Tangent - SHVec3 tangent{0.f, 0.f, 0.f}; - if (mesh.mTangents) - { - tangent.x = mesh.mTangents[i].x; - tangent.y = mesh.mTangents[i].y; - tangent.z = mesh.mTangents[i].z; - } - result.vertexTangent.push_back(tangent); - } - - for (size_t i {0}; i < mesh.mNumFaces; ++i) - { - aiFace face = mesh.mFaces[i]; - for (size_t j{0}; j < face.mNumIndices; ++j) - { - result.indices.push_back(face.mIndices[j]); - } - } - - result.header.vertexCount = static_cast(result.vertexPosition.size()); - result.header.indexCount = static_cast(result.indices.size()); - result.header.meshName = mesh.mName.C_Str(); - - return result; - } - - void SHMeshLoader::LoadExternal(std::vector& meshes, AssetPath path) noexcept - { - const aiScene* scene = aiImporter.ReadFile(path.string().c_str(), - aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons - | aiProcess_GenUVCoords // Convert any type of mapping to uv mapping - | aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...) - | aiProcess_FindInstances // search for instanced meshes and remove them by references to one master - | aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible - | aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing - | aiProcess_RemoveRedundantMaterials // remove redundant materials - | aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors - | aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs - ); - - if (!scene || !scene->HasMeshes()) - { - SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string()); - return; - } - - //TODO MATERIALS FROM MESHES - //if (scene->HasMaterials()) - //{ - // for (int i{0}; i < scene->mNumMaterials; ++i) - // { - // if (scene->mMaterials[i]->mNumProperties > 0) - // { - // for (int j{0}; j < scene->mMaterials[i]->mProperties[j].) - // } - //std::cout << scene->mMaterials[i]->; - // } - //} - - ProcessNode(*scene->mRootNode, *scene, meshes); - } - void SHMeshLoader::LoadSHMesh(SHMeshAsset& mesh, AssetPath path) noexcept { std::ifstream file{ path.string(), std::ios::in | std::ios::binary }; @@ -168,38 +50,6 @@ namespace SHADE file.read(reinterpret_cast(vertNorm.data()), vertexVec3Byte); file.read(reinterpret_cast(texCoord.data()), vertexVec2Byte); file.read(reinterpret_cast(indices.data()), sizeof(uint32_t) * indexCount); - - //for (auto i{ 0 }; i < vertCount; ++i) - //{ - // file >> vertPos[i].x; - // file >> vertPos[i].y; - // file >> vertPos[i].z; - //} - // - //for (auto i{ 0 }; i < vertCount; ++i) - //{ - // file >> vertTan[i].x; - // file >> vertTan[i].y; - // file >> vertTan[i].z; - //} - - //for (auto i{ 0 }; i < vertCount; ++i) - //{ - // file >> vertNorm[i].x; - // file >> vertNorm[i].y; - // file >> vertNorm[i].z; - //} - - //for (auto i{ 0 }; i < vertCount; ++i) - //{ - // file >> texCoord[i].x; - // file >> texCoord[i].y; - //} - - //for (auto i{ 0 }; i < indexCount; ++i) - //{ - // file >> indices[i]; - //} mesh.compiled = true; mesh.changed = false; @@ -216,16 +66,4 @@ namespace SHADE file.close(); } - - void SHMeshLoader::LoadMesh(std::vector& meshes, AssetPath path) noexcept - { - if (path.extension().string() == GLTF_EXTENSION) - { - LoadExternal(meshes, path); - return; - } - - meshes.emplace_back(); - LoadSHMesh(meshes.back(), path); - } } diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h index a27d63ea..f01b942a 100644 --- a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h +++ b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h @@ -10,27 +10,13 @@ * of DigiPen Institute of Technology is prohibited. *****************************************************************************/ #pragma once -#include -#include #include "../SHAssetMacros.h" #include "../Asset Types/SHMeshAsset.h" -#include namespace SHADE { - class SHMeshLoader + struct SHMeshLoader { - private: - static Assimp::Importer aiImporter; - - static void ProcessNode(aiNode const& node, aiScene const& scene, std::vector& meshes) noexcept; - - static SHMeshAsset ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept; - - static void LoadExternal(std::vector& meshes, AssetPath path) noexcept; - - public: - static void LoadMesh(std::vector& meshes, AssetPath path) noexcept; static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index aa9772dd..faca24b2 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -14,6 +14,7 @@ #include "SHAssetMetaHandler.h" #include "Filesystem/SHFileSystem.h" +#include "Libraries/SHAssimpLibrary.h" #include "Libraries/SHMeshLoader.h" #include "Libraries/SHTextureLoader.h" @@ -200,38 +201,38 @@ namespace SHADE } - void SHAssetManager::LoadDataTemp(std::string p) noexcept - { - AssetPath path{ p }; + //void SHAssetManager::LoadDataTemp(std::string p) noexcept + //{ + // AssetPath path{ p }; - if (path.extension().string() == FBX_EXTENSION - || path.extension().string() == GLTF_EXTENSION - || path.extension().string() == MESH_EXTENSION) - { - LoadGLTF( - { - .name {path.filename().string()}, - .id {0}, - .type {AssetType::MESH}, - .path {path}, - .location {0} - } - ); - } - else if (path.extension().string() == DDS_EXTENSION - || path.extension().string() == TEXTURE_EXTENSION) - { - LoadDDS( - { - .name {path.filename().string()}, - .id {0}, - .type {AssetType::DDS}, - .path {path}, - .location {0} - } - ); - } - } + // if (path.extension().string() == FBX_EXTENSION + // || path.extension().string() == GLTF_EXTENSION + // || path.extension().string() == MESH_EXTENSION) + // { + // LoadGLTF( + // { + // .name {path.filename().string()}, + // .id {0}, + // .type {AssetType::MESH}, + // .path {path}, + // .location {0} + // } + // ); + // } + // else if (path.extension().string() == DDS_EXTENSION + // || path.extension().string() == TEXTURE_EXTENSION) + // { + // LoadDDS( + // { + // .name {path.filename().string()}, + // .id {0}, + // .type {AssetType::DDS}, + // .path {path}, + // .location {0} + // } + // ); + // } + //} std::vector SHAssetManager::GetAllMeshes() noexcept { @@ -319,11 +320,12 @@ namespace SHADE return false; } - void SHAssetManager::LoadGLTF(SHAsset asset) noexcept + void SHAssetManager::LoadGLTF(AssetPath path) noexcept { std::vector meshes; - - SHMeshLoader::LoadMesh(meshes, asset.path); + std::vector anims; + + SHAssimpLibrary::LoadFromFile(path, meshes, anims); for (auto const& mesh : meshes) { @@ -333,7 +335,7 @@ namespace SHADE AssetPath path; if (!mesh.compiled) { - path = SHMeshCompiler::CompileMeshBinary(mesh, asset.path); + path = SHMeshCompiler::CompileMeshBinary(mesh, path); } assetCollection.emplace_back( @@ -344,6 +346,11 @@ namespace SHADE 0 ); } + + for (auto const& anim : anims) + { + //TODO Register anim resource and compile into binary + } } void SHAssetManager::LoadDDS(SHAsset asset) noexcept diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index 50549e01..b2c4216b 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -71,12 +71,16 @@ namespace SHADE // -------------------------------------------------------------------------/ //TODO: TEMPORARY FOR TESTING GLTF & DDS - static void LoadDataTemp(std::string path) noexcept; + //static void LoadDataTemp(std::string path) noexcept; static std::vector GetAllMeshes() noexcept; static std::vector GetAllTextures() noexcept; static SHMeshAsset const* GetMesh(AssetID id) noexcept; static SHTextureAsset const* GetTexture(AssetID id) noexcept; + + // Specialised load calls + static void LoadGLTF(AssetPath path) noexcept; + static void LoadDDS(SHAsset asset) noexcept; private: /**************************************************************************** * \brief Load resource data into memory @@ -118,9 +122,6 @@ namespace SHADE static bool IsRecognised(char const*) noexcept; - // Specialised load calls - static void LoadGLTF(SHAsset asset) noexcept; - static void LoadDDS(SHAsset asset) noexcept; static FMOD::System* audioSystem; static std::unordered_map* audioSoundList; From 5a0b34ceea63dd80bdedda43e6c74611424b5517 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 20 Oct 2022 17:47:32 +0800 Subject: [PATCH 03/28] Added Event for Scene Graph Change Parent --- SHADE_Engine/src/Events/SHEventDefines.h | 11 ++++++----- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 21 +++++++++++++++++++-- SHADE_Engine/src/Scene/SHSceneGraph.h | 15 +++++++++------ 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/SHADE_Engine/src/Events/SHEventDefines.h b/SHADE_Engine/src/Events/SHEventDefines.h index 317b67c1..fc9f41e1 100644 --- a/SHADE_Engine/src/Events/SHEventDefines.h +++ b/SHADE_Engine/src/Events/SHEventDefines.h @@ -5,8 +5,9 @@ typedef uint32_t SHEventIdentifier; typedef uint32_t SHEventHandle; //Add your event identifiers here: -constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0}; -constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 }; -constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 }; -constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT{ 3 }; -constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT{ 4 }; +constexpr SHEventIdentifier SH_EXAMPLE_EVENT { 0 }; +constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT { 1 }; +constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 }; +constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 }; +constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 }; +constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 }; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 572e5927..291b5b2b 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -15,6 +15,7 @@ // Project Headers #include "ECS_Base/Managers/SHEntityManager.h" +#include "Events/SHEventManager.hpp" #include "Tools/SHLogger.h" #include "Tools/SHException.h" @@ -364,10 +365,18 @@ namespace SHADE } //////////////////////////////////////// + const SHSceneGraphChangeParentEvent EVENT_DATA + { + .oldParentID = NODE_ITER->second->GetParent()->GetEntityID(), + .newParentID = parent->GetEntityID() + }; + if (parent == nullptr) parent = root; NODE_ITER->second->SetParent(parent); + + SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); } void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept @@ -401,8 +410,16 @@ namespace SHADE } //////////////////////////////////////// + const SHSceneGraphChangeParentEvent EVENT_DATA + { + .oldParentID = NODE_ITER->second->GetParent()->GetEntityID(), + .newParentID = parent + }; + SHSceneNode* currentNode = NODE_ITER->second; currentNode->SetParent(PARENT_ITER->second); + + SHEventManager::BroadcastEvent(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT); } /*-----------------------------------------------------------------------------------*/ @@ -563,7 +580,7 @@ namespace SHADE ReleaseNode(node); } - void SHSceneGraph::Traverse (const UnaryPredicate& predicate) const + void SHSceneGraph::Traverse (const UnaryFunction& predicate) const { TraverseAndInvokePredicate(root, predicate); } @@ -602,7 +619,7 @@ namespace SHADE delete node; } - void SHSceneGraph::TraverseAndInvokePredicate(const SHSceneNode* node, const UnaryPredicate& predicate) + void SHSceneGraph::TraverseAndInvokePredicate(const SHSceneNode* node, const UnaryFunction& predicate) { for (auto* child : node->children) { diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 3f3ebf92..62715f72 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -97,9 +97,8 @@ namespace SHADE /* Type Definitions */ /*---------------------------------------------------------------------------------*/ - using EntityNodeMap = std::unordered_map; - - using UnaryPredicate = std::function; + using EntityNodeMap = std::unordered_map; + using UnaryFunction = std::function; /*---------------------------------------------------------------------------------*/ @@ -143,8 +142,7 @@ namespace SHADE bool RemoveNode (SHSceneNode* nodeToRemove) noexcept; void Reset () noexcept; - void Traverse (const UnaryPredicate& predicate) const; - + void Traverse (const UnaryFunction& predicate) const; private: /*---------------------------------------------------------------------------------*/ @@ -160,8 +158,13 @@ namespace SHADE SHSceneNode* AllocateNode (EntityID entityID); void ReleaseNode (SHSceneNode* node) noexcept; - static void TraverseAndInvokePredicate (const SHSceneNode* node, const UnaryPredicate& predicate); + static void TraverseAndInvokePredicate (const SHSceneNode* node, const UnaryFunction& predicate); }; + struct SHSceneGraphChangeParentEvent + { + EntityID oldParentID; + EntityID newParentID; + }; } // namespace SHADE \ No newline at end of file From 314d497b66c93cf21c5f245e4846961297eb6a60 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 20 Oct 2022 18:35:57 +0800 Subject: [PATCH 04/28] Reparenting objects maintain world transforms --- Assets/Editor/Layouts/UserLayout.ini | 20 ++++----- SHADE_Application/src/Scenes/SBTestScene.cpp | 6 +-- .../src/Math/Transform/SHTransformSystem.cpp | 43 ++++++++++++++++++- .../src/Math/Transform/SHTransformSystem.h | 6 ++- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 10 +++-- SHADE_Engine/src/Scene/SHSceneGraph.h | 1 + 6 files changed, 65 insertions(+), 21 deletions(-) diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini index 530ee770..7b0a70f8 100644 --- a/Assets/Editor/Layouts/UserLayout.ini +++ b/Assets/Editor/Layouts/UserLayout.ini @@ -10,7 +10,7 @@ Collapsed=0 [Window][Hierarchy Panel] Pos=0,142 -Size=571,918 +Size=349,918 Collapsed=0 DockId=0x00000004,0 @@ -20,29 +20,29 @@ Size=400,400 Collapsed=0 [Window][Inspector] -Pos=1649,48 -Size=271,1012 +Pos=1483,48 +Size=437,1012 Collapsed=0 DockId=0x00000006,0 [Window][Profiler] Pos=0,48 -Size=571,92 +Size=349,92 Collapsed=0 DockId=0x00000003,0 [Window][Viewport] -Pos=573,48 -Size=1074,1012 +Pos=351,48 +Size=1130,1012 Collapsed=0 DockId=0x00000002,0 [Docking][Data] DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X - DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=571,1036 Split=Y Selected=0x1E6EB881 + DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1481,1036 Split=X + DockNode ID=0x00000001 Parent=0x00000005 SizeRef=349,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1074,1036 CentralNode=1 Selected=0x13926F0B - DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252 + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1130,1036 CentralNode=1 Selected=0x13926F0B + DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=437,1036 Selected=0xE7039252 diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index f1d656ee..d81550e1 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -77,9 +77,9 @@ namespace Sandbox customMat->SetProperty("data.alpha", 0.1f); // Create Stress Test Objects - static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f; - constexpr int NUM_ROWS = 10; - constexpr int NUM_COLS = 10; + static const SHVec3 TEST_OBJ_SCALE = SHVec3::One; + constexpr int NUM_ROWS = 2; + constexpr int NUM_COLS = 1; static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f }; static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f }; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 6b05e323..448fa60d 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -17,7 +17,6 @@ #include "Scene/SHSceneManager.h" #include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHEntityManager.h" -#include "Tools/SHException.h" namespace SHADE { @@ -47,7 +46,9 @@ namespace SHADE void SHTransformSystem::Init() { - + std::shared_ptr thisReceiver { std::make_shared>(this, &SHTransformSystem::ChangeParent) }; + ReceiverPtr receiver = std::dynamic_pointer_cast(thisReceiver); + SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, receiver); } void SHTransformSystem::Exit() @@ -59,6 +60,44 @@ namespace SHADE /* Private Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent) + { + const auto& eventData = reinterpret_cast*>(changeParentEvent.get()); + + // Get Current Respective Components + auto* tf = SHComponentManager::GetComponent(eventData->data->entityID); + const auto* PARENT = SHComponentManager::GetComponent_s(eventData->data->newParentID); + + // Recompute local transform and store localToWorld Matrix + SHMatrix localToWorld = SHMatrix::Identity; + SHMatrix worldToLocal = SHMatrix::Identity; + + if (PARENT != nullptr) // Not the root + { + localToWorld = PARENT->GetTRS(); + worldToLocal = SHMatrix::Inverse(localToWorld); + } + + // Maintain World Transform and recompute Local Transform + + // Compute Local Position + tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal); + + // Compute Local Rotation + tf->local.rotation = tf->world.rotation; + if (PARENT) + tf->local.rotation -= PARENT->GetLocalRotation(); + + // Compute Local Scale + tf->local.scale = tf->world.scale; + if (PARENT) + tf->local.scale /= PARENT->GetLocalScale(); + + tf->local.trs = localToWorld; + + return eventData->handle; + } + void SHTransformSystem::UpdateEntity(const SHSceneNode* node) { const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s(node->GetEntityID()); diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h index 02c3b6c6..8a50b368 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -84,8 +84,10 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - static void UpdateEntity (const SHSceneNode* node); - static void UpdateTransform(SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); + SHEventHandle ChangeParent (SHEventPtr changeParentEvent); + + static void UpdateEntity (const SHSceneNode* node); + static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); }; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index 291b5b2b..ac6975fb 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -367,8 +367,9 @@ namespace SHADE const SHSceneGraphChangeParentEvent EVENT_DATA { - .oldParentID = NODE_ITER->second->GetParent()->GetEntityID(), - .newParentID = parent->GetEntityID() + .entityID = entityID + , .oldParentID = NODE_ITER->second->GetParent()->GetEntityID() + , .newParentID = parent ? parent->GetEntityID() : root->GetEntityID() }; if (parent == nullptr) @@ -412,8 +413,9 @@ namespace SHADE const SHSceneGraphChangeParentEvent EVENT_DATA { - .oldParentID = NODE_ITER->second->GetParent()->GetEntityID(), - .newParentID = parent + .entityID = entityID + , .oldParentID = NODE_ITER->second->GetParent()->GetEntityID() + , .newParentID = parent }; SHSceneNode* currentNode = NODE_ITER->second; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 62715f72..1dfc1542 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -163,6 +163,7 @@ namespace SHADE struct SHSceneGraphChangeParentEvent { + EntityID entityID; EntityID oldParentID; EntityID newParentID; }; From fda33f7461087c84299a6afcac050a22e1ee81ac Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Thu, 20 Oct 2022 22:55:59 +0800 Subject: [PATCH 05/28] Fixed multi-level transform updates --- SHADE_Application/src/Scenes/SBTestScene.cpp | 2 +- .../src/Math/Transform/SHTransformSystem.cpp | 87 +++++++++++++++---- .../src/Math/Transform/SHTransformSystem.h | 7 +- SHADE_Engine/src/Scene/SHSceneGraph.cpp | 12 +-- SHADE_Engine/src/Scene/SHSceneGraph.h | 6 +- 5 files changed, 84 insertions(+), 30 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index d81550e1..be09768b 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -78,7 +78,7 @@ namespace Sandbox // Create Stress Test Objects static const SHVec3 TEST_OBJ_SCALE = SHVec3::One; - constexpr int NUM_ROWS = 2; + constexpr int NUM_ROWS = 3; constexpr int NUM_COLS = 1; static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f }; static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f }; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 448fa60d..a3ca3e75 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -64,17 +64,18 @@ namespace SHADE { const auto& eventData = reinterpret_cast*>(changeParentEvent.get()); - // Get Current Respective Components - auto* tf = SHComponentManager::GetComponent(eventData->data->entityID); - const auto* PARENT = SHComponentManager::GetComponent_s(eventData->data->newParentID); + auto* node = eventData->data->node; + auto* tf = SHComponentManager::GetComponent_s(node->GetEntityID()); // Recompute local transform and store localToWorld Matrix SHMatrix localToWorld = SHMatrix::Identity; SHMatrix worldToLocal = SHMatrix::Identity; - if (PARENT != nullptr) // Not the root + auto* newParent = eventData->data->newParent; + const auto* PARENT_TF = SHComponentManager::GetComponent_s(newParent->GetEntityID()); + if (PARENT_TF != nullptr) // Not the root { - localToWorld = PARENT->GetTRS(); + localToWorld = PARENT_TF->GetTRS(); worldToLocal = SHMatrix::Inverse(localToWorld); } @@ -83,21 +84,74 @@ namespace SHADE // Compute Local Position tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal); - // Compute Local Rotation - tf->local.rotation = tf->world.rotation; - if (PARENT) - tf->local.rotation -= PARENT->GetLocalRotation(); + + tf->local.rotation = tf->world.rotation; + tf->local.scale = tf->world.scale; - // Compute Local Scale - tf->local.scale = tf->world.scale; - if (PARENT) - tf->local.scale /= PARENT->GetLocalScale(); + if (PARENT_TF != nullptr) + { + // Compute Local Rotation + tf->local.rotation -= PARENT_TF->GetLocalRotation(); + + // Compute Local Scale + tf->local.scale /= PARENT_TF->GetLocalScale(); + } tf->local.trs = localToWorld; + // Propagate maintaining world transform down the branch + UpdateChildrenLocalTransforms(node); return eventData->handle; } + void SHTransformSystem::UpdateChildrenLocalTransforms(SHSceneNode* node) + { + // Structure is similar to update entity, albeit without a queue to do being a forced update + for (const auto* child : node->GetChildren()) + { + if (auto* childTransform = SHComponentManager::GetComponent_s(child->GetEntityID()); childTransform) + { + const bool IS_NODE_ACTIVE = child->IsActive(); + if (IS_NODE_ACTIVE && childTransform->isActive) + { + // Recompute local transform and store localToWorld Matrix + SHMatrix localToWorld = SHMatrix::Identity; + SHMatrix worldToLocal = SHMatrix::Identity; + + const auto* parent = SHComponentManager::GetComponent_s(node->GetEntityID()); + + if (parent != nullptr) // Not the root + { + localToWorld = parent->GetTRS(); + worldToLocal = SHMatrix::Inverse(localToWorld); + } + + // Maintain World Transform and recompute Local Transform + + // Compute Local Position + childTransform->local.position = SHVec3::Transform(childTransform->world.position, worldToLocal); + + + childTransform->local.rotation = childTransform->world.rotation; + childTransform->local.scale = childTransform->world.scale; + + if (parent) + { + // Compute Local Rotation + childTransform->local.rotation -= parent->GetLocalRotation(); + + // Compute Local Scale + childTransform->local.scale /= parent->GetLocalScale(); + } + + childTransform->local.trs = localToWorld; + } + } + + + } + } + void SHTransformSystem::UpdateEntity(const SHSceneNode* node) { const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s(node->GetEntityID()); @@ -113,7 +167,10 @@ namespace SHADE if (IS_NODE_ACTIVE && childTransform->isActive) { if (childTransform->dirty || HAS_PARENT_CHANGED) + { UpdateTransform(*childTransform, NODE_TRANSFORM); + childTransform->dirty = true; + } } } @@ -177,10 +234,6 @@ namespace SHADE tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One); tf.world.ComputeTRS(); - - // Transpose TRS to column major - //tf.local.trs.Transpose(); - //tf.world.trs.Transpose(); } } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h index 8a50b368..95957830 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -84,10 +84,11 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - SHEventHandle ChangeParent (SHEventPtr changeParentEvent); + SHEventHandle ChangeParent (SHEventPtr changeParentEvent); + static void UpdateChildrenLocalTransforms (SHSceneNode* node); - static void UpdateEntity (const SHSceneNode* node); - static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); + static void UpdateEntity (const SHSceneNode* node); + static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); }; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.cpp b/SHADE_Engine/src/Scene/SHSceneGraph.cpp index ac6975fb..950fd6a0 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.cpp +++ b/SHADE_Engine/src/Scene/SHSceneGraph.cpp @@ -367,9 +367,9 @@ namespace SHADE const SHSceneGraphChangeParentEvent EVENT_DATA { - .entityID = entityID - , .oldParentID = NODE_ITER->second->GetParent()->GetEntityID() - , .newParentID = parent ? parent->GetEntityID() : root->GetEntityID() + .node = NODE_ITER->second + , .oldParent = NODE_ITER->second->GetParent() + , .newParent = parent ? parent : root }; if (parent == nullptr) @@ -413,9 +413,9 @@ namespace SHADE const SHSceneGraphChangeParentEvent EVENT_DATA { - .entityID = entityID - , .oldParentID = NODE_ITER->second->GetParent()->GetEntityID() - , .newParentID = parent + .node = NODE_ITER->second + , .oldParent = NODE_ITER->second->GetParent() + , .newParent = PARENT_ITER->second }; SHSceneNode* currentNode = NODE_ITER->second; diff --git a/SHADE_Engine/src/Scene/SHSceneGraph.h b/SHADE_Engine/src/Scene/SHSceneGraph.h index 1dfc1542..a4cf45eb 100644 --- a/SHADE_Engine/src/Scene/SHSceneGraph.h +++ b/SHADE_Engine/src/Scene/SHSceneGraph.h @@ -163,9 +163,9 @@ namespace SHADE struct SHSceneGraphChangeParentEvent { - EntityID entityID; - EntityID oldParentID; - EntityID newParentID; + SHSceneNode* node; + SHSceneNode* oldParent; + SHSceneNode* newParent; }; } // namespace SHADE \ No newline at end of file From a52f0ddeed7f7090a21567daeb85c366437bd2d5 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Fri, 21 Oct 2022 00:08:24 +0800 Subject: [PATCH 06/28] Added a degree getter and setter for rotation --- Assets/Editor/Layouts/UserLayout.ini | 2 +- .../Math/Transform/SHTransformComponent.cpp | 64 ++++++++++++++++++- .../src/Math/Transform/SHTransformComponent.h | 42 ++++++------ 3 files changed, 86 insertions(+), 22 deletions(-) diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini index 7b0a70f8..396b853b 100644 --- a/Assets/Editor/Layouts/UserLayout.ini +++ b/Assets/Editor/Layouts/UserLayout.ini @@ -38,7 +38,7 @@ Collapsed=0 DockId=0x00000002,0 [Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X +DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=-227,-1256 Size=1920,1012 Split=X DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1481,1036 Split=X DockNode ID=0x00000001 Parent=0x00000005 SizeRef=349,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp index 949cfa67..a8b75497 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp @@ -12,6 +12,8 @@ // Primary Header #include "SHTransformComponent.h" +// Project Headers +#include "Math/SHMathHelpers.h" namespace SHADE { @@ -43,6 +45,15 @@ namespace SHADE return local.rotation; } + SHVec3 SHTransformComponent::GetLocalRotationDeg() const noexcept + { + SHVec3 rot = local.rotation; + rot.x = SHMath::RadiansToDegrees(rot.x); + rot.y = SHMath::RadiansToDegrees(rot.y); + rot.z = SHMath::RadiansToDegrees(rot.z); + return rot; + } + const SHVec3& SHTransformComponent::GetLocalScale() const noexcept { return local.scale; @@ -58,6 +69,15 @@ namespace SHADE return world.rotation; } + SHVec3 SHTransformComponent::GetWorldRotationDeg() const noexcept + { + SHVec3 rot = world.rotation; + rot.x = SHMath::RadiansToDegrees(rot.x); + rot.y = SHMath::RadiansToDegrees(rot.y); + rot.z = SHMath::RadiansToDegrees(rot.z); + return rot; + } + const SHVec3& SHTransformComponent::GetWorldScale() const noexcept { return world.scale; @@ -94,6 +114,15 @@ namespace SHADE local.rotation = newLocalRotation; } + void SHTransformComponent::SetLocalRotationDeg(SHVec3 newLocalRotationDeg) noexcept + { + dirty = true; + + local.rotation.x = SHMath::DegreesToRadians(newLocalRotationDeg.x); + local.rotation.y = SHMath::DegreesToRadians(newLocalRotationDeg.y); + local.rotation.z = SHMath::DegreesToRadians(newLocalRotationDeg.z); + } + void SHTransformComponent::SetLocalRotation(float pitch, float yaw, float roll) noexcept { dirty = true; @@ -103,6 +132,13 @@ namespace SHADE local.rotation.z = roll; } + void SHTransformComponent::SetLocalRotationDeg(float pitch, float yaw, float roll) noexcept + { + local.rotation.x = SHMath::DegreesToRadians(pitch); + local.rotation.y = SHMath::DegreesToRadians(yaw); + local.rotation.z = SHMath::DegreesToRadians(roll); + } + void SHTransformComponent::SetLocalScale(const SHVec3& newLocalScale) noexcept { dirty = true; @@ -125,6 +161,17 @@ namespace SHADE updateQueue.push({ UpdateCommandType::WORLD_ROTATION, newWorldRotation }); } + void SHTransformComponent::SetWorldRotationDeg(const SHVec3& newWorldRotation) noexcept + { + dirty = true; + + world.rotation.x = SHMath::DegreesToRadians(newWorldRotation.x); + world.rotation.y = SHMath::DegreesToRadians(newWorldRotation.y); + world.rotation.z = SHMath::DegreesToRadians(newWorldRotation.z); + + updateQueue.push({ UpdateCommandType::WORLD_ROTATION, world.rotation }); + } + void SHTransformComponent::SetWorldRotation(float pitch, float yaw, float roll) noexcept { dirty = true; @@ -136,6 +183,17 @@ namespace SHADE updateQueue.push({ UpdateCommandType::WORLD_ROTATION, SHVec3{ pitch, yaw, roll} }); } + void SHTransformComponent::SetWorldRotationDeg(float pitch, float yaw, float roll) noexcept + { + dirty = true; + + world.rotation.x = SHMath::DegreesToRadians(pitch); + world.rotation.y = SHMath::DegreesToRadians(yaw); + world.rotation.z = SHMath::DegreesToRadians(roll); + + updateQueue.push({ UpdateCommandType::WORLD_ROTATION, world.rotation }); + } + void SHTransformComponent::SetWorldScale(const SHVec3& newWorldScale) noexcept { dirty = true; @@ -152,7 +210,7 @@ RTTR_REGISTRATION using namespace rttr; registration::class_("Transform Component") - .property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition ) - .property("Rotate" , &SHTransformComponent::GetLocalRotation , select_overload(&SHTransformComponent::SetLocalRotation) ) - .property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale ); + .property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition ) + .property("Rotate" , &SHTransformComponent::GetLocalRotationDeg, select_overload(&SHTransformComponent::SetLocalRotationDeg)) + .property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale ); } \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h index ad355694..2a3fa7a0 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h @@ -56,32 +56,38 @@ namespace SHADE /* Getter Functions */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] bool HasChanged () const noexcept; + [[nodiscard]] bool HasChanged () const noexcept; - [[nodiscard]] const SHVec3& GetLocalPosition () const noexcept; - [[nodiscard]] const SHVec3& GetLocalRotation () const noexcept; - [[nodiscard]] const SHVec3& GetLocalScale () const noexcept; - [[nodiscard]] const SHVec3& GetWorldPosition () const noexcept; - [[nodiscard]] const SHVec3& GetWorldRotation () const noexcept; - [[nodiscard]] const SHVec3& GetWorldScale () const noexcept; + [[nodiscard]] const SHVec3& GetLocalPosition () const noexcept; + [[nodiscard]] const SHVec3& GetLocalRotation () const noexcept; + [[nodiscard]] SHVec3 GetLocalRotationDeg () const noexcept; + [[nodiscard]] const SHVec3& GetLocalScale () const noexcept; + [[nodiscard]] const SHVec3& GetWorldPosition () const noexcept; + [[nodiscard]] const SHVec3& GetWorldRotation () const noexcept; + [[nodiscard]] SHVec3 GetWorldRotationDeg () const noexcept; + [[nodiscard]] const SHVec3& GetWorldScale () const noexcept; - [[nodiscard]] const SHMatrix& GetLocalToWorld () const noexcept; - [[nodiscard]] SHMatrix GetWorldToLocal () const noexcept; + [[nodiscard]] const SHMatrix& GetLocalToWorld () const noexcept; + [[nodiscard]] SHMatrix GetWorldToLocal () const noexcept; - [[nodiscard]] const SHMatrix& GetTRS () const noexcept; + [[nodiscard]] const SHMatrix& GetTRS () const noexcept; /*---------------------------------------------------------------------------------*/ /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetLocalPosition (const SHVec3& newLocalPosition) noexcept; - void SetLocalRotation (const SHVec3& newLocalRotation) noexcept; - void SetLocalRotation (float pitch, float yaw, float roll) noexcept; - void SetLocalScale (const SHVec3& newLocalScale) noexcept; - void SetWorldPosition (const SHVec3& newWorldPosition) noexcept; - void SetWorldRotation (const SHVec3& newWorldRotation) noexcept; - void SetWorldRotation (float pitch, float yaw, float roll) noexcept; - void SetWorldScale (const SHVec3& newWorldScale) noexcept; + void SetLocalPosition (const SHVec3& newLocalPosition) noexcept; + void SetLocalRotation (const SHVec3& newLocalRotation) noexcept; + void SetLocalRotationDeg (SHVec3 newLocalRotationDeg) noexcept; + void SetLocalRotation (float pitch, float yaw, float roll) noexcept; + void SetLocalRotationDeg (float pitch, float yaw, float roll) noexcept; + void SetLocalScale (const SHVec3& newLocalScale) noexcept; + void SetWorldPosition (const SHVec3& newWorldPosition) noexcept; + void SetWorldRotation (const SHVec3& newWorldRotation) noexcept; + void SetWorldRotationDeg (const SHVec3& newWorldRotation) noexcept; + void SetWorldRotation (float pitch, float yaw, float roll) noexcept; + void SetWorldRotationDeg (float pitch, float yaw, float roll) noexcept; + void SetWorldScale (const SHVec3& newWorldScale) noexcept; private: /*---------------------------------------------------------------------------------*/ From 9df517f3b30885d78c5ce63a5add0d002680d9b6 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Fri, 21 Oct 2022 20:28:54 +0800 Subject: [PATCH 07/28] SP3-170 SP3-238 Restructured asset and asset loading library types to be derived from common base class. Storage of assets and loaders based on pointers. Created general templated calls to get data from asset manager based on asset type passed in as template argument. More concise internal interface when loading and storing assets with libraries --- Assets/Cube.003.shmesh.shmeta | 2 +- Assets/Cube.012.shmesh.shmeta | 2 +- .../RaccoonPreTexturedVer1_Base9.shtex.shmeta | 2 +- SHADE_Application/src/Scenes/SBTestScene.cpp | 47 +- .../src/Assets/Asset Types/SHAnimationAsset.h | 4 +- .../src/Assets/Asset Types/SHAssetData.h | 19 + .../src/Assets/Asset Types/SHInternalAsset.h | 21 + .../src/Assets/Asset Types/SHMeshAsset.h | 6 +- .../src/Assets/Asset Types/SHTextureAsset.h | 3 +- .../src/Assets/Libraries/SHAssetLoader.h | 21 + .../src/Assets/Libraries/SHAssimpLibrary.cpp | 26 +- .../src/Assets/Libraries/SHAssimpLibrary.h | 6 +- .../src/Assets/Libraries/SHMeshCompiler.cpp | 2 +- .../src/Assets/Libraries/SHMeshLoader.cpp | 13 +- .../src/Assets/Libraries/SHMeshLoader.h | 6 +- .../src/Assets/Libraries/SHTextureLoader.cpp | 9 + .../src/Assets/Libraries/SHTextureLoader.h | 17 +- SHADE_Engine/src/Assets/SHAsset.h | 5 +- SHADE_Engine/src/Assets/SHAssetMacros.h | 51 ++- SHADE_Engine/src/Assets/SHAssetManager.cpp | 422 ++++-------------- SHADE_Engine/src/Assets/SHAssetManager.h | 80 ++-- .../src/Assets/SHAssetMetaHandler.cpp | 14 +- 22 files changed, 300 insertions(+), 478 deletions(-) create mode 100644 SHADE_Engine/src/Assets/Asset Types/SHAssetData.h create mode 100644 SHADE_Engine/src/Assets/Asset Types/SHInternalAsset.h create mode 100644 SHADE_Engine/src/Assets/Libraries/SHAssetLoader.h diff --git a/Assets/Cube.003.shmesh.shmeta b/Assets/Cube.003.shmesh.shmeta index d41be546..207f3999 100644 --- a/Assets/Cube.003.shmesh.shmeta +++ b/Assets/Cube.003.shmesh.shmeta @@ -1,3 +1,3 @@ Name: Cube.003 ID: 110152941 -Type:  +Type: 6 diff --git a/Assets/Cube.012.shmesh.shmeta b/Assets/Cube.012.shmesh.shmeta index d5cd1090..3af04f93 100644 --- a/Assets/Cube.012.shmesh.shmeta +++ b/Assets/Cube.012.shmesh.shmeta @@ -1,3 +1,3 @@ Name: Cube.012 ID: 107348815 -Type:  +Type: 6 diff --git a/Assets/RaccoonPreTexturedVer1_Base9.shtex.shmeta b/Assets/RaccoonPreTexturedVer1_Base9.shtex.shmeta index f8c267d9..3905aa4f 100644 --- a/Assets/RaccoonPreTexturedVer1_Base9.shtex.shmeta +++ b/Assets/RaccoonPreTexturedVer1_Base9.shtex.shmeta @@ -1,3 +1,3 @@ Name: RaccoonPreTexturedVer1_Base9 ID: 91918845 -Type:  +Type: 4 diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index f1d656ee..50a87fd3 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -13,6 +13,9 @@ #include "Physics/Components/SHRigidBodyComponent.h" #include "Physics/Components/SHColliderComponent.h" +#include "Assets/Asset Types/SHMeshAsset.h" +#include "Assets/Asset Types/SHTextureAsset.h" + #include "Assets/SHAssetManager.h" using namespace SHADE; @@ -39,34 +42,26 @@ namespace Sandbox // Create temp meshes const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem); + auto assets = SHAssetManager::GetAllAssets(); + //Test Racoon mesh - auto meshes = SHADE::SHAssetManager::GetAllMeshes(); - std::vector> handles; - for (auto const& mesh : meshes) - { - if (mesh.header.meshName == "Cube.012") - { - handles.push_back(graphicsSystem->AddMesh( - mesh.header.vertexCount, - mesh.vertexPosition.data(), - mesh.texCoords.data(), - mesh.vertexTangent.data(), - mesh.vertexNormal.data(), - mesh.header.indexCount, - mesh.indices.data() - )); - } - } + auto mesh = SHAssetManager::GetData(107348815); + Handle handle; + handle = (graphicsSystem->AddMesh( + mesh->header.vertexCount, + mesh->vertexPosition.data(), + mesh->texCoords.data(), + mesh->vertexTangent.data(), + mesh->vertexNormal.data(), + mesh->header.indexCount, + mesh->indices.data() + )); graphicsSystem->BuildMeshBuffers(); // Load Textures - auto textures = SHADE::SHAssetManager::GetAllTextures(); - std::vector> texHandles; - for (const auto& tex : textures) - { - auto texture = graphicsSystem->Add(tex); - texHandles.push_back(texture); - } + auto texture = SHAssetManager::GetData(91918845); + Handle texHandle; + texHandle = graphicsSystem->Add(*texture); graphicsSystem->BuildTextures(); // Create Materials @@ -116,7 +111,7 @@ namespace Sandbox auto& renderable = *SHComponentManager::GetComponent_s(raccoonSpin); auto& transform = *SHComponentManager::GetComponent_s(raccoonSpin); - renderable.Mesh = handles.front(); + renderable.Mesh = handle; renderable.SetMaterial(customMat); renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f); @@ -157,7 +152,7 @@ namespace Sandbox auto& renderableShowcase = *SHComponentManager::GetComponent_s(raccoonShowcase); auto& transformShowcase = *SHComponentManager::GetComponent_s(raccoonShowcase); - renderableShowcase.Mesh = handles.front(); + renderableShowcase.Mesh = handle; renderableShowcase.SetMaterial(customMat); renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f); diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAnimationAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHAnimationAsset.h index 76f4c0ac..b411a11e 100644 --- a/SHADE_Engine/src/Assets/Asset Types/SHAnimationAsset.h +++ b/SHADE_Engine/src/Assets/Asset Types/SHAnimationAsset.h @@ -12,11 +12,11 @@ #include #include -#include "SH_API.h" +#include "SHAssetData.h" namespace SHADE { - struct SH_API SHAnimationAsset + struct SH_API SHAnimationAsset : SHAssetData { std::string name; diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAssetData.h b/SHADE_Engine/src/Assets/Asset Types/SHAssetData.h new file mode 100644 index 00000000..8db9824c --- /dev/null +++ b/SHADE_Engine/src/Assets/Asset Types/SHAssetData.h @@ -0,0 +1,19 @@ +/*************************************************************************//** + * \file SHAssetDataBase.h + * \author Loh Xiao Qi + * \date October 2022 + * \brief + * + * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. + *****************************************************************************/ +#pragma once + +namespace SHADE +{ + struct SHAssetData + { + virtual ~SHAssetData(){} + }; +} diff --git a/SHADE_Engine/src/Assets/Asset Types/SHInternalAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHInternalAsset.h new file mode 100644 index 00000000..8bef34e9 --- /dev/null +++ b/SHADE_Engine/src/Assets/Asset Types/SHInternalAsset.h @@ -0,0 +1,21 @@ +/*************************************************************************//** + * \file SHInternalAsset.h + * \author Loh Xiao Qi + * \date October 2022 + * \brief + * + * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. + *****************************************************************************/ +#pragma once + +#include "SHAsset.h" + +namespace SHADE +{ + struct SHInternalAsset : SHAsset + { + + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/Asset Types/SHMeshAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHMeshAsset.h index 68c0d150..20b442ba 100644 --- a/SHADE_Engine/src/Assets/Asset Types/SHMeshAsset.h +++ b/SHADE_Engine/src/Assets/Asset Types/SHMeshAsset.h @@ -14,7 +14,7 @@ #include #include "Math/SHMath.h" -#include "SH_API.h" +#include "SHAssetData.h" namespace SHADE { @@ -22,10 +22,10 @@ namespace SHADE { uint32_t vertexCount; uint32_t indexCount; - std::string meshName; + std::string name; }; - struct SH_API SHMeshAsset + struct SH_API SHMeshAsset : SHAssetData { bool compiled; bool changed; diff --git a/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h index d24b6c02..d26a2c30 100644 --- a/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h +++ b/SHADE_Engine/src/Assets/Asset Types/SHTextureAsset.h @@ -2,10 +2,11 @@ #include "tinyddsloader.h" #include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h" +#include "SHAssetData.h" namespace SHADE { - struct SHTextureAsset + struct SHTextureAsset : SHAssetData { bool compiled; diff --git a/SHADE_Engine/src/Assets/Libraries/SHAssetLoader.h b/SHADE_Engine/src/Assets/Libraries/SHAssetLoader.h new file mode 100644 index 00000000..41595519 --- /dev/null +++ b/SHADE_Engine/src/Assets/Libraries/SHAssetLoader.h @@ -0,0 +1,21 @@ +/*************************************************************************//** + * \file SHAssetLoader.h + * \author Loh Xiao Qi + * \date October 2022 + * \brief + * + * Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or + * disclosure of this file or its contents without the prior written consent + * of DigiPen Institute of Technology is prohibited. + *****************************************************************************/ +#pragma once + +#include "Assets/Asset Types/SHAssetData.h" + +namespace SHADE +{ + struct SHAssetLoader + { + virtual SHAssetData* Load(AssetPath path) = 0; + }; +} diff --git a/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.cpp b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.cpp index feea9f35..f4be0b68 100644 --- a/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.cpp +++ b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.cpp @@ -51,13 +51,11 @@ namespace SHADE } } - SHMeshAsset SHAssimpLibrary::ProcessMesh(aiMesh const& mesh) noexcept + SHMeshAsset* SHAssimpLibrary::ProcessMesh(aiMesh const& mesh) noexcept { - SHMeshAsset result - { - .compiled { false}, - .changed { false } - }; + SHMeshAsset* result = new SHMeshAsset(); + result->compiled = false; + result->changed = false; for (size_t i{0}; i < mesh.mNumVertices; ++i) { @@ -66,7 +64,7 @@ namespace SHADE vertex.x = mesh.mVertices[i].x; vertex.y = mesh.mVertices[i].y; vertex.z = mesh.mVertices[i].z; - result.vertexPosition.push_back(vertex); + result->vertexPosition.push_back(vertex); // Tex coords SHVec2 texCoord{0.f, 0.f}; @@ -75,7 +73,7 @@ namespace SHADE texCoord.x = mesh.mTextureCoords[0][i].x; texCoord.y = mesh.mTextureCoords[0][i].y; } - result.texCoords.push_back(texCoord); + result->texCoords.push_back(texCoord); // Normals SHVec3 normal{0.f, 0.f, 0.f}; @@ -85,7 +83,7 @@ namespace SHADE normal.y = mesh.mNormals[i].y; normal.z = mesh.mNormals[i].z; } - result.vertexNormal.push_back(normal); + result->vertexNormal.push_back(normal); // Tangent SHVec3 tangent{0.f, 0.f, 0.f}; @@ -95,7 +93,7 @@ namespace SHADE tangent.y = mesh.mTangents[i].y; tangent.z = mesh.mTangents[i].z; } - result.vertexTangent.push_back(tangent); + result->vertexTangent.push_back(tangent); } for (size_t i {0}; i < mesh.mNumFaces; ++i) @@ -103,13 +101,13 @@ namespace SHADE aiFace face = mesh.mFaces[i]; for (size_t j{0}; j < face.mNumIndices; ++j) { - result.indices.push_back(face.mIndices[j]); + result->indices.push_back(face.mIndices[j]); } } - result.header.vertexCount = static_cast(result.vertexPosition.size()); - result.header.indexCount = static_cast(result.indices.size()); - result.header.meshName = mesh.mName.C_Str(); + result->header.vertexCount = static_cast(result->vertexPosition.size()); + result->header.indexCount = static_cast(result->indices.size()); + result->header.name = mesh.mName.C_Str(); return result; } diff --git a/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.h b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.h index a4a0447a..83755b4c 100644 --- a/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.h +++ b/SHADE_Engine/src/Assets/Libraries/SHAssimpLibrary.h @@ -22,13 +22,13 @@ namespace SHADE class SHAssimpLibrary { private: - using MeshVectorRef = std::vector&; - using AnimVectorRef = std::vector&; + using MeshVectorRef = std::vector&; + using AnimVectorRef = std::vector&; static Assimp::Importer aiImporter; static void ProcessNode(aiNode const& node, aiScene const& scene,MeshVectorRef meshes) noexcept; static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept; - static SHMeshAsset ProcessMesh(aiMesh const& mesh) noexcept; + static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept; public: static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept; diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp b/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp index 8026f0e1..2346714e 100644 --- a/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp +++ b/SHADE_Engine/src/Assets/Libraries/SHMeshCompiler.cpp @@ -20,7 +20,7 @@ std::string SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, A { std::string newPath{ path.string() }; newPath = newPath.substr(0, newPath.find_last_of('/') + 1); - newPath += asset.header.meshName + MESH_EXTENSION; + newPath += asset.header.name + MESH_EXTENSION.data(); std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc }; if (!file.is_open()) diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp index 73fed1fb..90dd58d4 100644 --- a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp +++ b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.cpp @@ -16,7 +16,7 @@ namespace SHADE { - void SHMeshLoader::LoadSHMesh(SHMeshAsset& mesh, AssetPath path) noexcept + void SHMeshLoader::LoadSHMesh(AssetPath path, SHMeshAsset& mesh) noexcept { std::ifstream file{ path.string(), std::ios::in | std::ios::binary }; if (!file.is_open()) @@ -56,7 +56,7 @@ namespace SHADE mesh.header.indexCount = indexCount; mesh.header.vertexCount = vertCount; - mesh.header.meshName = name; + mesh.header.name = name; mesh.vertexPosition = std::move(vertPos); mesh.vertexTangent = std::move(vertTan); @@ -66,4 +66,13 @@ namespace SHADE file.close(); } + + SHAssetData* SHMeshLoader::Load(AssetPath path) + { + auto result = new SHMeshAsset(); + + LoadSHMesh(path, *result); + + return result; + } } diff --git a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h index f01b942a..34c4e5d2 100644 --- a/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h +++ b/SHADE_Engine/src/Assets/Libraries/SHMeshLoader.h @@ -12,11 +12,13 @@ #pragma once #include "../SHAssetMacros.h" #include "../Asset Types/SHMeshAsset.h" +#include "SHAssetLoader.h" namespace SHADE { - struct SHMeshLoader + struct SHMeshLoader : public SHAssetLoader { - static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept; + void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept; + SHAssetData* Load(AssetPath path) override; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp index 5147562a..8b986524 100644 --- a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp +++ b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.cpp @@ -133,6 +133,15 @@ namespace SHADE file.close(); } + SHAssetData* SHTextureLoader::Load(AssetPath path) + { + auto result = new SHTextureAsset(); + + LoadImageAsset(path, *result); + + return result; + } + void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset) { if (path.extension().string() == DDS_EXTENSION) diff --git a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h index eb61ea91..8bdf91b1 100644 --- a/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h +++ b/SHADE_Engine/src/Assets/Libraries/SHTextureLoader.h @@ -15,19 +15,20 @@ #include "../SHAssetMacros.h" #include "../Asset Types/SHTextureAsset.h" #include "tinyddsloader.h" +#include "SHAssetLoader.h" namespace SHADE { - class SHTextureLoader + class SHTextureLoader : public SHAssetLoader { private: - static std::string TinyDDSResultToString(tinyddsloader::Result value); - static vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear); - - - static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept; + std::string TinyDDSResultToString(tinyddsloader::Result value); + vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear); + + void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept; public: - static void LoadImageAsset(AssetPath paths, SHTextureAsset& image); - static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept; + void LoadImageAsset(AssetPath paths, SHTextureAsset& image); + void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept; + SHAssetData* Load(AssetPath path) override; }; } diff --git a/SHADE_Engine/src/Assets/SHAsset.h b/SHADE_Engine/src/Assets/SHAsset.h index 8d7b55d1..86e8a722 100644 --- a/SHADE_Engine/src/Assets/SHAsset.h +++ b/SHADE_Engine/src/Assets/SHAsset.h @@ -12,11 +12,12 @@ #pragma once #include "Filesystem/SHFileSystem.h" -#include "SHAssetMacros.h" +#include "Assets/SHAssetMacros.h" +#include "SH_API.h" namespace SHADE { - struct SHAsset + struct SH_API SHAsset { AssetName name; AssetID id; diff --git a/SHADE_Engine/src/Assets/SHAssetMacros.h b/SHADE_Engine/src/Assets/SHAssetMacros.h index 61c5879d..0fdfa04e 100644 --- a/SHADE_Engine/src/Assets/SHAssetMacros.h +++ b/SHADE_Engine/src/Assets/SHAssetMacros.h @@ -32,12 +32,12 @@ typedef std::filesystem::path AssetPath; typedef unsigned char* AssetData; typedef std::string AssetMetaVersion; typedef std::string AssetExtension; -typedef unsigned char AssetTypeMeta; +typedef size_t AssetTypeMeta; typedef FMOD::Sound* SHSound; // Asset Meta Version -#define ASSET_META_VER "1.0" +constexpr std::string_view ASSET_META_VER { "1.0" }; // Asset type enum enum class AssetType : AssetTypeMeta @@ -53,34 +53,35 @@ enum class AssetType : AssetTypeMeta SCENE, PREFAB, AUDIO_WAV, - DDS + DDS, + MAX_COUNT }; //Directory #ifdef _PUBLISH -#define ASSET_ROOT "Assets" +constexpr std::string_view ASSET_ROOT {"Assets"}; #else -#define ASSET_ROOT "../../Assets" +constexpr std::string_view ASSET_ROOT {"../../Assets"}; #endif // ASSET EXTENSIONS -#define META_EXTENSION ".shmeta" -#define IMAGE_EXTENSION ".png" -#define AUDIO_EXTENSION ".ogg" -#define AUDIO_WAV_EXTENSION ".wav" -#define SHADER_EXTENSION ".glsl" -#define SCRIPT_EXTENSION ".cs" -#define SCENE_EXTENSION ".SHADE" -#define PREFAB_EXTENSION ".SHPrefab" -#define MATERIAL_EXTENSION ".SHMat" -#define TEXTURE_EXTENSION ".shtex" -#define DDS_EXTENSION ".dds" -#define FBX_EXTENSION ".fbx" -#define GLTF_EXTENSION ".gltf" -#define MESH_EXTENSION ".shmesh" +constexpr std::string_view META_EXTENSION {".shmeta"}; +constexpr std::string_view IMAGE_EXTENSION {".png"}; +constexpr std::string_view AUDIO_EXTENSION {".ogg"}; +constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"}; +constexpr std::string_view SHADER_EXTENSION {".glsl"}; +constexpr std::string_view SCRIPT_EXTENSION {".cs"}; +constexpr std::string_view SCENE_EXTENSION {".SHADE"}; +constexpr std::string_view PREFAB_EXTENSION {".SHPrefab"}; +constexpr std::string_view MATERIAL_EXTENSION {".SHMat"}; +constexpr std::string_view TEXTURE_EXTENSION {".shtex"}; +constexpr std::string_view DDS_EXTENSION {".dds"}; +constexpr std::string_view FBX_EXTENSION {".fbx"}; +constexpr std::string_view GLTF_EXTENSION {".gltf"}; +constexpr std::string_view MESH_EXTENSION {".shmesh"}; -std::string const EXTENSIONS[] = { +constexpr std::string_view EXTENSIONS[] = { AUDIO_EXTENSION, SHADER_EXTENSION, MATERIAL_EXTENSION, @@ -96,10 +97,12 @@ std::string const EXTENSIONS[] = { GLTF_EXTENSION }; +constexpr size_t TYPE_COUNT {static_cast(AssetType::MAX_COUNT) }; + // Error flags -#define FILE_NOT_FOUND_ERR "FILE NOT FOUND" -#define META_NOT_FOUND_ERR "META NOT FOUND" -#define ASSET_NOT_FOUND_ERR "ASSET NOT FOUND" -#define EXT_DOES_NOT_EXIST "TYPE DOES NOT HAVE EXTENSION DEFINED" +constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"}; +constexpr std::string_view META_NOT_FOUND_ERR {"META NOT FOUND"}; +constexpr std::string_view ASSET_NOT_FOUND_ERR {"ASSET NOT FOUND"}; +constexpr std::string_view EXT_DOES_NOT_EXIST {"TYPE DOES NOT HAVE EXTENSION DEFINED"}; #endif // !SH_ASSET_MACROS_H diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index faca24b2..2658e83b 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -26,11 +26,10 @@ namespace SHADE FMOD::System* SHAssetManager::audioSystem; std::unordered_map* SHAssetManager::audioSoundList; - std::vector SHAssetManager::assetCollection; - std::unordered_map SHAssetManager::assetRegistry; + std::vector SHAssetManager::loaders(TYPE_COUNT); - std::unordered_map SHAssetManager::meshCollection; - std::unordered_map SHAssetManager::textureCollection; + std::vector SHAssetManager::assetCollection; + std::unordered_map SHAssetManager::assetData; /**************************************************************************** * \brief Static function to generate asset ID. @@ -81,7 +80,37 @@ namespace SHADE // return std::filesystem::path(); //} - return std::filesystem::path(ASSET_ROOT + folder + path.filename().string()); + return std::filesystem::path(std::string(ASSET_ROOT) + folder + path.filename().string()); + } + + AssetPath SHAssetManager::GenerateNewPath(AssetName name, AssetType type) + { + std::string folder; + + switch(type) + { + case AssetType::SCENE: + folder = "scenes/"; + break; + + case AssetType::PREFAB: + folder = "prefabs/"; + break; + + case AssetType::MATERIAL: + folder = "materials/"; + break; + + default: + folder = "/"; + } + + return std::filesystem::path{ + std::string(ASSET_ROOT) + + folder + + name + + std::string(EXTENSIONS[static_cast(type)]) + }; } /**************************************************************************** @@ -117,7 +146,7 @@ namespace SHADE // folder = ""; // break; //} - AssetPath path{ ASSET_ROOT + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) }; + AssetPath path{ std::string{ASSET_ROOT} + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) }; SHAssetMetaHandler::WriteMetaData(meta); @@ -126,6 +155,19 @@ namespace SHADE return id; } + AssetID SHAssetManager::CreateAsset(AssetName name, AssetType type) noexcept + { + AssetID id = GenerateAssetID(type); + + assetCollection.emplace_back( + name, + id, + type, + GenerateNewPath(name, type), + 0 + ); + return id; + } /**************************************************************************** * \brief Import new asset from outside editor window. * @@ -134,7 +176,10 @@ namespace SHADE ****************************************************************************/ AssetID SHAssetManager::ImportNewAsset(char const* p) noexcept { - std::filesystem::path const path{ p }; + std::filesystem::path const path{ p }; + + auto const type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string()); + auto const id = GenerateAssetID(type); std::filesystem::path const newPath{ GenerateLocalPath(path) }; if (newPath.empty()) @@ -145,11 +190,7 @@ namespace SHADE std::filesystem::copy(path, newPath); - AssetID id{ RetrieveAsset(newPath.string().c_str()) }; - if (id != 0) - { - LoadData(id); - } + assetCollection.push_back(CreateAssetFromPath(newPath)); return id; } @@ -160,158 +201,14 @@ namespace SHADE ****************************************************************************/ void SHAssetManager::RefreshAllAssets() noexcept { - std::vector metaFiles; - std::vector AssetFiles; - //SHFileSystem::LoadAllFiles(metaFiles, AssetFiles); - //std::vector AssetFilesVerified; - std::vector AssetFilesNew; - - for (auto const& asset : AssetFiles) - { - bool found = false; - for (auto it {metaFiles.begin()}; it != metaFiles.end(); ++it) - { - std::string fileExtCheck{ asset.filename().string() }; - fileExtCheck += META_EXTENSION; - if (it->filename().string() == fileExtCheck) - { - metaFiles.erase(it); - found = true; - break; - } - } - - if (!found && IsRecognised(asset.extension().string().c_str())) - { - AssetFilesNew.push_back(asset); - } - } - - std::vector newLoad; - newLoad.reserve(AssetFilesNew.size()); - - //TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa) - for (auto const& file : AssetFilesNew) - { - newLoad.push_back(RegisterAssetNew(file)); - } - - //UpdateAllSpriteSets(); - - } - - //void SHAssetManager::LoadDataTemp(std::string p) noexcept - //{ - // AssetPath path{ p }; - - // if (path.extension().string() == FBX_EXTENSION - // || path.extension().string() == GLTF_EXTENSION - // || path.extension().string() == MESH_EXTENSION) - // { - // LoadGLTF( - // { - // .name {path.filename().string()}, - // .id {0}, - // .type {AssetType::MESH}, - // .path {path}, - // .location {0} - // } - // ); - // } - // else if (path.extension().string() == DDS_EXTENSION - // || path.extension().string() == TEXTURE_EXTENSION) - // { - // LoadDDS( - // { - // .name {path.filename().string()}, - // .id {0}, - // .type {AssetType::DDS}, - // .path {path}, - // .location {0} - // } - // ); - // } - //} - - std::vector SHAssetManager::GetAllMeshes() noexcept - { - std::vector result; - for (auto const& mesh : meshCollection) - { - result.push_back(mesh.second); - } - - return result; - } - - std::vector SHAssetManager::GetAllTextures() noexcept - { - std::vector result; - for (auto const& dds : textureCollection) - { - result.push_back(dds.second); - } - - return result; - } - - SHMeshAsset const* SHAssetManager::GetMesh(AssetID id) noexcept - { - if (meshCollection.find(id) == meshCollection.end()) - { - return nullptr; - } - - return &meshCollection[id]; - } - - SHTextureAsset const* SHAssetManager::GetTexture(AssetID id) noexcept - { - if (textureCollection.find(id) == textureCollection.end()) - { - return nullptr; - } - - return &textureCollection[id]; - } - - /**************************************************************************** - * \param Path for meta data file - * \param Path for asset file - - * \brief Links meta data to asset in registries. Meta data should - * already exist - ****************************************************************************/ - void SHAssetManager::RegisterAsset(AssetPath const& metaPath, AssetPath const& path) noexcept - { - SHAsset const meta = SHAssetMetaHandler::RetrieveMetaData(metaPath); - - assetCollection.push_back(meta); - } - - /**************************************************************************** - * \param Path for asset file - - * \brief Creates new meta data for new asset. - ****************************************************************************/ - SHAsset SHAssetManager::RegisterAssetNew(AssetPath const& asset) noexcept - { - SHAsset meta; - meta.type = SHAssetMetaHandler::GetTypeFromExtension(asset.extension().string()); - meta.id = GenerateAssetID(meta.type); - - assetCollection.push_back(meta); - - SHAssetMetaHandler::WriteMetaData(meta); - return assetCollection.back(); } bool SHAssetManager::IsRecognised(char const* ext) noexcept { for (auto const& e : EXTENSIONS) { - if (strcmp(ext, e.c_str()) == 0) + if (strcmp(ext, e.data()) == 0) { return true; } @@ -320,60 +217,31 @@ namespace SHADE return false; } - void SHAssetManager::LoadGLTF(AssetPath path) noexcept + SHAsset SHAssetManager::CreateAssetFromPath(AssetPath path) noexcept { - std::vector meshes; - std::vector anims; - - SHAssimpLibrary::LoadFromFile(path, meshes, anims); + SHAsset result; - for (auto const& mesh : meshes) - { - auto id{ GenerateAssetID(AssetType::MESH) }; - meshCollection.emplace(id, mesh); + result.name = path.stem().string(); + result.type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string()); + result.id = GenerateAssetID(result.type); + result.path = path; - AssetPath path; - if (!mesh.compiled) - { - path = SHMeshCompiler::CompileMeshBinary(mesh, path); - } - - assetCollection.emplace_back( - mesh.header.meshName, - id, - AssetType::MESH, - path, - 0 - ); - } - - for (auto const& anim : anims) - { - //TODO Register anim resource and compile into binary - } + return result; } - void SHAssetManager::LoadDDS(SHAsset asset) noexcept + void SHAssetManager::InitLoaders() noexcept { - SHTextureAsset image; - - SHTextureLoader::LoadImageAsset(asset.path, image); - - if (!image.compiled) - { - auto id{ GenerateAssetID(AssetType::TEXTURE) }; - textureCollection.emplace(id, image); - - auto path{ SHTextureCompiler::CompileTextureBinary(image, asset.path) }; - - assetCollection.emplace_back( - image.name, - id, - AssetType::TEXTURE, - path, - 0 - ); - } + loaders[static_cast(AssetType::AUDIO)] = nullptr; + loaders[static_cast(AssetType::SHADER)] = nullptr; + loaders[static_cast(AssetType::MATERIAL)] = nullptr; + loaders[static_cast(AssetType::IMAGE)] = dynamic_cast(new SHTextureLoader()); + loaders[static_cast(AssetType::TEXTURE)] = nullptr; + loaders[static_cast(AssetType::MESH)] = dynamic_cast(new SHMeshLoader()); + loaders[static_cast(AssetType::SCRIPT)] = nullptr; + loaders[static_cast(AssetType::SCENE)] = nullptr; + loaders[static_cast(AssetType::PREFAB)] = nullptr; + loaders[static_cast(AssetType::AUDIO_WAV)] = nullptr; + loaders[static_cast(AssetType::DDS)] = nullptr; } /**************************************************************************** @@ -381,7 +249,8 @@ namespace SHADE ****************************************************************************/ void SHAssetManager::Load() noexcept { - RetrieveAssets(); + InitLoaders(); + BuildAssetCollection(); LoadAllData(); } @@ -390,143 +259,40 @@ namespace SHADE ****************************************************************************/ void SHAssetManager::LoadAllData() noexcept { - //TODO Remove when on demand loading is done for (auto const& asset : assetCollection) { - switch (asset.type) - { - case AssetType::MESH: - meshCollection.emplace(asset.id, SHMeshAsset()); - SHMeshLoader::LoadSHMesh(meshCollection[asset.id], asset.path); - break; - - case AssetType::TEXTURE: - textureCollection.emplace(asset.id, SHTextureAsset()); - SHTextureLoader::LoadSHTexture(asset.path, textureCollection[asset.id]); - break; - - default: - void; - } + SHAssetData* data = loaders[static_cast(asset.type)]->Load(asset.path); + assetData.emplace(asset.id, data); } } - void SHAssetManager::LoadData(AssetID id) noexcept + SHAssetData* SHAssetManager::LoadData(SHAsset const& asset) noexcept { - (void)id; - } + SHAssetData* data = loaders[static_cast(asset.type)]->Load(asset.path); - /**************************************************************************** - * \brief Retrieve all asset files and meta files from filesystem - ****************************************************************************/ - void SHAssetManager::RetrieveAssets() noexcept - { - std::vector metaFiles; - std::vector AssetFiles; - - for (auto const dir : std::filesystem::recursive_directory_iterator(ASSET_ROOT)) + if (data == nullptr) { - if (dir.path().extension().string() == META_EXTENSION) - { - auto meta{ SHAssetMetaHandler::RetrieveMetaData(dir.path()) }; - - assetCollection.push_back(meta); - assetRegistry.emplace(meta.id, meta); - } - } - - //TODO: Write new function for file manager to loop through all files - //SHFileSystem::StartupFillDirectories(ASSET_ROOT); - //FolderPointer rootFolder = SHFileSystem::GetRoot(); - - //for (auto const& meta : metaFiles) - //{ - // for (std::vector::const_iterator it{ AssetFiles.cbegin() }; - // it != AssetFiles.cend(); - // ++it) - // { - // // Asset exists for meta file - // std::string fileExtCheck{ it->filename().string() }; - // fileExtCheck += META_EXTENSION; - // if (meta.filename().string() == fileExtCheck) - // { - // RegisterAsset(meta, *it); - // AssetFiles.erase(it); - // break; - // } - // } - //} - - //TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa) - //for (auto const& file : AssetFiles) - //{ - // if (IsRecognised(file.extension().string().c_str())) - // { - // SHAssetMetaHandler::WriteMetaData(RegisterAssetNew(file)); - // } - // else - // { - // std::cout << "Unsupported File Format: " << file.filename() << "\n"; - // } - //} - } - - AssetID SHAssetManager::RetrieveAsset(char const* path) noexcept - { - std::filesystem::path p{ path }; - if (IsRecognised(p.extension().string().c_str())) - { - SHAsset const& meta{ RegisterAssetNew(p) }; - SHAssetMetaHandler::WriteMetaData(meta); - return meta.id; + SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string()); } else { - std::cout << "Unsupported File Format: " << p.filename() << "\n"; + assetData.emplace(asset.id, data); } - // Assert that file imported is not recognised - return 0; + return data; } - /**************************************************************************** - * \param Full path of file - - * \brief Extracts file name from path. Formats file name into readable - * with spaces and capitalises first letter of every word - ****************************************************************************/ - AssetName SHAssetManager::GetNameFromPath(AssetPath filepath) noexcept + void SHAssetManager::BuildAssetCollection() noexcept { - std::string name{ filepath.filename().string() }; - name = name.substr(0, name.find_last_of('.')); - - //if (name[0] <= 122 && name[0] >= 97) - //{ - // name[0] -= 32; - //} - - //for (size_t i{ 1 }; i < name.length(); ++i) - //{ - // // Replace all underscores with spaces - // if (name[i] == '_') - // { - // name[i] = ' '; - // continue; - // } - - // if (name[i + 1] <= 'Z' && name[i + 1] >= 'A' - // && name[i] <= 'z' && name[i] >= 'a') - // { - // name.insert(i + 1, 1, ' '); - // continue; - // } - - // if (name[i - 1] == ' ' && name[i] <= 'z' && name[i] >= 'a') - // { - // name[i] -= 32; - // } - //} - - return name; + for (auto const& dir : std::filesystem::recursive_directory_iterator{ASSET_ROOT}) + { + if (dir.is_regular_file()) + { + if (dir.path().extension().string() == META_EXTENSION.data()) + { + assetCollection.push_back(SHAssetMetaHandler::RetrieveMetaData(dir.path())); + } + } + } } } diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index b2c4216b..74029bdd 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -11,9 +11,10 @@ #pragma once #include "tinyddsloader.h" #include "SHAsset.h" +#include "Asset Types/SHAssetData.h" +#include "Libraries/SHAssetLoader.h" +#include -#include "Asset Types/SHMeshAsset.h" -#include "Asset Types/SHTextureAsset.h" #include "SH_API.h" namespace SHADE @@ -28,6 +29,8 @@ namespace SHADE static AssetPath GenerateLocalPath(AssetPath path) noexcept; + static AssetPath GenerateNewPath(AssetName name, AssetType type); + /**************************************************************************** * \brief Deallocate all memory used by resource data ****************************************************************************/ @@ -54,6 +57,7 @@ namespace SHADE * \return resource id generated for new asset ****************************************************************************/ static AssetID CreateNewAsset(AssetType, AssetName) noexcept; + static AssetID CreateAsset(AssetName name, AssetType type) noexcept; /**************************************************************************** * \brief Import new resource from outside editor window. @@ -70,67 +74,49 @@ namespace SHADE static void RefreshAllAssets() noexcept; // -------------------------------------------------------------------------/ - //TODO: TEMPORARY FOR TESTING GLTF & DDS - //static void LoadDataTemp(std::string path) noexcept; - static std::vector GetAllMeshes() noexcept; - static std::vector GetAllTextures() noexcept; + template + static std::enable_if_t, T const * const> GetData(AssetID id) noexcept + { + if (assetData.contains(id)) + { + for (auto const& asset : assetCollection) + { + if (asset.id == id) + { + assetData.emplace(id, LoadData(asset)); + return dynamic_cast(assetData[id]); + } + } - static SHMeshAsset const* GetMesh(AssetID id) noexcept; - static SHTextureAsset const* GetTexture(AssetID id) noexcept; - - // Specialised load calls - static void LoadGLTF(AssetPath path) noexcept; - static void LoadDDS(SHAsset asset) noexcept; + SHLOG_ERROR("Asset ID provided does not exist: {}", id); + return nullptr; + } + + return dynamic_cast(assetData[id]); + } private: /**************************************************************************** * \brief Load resource data into memory ****************************************************************************/ static void LoadAllData() noexcept; - static void LoadData(AssetID id) noexcept; + static SHAssetData* LoadData(SHAsset const& asset) noexcept; - /**************************************************************************** - * \brief Retrieve all resource files and meta files from filesystem - ****************************************************************************/ - static void RetrieveAssets() noexcept; - - static AssetID RetrieveAsset(char const* path) noexcept; - - /**************************************************************************** - * \param Full path of file - - * \brief Extracts file name from path. Formats file name into readable - * with spaces and capitalises first letter of every word - ****************************************************************************/ - static AssetName GetNameFromPath(AssetPath) noexcept; - - /**************************************************************************** - * \param Path for meta data file - * \param Path for resource file - - * \brief Links meta data to resource in registries. Meta data should - * already exist - ****************************************************************************/ - static void RegisterAsset(AssetPath const&, AssetPath const&) noexcept; - - /**************************************************************************** - * \param Path for resource file - - * \brief Creates new meta data for new resource. - ****************************************************************************/ - static SHAsset RegisterAssetNew(AssetPath const&) noexcept; + inline static void BuildAssetCollection() noexcept; static bool IsRecognised(char const*) noexcept; + + static SHAsset CreateAssetFromPath(AssetPath path) noexcept; + static void InitLoaders() noexcept; static FMOD::System* audioSystem; static std::unordered_map* audioSoundList; + static std::vector loaders; + // For all resources static std::vector assetCollection; - static std::unordered_map assetRegistry; - - static std::unordered_map meshCollection; - static std::unordered_map textureCollection; + static std::unordered_map assetData; }; } diff --git a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp index 442c3d96..1bfec00d 100644 --- a/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp +++ b/SHADE_Engine/src/Assets/SHAssetMetaHandler.cpp @@ -37,7 +37,7 @@ namespace SHADE { for (int i{0}; i < EXTENSIONS->size(); ++i) { - if (ext == EXTENSIONS[i]) + if (strcmp(ext.c_str(), EXTENSIONS[i].data()) == 0) { return static_cast(i); } @@ -53,7 +53,7 @@ namespace SHADE ****************************************************************************/ AssetExtension SHAssetMetaHandler::GetExtensionFromType(AssetType type) noexcept { - return EXTENSIONS[static_cast(type)]; + return AssetExtension(EXTENSIONS[static_cast(type)]); } /**************************************************************************** @@ -124,16 +124,6 @@ namespace SHADE metaFile << "ID: " << meta.id << "\n"; metaFile << "Type: " << static_cast(meta.type) << std::endl; - ////TODO Add in information that is specific to types like mesh - //switch(meta.type) - //{ - //case AssetType::MESH: - // break; - - //default: - // break; - //} - metaFile.close(); } From 449cd28bb353b5b3a41f103dc1b6cc3540b22b17 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Fri, 21 Oct 2022 20:55:21 +0800 Subject: [PATCH 08/28] Took test scene from main --- SHADE_Application/src/Scenes/SBTestScene.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index bd33e63c..41326174 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -13,9 +13,6 @@ #include "Physics/Components/SHRigidBodyComponent.h" #include "Physics/Components/SHColliderComponent.h" -#include "Assets/Asset Types/SHMeshAsset.h" -#include "Assets/Asset Types/SHTextureAsset.h" - #include "Assets/SHAssetManager.h" #include "Resource/SHResourceManager.h" @@ -43,8 +40,6 @@ namespace Sandbox // Create temp meshes const auto CUBE_MESH = SHADE::SHPrimitiveGenerator::Cube(*graphicsSystem); - auto assets = SHAssetManager::GetAllAssets(); - //Test Racoon mesh std::vector> handles; std::vector> texHandles; From 304071cb0abc4d629bcf25aab651b73f87061028 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Sat, 22 Oct 2022 00:42:50 +0800 Subject: [PATCH 09/28] Apparently static keyword gives error but it compiles --- SHADE_Engine/src/Resource/SHResourceManager.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp index cff4e84b..fb0dcc6a 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.hpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -134,7 +134,7 @@ namespace SHADE /* Query Functions */ /*-----------------------------------------------------------------------------------*/ template - std::optional SHResourceManager::GetAssetID(Handle handle) + static std::optional SHResourceManager::GetAssetID(Handle handle) { const Handle GENERIC_HANDLE = Handle(handle); auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap(); From db751bd1418955f3b35be6e384aeedff65cdf438 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sat, 22 Oct 2022 18:22:26 +0800 Subject: [PATCH 10/28] Editor & Scripts can now override Physics-Based objects' Transforms --- Assets/Editor/Layouts/UserLayout.ini | 2 +- .../src/Application/SBApplication.cpp | 4 +- .../src/Math/Transform/SHTransformSystem.cpp | 44 +++++++++++++++++-- .../src/Math/Transform/SHTransformSystem.h | 42 +++++++++++++++--- 4 files changed, 80 insertions(+), 12 deletions(-) diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini index 396b853b..7b0a70f8 100644 --- a/Assets/Editor/Layouts/UserLayout.ini +++ b/Assets/Editor/Layouts/UserLayout.ini @@ -38,7 +38,7 @@ Collapsed=0 DockId=0x00000002,0 [Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=-227,-1256 Size=1920,1012 Split=X +DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1481,1036 Split=X DockNode ID=0x00000001 Parent=0x00000005 SizeRef=349,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 8733e7b9..3675e275 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -83,11 +83,13 @@ namespace Sandbox SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); - SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index a3ca3e75..4b4f1cce 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -28,8 +28,12 @@ namespace SHADE /* Constructors & Destructor Definitions */ /*-----------------------------------------------------------------------------------*/ - SHTransformSystem::TransformUpdateRoutine::TransformUpdateRoutine() - : SHSystemRoutine { "Transform Update", true } + SHTransformSystem::TransformPostLogicUpdate::TransformPostLogicUpdate() + : SHSystemRoutine { "Transform Post-Logic Update", true } + {} + + SHTransformSystem::TransformPostPhysicsUpdate::TransformPostPhysicsUpdate() + : SHSystemRoutine { "Transform Post-Physics Update", false } {} @@ -37,13 +41,20 @@ namespace SHADE /* Public Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ - void SHTransformSystem::TransformUpdateRoutine::Execute(double) noexcept + void SHTransformSystem::TransformPostLogicUpdate::Execute(double) noexcept { // Get the current scene graph to traverse and update const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); UpdateEntity(SCENE_GRAPH.GetRoot()); } + void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double dt) noexcept + { + // Get the current scene graph to traverse and update + const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); + UpdateEntityAndClear(SCENE_GRAPH.GetRoot()); + } + void SHTransformSystem::Init() { std::shared_ptr thisReceiver { std::make_shared>(this, &SHTransformSystem::ChangeParent) }; @@ -175,6 +186,33 @@ namespace SHADE } UpdateEntity(child); + } + } + + + void SHTransformSystem::UpdateEntityAndClear(const SHSceneNode* node) + { + const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s(node->GetEntityID()); + const bool HAS_PARENT_CHANGED = NODE_TRANSFORM && NODE_TRANSFORM->dirty; + + for (const auto* child : node->GetChildren()) + { + auto* childTransform = SHComponentManager::GetComponent_s(child->GetEntityID()); + if (childTransform) + { + // Only update if node in hierarchy and component are both active + const bool IS_NODE_ACTIVE = child->IsActive(); + if (IS_NODE_ACTIVE && childTransform->isActive) + { + if (childTransform->dirty || HAS_PARENT_CHANGED) + { + UpdateTransform(*childTransform, NODE_TRANSFORM); + childTransform->dirty = true; + } + } + } + + UpdateEntityAndClear(child); // Clear dirty flag after all children are updated if (childTransform) diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h index 95957830..256c1561 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -45,25 +45,52 @@ namespace SHADE /* System Routines */ /*---------------------------------------------------------------------------------*/ - class SH_API TransformUpdateRoutine final: public SHSystemRoutine + class SH_API TransformPostLogicUpdate final: public SHSystemRoutine { public: /*-------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*-------------------------------------------------------------------------------*/ - TransformUpdateRoutine (); - ~TransformUpdateRoutine () = default; + TransformPostLogicUpdate (); + ~TransformPostLogicUpdate () = default; - TransformUpdateRoutine (const TransformUpdateRoutine&) = delete; - TransformUpdateRoutine (TransformUpdateRoutine&&) = delete; + TransformPostLogicUpdate (const TransformPostLogicUpdate&) = delete; + TransformPostLogicUpdate (TransformPostLogicUpdate&&) = delete; /*-------------------------------------------------------------------------------*/ /* Operator Overloads */ /*-------------------------------------------------------------------------------*/ - TransformUpdateRoutine& operator= (const TransformUpdateRoutine&) = delete; - TransformUpdateRoutine& operator= (TransformUpdateRoutine&&) = delete; + TransformPostLogicUpdate& operator= (const TransformPostLogicUpdate&) = delete; + TransformPostLogicUpdate& operator= (TransformPostLogicUpdate&&) = delete; + + /*-------------------------------------------------------------------------------*/ + /* Function Members */ + /*-------------------------------------------------------------------------------*/ + + void Execute(double dt) noexcept override; + }; + + class SH_API TransformPostPhysicsUpdate final: public SHSystemRoutine + { + public: + /*-------------------------------------------------------------------------------*/ + /* Constructors & Destructor */ + /*-------------------------------------------------------------------------------*/ + + TransformPostPhysicsUpdate (); + ~TransformPostPhysicsUpdate () = default; + + TransformPostPhysicsUpdate (const TransformPostPhysicsUpdate&) = delete; + TransformPostPhysicsUpdate (TransformPostPhysicsUpdate&&) = delete; + + /*-------------------------------------------------------------------------------*/ + /* Operator Overloads */ + /*-------------------------------------------------------------------------------*/ + + TransformPostPhysicsUpdate& operator= (const TransformPostPhysicsUpdate&) = delete; + TransformPostPhysicsUpdate& operator= (TransformPostPhysicsUpdate&&) = delete; /*-------------------------------------------------------------------------------*/ /* Function Members */ @@ -88,6 +115,7 @@ namespace SHADE static void UpdateChildrenLocalTransforms (SHSceneNode* node); static void UpdateEntity (const SHSceneNode* node); + static void UpdateEntityAndClear (const SHSceneNode* node); static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); }; From ebfcf1c6bbbeae4c8a16c7d96ed3be9b4205fb6c Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sat, 22 Oct 2022 20:16:38 +0800 Subject: [PATCH 11/28] Transform now stores orientation as Quaternions. Interface unchanged --- SHADE_Application/src/Scenes/SBTestScene.cpp | 6 +- SHADE_Engine/src/Math/SHMatrix.cpp | 81 +++----- SHADE_Engine/src/Math/SHMatrix.h | 2 + SHADE_Engine/src/Math/SHQuaternion.cpp | 174 +++++++----------- SHADE_Engine/src/Math/SHQuaternion.h | 9 +- .../src/Math/Transform/SHTransform.cpp | 18 +- SHADE_Engine/src/Math/Transform/SHTransform.h | 22 +-- .../Math/Transform/SHTransformComponent.cpp | 78 +++----- .../src/Math/Transform/SHTransformComponent.h | 36 ++-- .../src/Math/Transform/SHTransformSystem.cpp | 75 ++++---- .../src/Math/Transform/SHTransformSystem.h | 3 +- SHADE_Engine/src/Physics/SHPhysicsObject.cpp | 6 +- 12 files changed, 209 insertions(+), 301 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index be09768b..23259ee4 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -104,10 +104,10 @@ namespace Sandbox transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber()); transform.SetWorldScale(TEST_OBJ_SCALE); - if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN) + //if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN) collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero); - else - collider.AddBoundingSphere(0.5f, SHVec3::Zero); + //else + // collider.AddBoundingSphere(0.5f, SHVec3::Zero); stressTestObjects.emplace_back(entity); } diff --git a/SHADE_Engine/src/Math/SHMatrix.cpp b/SHADE_Engine/src/Math/SHMatrix.cpp index 571fa4e0..ec3951e2 100644 --- a/SHADE_Engine/src/Math/SHMatrix.cpp +++ b/SHADE_Engine/src/Math/SHMatrix.cpp @@ -295,32 +295,33 @@ namespace SHADE ) != 0; } + SHMatrix::operator XMMATRIX() const noexcept + { + return XMLoadFloat4x4(this); + } + SHMatrix operator*(float lhs, const SHMatrix& rhs) noexcept { return rhs * lhs; } - /*-----------------------------------------------------------------------------------*/ /* Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ void SHMatrix::Transpose() noexcept { - const XMMATRIX M = XMLoadFloat4x4(this); - XMStoreFloat4x4(this, XMMatrixTranspose(M)); + XMStoreFloat4x4(this, XMMatrixTranspose(*this)); } void SHMatrix::Invert() noexcept { - const XMMATRIX M = XMLoadFloat4x4(this); - XMStoreFloat4x4(this, XMMatrixInverse(nullptr, M)); + XMStoreFloat4x4(this, XMMatrixInverse(nullptr, *this)); } float SHMatrix::Determinant() const noexcept { - const XMMATRIX M = XMLoadFloat4x4(this); - return XMVectorGetX(XMMatrixDeterminant(M)); + return XMVectorGetX(XMMatrixDeterminant(*this)); } std::string SHMatrix::ToString() const noexcept @@ -337,9 +338,8 @@ namespace SHADE bool SHMatrix::Decompose(SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept { XMVECTOR s, r, t; - const XMMATRIX M = XMLoadFloat4x4(this); - if (!XMMatrixDecompose(&s, &r, &t, M)) + if (!XMMatrixDecompose(&s, &r, &t, *this)) return false; SHQuaternion orientation; @@ -356,9 +356,8 @@ namespace SHADE bool SHMatrix::Decompose(SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept { XMVECTOR s, r, t; - const XMMATRIX M = XMLoadFloat4x4(this); - if (!XMMatrixDecompose(&s, &r, &t, M)) + if (!XMMatrixDecompose(&s, &r, &t, *this)) return false; XMStoreFloat3(&scale, s); @@ -376,8 +375,7 @@ namespace SHADE { SHMatrix result; - const XMMATRIX M = XMLoadFloat4x4(&matrix); - XMStoreFloat4x4(&result, XMMatrixTranspose(M)); + XMStoreFloat4x4(&result, XMMatrixTranspose(matrix)); return result; } @@ -385,8 +383,7 @@ namespace SHADE { SHMatrix result; - const XMMATRIX M = XMLoadFloat4x4(&matrix); - XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, M)); + XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, matrix)); return result; } @@ -401,8 +398,8 @@ namespace SHADE SHMatrix SHMatrix::Translate(const SHVec3& pos) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z)); + XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z)); return result; } @@ -410,25 +407,23 @@ namespace SHADE { SHMatrix result; - const XMVECTOR A = XMLoadFloat3(&axis); - XMStoreFloat4x4(&result, XMMatrixRotationAxis(A, angleInRad)); - + XMStoreFloat4x4(&result, XMMatrixRotationAxis(axis, angleInRad)); return result; } SHMatrix SHMatrix::Rotate(float yaw, float pitch, float roll) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll)); + XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll)); return result; } SHMatrix SHMatrix::Rotate(const SHVec3& eulerAngles) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(eulerAngles.x, eulerAngles.y, eulerAngles.z)); + XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYawFromVector(eulerAngles)); return result; } @@ -436,57 +431,55 @@ namespace SHADE { SHMatrix result; - const XMVECTOR Q = XMLoadFloat4(&q); - XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(Q)); - + XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(q)); return result; } SHMatrix SHMatrix::RotateX(float angleInRad) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad)); + XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad)); return result; } SHMatrix SHMatrix::RotateY(float angleInRad) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad)); + XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad)); return result; } SHMatrix SHMatrix::RotateZ(float angleInRad) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad)); + XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad)); return result; } SHMatrix SHMatrix::Scale(float uniformScaleFactor) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor)); + XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor)); return result; } SHMatrix SHMatrix::Scale(float x, float y, float z) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z)); + XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z)); return result; } SHMatrix SHMatrix::Scale(const SHVec3& scale) noexcept { SHMatrix result; - XMStoreFloat4x4(&result, XMMatrixScaling(scale.x, scale.y, scale.z)); + XMStoreFloat4x4(&result, XMMatrixScalingFromVector(scale)); return result; } @@ -494,12 +487,7 @@ namespace SHADE { SHMatrix result; - const XMVECTOR EYE = XMLoadFloat3(&eye); - const XMVECTOR TGT = XMLoadFloat3(&target); - const XMVECTOR UP = XMLoadFloat3(&up); - - XMStoreFloat4x4(&result, XMMatrixLookAtRH(EYE, TGT, UP)); - + XMStoreFloat4x4(&result, XMMatrixLookAtRH(eye, target, up)); return result; } @@ -507,12 +495,7 @@ namespace SHADE { SHMatrix result; - const XMVECTOR EYE = XMLoadFloat3(&eye); - const XMVECTOR TGT = XMLoadFloat3(&target); - const XMVECTOR UP = XMLoadFloat3(&up); - - XMStoreFloat4x4(&result, XMMatrixLookAtLH(EYE, TGT, UP)); - + XMStoreFloat4x4(&result, XMMatrixLookAtLH(eye, target, up)); return result; } @@ -522,8 +505,8 @@ namespace SHADE const SHVec3 FWD_HAT = SHVec3::Normalise(-forward); - const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT)); - const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT)); + const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT); + const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT)); const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT); XMStoreFloat3(reinterpret_cast(&result._11), X_HAT); @@ -543,8 +526,8 @@ namespace SHADE const SHVec3 FWD_HAT = SHVec3::Normalise(forward); - const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT)); - const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT)); + const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT); + const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT)); const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT); XMStoreFloat3(reinterpret_cast(&result._11), X_HAT); @@ -563,7 +546,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixPerspectiveFovRH(fov, aspectRatio, nearPlane, farPlane)); - return result; } @@ -572,7 +554,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixPerspectiveFovLH(fov, aspectRatio, nearPlane, farPlane)); - return result; } @@ -581,7 +562,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixPerspectiveRH(width, height, nearPlane, farPlane)); - return result; } @@ -590,7 +570,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixPerspectiveLH(width, height, nearPlane, farPlane)); - return result; } @@ -599,7 +578,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixOrthographicRH(width, height, nearPlane, farPlane)); - return result; } @@ -608,7 +586,6 @@ namespace SHADE SHMatrix result; XMStoreFloat4x4(&result, XMMatrixOrthographicLH(width, height, nearPlane, farPlane)); - return result; } diff --git a/SHADE_Engine/src/Math/SHMatrix.h b/SHADE_Engine/src/Math/SHMatrix.h index 7a662478..4d8f1bfe 100644 --- a/SHADE_Engine/src/Math/SHMatrix.h +++ b/SHADE_Engine/src/Math/SHMatrix.h @@ -77,6 +77,8 @@ namespace SHADE SHMatrix& operator= (const SHMatrix& rhs) = default; SHMatrix& operator= (SHMatrix&& rhs) = default; + operator DirectX::XMMATRIX () const noexcept; + SHMatrix& operator+= (const SHMatrix& rhs) noexcept; SHMatrix& operator-= (const SHMatrix& rhs) noexcept; SHMatrix& operator*= (const SHMatrix& rhs) noexcept; diff --git a/SHADE_Engine/src/Math/SHQuaternion.cpp b/SHADE_Engine/src/Math/SHQuaternion.cpp index 33c568a5..924ac67a 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.cpp +++ b/SHADE_Engine/src/Math/SHQuaternion.cpp @@ -40,40 +40,10 @@ namespace SHADE : XMFLOAT4( _x, _y, _z, _w ) {} - SHQuaternion::SHQuaternion(float yaw, float pitch, float roll) noexcept - : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) - { - XMStoreFloat4(this, XMQuaternionRotationRollPitchYaw(pitch, yaw, roll)); - } - - SHQuaternion::SHQuaternion(const SHVec3& eulerAngles) noexcept - : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) - { - const XMVECTOR V = XMLoadFloat3(&eulerAngles); - XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V)); - } - - SHQuaternion::SHQuaternion(const SHVec3& axis, float angleInRad) noexcept - : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) - { - const XMVECTOR AXIS = XMLoadFloat3(&axis); - XMStoreFloat4(this, XMQuaternionRotationAxis(AXIS, angleInRad)); - } - - SHQuaternion::SHQuaternion(const SHMatrix& rotationMatrix) noexcept - : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) - { - const XMMATRIX M = XMLoadFloat4x4(&rotationMatrix); - XMStoreFloat4(this, XMQuaternionRotationMatrix(M)); - } - SHQuaternion::SHQuaternion(const reactphysics3d::Vector3& rp3dEuler) noexcept : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) { - const SHVec3& SHADE_VEC{ rp3dEuler }; - - const XMVECTOR V = XMLoadFloat3(&SHADE_VEC); - XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V)); + XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(SHVec3 { rp3dEuler })); } SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept @@ -113,10 +83,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - XMStoreFloat4(&result, XMVectorAdd(Q1, Q2)); + XMStoreFloat4(&result, XMVectorAdd(*this, rhs)); return result; } @@ -124,10 +91,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - XMStoreFloat4(&result, XMVectorSubtract(Q1, Q2)); + XMStoreFloat4(&result, XMVectorSubtract(*this, rhs)); return result; } @@ -135,9 +99,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q = XMLoadFloat4(this); - - XMStoreFloat4(&result, XMVectorNegate(Q)); + XMStoreFloat4(&result, XMVectorNegate(*this)); return result; } @@ -145,10 +107,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2)); + XMStoreFloat4(&result, XMQuaternionMultiply(*this, rhs)); return result; } @@ -156,9 +115,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q = XMLoadFloat4(this); - - XMStoreFloat4(&result, XMVectorScale(Q, rhs)); + XMStoreFloat4(&result, XMVectorScale(*this, rhs)); return result; } @@ -166,27 +123,18 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMQuaternionInverse(XMLoadFloat4(&rhs)); - - XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2)); + XMStoreFloat4(&result, XMQuaternionMultiply(*this, XMQuaternionInverse(rhs))); return result; } bool SHQuaternion::operator==(const SHQuaternion& rhs) const noexcept { - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - return XMQuaternionEqual(Q1, Q2); + return XMQuaternionEqual(*this, rhs); } bool SHQuaternion::operator!=(const SHQuaternion& rhs) const noexcept { - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - return XMQuaternionNotEqual(Q1, Q2); + return XMQuaternionNotEqual(*this, rhs); } SHQuaternion::operator reactphysics3d::Quaternion() const noexcept @@ -199,6 +147,11 @@ namespace SHADE return reactphysics3d::Vector3{ ToEuler() }; } + SHQuaternion::operator XMVECTOR() const noexcept + { + return XMLoadFloat4(this); + } + SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept { return rhs * lhs; @@ -213,8 +166,7 @@ namespace SHADE XMVECTOR axis; float angle; - const XMVECTOR Q = XMLoadFloat4(this); - XMQuaternionToAxisAngle(&axis, &angle, Q); + XMQuaternionToAxisAngle(&axis, &angle, *this); return angle; } @@ -223,8 +175,7 @@ namespace SHADE XMVECTOR axis; float angle; - const XMVECTOR Q = XMLoadFloat4(this); - XMQuaternionToAxisAngle(&axis, &angle, Q); + XMQuaternionToAxisAngle(&axis, &angle, *this); return SHVec4{XMVectorGetX(axis), XMVectorGetY(axis), XMVectorGetZ(axis), angle}; @@ -238,28 +189,22 @@ namespace SHADE void SHQuaternion::Invert() noexcept { - const XMVECTOR Q = XMLoadFloat4(this); - XMStoreFloat4(this, XMQuaternionInverse(Q)); + XMStoreFloat4(this, XMQuaternionInverse(*this)); } float SHQuaternion::Length() const noexcept { - const XMVECTOR Q = XMLoadFloat4(this); - return XMVectorGetX(XMQuaternionLength(Q)); + return XMVectorGetX(XMQuaternionLength(*this)); } float SHQuaternion::LengthSquared() const noexcept { - const XMVECTOR Q = XMLoadFloat4(this); - return XMVectorGetX(XMQuaternionLengthSq(Q)); + return XMVectorGetX(XMQuaternionLengthSq(*this)); } float SHQuaternion::Dot(const SHQuaternion& rhs) const noexcept { - const XMVECTOR Q1 = XMLoadFloat4(this); - const XMVECTOR Q2 = XMLoadFloat4(&rhs); - - return XMVectorGetX(XMQuaternionDot(Q1, Q2)); + return XMVectorGetX(XMQuaternionDot(*this, rhs)); } SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion&, float) const noexcept @@ -273,29 +218,29 @@ namespace SHADE SHVec3 SHQuaternion::ToEuler() const noexcept { - const float xx = x * x; - const float yy = y * y; - const float zz = z * z; + const float XX = x * x; + const float YY = y * y; + const float ZZ = z * z; - const float m31 = 2.f * x * z + 2.f * y * w; - const float m32 = 2.f * y * z - 2.f * x * w; - const float m33 = 1.f - 2.f * xx - 2.f * yy; + const float M_31 = 2.f * x * z + 2.f * y * w; + const float M_32 = 2.f * y * z - 2.f * x * w; + const float M_33 = 1.f - 2.f * XX - 2.f * YY; - const float cy = sqrtf(m33 * m33 + m31 * m31); - const float cx = atan2f(-m32, cy); - if (cy > 16.0f * SHMath::EPSILON) + const float CY = sqrtf(M_33 * M_33 + M_31 * M_31); + const float CX = atan2f(-M_32, CY); + if (CY > 16.0f * SHMath::EPSILON) { - const float m12 = 2.f * x * y + 2.f * z * w; - const float m22 = 1.f - 2.f * xx - 2.f * zz; + const float M_12 = 2.f * x * y + 2.f * z * w; + const float M_22 = 1.f - 2.f * XX - 2.f * ZZ; - return SHVec3(cx, atan2f(m31, m33), atan2f(m12, m22)); + return SHVec3(CX, atan2f(M_31, M_33), atan2f(M_12, M_22)); } else { - const float m11 = 1.f - 2.f * yy - 2.f * zz; - const float m21 = 2.f * x * y - 2.f * z * w; + const float m11 = 1.f - 2.f * YY - 2.f * ZZ; + const float m21 = 2.f * x * y - 2.f * z * w; - return SHVec3(cx, 0.f, atan2f(-m21, m11)); + return SHVec3(CX, 0.f, atan2f(-m21, m11)); } } @@ -311,13 +256,43 @@ namespace SHADE /* Static Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ + SHQuaternion SHQuaternion::FromEuler(const SHVec3& eulerAngles) noexcept + { + SHQuaternion result; + + XMStoreFloat4(&result, XMQuaternionRotationRollPitchYawFromVector(eulerAngles)); + return result; + } + + SHQuaternion SHQuaternion::FromPitchYawRoll(float pitch, float yaw, float roll) noexcept + { + SHQuaternion result; + + XMStoreFloat4(&result, XMQuaternionRotationRollPitchYaw(pitch, yaw, roll)); + return result; + } + + SHQuaternion SHQuaternion::FromAxisAngle(const SHVec3& axis, float angle) noexcept + { + SHQuaternion result; + + XMStoreFloat4(&result, XMQuaternionRotationAxis(axis, angle)); + return result; + } + + SHQuaternion SHQuaternion::FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept + { + SHQuaternion result; + + XMStoreFloat4(&result, XMQuaternionRotationMatrix(rotationMatrix)); + return result; + } + SHQuaternion SHQuaternion::Normalise(const SHQuaternion& q) noexcept { SHQuaternion result; - const XMVECTOR Q = XMLoadFloat4(&q); - - XMStoreFloat4(&result, XMQuaternionNormalize(Q)); + XMStoreFloat4(&result, XMQuaternionNormalize(q)); return result; } @@ -325,9 +300,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q = XMLoadFloat4(&q); - - XMStoreFloat4(&result, XMQuaternionConjugate(Q)); + XMStoreFloat4(&result, XMQuaternionConjugate(q)); return result; } @@ -335,9 +308,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q = XMLoadFloat4(&q); - XMStoreFloat4(&result, XMQuaternionInverse(Q)); - + XMStoreFloat4(&result, XMQuaternionInverse(q)); return result; } @@ -362,10 +333,7 @@ namespace SHADE { SHQuaternion result; - const XMVECTOR Q1 = XMLoadFloat4(&q1); - const XMVECTOR Q2 = XMLoadFloat4(&q2); - - XMStoreFloat4(&result, XMQuaternionSlerp(Q1, Q2, t)); + XMStoreFloat4(&result, XMQuaternionSlerp(q1, q2, t)); return result; } diff --git a/SHADE_Engine/src/Math/SHQuaternion.h b/SHADE_Engine/src/Math/SHQuaternion.h index c94907b5..f3ce3d61 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.h +++ b/SHADE_Engine/src/Math/SHQuaternion.h @@ -51,9 +51,6 @@ namespace SHADE SHQuaternion () noexcept; SHQuaternion (float x, float y, float z, float w) noexcept; SHQuaternion (float yaw, float pitch, float roll) noexcept; - SHQuaternion (const SHVec3& eulerAngles) noexcept; - SHQuaternion (const SHVec3& axis, float angleInRad) noexcept; - SHQuaternion (const SHMatrix& rotationMatrix) noexcept; // Conversion from other math types @@ -87,6 +84,7 @@ namespace SHADE operator reactphysics3d::Quaternion () const noexcept; operator reactphysics3d::Vector3 () const noexcept; + operator DirectX::XMVECTOR () const noexcept; /*---------------------------------------------------------------------------------*/ /* Getter Functions */ @@ -113,6 +111,11 @@ namespace SHADE /* Static Function Members */ /*---------------------------------------------------------------------------------*/ + [[nodiscard]] static SHQuaternion FromEuler (const SHVec3& eulerAngles) noexcept; + [[nodiscard]] static SHQuaternion FromPitchYawRoll (float pitch, float yaw, float roll) noexcept; + [[nodiscard]] static SHQuaternion FromAxisAngle (const SHVec3& axis, float angle) noexcept; + [[nodiscard]] static SHQuaternion FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept; + [[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept; [[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept; [[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept; diff --git a/SHADE_Engine/src/Math/Transform/SHTransform.cpp b/SHADE_Engine/src/Math/Transform/SHTransform.cpp index f51d73ec..ef7c5fda 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransform.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransform.cpp @@ -26,15 +26,15 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ SHTransform::SHTransform() noexcept - : position { SHVec3::Zero } - , rotation { SHVec3::Zero } - , scale { SHVec3::One } + : position { SHVec3::Zero } + , orientation { SHQuaternion::Identity } + , scale { SHVec3::One } {} SHTransform::SHTransform(const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept - : position { pos } - , rotation { rot } - , scale { scl } + : position { pos } + , orientation { SHQuaternion::FromEuler(rot) } + , scale { scl } {} /*-----------------------------------------------------------------------------------*/ @@ -43,12 +43,12 @@ namespace SHADE bool SHTransform::operator==(const SHTransform& rhs) const noexcept { - return !(position != rhs.position || rotation != rhs.rotation || scale != rhs.scale); + return !(position != rhs.position || orientation != rhs.orientation || scale != rhs.scale); } bool SHTransform::operator!=(const SHTransform& rhs) const noexcept { - return (position != rhs.position || rotation != rhs.rotation || scale != rhs.scale); + return (position != rhs.position || orientation != rhs.orientation || scale != rhs.scale); } /*-----------------------------------------------------------------------------------*/ @@ -59,7 +59,7 @@ namespace SHADE { const SHMatrix T = SHMatrix::Translate(position); - const SHMatrix R = SHMatrix::Rotate(rotation); + const SHMatrix R = SHMatrix::Rotate(orientation); const SHMatrix S = SHMatrix::Scale(scale); trs = S * R * T; diff --git a/SHADE_Engine/src/Math/Transform/SHTransform.h b/SHADE_Engine/src/Math/Transform/SHTransform.h index c1a0e565..2e7d236c 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransform.h +++ b/SHADE_Engine/src/Math/Transform/SHTransform.h @@ -12,8 +12,8 @@ // Project Headers #include "SH_API.h" -#include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" +#include "Math/SHQuaternion.h" #include "Math/SHMatrix.h" namespace SHADE @@ -31,22 +31,23 @@ namespace SHADE static const SHTransform Identity; - SHVec3 position; - SHVec3 rotation; - SHVec3 scale; + SHVec3 position; + SHQuaternion orientation; + SHVec3 scale; - SHMatrix trs; + SHMatrix trs; /*---------------------------------------------------------------------------------*/ /* Constructors & Destructor */ /*---------------------------------------------------------------------------------*/ - SHTransform (const SHTransform&) = default; - SHTransform (SHTransform&&) = default; - ~SHTransform () = default; + SHTransform (const SHTransform&) = default; + SHTransform (SHTransform&&) = default; + ~SHTransform () = default; - SHTransform () noexcept; - SHTransform (const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept; + SHTransform () noexcept; + SHTransform (const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept; + SHTransform (const SHVec3& pos, const SHQuaternion& quat, const SHVec3& scl) noexcept; /*---------------------------------------------------------------------------------*/ /* Operator Overloads */ @@ -63,7 +64,6 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ const SHMatrix& ComputeTRS(); - }; } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp index a8b75497..306cde67 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp @@ -42,16 +42,12 @@ namespace SHADE const SHVec3& SHTransformComponent::GetLocalRotation() const noexcept { - return local.rotation; + return localRotation; } - SHVec3 SHTransformComponent::GetLocalRotationDeg() const noexcept + const SHQuaternion& SHTransformComponent::GetLocalOrientation() const noexcept { - SHVec3 rot = local.rotation; - rot.x = SHMath::RadiansToDegrees(rot.x); - rot.y = SHMath::RadiansToDegrees(rot.y); - rot.z = SHMath::RadiansToDegrees(rot.z); - return rot; + return local.orientation; } const SHVec3& SHTransformComponent::GetLocalScale() const noexcept @@ -66,16 +62,12 @@ namespace SHADE const SHVec3& SHTransformComponent::GetWorldRotation() const noexcept { - return world.rotation; + return worldRotation; } - SHVec3 SHTransformComponent::GetWorldRotationDeg() const noexcept + const SHQuaternion& SHTransformComponent::GetWorldOrientation() const noexcept { - SHVec3 rot = world.rotation; - rot.x = SHMath::RadiansToDegrees(rot.x); - rot.y = SHMath::RadiansToDegrees(rot.y); - rot.z = SHMath::RadiansToDegrees(rot.z); - return rot; + return world.orientation; } const SHVec3& SHTransformComponent::GetWorldScale() const noexcept @@ -111,32 +103,21 @@ namespace SHADE void SHTransformComponent::SetLocalRotation(const SHVec3& newLocalRotation) noexcept { dirty = true; - local.rotation = newLocalRotation; - } - - void SHTransformComponent::SetLocalRotationDeg(SHVec3 newLocalRotationDeg) noexcept - { - dirty = true; - - local.rotation.x = SHMath::DegreesToRadians(newLocalRotationDeg.x); - local.rotation.y = SHMath::DegreesToRadians(newLocalRotationDeg.y); - local.rotation.z = SHMath::DegreesToRadians(newLocalRotationDeg.z); + localRotation = newLocalRotation; } void SHTransformComponent::SetLocalRotation(float pitch, float yaw, float roll) noexcept { dirty = true; - local.rotation.x = pitch; - local.rotation.y = yaw; - local.rotation.z = roll; + localRotation.x = pitch; + localRotation.y = yaw; + localRotation.z = roll; } - void SHTransformComponent::SetLocalRotationDeg(float pitch, float yaw, float roll) noexcept + void SHTransformComponent::SetLocalOrientation(const SHQuaternion& newLocalOrientation) noexcept { - local.rotation.x = SHMath::DegreesToRadians(pitch); - local.rotation.y = SHMath::DegreesToRadians(yaw); - local.rotation.z = SHMath::DegreesToRadians(roll); + } void SHTransformComponent::SetLocalScale(const SHVec3& newLocalScale) noexcept @@ -157,41 +138,24 @@ namespace SHADE { dirty = true; - world.rotation = newWorldRotation; + worldRotation = newWorldRotation; updateQueue.push({ UpdateCommandType::WORLD_ROTATION, newWorldRotation }); } - void SHTransformComponent::SetWorldRotationDeg(const SHVec3& newWorldRotation) noexcept - { - dirty = true; - - world.rotation.x = SHMath::DegreesToRadians(newWorldRotation.x); - world.rotation.y = SHMath::DegreesToRadians(newWorldRotation.y); - world.rotation.z = SHMath::DegreesToRadians(newWorldRotation.z); - - updateQueue.push({ UpdateCommandType::WORLD_ROTATION, world.rotation }); - } - void SHTransformComponent::SetWorldRotation(float pitch, float yaw, float roll) noexcept { dirty = true; - world.rotation.x = pitch; - world.rotation.y = yaw; - world.rotation.z = roll; + worldRotation.x = pitch; + worldRotation.y = yaw; + worldRotation.z = roll; updateQueue.push({ UpdateCommandType::WORLD_ROTATION, SHVec3{ pitch, yaw, roll} }); } - void SHTransformComponent::SetWorldRotationDeg(float pitch, float yaw, float roll) noexcept + void SHTransformComponent::SetWorldOrientation(const SHQuaternion& newWorldOrientation) noexcept { - dirty = true; - - world.rotation.x = SHMath::DegreesToRadians(pitch); - world.rotation.y = SHMath::DegreesToRadians(yaw); - world.rotation.z = SHMath::DegreesToRadians(roll); - - updateQueue.push({ UpdateCommandType::WORLD_ROTATION, world.rotation }); + } void SHTransformComponent::SetWorldScale(const SHVec3& newWorldScale) noexcept @@ -210,7 +174,7 @@ RTTR_REGISTRATION using namespace rttr; registration::class_("Transform Component") - .property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition ) - .property("Rotate" , &SHTransformComponent::GetLocalRotationDeg, select_overload(&SHTransformComponent::SetLocalRotationDeg)) - .property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale ); + .property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition ) + .property("Rotate" , &SHTransformComponent::GetLocalRotation , select_overload(&SHTransformComponent::SetLocalRotation) ) + .property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale ); } \ No newline at end of file diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h index 2a3fa7a0..d1d21bec 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h @@ -60,11 +60,11 @@ namespace SHADE [[nodiscard]] const SHVec3& GetLocalPosition () const noexcept; [[nodiscard]] const SHVec3& GetLocalRotation () const noexcept; - [[nodiscard]] SHVec3 GetLocalRotationDeg () const noexcept; + [[nodiscard]] const SHQuaternion& GetLocalOrientation () const noexcept; [[nodiscard]] const SHVec3& GetLocalScale () const noexcept; [[nodiscard]] const SHVec3& GetWorldPosition () const noexcept; [[nodiscard]] const SHVec3& GetWorldRotation () const noexcept; - [[nodiscard]] SHVec3 GetWorldRotationDeg () const noexcept; + [[nodiscard]] const SHQuaternion& GetWorldOrientation () const noexcept; [[nodiscard]] const SHVec3& GetWorldScale () const noexcept; [[nodiscard]] const SHMatrix& GetLocalToWorld () const noexcept; @@ -76,28 +76,30 @@ namespace SHADE /* Setter Functions */ /*---------------------------------------------------------------------------------*/ - void SetLocalPosition (const SHVec3& newLocalPosition) noexcept; - void SetLocalRotation (const SHVec3& newLocalRotation) noexcept; - void SetLocalRotationDeg (SHVec3 newLocalRotationDeg) noexcept; - void SetLocalRotation (float pitch, float yaw, float roll) noexcept; - void SetLocalRotationDeg (float pitch, float yaw, float roll) noexcept; - void SetLocalScale (const SHVec3& newLocalScale) noexcept; - void SetWorldPosition (const SHVec3& newWorldPosition) noexcept; - void SetWorldRotation (const SHVec3& newWorldRotation) noexcept; - void SetWorldRotationDeg (const SHVec3& newWorldRotation) noexcept; - void SetWorldRotation (float pitch, float yaw, float roll) noexcept; - void SetWorldRotationDeg (float pitch, float yaw, float roll) noexcept; - void SetWorldScale (const SHVec3& newWorldScale) noexcept; + void SetLocalPosition (const SHVec3& newLocalPosition) noexcept; + void SetLocalRotation (const SHVec3& newLocalRotation) noexcept; + void SetLocalRotation (float pitch, float yaw, float roll) noexcept; + void SetLocalOrientation (const SHQuaternion& newLocalOrientation) noexcept; + void SetLocalScale (const SHVec3& newLocalScale) noexcept; + void SetWorldPosition (const SHVec3& newWorldPosition) noexcept; + void SetWorldRotation (const SHVec3& newWorldRotation) noexcept; + void SetWorldRotation (float pitch, float yaw, float roll) noexcept; + void SetWorldOrientation (const SHQuaternion& newWorldOrientation) noexcept; + void SetWorldScale (const SHVec3& newWorldScale) noexcept; private: /*---------------------------------------------------------------------------------*/ /* Type Definitions */ /*---------------------------------------------------------------------------------*/ + // Differentiate between rotation and orientation for setters + // Setting a quaternion directly is different from using euler angle rotations. + enum class UpdateCommandType { WORLD_POSITION , WORLD_ROTATION + , WORLD_ORIENTATION , WORLD_SCALE }; @@ -120,6 +122,12 @@ namespace SHADE bool dirty; + // We store euler angle rotations separately to interface with transform quaternions. + // Reading quaternions are unreliable. + + SHVec3 localRotation; // Stored in degrees + SHVec3 worldRotation; // Stored in degrees + SHTransform local; // Local TRS holds Local To World Transform SHTransform world; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 4b4f1cce..3244db1b 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -17,6 +17,8 @@ #include "Scene/SHSceneManager.h" #include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHEntityManager.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "Math/SHMathHelpers.h" namespace SHADE { @@ -45,14 +47,16 @@ namespace SHADE { // Get the current scene graph to traverse and update const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); - UpdateEntity(SCENE_GRAPH.GetRoot()); + + // TODO(Diren): Consider how to clear dirty in pause / stop mode and update physics, but do not clear in play mode. + UpdateEntity(SCENE_GRAPH.GetRoot(), false); } - void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double dt) noexcept + void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double) noexcept { // Get the current scene graph to traverse and update const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph(); - UpdateEntityAndClear(SCENE_GRAPH.GetRoot()); + UpdateEntity(SCENE_GRAPH.GetRoot(), true); } void SHTransformSystem::Init() @@ -96,13 +100,13 @@ namespace SHADE tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal); - tf->local.rotation = tf->world.rotation; - tf->local.scale = tf->world.scale; + tf->localRotation = tf->worldRotation; + tf->local.scale = tf->world.scale; if (PARENT_TF != nullptr) { // Compute Local Rotation - tf->local.rotation -= PARENT_TF->GetLocalRotation(); + tf->localRotation -= PARENT_TF->GetLocalRotation(); // Compute Local Scale tf->local.scale /= PARENT_TF->GetLocalScale(); @@ -143,13 +147,13 @@ namespace SHADE childTransform->local.position = SHVec3::Transform(childTransform->world.position, worldToLocal); - childTransform->local.rotation = childTransform->world.rotation; - childTransform->local.scale = childTransform->world.scale; + childTransform->localRotation = childTransform->worldRotation; + childTransform->local.scale = childTransform->world.scale; if (parent) { // Compute Local Rotation - childTransform->local.rotation -= parent->GetLocalRotation(); + childTransform->localRotation -= parent->GetLocalRotation(); // Compute Local Scale childTransform->local.scale /= parent->GetLocalScale(); @@ -158,12 +162,10 @@ namespace SHADE childTransform->local.trs = localToWorld; } } - - } } - void SHTransformSystem::UpdateEntity(const SHSceneNode* node) + void SHTransformSystem::UpdateEntity(const SHSceneNode* node, bool clearDirtyFlag) { const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s(node->GetEntityID()); const bool HAS_PARENT_CHANGED = NODE_TRANSFORM && NODE_TRANSFORM->dirty; @@ -185,37 +187,10 @@ namespace SHADE } } - UpdateEntity(child); - } - } - - - void SHTransformSystem::UpdateEntityAndClear(const SHSceneNode* node) - { - const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s(node->GetEntityID()); - const bool HAS_PARENT_CHANGED = NODE_TRANSFORM && NODE_TRANSFORM->dirty; - - for (const auto* child : node->GetChildren()) - { - auto* childTransform = SHComponentManager::GetComponent_s(child->GetEntityID()); - if (childTransform) - { - // Only update if node in hierarchy and component are both active - const bool IS_NODE_ACTIVE = child->IsActive(); - if (IS_NODE_ACTIVE && childTransform->isActive) - { - if (childTransform->dirty || HAS_PARENT_CHANGED) - { - UpdateTransform(*childTransform, NODE_TRANSFORM); - childTransform->dirty = true; - } - } - } - - UpdateEntityAndClear(child); + UpdateEntity(child, clearDirtyFlag); // Clear dirty flag after all children are updated - if (childTransform) + if (childTransform && clearDirtyFlag) childTransform->dirty = false; } } @@ -244,12 +219,17 @@ namespace SHADE } case SHTransformComponent::UpdateCommandType::WORLD_ROTATION: { - tf.local.rotation = tf.world.rotation; + tf.localRotation = tf.worldRotation; if (parent) - tf.local.rotation -= parent->GetLocalRotation(); + tf.localRotation -= parent->GetLocalRotation(); break; } + case SHTransformComponent::UpdateCommandType::WORLD_ORIENTATION: + { + // TODO(Diren): Test using scripts by concat quaternions? + break; + } case SHTransformComponent::UpdateCommandType::WORLD_SCALE: { tf.local.scale = tf.world.scale; @@ -268,7 +248,14 @@ namespace SHADE tf.local.trs = localToWorld; tf.world.position = SHVec3::Transform(tf.local.position, localToWorld); - tf.world.rotation = tf.local.rotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero); + + tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero); + + // TODO(Diren): Wrap rotations between -360 and 360 + + tf.world.orientation = SHQuaternion::FromEuler(tf.worldRotation); + tf.local.orientation = SHQuaternion::FromEuler(tf.localRotation); + tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One); tf.world.ComputeTRS(); diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h index 256c1561..e63969ce 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.h @@ -114,8 +114,7 @@ namespace SHADE SHEventHandle ChangeParent (SHEventPtr changeParentEvent); static void UpdateChildrenLocalTransforms (SHSceneNode* node); - static void UpdateEntity (const SHSceneNode* node); - static void UpdateEntityAndClear (const SHSceneNode* node); + static void UpdateEntity (const SHSceneNode* node, bool clearDirtyFlag); static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr); }; diff --git a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp index 36f7c57e..f9b476ef 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsObject.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsObject.cpp @@ -140,12 +140,12 @@ namespace SHADE isRigidBody = true; rb->position = tf->GetWorldPosition(); - rb->orientation = tf->GetWorldRotation(); + rb->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation()); if (hasColliders) { c->position = tf->GetWorldPosition(); - c->orientation = tf->GetWorldRotation(); + c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation()); // Get array of colliders and add them back into the rigidbody for (auto& collider : c->colliders | std::views::keys) AddCollider(&collider); @@ -160,7 +160,7 @@ namespace SHADE hasColliders = true; c->position = tf->GetWorldPosition(); - c->orientation = tf->GetWorldRotation(); + c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation()); for (auto& collider : c->colliders | std::views::keys) AddCollider(&collider); From 33a6d3798c38ce0de2dcfe2aff19c94c8a39452f Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sun, 23 Oct 2022 16:55:01 +0800 Subject: [PATCH 12/28] Added orientation interface and fixed compatibility between physics and transform --- SHADE_Application/src/Scenes/SBTestScene.cpp | 2 +- SHADE_Engine/src/Math/SHQuaternion.cpp | 4 ++ SHADE_Engine/src/Math/SHQuaternion.h | 1 + .../Math/Transform/SHTransformComponent.cpp | 14 +++- .../src/Math/Transform/SHTransformComponent.h | 6 +- .../src/Math/Transform/SHTransformSystem.cpp | 68 +++++++++++++++---- SHADE_Engine/src/Math/Vector/SHVec4.cpp | 9 +++ SHADE_Engine/src/Math/Vector/SHVec4.h | 14 ++-- SHADE_Engine/src/Physics/SHPhysicsSystem.cpp | 6 +- 9 files changed, 99 insertions(+), 25 deletions(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index 23259ee4..966a00a5 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -101,7 +101,7 @@ namespace Sandbox //Set initial positions transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) }); //transform.SetWorldPosition({-1.0f, -1.0f, -1.0f}); - transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber()); + transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f)); transform.SetWorldScale(TEST_OBJ_SCALE); //if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN) diff --git a/SHADE_Engine/src/Math/SHQuaternion.cpp b/SHADE_Engine/src/Math/SHQuaternion.cpp index 924ac67a..3878cea1 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.cpp +++ b/SHADE_Engine/src/Math/SHQuaternion.cpp @@ -36,6 +36,10 @@ namespace SHADE : XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) {} + SHQuaternion::SHQuaternion(const SHVec4& vec4) noexcept + : XMFLOAT4( vec4.x, vec4.y, vec4.z, vec4.w ) + {} + SHQuaternion::SHQuaternion(float _x, float _y, float _z, float _w) noexcept : XMFLOAT4( _x, _y, _z, _w ) {} diff --git a/SHADE_Engine/src/Math/SHQuaternion.h b/SHADE_Engine/src/Math/SHQuaternion.h index f3ce3d61..cc1b5ff4 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.h +++ b/SHADE_Engine/src/Math/SHQuaternion.h @@ -49,6 +49,7 @@ namespace SHADE SHQuaternion (SHQuaternion&& rhs) = default; SHQuaternion () noexcept; + SHQuaternion (const SHVec4& vec4) noexcept; SHQuaternion (float x, float y, float z, float w) noexcept; SHQuaternion (float yaw, float pitch, float roll) noexcept; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp index 306cde67..e56cbc8d 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.cpp @@ -103,7 +103,9 @@ namespace SHADE void SHTransformComponent::SetLocalRotation(const SHVec3& newLocalRotation) noexcept { dirty = true; + localRotation = newLocalRotation; + updateQueue.push({ UpdateCommandType::LOCAL_ROTATION, newLocalRotation }); } void SHTransformComponent::SetLocalRotation(float pitch, float yaw, float roll) noexcept @@ -113,11 +115,16 @@ namespace SHADE localRotation.x = pitch; localRotation.y = yaw; localRotation.z = roll; + + updateQueue.push({ UpdateCommandType::LOCAL_ROTATION, SHVec3{pitch, yaw, roll} }); } void SHTransformComponent::SetLocalOrientation(const SHQuaternion& newLocalOrientation) noexcept { - + dirty = true; + + local.orientation = newLocalOrientation; + updateQueue.push({ UpdateCommandType::LOCAL_ORIENTATION, newLocalOrientation }); } void SHTransformComponent::SetLocalScale(const SHVec3& newLocalScale) noexcept @@ -155,7 +162,10 @@ namespace SHADE void SHTransformComponent::SetWorldOrientation(const SHQuaternion& newWorldOrientation) noexcept { - + dirty = true; + + world.orientation = newWorldOrientation; + updateQueue.push({ UpdateCommandType::WORLD_ORIENTATION, newWorldOrientation }); } void SHTransformComponent::SetWorldScale(const SHVec3& newWorldScale) noexcept diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h index d1d21bec..ce8bb6fe 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h @@ -97,7 +97,9 @@ namespace SHADE enum class UpdateCommandType { - WORLD_POSITION + LOCAL_ROTATION + , LOCAL_ORIENTATION + , WORLD_POSITION , WORLD_ROTATION , WORLD_ORIENTATION , WORLD_SCALE @@ -111,7 +113,7 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ UpdateCommandType type; - SHVec3 data; + SHVec4 data; }; using UpdateQueue = std::queue; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 3244db1b..8bd01fb4 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -200,6 +200,8 @@ namespace SHADE SHMatrix localToWorld = SHMatrix::Identity; SHMatrix worldToLocal = SHMatrix::Identity; + bool convertRotation = true; + if (parent) { localToWorld = parent->GetTRS(); @@ -212,27 +214,44 @@ namespace SHADE switch (UPDATE_COMMAND.type) { + case SHTransformComponent::UpdateCommandType::LOCAL_ROTATION: + { + convertRotation = true; + break; + } + case SHTransformComponent::UpdateCommandType::LOCAL_ORIENTATION: + { + convertRotation = false; + break; + } case SHTransformComponent::UpdateCommandType::WORLD_POSITION: { - tf.local.position = SHVec3::Transform(UPDATE_COMMAND.data, worldToLocal); + tf.local.position = SHVec3::Transform(UPDATE_COMMAND.data.ToVec3(), worldToLocal); break; } case SHTransformComponent::UpdateCommandType::WORLD_ROTATION: { - tf.localRotation = tf.worldRotation; + tf.localRotation = UPDATE_COMMAND.data.ToVec3(); if (parent) tf.localRotation -= parent->GetLocalRotation(); + convertRotation = true; + break; } case SHTransformComponent::UpdateCommandType::WORLD_ORIENTATION: { - // TODO(Diren): Test using scripts by concat quaternions? + tf.local.orientation = UPDATE_COMMAND.data; + if (parent) + tf.local.orientation /= parent->GetLocalOrientation(); + + convertRotation = false; + break; } case SHTransformComponent::UpdateCommandType::WORLD_SCALE: { - tf.local.scale = tf.world.scale; + tf.local.scale = UPDATE_COMMAND.data.ToVec3(); if (parent) tf.local.scale /= parent->GetLocalScale(); @@ -247,17 +266,42 @@ namespace SHADE tf.local.trs = localToWorld; + // Compute world transforms tf.world.position = SHVec3::Transform(tf.local.position, localToWorld); - - tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero); - - // TODO(Diren): Wrap rotations between -360 and 360 - - tf.world.orientation = SHQuaternion::FromEuler(tf.worldRotation); - tf.local.orientation = SHQuaternion::FromEuler(tf.localRotation); - tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One); + SHVec3 worldRotRad, localRotRad; + + if (convertRotation) + { + tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero); + + // Set the orientation + // Wrap rotations between -360 and 360 and convert to radians + for (size_t i = 0; i < SHVec3::SIZE; ++i) + { + worldRotRad[i] = SHMath::DegreesToRadians(SHMath::Wrap(tf.worldRotation[i], -360.0f, 360.0f)); + localRotRad[i] = SHMath::DegreesToRadians(SHMath::Wrap(tf.localRotation[i], -360.0f, 360.0f)); + } + + tf.world.orientation = SHQuaternion::FromEuler(worldRotRad); + tf.local.orientation = SHQuaternion::FromEuler(localRotRad); + } + else + { + tf.world.orientation = (parent ? parent->GetLocalOrientation() : SHQuaternion::Identity) * tf.local.orientation; + + // Set the euler angle rotations + worldRotRad = tf.world.orientation.ToEuler(); + localRotRad = tf.local.orientation.ToEuler(); + + for (size_t i = 0; i < SHVec3::SIZE; ++i) + { + tf.worldRotation[i] = SHMath::RadiansToDegrees(worldRotRad[i]); + tf.localRotation[i] = SHMath::RadiansToDegrees(localRotRad[i]); + } + } + tf.world.ComputeTRS(); } diff --git a/SHADE_Engine/src/Math/Vector/SHVec4.cpp b/SHADE_Engine/src/Math/Vector/SHVec4.cpp index bcf2ef97..9857818a 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec4.cpp +++ b/SHADE_Engine/src/Math/Vector/SHVec4.cpp @@ -38,6 +38,10 @@ namespace SHADE : XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f ) {} + SHVec4::SHVec4(const SHVec3& vec3) noexcept + : XMFLOAT4( vec3.x, vec3.y, vec3.z, 1.0f ) + {} + SHVec4::SHVec4(const XMFLOAT4& xmfloat4) noexcept : XMFLOAT4( xmfloat4.x, xmfloat4.y, xmfloat4.z, xmfloat4.w ) {} @@ -271,6 +275,11 @@ namespace SHADE return result; } + SHVec3 SHVec4::ToVec3() const noexcept + { + return SHVec3{ x, y, z }; + } + /*-----------------------------------------------------------------------------------*/ /* Static Function Member Definitions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/Vector/SHVec4.h b/SHADE_Engine/src/Math/Vector/SHVec4.h index 911a714e..ce341bed 100644 --- a/SHADE_Engine/src/Math/Vector/SHVec4.h +++ b/SHADE_Engine/src/Math/Vector/SHVec4.h @@ -16,6 +16,7 @@ // Project Headers #include "SH_API.h" +#include "SHVec3.h" namespace SHADE { @@ -53,6 +54,7 @@ namespace SHADE ~SHVec4 () = default; SHVec4 () noexcept; + SHVec4 (const SHVec3& vec3) noexcept; SHVec4 (const XMFLOAT4& xmfloat4) noexcept; SHVec4 (float x, float y, float z, float w) noexcept; @@ -102,16 +104,18 @@ namespace SHADE [[nodiscard]] float Dot3D (const SHVec4& rhs) const noexcept; [[nodiscard]] SHVec4 Cross3D (const SHVec4& rhs) const noexcept; [[nodiscard]] SHVec4 Cross (const SHVec4& v1, const SHVec4& v2) const noexcept; + + [[nodiscard]] SHVec3 ToVec3 () const noexcept; /*---------------------------------------------------------------------------------*/ /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static SHVec4 Normalise (const SHVec4& v) noexcept; - [[nodiscard]] static SHVec4 Normalise3D (const SHVec4& v) noexcept; - [[nodiscard]] static SHVec4 Abs (const SHVec4& v) noexcept; - [[nodiscard]] static SHVec4 Min (const std::initializer_list& vs) noexcept; - [[nodiscard]] static SHVec4 Max (const std::initializer_list& vs) noexcept; + [[nodiscard]] static SHVec4 Normalise (const SHVec4& v) noexcept; + [[nodiscard]] static SHVec4 Normalise3D (const SHVec4& v) noexcept; + [[nodiscard]] static SHVec4 Abs (const SHVec4& v) noexcept; + [[nodiscard]] static SHVec4 Min (const std::initializer_list& vs) noexcept; + [[nodiscard]] static SHVec4 Max (const std::initializer_list& vs) noexcept; [[nodiscard]] static SHVec4 Clamp (const SHVec4& v, const SHVec4& vMin, const SHVec4& vMax) noexcept; [[nodiscard]] static SHVec4 Lerp (const SHVec4& a, const SHVec4& b, float t) noexcept; [[nodiscard]] static SHVec4 ClampedLerp (const SHVec4& a, const SHVec4& b, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept; diff --git a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp index 7dc6c44e..a1994ad2 100644 --- a/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp +++ b/SHADE_Engine/src/Physics/SHPhysicsSystem.cpp @@ -16,6 +16,7 @@ // Project Headers #include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHEntityManager.h" +#include "Math/SHMathHelpers.h" #include "Scene/SHSceneManager.h" #include "Math/Transform/SHTransformComponent.h" @@ -315,7 +316,7 @@ namespace SHADE if (TF->HasChanged()) { physicsObject.SetPosition(TF->GetWorldPosition()); - physicsObject.SetRotation(TF->GetWorldRotation()); + physicsObject.SetOrientation(TF->GetWorldOrientation()); } } } @@ -492,8 +493,7 @@ namespace SHADE // Convert RP3D Transform to SHADE auto* tfComponent = SHComponentManager::GetComponent(entityID); tfComponent->SetWorldPosition(rp3dPos); - tfComponent->SetWorldRotation(SHQuaternion{ rp3dRot }.ToEuler()); - + tfComponent->SetWorldOrientation(SHQuaternion{ rp3dRot }); // Cache transforms physicsObject.prevTransform = CURRENT_TF; From a83d1f8f04ae82332d9fd065b34eec911e2e4ff3 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Sun, 23 Oct 2022 16:55:57 +0800 Subject: [PATCH 13/28] Removed line that loaded all assets Separated template function in asset manager into hpp file Fixed bug in checking map contains --- SHADE_Engine/src/Assets/SHAssetManager.cpp | 17 +++++------- SHADE_Engine/src/Assets/SHAssetManager.h | 22 +++------------- SHADE_Engine/src/Assets/SHAssetManager.hpp | 26 +++++++++++++++++++ .../src/Resource/SHResourceManager.hpp | 2 +- 4 files changed, 37 insertions(+), 30 deletions(-) create mode 100644 SHADE_Engine/src/Assets/SHAssetManager.hpp diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index bcae992e..3032ba51 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -56,18 +56,15 @@ namespace SHADE ****************************************************************************/ void SHAssetManager::Unload() noexcept { - for (auto const& asset : assetCollection) - { - SHAssetMetaHandler::WriteMetaData(asset); - } + } - void SHAssetManager::Unload(AssetID assetId) noexcept - { - // TODO - } + void SHAssetManager::Unload(AssetID assetId) noexcept + { + // TODO + } - AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept + AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept { if (!IsRecognised(path.extension().string().c_str())) { @@ -256,7 +253,7 @@ namespace SHADE { InitLoaders(); BuildAssetCollection(); - LoadAllData(); + //LoadAllData(); } /**************************************************************************** diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index 4c1ded71..9ee7ab92 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -76,25 +76,7 @@ namespace SHADE // -------------------------------------------------------------------------/ template - static std::enable_if_t, T const * const> GetData(AssetID id) noexcept - { - if (assetData.contains(id)) - { - for (auto const& asset : assetCollection) - { - if (asset.id == id) - { - assetData.emplace(id, LoadData(asset)); - return dynamic_cast(assetData[id]); - } - } - - SHLOG_ERROR("Asset ID provided does not exist: {}", id); - return nullptr; - } - - return dynamic_cast(assetData[id]); - } + static std::enable_if_t, T const* const> GetData(AssetID id) noexcept; private: /**************************************************************************** * \brief Load resource data into memory @@ -121,3 +103,5 @@ namespace SHADE static std::unordered_map assetData; }; } + +#include "SHAssetManager.hpp" diff --git a/SHADE_Engine/src/Assets/SHAssetManager.hpp b/SHADE_Engine/src/Assets/SHAssetManager.hpp new file mode 100644 index 00000000..6c420778 --- /dev/null +++ b/SHADE_Engine/src/Assets/SHAssetManager.hpp @@ -0,0 +1,26 @@ + +#include "SHAssetManager.h" + +namespace SHADE +{ + template + std::enable_if_t, T const* const> SHAssetManager::GetData(AssetID id) noexcept + { + if (!assetData.contains(id)) + { + for (auto const& asset : assetCollection) + { + if (asset.id == id) + { + assetData.emplace(id, LoadData(asset)); + return dynamic_cast(assetData[id]); + } + } + + SHLOG_ERROR("Asset ID provided does not exist: {}", id); + return nullptr; + } + + return dynamic_cast(assetData[id]); + } +} diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp index fb0dcc6a..cff4e84b 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.hpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -134,7 +134,7 @@ namespace SHADE /* Query Functions */ /*-----------------------------------------------------------------------------------*/ template - static std::optional SHResourceManager::GetAssetID(Handle handle) + std::optional SHResourceManager::GetAssetID(Handle handle) { const Handle GENERIC_HANDLE = Handle(handle); auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap(); From f9a28c81d4ab01f182114524119b8ef290627ad8 Mon Sep 17 00:00:00 2001 From: Xiao Qi Date: Sun, 23 Oct 2022 17:18:46 +0800 Subject: [PATCH 14/28] Fixed vulkan breaking error --- SHADE_Application/src/Scenes/SBTestScene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SHADE_Application/src/Scenes/SBTestScene.cpp b/SHADE_Application/src/Scenes/SBTestScene.cpp index b414ecaf..0c06a092 100644 --- a/SHADE_Application/src/Scenes/SBTestScene.cpp +++ b/SHADE_Application/src/Scenes/SBTestScene.cpp @@ -52,7 +52,7 @@ namespace Sandbox if (asset.name == "Cube.012") handles.emplace_back(SHResourceManager::LoadOrGet(asset.id)); break; - case AssetType::TEXTURE: + case AssetType::IMAGE: texHandles.emplace_back(SHResourceManager::LoadOrGet(asset.id)); break; } From e15f7696e62ad51896e58fde0bda32df87339d8a Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sun, 23 Oct 2022 18:22:58 +0800 Subject: [PATCH 15/28] Rotations are stored as radians to reduce the number of conversions --- .../src/Math/Transform/SHTransformComponent.h | 4 ++-- .../src/Math/Transform/SHTransformSystem.cpp | 17 ++++++----------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h index ce8bb6fe..2fe67bdd 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformComponent.h +++ b/SHADE_Engine/src/Math/Transform/SHTransformComponent.h @@ -127,8 +127,8 @@ namespace SHADE // We store euler angle rotations separately to interface with transform quaternions. // Reading quaternions are unreliable. - SHVec3 localRotation; // Stored in degrees - SHVec3 worldRotation; // Stored in degrees + SHVec3 localRotation; // Stored in Radians + SHVec3 worldRotation; // Stored in Radians SHTransform local; // Local TRS holds Local To World Transform SHTransform world; diff --git a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp index 8bd01fb4..5a540cd4 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransformSystem.cpp @@ -270,7 +270,7 @@ namespace SHADE tf.world.position = SHVec3::Transform(tf.local.position, localToWorld); tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One); - SHVec3 worldRotRad, localRotRad; + if (convertRotation) { @@ -278,10 +278,11 @@ namespace SHADE // Set the orientation // Wrap rotations between -360 and 360 and convert to radians + SHVec3 worldRotRad, localRotRad; for (size_t i = 0; i < SHVec3::SIZE; ++i) { - worldRotRad[i] = SHMath::DegreesToRadians(SHMath::Wrap(tf.worldRotation[i], -360.0f, 360.0f)); - localRotRad[i] = SHMath::DegreesToRadians(SHMath::Wrap(tf.localRotation[i], -360.0f, 360.0f)); + worldRotRad[i] = SHMath::Wrap(tf.worldRotation[i], -SHMath::TWO_PI, SHMath::TWO_PI); + localRotRad[i] = SHMath::Wrap(tf.localRotation[i], -SHMath::TWO_PI, SHMath::TWO_PI); } tf.world.orientation = SHQuaternion::FromEuler(worldRotRad); @@ -292,14 +293,8 @@ namespace SHADE tf.world.orientation = (parent ? parent->GetLocalOrientation() : SHQuaternion::Identity) * tf.local.orientation; // Set the euler angle rotations - worldRotRad = tf.world.orientation.ToEuler(); - localRotRad = tf.local.orientation.ToEuler(); - - for (size_t i = 0; i < SHVec3::SIZE; ++i) - { - tf.worldRotation[i] = SHMath::RadiansToDegrees(worldRotRad[i]); - tf.localRotation[i] = SHMath::RadiansToDegrees(localRotRad[i]); - } + tf.worldRotation = tf.world.orientation.ToEuler(); + tf.localRotation = tf.local.orientation.ToEuler(); } tf.world.ComputeTRS(); From 57f9898e07667e00fede342e79fc4bee42551693 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Sun, 23 Oct 2022 20:03:18 +0800 Subject: [PATCH 16/28] Finished quaternion implementation --- SHADE_Engine/src/Math/SHQuaternion.cpp | 125 +++++++++++++++++++++---- SHADE_Engine/src/Math/SHQuaternion.h | 40 ++++---- SHADE_Managed/Quaternion.hxx | 17 ++++ SHADE_Managed/src/Math/Vector3.hxx | 1 + 4 files changed, 148 insertions(+), 35 deletions(-) create mode 100644 SHADE_Managed/Quaternion.hxx diff --git a/SHADE_Engine/src/Math/SHQuaternion.cpp b/SHADE_Engine/src/Math/SHQuaternion.cpp index 3878cea1..3564916a 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.cpp +++ b/SHADE_Engine/src/Math/SHQuaternion.cpp @@ -211,15 +211,6 @@ namespace SHADE return XMVectorGetX(XMQuaternionDot(*this, rhs)); } - SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion&, float) const noexcept - { - SHQuaternion result; - - // TODO (Diren) - - return result; - } - SHVec3 SHQuaternion::ToEuler() const noexcept { const float XX = x * x; @@ -317,19 +308,32 @@ namespace SHADE } - float SHQuaternion::Angle(const SHQuaternion&, const SHQuaternion&) noexcept + float SHQuaternion::Angle(const SHQuaternion& q1, const SHQuaternion& q2) noexcept { - // TODO (Diren) + XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(q1), q2); - return 0.0f; + const float RS = XMVectorGetW(R); + R = XMVector3Length(R); + return 2.0f * atan2f(XMVectorGetX(R), RS); } - SHQuaternion SHQuaternion::Lerp(const SHQuaternion&, const SHQuaternion&, float) noexcept + SHQuaternion SHQuaternion::Lerp(const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept { SHQuaternion result; - // TODO (Diren) + XMVECTOR R = XMVectorZero(); + if (XMVector4GreaterOrEqual(XMVector4Dot(q1, q2), R)) + { + R = XMVectorLerp(q1, q2, t); + } + else + { + const XMVECTOR X0 = XMVectorMultiply(q1, XMVectorReplicate(1.f - t)); + const XMVECTOR X1 = XMVectorMultiply(q2, XMVectorReplicate(t)); + R = XMVectorSubtract(X0, X1); + } + XMStoreFloat4(&result, XMQuaternionNormalize(R)); return result; } @@ -341,13 +345,102 @@ namespace SHADE return result; } - SHQuaternion SHQuaternion::Rotate(const SHVec3& , const SHVec3&) noexcept + SHQuaternion SHQuaternion::ClampedLerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept { + return Lerp(q1, q2, std::clamp(t, tMin, tMax)); + } + + + SHQuaternion SHQuaternion::ClampedSlerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept + { + return Slerp(q1, q2, std::clamp(t, tMin, tMax)); + } + + SHQuaternion SHQuaternion::FromToRotation(const SHVec3& from, const SHVec3& to) noexcept + { + // Melax, "The Shortest Arc Quaternion", Game Programming Gems + SHQuaternion result; - // TODO (Diren) + const XMVECTOR F = XMVector3Normalize(from); + const XMVECTOR T = XMVector3Normalize(to); + + const float dot = XMVectorGetX(XMVector3Dot(F, T)); + if (dot >= 1.f) + { + result = Identity; + } + else if (dot <= -1.f) + { + XMVECTOR axis = XMVector3Cross(F, SHVec3::Right); + if (XMVector3NearEqual(XMVector3LengthSq(axis), g_XMZero, g_XMEpsilon)) + { + axis = XMVector3Cross(F, SHVec3::Up); + } + + const XMVECTOR Q = XMQuaternionRotationAxis(axis, XM_PI); + XMStoreFloat4(&result, Q); + } + else + { + const XMVECTOR C = XMVector3Cross(F, T); + XMStoreFloat4(&result, C); + + const float s = sqrtf((1.f + dot) * 2.f); + result.x /= s; + result.y /= s; + result.z /= s; + result.w = s * 0.5f; + } return result; } + SHQuaternion SHQuaternion::LookRotation(const SHVec3& forward, const SHVec3& up) noexcept + { + SHQuaternion result; + + const SHQuaternion Q1 = FromToRotation(SHVec3::Forward, forward); + + const XMVECTOR C = XMVector3Cross(forward, up); + if (XMVector3NearEqual(XMVector3LengthSq(C), g_XMZero, g_XMEpsilon)) + { + // forward and up are co-linear + return Q1; + } + + SHVec3 qU; + XMStoreFloat3(&qU, XMQuaternionMultiply(Q1, SHVec3::Up)); + + const SHQuaternion Q2 = FromToRotation(qU, up); + + XMStoreFloat4(&result, XMQuaternionMultiply(Q2, Q1)); + + return result; + } + + SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept + { + SHQuaternion result; + + // We can use the conjugate here instead of inverse assuming q1 & q2 are normalized. + const XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(from), to); + + const float RS = XMVectorGetW(R); + const XMVECTOR L = XMVector3Length(R); + const float angle = 2.f * atan2f(XMVectorGetX(L), RS); + if (angle > maxAngleInRad) + { + const XMVECTOR delta = XMQuaternionRotationAxis(R, maxAngleInRad); + const XMVECTOR Q = XMQuaternionMultiply(delta, from); + XMStoreFloat4(&result, Q); + } + else + { + // Don't overshoot. + result = to; + } + return result; + } + } // namespace SHADE \ No newline at end of file diff --git a/SHADE_Engine/src/Math/SHQuaternion.h b/SHADE_Engine/src/Math/SHQuaternion.h index cc1b5ff4..fa5b5d36 100644 --- a/SHADE_Engine/src/Math/SHQuaternion.h +++ b/SHADE_Engine/src/Math/SHQuaternion.h @@ -51,7 +51,6 @@ namespace SHADE SHQuaternion () noexcept; SHQuaternion (const SHVec4& vec4) noexcept; SHQuaternion (float x, float y, float z, float w) noexcept; - SHQuaternion (float yaw, float pitch, float roll) noexcept; // Conversion from other math types @@ -98,34 +97,37 @@ namespace SHADE /* Function Members */ /*---------------------------------------------------------------------------------*/ - void Invert () noexcept; + void Invert () noexcept; - [[nodiscard]] float Length () const noexcept; - [[nodiscard]] float LengthSquared () const noexcept; - [[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept; - [[nodiscard]] SHQuaternion RotateTowards (const SHQuaternion& target, float maxAngleInRad) const noexcept; + [[nodiscard]] float Length () const noexcept; + [[nodiscard]] float LengthSquared () const noexcept; + [[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept; - [[nodiscard]] SHVec3 ToEuler () const noexcept; - [[nodiscard]] std::string ToString () const noexcept; + [[nodiscard]] SHVec3 ToEuler () const noexcept; + [[nodiscard]] std::string ToString () const noexcept; /*---------------------------------------------------------------------------------*/ /* Static Function Members */ /*---------------------------------------------------------------------------------*/ - [[nodiscard]] static SHQuaternion FromEuler (const SHVec3& eulerAngles) noexcept; - [[nodiscard]] static SHQuaternion FromPitchYawRoll (float pitch, float yaw, float roll) noexcept; - [[nodiscard]] static SHQuaternion FromAxisAngle (const SHVec3& axis, float angle) noexcept; - [[nodiscard]] static SHQuaternion FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept; + [[nodiscard]] static SHQuaternion FromEuler (const SHVec3& eulerAngles) noexcept; + [[nodiscard]] static SHQuaternion FromPitchYawRoll (float pitch, float yaw, float roll) noexcept; + [[nodiscard]] static SHQuaternion FromAxisAngle (const SHVec3& axis, float angle) noexcept; + [[nodiscard]] static SHQuaternion FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept; - [[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept; - [[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept; - [[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept; - [[nodiscard]] static float Angle (const SHQuaternion& q1, const SHQuaternion& q2) noexcept; + [[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept; + [[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept; + [[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept; + [[nodiscard]] static float Angle (const SHQuaternion& q1, const SHQuaternion& q2) noexcept; - [[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; - [[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; + [[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; + [[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept; + [[nodiscard]] static SHQuaternion ClampedLerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept; + [[nodiscard]] static SHQuaternion ClampedSlerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept; - [[nodiscard]] static SHQuaternion Rotate (const SHVec3& from, const SHVec3& to) noexcept; + [[nodiscard]] static SHQuaternion FromToRotation (const SHVec3& from, const SHVec3& to) noexcept; + [[nodiscard]] static SHQuaternion LookRotation (const SHVec3& forward, const SHVec3& up) noexcept; + [[nodiscard]] static SHQuaternion RotateTowards (const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept; }; SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept; diff --git a/SHADE_Managed/Quaternion.hxx b/SHADE_Managed/Quaternion.hxx new file mode 100644 index 00000000..0b07a34e --- /dev/null +++ b/SHADE_Managed/Quaternion.hxx @@ -0,0 +1,17 @@ +/************************************************************************************//*! +\file Quaternion.hxx +\author Diren D Bharwani, diren.dbharwani, 390002520 +\par email: diren.dbharwani\@digipen.edu +\date Oct 23, 2022 +\brief Contains the definitions of Quaternion struct. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2021 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ + +#pragma once + +// TODO(Diren) diff --git a/SHADE_Managed/src/Math/Vector3.hxx b/SHADE_Managed/src/Math/Vector3.hxx index e6cdc7d4..8b66439c 100644 --- a/SHADE_Managed/src/Math/Vector3.hxx +++ b/SHADE_Managed/src/Math/Vector3.hxx @@ -11,6 +11,7 @@ Copyright (C) 2021 DigiPen Institute of Technology. Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ + #pragma once // Standard Libraries From c34faade8679b7d34735ad47332e445bafc4abb8 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 24 Oct 2022 02:45:47 +0800 Subject: [PATCH 17/28] Converted doubles to floats in SHADE Managed. Added Quaternions. --- SHADE_Managed/Quaternion.hxx | 17 -- SHADE_Managed/src/Math/Math.cxx | 14 +- SHADE_Managed/src/Math/Math.hxx | 24 +-- SHADE_Managed/src/Math/Quaternion.cxx | 170 ++++++++++++++++++ SHADE_Managed/src/Math/Quaternion.hxx | 237 ++++++++++++++++++++++++++ SHADE_Managed/src/Math/Vector2.cxx | 52 +++--- SHADE_Managed/src/Math/Vector2.hxx | 76 ++++----- SHADE_Managed/src/Math/Vector3.cxx | 61 +++---- SHADE_Managed/src/Math/Vector3.hxx | 98 +++++------ SHADE_Managed/src/Utility/Convert.cxx | 19 ++- SHADE_Managed/src/Utility/Convert.hxx | 14 ++ 11 files changed, 596 insertions(+), 186 deletions(-) delete mode 100644 SHADE_Managed/Quaternion.hxx create mode 100644 SHADE_Managed/src/Math/Quaternion.cxx create mode 100644 SHADE_Managed/src/Math/Quaternion.hxx diff --git a/SHADE_Managed/Quaternion.hxx b/SHADE_Managed/Quaternion.hxx deleted file mode 100644 index 0b07a34e..00000000 --- a/SHADE_Managed/Quaternion.hxx +++ /dev/null @@ -1,17 +0,0 @@ -/************************************************************************************//*! -\file Quaternion.hxx -\author Diren D Bharwani, diren.dbharwani, 390002520 -\par email: diren.dbharwani\@digipen.edu -\date Oct 23, 2022 -\brief Contains the definitions of Quaternion struct. - - Note: This file is written in C++17/CLI. - -Copyright (C) 2021 DigiPen Institute of Technology. -Reproduction or disclosure of this file or its contents without the prior written consent -of DigiPen Institute of Technology is prohibited. -*//*************************************************************************************/ - -#pragma once - -// TODO(Diren) diff --git a/SHADE_Managed/src/Math/Math.cxx b/SHADE_Managed/src/Math/Math.cxx index 5ec850a1..fa72e2b6 100644 --- a/SHADE_Managed/src/Math/Math.cxx +++ b/SHADE_Managed/src/Math/Math.cxx @@ -21,7 +21,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Utility Functions */ /*---------------------------------------------------------------------------------*/ - double Math::Wrap(double value, double min, double max) + float Math::Wrap(float value, float min, float max) { while (value < min) { @@ -33,24 +33,24 @@ namespace SHADE } return value; } - double Math::DegreesToRadians(double degrees) + float Math::DegreesToRadians(float degrees) { return degrees * Deg2Rad; } - double Math::RadiansToDegrees(double radians) + float Math::RadiansToDegrees(float radians) { return radians * Rad2Deg; } - double Math::Lerp(double a, double b, double t) + float Math::Lerp(float a, float b, float t) { - return LerpUnclamped(a, b, System::Math::Clamp(t, 0.0, 1.0)); + return LerpUnclamped(a, b, System::Math::Clamp(t, 0.0f, 1.0f)); } - double Math::LerpUnclamped(double a, double b, double t) + float Math::LerpUnclamped(float a, float b, float t) { return a + t * (b - a); } - double Math::InverseLerp(double a, double b, double value) + float Math::InverseLerp(float a, float b, float value) { return (value - a) / (b - a); } diff --git a/SHADE_Managed/src/Math/Math.hxx b/SHADE_Managed/src/Math/Math.hxx index 3ddc5149..1578d97c 100644 --- a/SHADE_Managed/src/Math/Math.hxx +++ b/SHADE_Managed/src/Math/Math.hxx @@ -27,11 +27,11 @@ namespace SHADE /// /// Degrees-to-radians conversion constant /// - static constexpr double Deg2Rad = System::Math::PI / 180.0; + static constexpr float Deg2Rad = System::Math::PI / 180.0f; /// /// Radians-to-degrees conversion constant /// - static constexpr double Rad2Deg = 180.0 / System::Math::PI; + static constexpr float Rad2Deg = 180.0f / System::Math::PI; /// /// Small value used for single precision floating point comparisons. /// @@ -47,28 +47,28 @@ namespace SHADE /// Minimum value to wrap at. /// Maximum value to wrap at. /// Wrapped value. - static double Wrap(double value, double min, double max); + static float Wrap(float value, float min, float max); /// /// Converts an angle from degree representation to radian representation. /// /// Degree-based angle to convert. /// The specified angle in radians. - static double DegreesToRadians(double degrees); + static float DegreesToRadians(float degrees); /// /// Converts an angle from radian representation to degree representation. /// /// Radian-based angle to convert. /// The specified angle in degrees. - static double RadiansToDegrees(double radians); + static float RadiansToDegrees(float radians); /// /// Linearly interpolates between a and b by t. /// The parameter t is clamped to the range [0, 1]. /// /// The start value. /// The end value. - /// The interpolation value between the two double. - /// The interpolated double result between the two double values. - static double Lerp(double a, double b, double t); + /// The interpolation value between the two float. + /// The interpolated float result between the two float values. + static float Lerp(float a, float b, float t); /// /// Linearly interpolates between a and b by t. /// The parameter t is not clamped and a value based on a and b is supported. @@ -77,9 +77,9 @@ namespace SHADE /// /// The start value. /// The end value. - /// The interpolation value between the two double. - /// The interpolated double result between the two double values. - static double LerpUnclamped(double a, double b, double t); + /// The interpolation value between the two float. + /// The interpolated float result between the two float values. + static float LerpUnclamped(float a, float b, float t); /// /// Calculates the linear parameter t that produces the interpolant value within the range [a, b]. /// @@ -87,6 +87,6 @@ namespace SHADE /// End value. /// Value between start and end. /// Percentage of value between start and end. - static double InverseLerp(double a, double b, double value); + static float InverseLerp(float a, float b, float value); }; } diff --git a/SHADE_Managed/src/Math/Quaternion.cxx b/SHADE_Managed/src/Math/Quaternion.cxx new file mode 100644 index 00000000..863241ac --- /dev/null +++ b/SHADE_Managed/src/Math/Quaternion.cxx @@ -0,0 +1,170 @@ +/************************************************************************************//*! +\file Quaternion.cxx +\author Diren D Bharwani, diren.dbharwani, 390002520 +\par email: diren.dbharwani\@digipen.edu +\date Oct 23, 2022 +\brief Contains the definitions of functions in the Quaternion struct. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2021 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ + +// Precompiled Headers +#include "SHpch.h" +// Primary Header +#include "Quaternion.hxx" +// External Dependencies +#include "Math/SHQuaternion.h" +#include "Math/Vector/SHVec4.h" +// Project Headers +#include "Utility/Convert.hxx" +#include "Math.hxx" + +namespace SHADE +{ + /*---------------------------------------------------------------------------------*/ + /* Constructors */ + /*---------------------------------------------------------------------------------*/ + + Quaternion::Quaternion(float _x, float _y, float _z, float _w) + : x { _x } + , y { _y } + , z { _z } + , w { _w } + {} + + /*---------------------------------------------------------------------------------*/ + /* Usage Functions */ + /*---------------------------------------------------------------------------------*/ + + void Quaternion::SetFromToRotation(Vector3 fromDirection, Vector3 toDirection) + { + const SHQuaternion R = SHQuaternion::FromToRotation(Convert::ToNative(fromDirection), Convert::ToNative(toDirection)); + *this = Convert::ToCLI(R); + } + + void Quaternion::SetLookRotation(Vector3 view, Vector3 up) + { + const SHQuaternion R = SHQuaternion::LookRotation(Convert::ToNative(view), Convert::ToNative(up)); + *this = Convert::ToCLI(R); + } + + void Quaternion::ToAngleAxis(float^% angle, Vector3^% axis) + { + const SHVec4 NATIVE_AXIS_ANGLE = Convert::ToNative(*this).GetAxisAngle(); + axis = Convert::ToCLI(NATIVE_AXIS_ANGLE.ToVec3()); + angle = NATIVE_AXIS_ANGLE.w; + } + + System::String^ Quaternion::ToString() + { + return ValueType::ToString(); + } + + /*---------------------------------------------------------------------------------*/ + /* IEquatable */ + /*---------------------------------------------------------------------------------*/ + + bool Quaternion::Equals(Quaternion other) + { + const float DOT = Dot(*this, other); + return fabs(1.0f - DOT) <= Math::Epsilon; + } + + /*---------------------------------------------------------------------------------*/ + /* Object Overrides */ + /*---------------------------------------------------------------------------------*/ + + bool Quaternion::Equals(Object^ o) + { + return ValueType::Equals(o); + } + + int Quaternion::GetHashCode() + { + return ValueType::GetHashCode(); + } + + /*---------------------------------------------------------------------------------*/ + /* Static Functions */ + /*---------------------------------------------------------------------------------*/ + + float Quaternion::Angle(Quaternion a, Quaternion b) + { + return SHQuaternion::Angle(Convert::ToNative(a), Convert::ToNative(b)); + } + + Quaternion Quaternion::AngleAxis(float angle, Vector3 axis) + { + return Convert::ToCLI(SHQuaternion::FromAxisAngle(Convert::ToNative(axis), angle)); + } + + float Quaternion::Dot(Quaternion a, Quaternion b) + { + return (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); + } + + Quaternion Quaternion::Euler(float _x, float _y, float _z) + { + return Convert::ToCLI(SHQuaternion::FromPitchYawRoll(_x, _y, _z)); + } + + Quaternion Quaternion::FromToRotation(Vector3 fromDirection, Vector3 toDirection) + { + return Convert::ToCLI(SHQuaternion::FromToRotation(Convert::ToNative(fromDirection), Convert::ToNative(toDirection))); + } + + Quaternion Quaternion::Inverse(Quaternion rotation) + { + return Convert::ToCLI(SHQuaternion::Inverse(Convert::ToNative(rotation))); + } + + Quaternion Quaternion::Lerp(Quaternion a, Quaternion b, float t) + { + return Convert::ToCLI(SHQuaternion::ClampedLerp(Convert::ToNative(a), Convert::ToNative(b), t)); + } + + Quaternion Quaternion::LerpUnclamped(Quaternion a, Quaternion b, float t) + { + return Convert::ToCLI(SHQuaternion::Lerp(Convert::ToNative(a), Convert::ToNative(b), t)); + } + + Quaternion Quaternion::LookRotation(Vector3 forward, Vector3 upwards) + { + return Convert::ToCLI(SHQuaternion::LookRotation(Convert::ToNative(forward), Convert::ToNative(upwards))); + } + + Quaternion Quaternion::Normalize(Quaternion q) + { + return Convert::ToCLI(SHQuaternion::Normalise(Convert::ToNative(q))); + } + + Quaternion Quaternion::RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta) + { + return Convert::ToCLI(SHQuaternion::RotateTowards(Convert::ToNative(from), Convert::ToNative(to), Math::DegreesToRadians(maxDegreesDelta))); + } + + Quaternion Quaternion::Slerp(Quaternion a, Quaternion b, float t) + { + return Convert::ToCLI(SHQuaternion::ClampedSlerp(Convert::ToNative(a), Convert::ToNative(b), t)); + } + + Quaternion Quaternion::SlerpUnclamped(Quaternion a, Quaternion b, float t) + { + return Convert::ToCLI(SHQuaternion::Slerp(Convert::ToNative(a), Convert::ToNative(b), t)); + } + + + Quaternion Quaternion::operator*(Quaternion lhs, Quaternion rhs) + { + return Convert::ToCLI(Convert::ToNative(lhs) * Convert::ToNative(rhs)); + } + + bool Quaternion::operator==(Quaternion lhs, Quaternion rhs) + { + return lhs.Equals(rhs); + } +} \ No newline at end of file diff --git a/SHADE_Managed/src/Math/Quaternion.hxx b/SHADE_Managed/src/Math/Quaternion.hxx new file mode 100644 index 00000000..783038c9 --- /dev/null +++ b/SHADE_Managed/src/Math/Quaternion.hxx @@ -0,0 +1,237 @@ +/************************************************************************************//*! +\file Quaternion.hxx +\author Diren D Bharwani, diren.dbharwani, 390002520 +\par email: diren.dbharwani\@digipen.edu +\date Oct 23, 2022 +\brief Contains the definitions of Quaternion struct. + + Note: This file is written in C++17/CLI. + +Copyright (C) 2021 DigiPen Institute of Technology. +Reproduction or disclosure of this file or its contents without the prior written consent +of DigiPen Institute of Technology is prohibited. +*//*************************************************************************************/ + +#pragma once + +// Standard Libraries +#include +// Project Includes +#include "Vector3.hxx" + +namespace SHADE +{ + /// + /// CLR version of SHADE's Quaternion class that represents an orientation. + /// Designed to closely match Unity's Quaternion struct. + /// + [System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)] + public value struct Quaternion : public System::IEquatable + { + public: + /*-----------------------------------------------------------------------------*/ + /* Constants */ + /*-----------------------------------------------------------------------------*/ +#pragma region Constants + + /// + /// Shorthand for writing Quaternion(0, 0, 0, 1). + /// + static initonly Quaternion Identity = Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + +#pragma endregion + + /*-----------------------------------------------------------------------------*/ + /* Public Members */ + /*-----------------------------------------------------------------------------*/ + + /// + /// X-component of the Quaternion. + /// Don't modify this directly unless you know quaternions inside out. + /// + float x; + /// + /// Y-component of the Quaternion. + /// Don't modify this directly unless you know quaternions inside out. + /// + float y; + /// + /// Z-component of the Quaternion. + /// Don't modify this directly unless you know quaternions inside out. + /// + float z; + /// + /// W-component of the Quaternion. Do not directly modify quaternions. + /// + float w; + + /*-----------------------------------------------------------------------------*/ + /* Constructors */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Constructor to construct a Quaternion with the specified components. + /// + /// X-coordinate to set. + /// Y-coordinate to set. + /// Z-coordinate to set. + /// W-coordinate to set. + Quaternion(float _x, float _y, float _z, float _w); + + /*-----------------------------------------------------------------------------*/ + /* Usage Functions */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Creates a rotation which rotates from fromDirection to toDirection.
+ /// Use this to create a rotation which starts at the first Vector (fromDirection) and rotates to the second Vector (toDirection). + /// These Vectors must be set up in a script. + ///
+ void SetFromToRotation(Vector3 fromDirection, Vector3 toDirection); + + /// + /// Creates a rotation with the specified forward and upwards directions.
+ /// The result is applied to this quaternion. + /// If used to orient a Transform, the Z axis will be aligned with forward and the Y axis with upwards, assuming these vectors are orthogonal. + /// Logs an error if the forward direction is zero. + ///
+ /// The direction to look in. + /// The vector that defines in which direction up is. + void SetLookRotation(Vector3 view, Vector3 up); + + /// + /// Converts a rotation to angle-axis representation (angles in degrees). + /// + void ToAngleAxis(float^% angle, Vector3^% axis); + + System::String^ ToString() override; + + /*-----------------------------------------------------------------------------*/ + /* IEquatable */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Compares equality with an object of the same type. + /// + /// The object to compare with. + /// True if both objects are the same. + virtual bool Equals(Quaternion other); + + /*-----------------------------------------------------------------------------*/ + /* Object */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Compares equality with another unboxed object. + /// + /// The unboxed object to compare with. + /// True if both objects are the same. + bool Equals(Object^ o) override; + + /// + /// Gets a unique hash for this object. + /// + /// Unique hash for this object. + int GetHashCode() override; + + /*-----------------------------------------------------------------------------*/ + /* Static Functions */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Returns the angle in degrees between two rotations a and b.
+ ///
+ /// The angle in degrees between the two vectors. + static float Angle(Quaternion a, Quaternion b); + + /// + /// Creates a rotation which rotates angle degrees around axis. + /// + static Quaternion AngleAxis(float angle, Vector3 axis); + + /// + /// The dot product between two rotations. + /// + static float Dot(Quaternion a, Quaternion b); + + /// + /// Returns a rotation that rotates y degrees around the y axis, x degrees around the x axis, and z degrees around the z axis; applied in that order. + /// + static Quaternion Euler(float _x, float _y, float _z); + + /// + /// Creates a rotation which rotates from fromDirection to toDirection. + /// + static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection); + + /// + /// Returns the Inverse of rotation. + /// + static Quaternion Inverse(Quaternion rotation); + + /// + /// Interpolates between a and b by t and normalizes the result afterwards. The parameter t is clamped to the range [0, 1]. + /// + /// Start value, returned when t = 0. + /// End value, returned when t = 1. + /// Interpolation ratio. + /// A quaternion interpolated between quaternions a and b. + static Quaternion Lerp(Quaternion a, Quaternion b, float t); + + /// + /// Interpolates between a and b by t and normalizes the result afterwards. The parameter t is not clamped. + /// + static Quaternion LerpUnclamped(Quaternion a, Quaternion b, float t); + + /// + /// Creates a rotation with the specified forward and upwards directions.
+ /// Z axis will be aligned with forward, X axis aligned with cross product between forward and upwards, and Y axis aligned with cross product between Z and X. + ///
+ static Quaternion LookRotation(Vector3 forward, Vector3 upwards); + + /// + /// Converts this quaternion to one with the same orientation but with a magnitude of 1. + /// + static Quaternion Normalize(Quaternion q); + + /// + /// Rotates a rotation from towards to.
+ /// The from quaternion is rotated towards to by an angular step of maxDegreesDelta (but note that the rotation will not overshoot). + /// Negative values of maxDegreesDelta will move away from to until the rotation is exactly the opposite direction. + ///
+ static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta); + + /// + /// Spherically interpolates between quaternions a and b by ratio t. The parameter t is clamped to the range [0, 1]. + /// + /// Start value, returned when t = 0. + /// End value, returned when t = 1. + /// Interpolation ratio. + /// A quaternion spherically interpolated between quaternions a and b. + static Quaternion Slerp(Quaternion a, Quaternion b, float t); + + /// + /// Spherically interpolates between a and b by t. The parameter t is not clamped. + /// + static Quaternion SlerpUnclamped(Quaternion a, Quaternion b, float t); + + /*-----------------------------------------------------------------------------*/ + /* Overloaded Operators */ + /*-----------------------------------------------------------------------------*/ + + /// + /// Combines rotations lhs and rhs. + /// + /// Left-hand side quaternion. + /// Right-hand side quaternion. + static Quaternion operator*(Quaternion lhs, Quaternion rhs); + + /// + /// Are two quaternions equal to each other? + /// + /// Left-hand side quaternion. + /// Right-hand side quaternion. + static bool operator==(Quaternion lhs, Quaternion rhs); + }; + +} // namespace SHADE diff --git a/SHADE_Managed/src/Math/Vector2.cxx b/SHADE_Managed/src/Math/Vector2.cxx index d40e2323..b110d4f8 100644 --- a/SHADE_Managed/src/Math/Vector2.cxx +++ b/SHADE_Managed/src/Math/Vector2.cxx @@ -26,10 +26,10 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Constructors */ /*---------------------------------------------------------------------------------*/ - Vector2::Vector2(double _x) - : Vector2 { _x, 0.0 } + Vector2::Vector2(float _x) + : Vector2 { _x, 0.0f } {} - Vector2::Vector2(double _x, double _y) + Vector2::Vector2(float _x, float _y) : x { _x } , y { _y } {} @@ -47,22 +47,22 @@ namespace SHADE return *this / GetMagnitude(); } - double Vector2::GetMagnitude() + float Vector2::GetMagnitude() { return sqrt(x * x + y * y); } - double Vector2::GetSqrMagnitude() + float Vector2::GetSqrMagnitude() { return x * x + y * y; } - double Vector2::AngleFromRightRadians() + float Vector2::AngleFromRightRadians() { return atan2(y, x); } - double Vector2::AngleFromRightDegrees() + float Vector2::AngleFromRightDegrees() { return Math::RadiansToDegrees(AngleFromRightRadians()); } @@ -72,7 +72,7 @@ namespace SHADE return IsNearPoint(point, Math::Epsilon); } - bool Vector2::IsNearPoint(Vector2 point, double tolerance) + bool Vector2::IsNearPoint(Vector2 point, float tolerance) { return (*this - point).GetSqrMagnitude() < (tolerance * tolerance); } @@ -113,13 +113,13 @@ namespace SHADE { return IsNear(lhs, rhs, Math::Epsilon); } - bool Vector2::IsNear(Vector2 lhs, Vector2 rhs, double tolerance) + bool Vector2::IsNear(Vector2 lhs, Vector2 rhs, float tolerance) { return (std::abs(lhs.x) - std::abs(rhs.x)) < tolerance && (std::abs(lhs.y) - std::abs(rhs.y)) < tolerance; } - double Vector2::Dot(Vector2 lhs, Vector2 rhs) + float Vector2::Dot(Vector2 lhs, Vector2 rhs) { return lhs.x * rhs.x + lhs.y * rhs.y; } @@ -153,12 +153,12 @@ namespace SHADE } Vector2 Vector2::Reflect(Vector2 vec, Vector2 normal) { - return vec - (Project(vec, normal.GetNormalised()) * 2.0); + return vec - (Project(vec, normal.GetNormalised()) * 2.0f); } - Vector2 Vector2::RotateRadians(Vector2 vec, double radians) + Vector2 Vector2::RotateRadians(Vector2 vec, float radians) { - const double SINE = sin(radians); - const double COSINE = cos(radians); + const float SINE = sin(radians); + const float COSINE = cos(radians); return Vector2 ( @@ -166,35 +166,35 @@ namespace SHADE vec.x * SINE + vec.y * COSINE ); } - Vector2 Vector2::RotateDegrees(Vector2 vec, double degrees) + Vector2 Vector2::RotateDegrees(Vector2 vec, float degrees) { return RotateRadians(vec, Math::DegreesToRadians(degrees)); } Vector2 Vector2::Min(Vector2 lhs, Vector2 rhs) { - double lx = lhs.x, rx = rhs.x; - double ly = lhs.y, ry = rhs.y; + float lx = lhs.x, rx = rhs.x; + float ly = lhs.y, ry = rhs.y; return Vector2(std::min(lx, rx), std::min(ly, ry)); } Vector2 Vector2::Max(Vector2 lhs, Vector2 rhs) { - double lx = lhs.x, rx = rhs.x; - double ly = lhs.y, ry = rhs.y; + float lx = lhs.x, rx = rhs.x; + float ly = lhs.y, ry = rhs.y; return Vector2(std::max(lx, rx), std::max(ly, ry)); } - Vector2 Vector2::Lerp(Vector2 a, Vector2 b, double t) + Vector2 Vector2::Lerp(Vector2 a, Vector2 b, float t) { - return LerpUnclamped(a, b, std::clamp(t, 0.0, 1.0)); + return LerpUnclamped(a, b, std::clamp(t, 0.0f, 1.0f)); } - Vector2 Vector2::LerpUnclamped(Vector2 a, Vector2 b, double t) + Vector2 Vector2::LerpUnclamped(Vector2 a, Vector2 b, float t) { return a + ((b - a) * t); } - Vector2 Vector2::MoveTowards(Vector2 current, Vector2 target, double maxDistanceDelta) + Vector2 Vector2::MoveTowards(Vector2 current, Vector2 target, float maxDistanceDelta) { // Ignore if it is exactly on the same point if (current == target) @@ -206,7 +206,7 @@ namespace SHADE // Check if check if is behind or ahead of target Vector2 DIFF = target - newPos; - if (Dot(DELTA, DIFF) < 0.0) + if (Dot(DELTA, DIFF) < 0.0f) { newPos = target; } @@ -236,7 +236,7 @@ namespace SHADE lhs.y * rhs.y ); } - Vector2 Vector2::operator*(Vector2 lhs, double rhs) + Vector2 Vector2::operator*(Vector2 lhs, float rhs) { return Vector2 ( @@ -244,7 +244,7 @@ namespace SHADE lhs.y * rhs ); } - Vector2 Vector2::operator/(Vector2 lhs, double rhs) + Vector2 Vector2::operator/(Vector2 lhs, float rhs) { return Vector2 ( diff --git a/SHADE_Managed/src/Math/Vector2.hxx b/SHADE_Managed/src/Math/Vector2.hxx index 9253a703..94b1989f 100644 --- a/SHADE_Managed/src/Math/Vector2.hxx +++ b/SHADE_Managed/src/Math/Vector2.hxx @@ -19,8 +19,8 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { /// - /// CLR version of the the SHADE Engine's Vector2 class that represents a - /// 2-Dimensional Vector. Designed to closely match Unity's Vector2 struct. + /// CLR version of SHADE Engine's Vector2 class that represents a 2-Dimensional Vector. + /// Designed to closely match Unity's Vector2 struct. /// [System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)] public value struct Vector2 : public System::IEquatable @@ -33,37 +33,37 @@ namespace SHADE /// /// Shorthand for writing Vector2(0, -1). /// - static initonly Vector2 Down = Vector2(0.0, -1.0); + static initonly Vector2 Down = Vector2(0.0f, -1.0f); /// /// Shorthand for writing Vector2(-1, 0). /// - static initonly Vector2 Left = Vector2(-1.0, 0.0); + static initonly Vector2 Left = Vector2(-1.0f, 0.0f); /// - /// Shorthand for writing Vector2(double.NegativeInfinity, - /// double.NegativeInfinity). + /// Shorthand for writing Vector2(float.NegativeInfinity, + /// float.NegativeInfinity). /// - static initonly Vector2 NegativeInfinity = Vector2(std::numeric_limits::lowest(), std::numeric_limits::lowest()); + static initonly Vector2 NegativeInfinity = Vector2(std::numeric_limits::lowest(), std::numeric_limits::lowest()); /// /// Shorthand for writing Vector2(1, 1). /// - static initonly Vector2 One = Vector2(1.0, 1.0); + static initonly Vector2 One = Vector2(1.0f, 1.0f); /// - /// Shorthand for writing Vector2(double.PositiveInfinity, - /// double.PositiveInfinity). + /// Shorthand for writing Vector2(float.PositiveInfinity, + /// float.PositiveInfinity). /// - static initonly Vector2 PositiveInfinity = Vector2(std::numeric_limits::max(), std::numeric_limits::max()); + static initonly Vector2 PositiveInfinity = Vector2(std::numeric_limits::max(), std::numeric_limits::max()); /// /// Shorthand for writing Vector2(1, 0). /// - static initonly Vector2 Right = Vector2(1.0, 0.0); + static initonly Vector2 Right = Vector2(1.0f, 0.0f); /// /// Shorthand for writing Vector2(0, 1). /// - static initonly Vector2 Up = Vector2(0.0, 1.0); + static initonly Vector2 Up = Vector2(0.0f, 1.0f); /// /// Shorthand for writing Vector2(0, 0). /// - static initonly Vector2 Zero = Vector2(0.0, 0.0); + static initonly Vector2 Zero = Vector2(0.0f, 0.0f); #pragma endregion /*-----------------------------------------------------------------------------*/ @@ -72,27 +72,27 @@ namespace SHADE /// /// X-component of the Vector2. /// - double x; + float x; /// /// Y-component of the Vector2. /// - double y; + float y; /*-----------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------*/ /// /// Constructor to construct a Vector2 with the specified components with the - /// Y-component set to 0.0. + /// Y-component set to 0.0f. /// /// X-coordinate to set. - Vector2(double _x); + Vector2(float _x); /// /// Constructor to construct a Vector2 with the specified components.. /// /// X-coordinate to set. /// Y-coordinate to set. - Vector2(double _x, double _y); + Vector2(float _x, float _y); /*-----------------------------------------------------------------------------*/ /* Usage Functions */ @@ -117,24 +117,24 @@ namespace SHADE /// need the precise magnitude, consider using GetSqrMagnitude() instead. /// /// Returns the length of this Vector2. - double GetMagnitude(); + float GetMagnitude(); /// /// Calculates and returns the squared magnitude of this Vector2. /// /// Returns the squared length of this Vector2. - double GetSqrMagnitude(); + float GetSqrMagnitude(); /// /// Calculates and returns the angle of this vector from the right vector. This /// function returns values between -Math.PI and Math.PI. /// /// Returns the angle of this vector from the right vector in radians. - double AngleFromRightRadians(); + float AngleFromRightRadians(); /// /// Calculates and returns the angle of this vector from the right vector. This - /// function returns values between -180.0 and 180.0. + /// function returns values between -180.0f and 180.0f. /// /// Returns the angle of this vector from the right vector in degrees. - double AngleFromRightDegrees(); + float AngleFromRightDegrees(); /// /// Checks if a specified point is near this Vector2 that represents a point with /// a tolerance value of PLS_EPSILON. @@ -156,7 +156,7 @@ namespace SHADE /// True if this Vector2 representing a point and the specified point are within /// the range of the specified tolerance. False otherwise. /// - bool IsNearPoint(Vector2 point, double tolerance); + bool IsNearPoint(Vector2 point, float tolerance); /*-----------------------------------------------------------------------------*/ /* IEquatable */ @@ -206,7 +206,7 @@ namespace SHADE /// /// True if the two Vector2s are within the tolerance value specified /// - static bool IsNear(Vector2 lhs, Vector2 rhs, double tolerance); + static bool IsNear(Vector2 lhs, Vector2 rhs, float tolerance); /// /// Computes and returns the dot product of 2 specified Vector2s. /// @@ -215,7 +215,7 @@ namespace SHADE /// /// Scalar value representing the dot product of the two Vector2s. /// - static double Dot(Vector2 lhs, Vector2 rhs); + static float Dot(Vector2 lhs, Vector2 rhs); /// /// Computes the inward perpendicular Vector2 to the specified Vector2. /// Equivalent to calling Perpendicular(lhs, true). This means, the @@ -260,7 +260,7 @@ namespace SHADE /// Angle to rotate the vector by in an anti-clockwise direction in radians. /// /// The Vector2 that represents the rotated vector. - static Vector2 RotateRadians(Vector2 vec, double radians); + static Vector2 RotateRadians(Vector2 vec, float radians); /// /// Rotates a Vector2 on the Z-axis by a specified angle in an anti-clockwise /// direction. @@ -270,7 +270,7 @@ namespace SHADE /// Angle to rotate the vector by in an anti-clockwise direction in degrees. /// /// The Vector2 that represents the rotated vector. - static Vector2 RotateDegrees(Vector2 vec, double degrees); + static Vector2 RotateDegrees(Vector2 vec, float degrees); /// /// Computes and returns a Vector2 that is made from the smallest components of /// the two specified Vector2s. @@ -298,25 +298,25 @@ namespace SHADE /// This is most commonly used to find a point some fraction of the way along a /// line between two endpoints. /// - /// The start Vector2, returned when t = 0.0. - /// The end Vector2, returned when t = 1.0. + /// The start Vector2, returned when t = 0.0f. + /// The end Vector2, returned when t = 1.0f. /// /// Value used to interpolate between a and b which is clamped to /// the range[0, 1]. /// /// The interpolated Vector2. - static Vector2 Lerp(Vector2 a, Vector2 b, double t); + static Vector2 Lerp(Vector2 a, Vector2 b, float t); /// /// Linearly interpolates between two specified points. /// This is most commonly used to find a point some fraction of the way along a /// line between two endpoints. /// Unlike Lerp(), t is not clamped to a range at all. /// - /// The start Vector2, returned when t = 0.0. - /// The end Vector2, returned when t = 1.0. + /// The start Vector2, returned when t = 0.0f. + /// The end Vector2, returned when t = 1.0f. /// Value used to interpolate between a and b. /// The interpolated Vector2. - static Vector2 LerpUnclamped(Vector2 a, Vector2 b, double t); + static Vector2 LerpUnclamped(Vector2 a, Vector2 b, float t); /// /// Moves a point current towards target. /// Similar to Lerp(), however, the function will ensure that the distance never @@ -327,7 +327,7 @@ namespace SHADE /// The target position to move to. /// Maximum distance moved per call. /// Vector representing the moved point. - static Vector2 MoveTowards(Vector2 current, Vector2 target, double maxDistanceDelta); + static Vector2 MoveTowards(Vector2 current, Vector2 target, float maxDistanceDelta); /*-----------------------------------------------------------------------------*/ /* Overloaded Operators */ @@ -361,7 +361,7 @@ namespace SHADE /// Vector2 to multiply with. /// Scalar to multiply with. /// The result of the scalar multiplication. - static Vector2 operator*(Vector2 lhs, double rhs); + static Vector2 operator*(Vector2 lhs, float rhs); /// /// Calculates the division of a Vector2 with a scalar value and returns /// the result. @@ -369,7 +369,7 @@ namespace SHADE /// Scalar to divide with. /// Vector2 to divide with. /// The result of the scalar division. - static Vector2 operator/(Vector2 lhs, double rhs); + static Vector2 operator/(Vector2 lhs, float rhs); /// /// Checks if two Vector2s are approximately equal. This is equivalent to /// calling Vector2.IsNear() with default tolerance values. diff --git a/SHADE_Managed/src/Math/Vector3.cxx b/SHADE_Managed/src/Math/Vector3.cxx index 26ff5a72..adbb4d3a 100644 --- a/SHADE_Managed/src/Math/Vector3.cxx +++ b/SHADE_Managed/src/Math/Vector3.cxx @@ -11,6 +11,7 @@ Copyright (C) 2021 DigiPen Institute of Technology. Reproduction or disclosure of this file or its contents without the prior written consent of DigiPen Institute of Technology is prohibited. *//*************************************************************************************/ + // Precompiled Headers #include "SHpch.h" // Primary Header @@ -26,13 +27,13 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ /* Constructors */ /*---------------------------------------------------------------------------------*/ - Vector3::Vector3(double _x) - : Vector3 {_x, 0.0, 0.0} + Vector3::Vector3(float _x) + : Vector3 {_x, 0.0f, 0.0f} {} - Vector3::Vector3(double _x, double _y) - : Vector3 {_x, _y, 0.0} + Vector3::Vector3(float _x, float _y) + : Vector3 {_x, _y, 0.0f} {} - Vector3::Vector3(double _x, double _y, double _z) + Vector3::Vector3(float _x, float _y, float _z) : x { _x } , y { _y } , z { _z } @@ -54,22 +55,22 @@ namespace SHADE return *this / GetSqrMagnitude(); } - double Vector3::GetMagnitude() + float Vector3::GetMagnitude() { return sqrt(x * x + y * y + z * z); } - double Vector3::GetSqrMagnitude() + float Vector3::GetSqrMagnitude() { return x * x + y * y + z * z; } - double Vector3::Angle2DFromRightRadians() + float Vector3::Angle2DFromRightRadians() { return atan2(y, x); } - double Vector3::Angle2DFromRightDegrees() + float Vector3::Angle2DFromRightDegrees() { return Math::RadiansToDegrees(Angle2DFromRightRadians()); } @@ -79,7 +80,7 @@ namespace SHADE return IsNearPoint(point, Math::Epsilon); } - bool Vector3::IsNearPoint(Vector3 point, double tolerance) + bool Vector3::IsNearPoint(Vector3 point, float tolerance) { return (*this - point).GetSqrMagnitude() < (tolerance * tolerance); } @@ -121,7 +122,7 @@ namespace SHADE { return IsNear(lhs, rhs, Math::Epsilon); } - bool Vector3::IsNear(Vector3 lhs, Vector3 rhs, double tolerance) + bool Vector3::IsNear(Vector3 lhs, Vector3 rhs, float tolerance) { return (std::abs(lhs.x) - std::abs(rhs.x)) < tolerance && @@ -129,7 +130,7 @@ namespace SHADE && (std::abs(lhs.z) - std::abs(rhs.z)) < tolerance; } - double Vector3::Dot(Vector3 lhs, Vector3 rhs) + float Vector3::Dot(Vector3 lhs, Vector3 rhs) { return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; } @@ -145,12 +146,12 @@ namespace SHADE } Vector3 Vector3::Reflect(Vector3 vec, Vector3 normal) { - return vec - (Project(vec, normal.GetNormalised()) * 2.0); + return vec - (Project(vec, normal.GetNormalised()) * 2.0f); } - Vector3 Vector3::RotateRadians(Vector3 vec, double radians) + Vector3 Vector3::RotateRadians(Vector3 vec, float radians) { - const double SINE = sin(radians); - const double COSINE = cos(radians); + const float SINE = sin(radians); + const float COSINE = cos(radians); return Vector3 ( @@ -159,15 +160,15 @@ namespace SHADE vec.z ); } - Vector3 Vector3::RotateDegrees(Vector3 vec, double degrees) + Vector3 Vector3::RotateDegrees(Vector3 vec, float degrees) { return RotateRadians(vec, Math::DegreesToRadians(degrees)); } Vector3 Vector3::Min(Vector3 lhs, Vector3 rhs) { - double lx = lhs.x, rx = rhs.x; - double ly = lhs.y, ry = rhs.y; - double lz = lhs.z, rz = rhs.z; + float lx = lhs.x, rx = rhs.x; + float ly = lhs.y, ry = rhs.y; + float lz = lhs.z, rz = rhs.z; return Vector3(std::min(lx, rx), std::min(ly, ry), @@ -175,23 +176,23 @@ namespace SHADE } Vector3 Vector3::Max(Vector3 lhs, Vector3 rhs) { - double lx = lhs.x, rx = rhs.x; - double ly = lhs.y, ry = rhs.y; - double lz = lhs.z, rz = rhs.z; + float lx = lhs.x, rx = rhs.x; + float ly = lhs.y, ry = rhs.y; + float lz = lhs.z, rz = rhs.z; return Vector3(std::max(lx, rx), std::max(ly, ry), std::max(lz, rz)); } - Vector3 Vector3::Lerp(Vector3 a, Vector3 b, double t) + Vector3 Vector3::Lerp(Vector3 a, Vector3 b, float t) { - return LerpUnclamped(a, b, std::clamp(t, 0.0, 1.0)); + return LerpUnclamped(a, b, std::clamp(t, 0.0f, 1.0f)); } - Vector3 Vector3::LerpUnclamped(Vector3 a, Vector3 b, double t) + Vector3 Vector3::LerpUnclamped(Vector3 a, Vector3 b, float t) { return a + ((b - a) * t); } - Vector3 Vector3::MoveTowards(Vector3 current, Vector3 target, double maxDistanceDelta) + Vector3 Vector3::MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta) { // Ignore if it is exactly on the same point if (current == target) @@ -203,7 +204,7 @@ namespace SHADE // Check if check if is behind or ahead of target Vector3 DIFF = target - newPos; - if (Dot(DELTA, DIFF) < 0.0) + if (Dot(DELTA, DIFF) < 0.0f) { newPos = target; } @@ -236,7 +237,7 @@ namespace SHADE lhs.z * rhs.z ); } - Vector3 Vector3::operator*(Vector3 lhs, double rhs) + Vector3 Vector3::operator*(Vector3 lhs, float rhs) { return Vector3 ( @@ -245,7 +246,7 @@ namespace SHADE lhs.z * rhs ); } - Vector3 Vector3::operator/(Vector3 lhs, double rhs) + Vector3 Vector3::operator/(Vector3 lhs, float rhs) { return Vector3 ( diff --git a/SHADE_Managed/src/Math/Vector3.hxx b/SHADE_Managed/src/Math/Vector3.hxx index 8b66439c..70cff88f 100644 --- a/SHADE_Managed/src/Math/Vector3.hxx +++ b/SHADE_Managed/src/Math/Vector3.hxx @@ -22,8 +22,8 @@ of DigiPen Institute of Technology is prohibited. namespace SHADE { /// - /// CLR version of the the PlushieEngine's Vector3 class that represents a - /// 3-Dimensional Vector. Designed to closely match Unity's Vector3 struct. + /// CLR version of SHADE Engine's Vector3 class that represents a 3-Dimensional Vector. + /// Designed to closely match Unity's Vector3 struct. /// [System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)] public value struct Vector3 : public System::IEquatable @@ -36,49 +36,49 @@ namespace SHADE /// /// Shorthand for writing Vector3(0, 0, -1). /// - static initonly Vector3 Back = Vector3(0.0, 0.0, -1.0); + static initonly Vector3 Back = Vector3(0.0f, 0.0f, -1.0f); /// /// Shorthand for writing Vector3(0, -1, 0). /// - static initonly Vector3 Down = Vector3(0.0, -1.0, 0.0); + static initonly Vector3 Down = Vector3(0.0f, -1.0f, 0.0f); /// /// Shorthand for writing Vector3(0, 0, 1). /// - static initonly Vector3 Forward = Vector3(0.0, 0.0, 1.0); + static initonly Vector3 Forward = Vector3(0.0f, 0.0f, 1.0f); /// /// Shorthand for writing Vector3(-1, 0, 0). /// - static initonly Vector3 Left = Vector3(-1.0, 0.0, 0.0); + static initonly Vector3 Left = Vector3(-1.0f, 0.0f, 0.0f); /// - /// Shorthand for writing Vector3(double.NegativeInfinity, - /// double.NegativeInfinity, double.NegativeInfinity). + /// Shorthand for writing Vector3(float.NegativeInfinity, + /// float.NegativeInfinity, float.NegativeInfinity). /// - static initonly Vector3 NegativeInfinity = Vector3(std::numeric_limits::lowest(), - std::numeric_limits::lowest(), - std::numeric_limits::lowest()); + static initonly Vector3 NegativeInfinity = Vector3(std::numeric_limits::lowest(), + std::numeric_limits::lowest(), + std::numeric_limits::lowest()); /// /// Shorthand for writing Vector3(1, 1, 1). /// - static initonly Vector3 One = Vector3(1.0, 1.0, 1.0); + static initonly Vector3 One = Vector3(1.0f, 1.0f, 1.0f); /// - /// Shorthand for writing Vector3(double.PositiveInfinity, - /// double.PositiveInfinity, double.PositiveInfinity). + /// Shorthand for writing Vector3(float.PositiveInfinity, + /// float.PositiveInfinity, float.PositiveInfinity). /// - static initonly Vector3 PositiveInfinity = Vector3(std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max()); + static initonly Vector3 PositiveInfinity = Vector3(std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max()); /// /// Shorthand for writing Vector3(1, 0, 0). /// - static initonly Vector3 Right = Vector3(1.0, 0.0, 0.0); + static initonly Vector3 Right = Vector3(1.0f, 0.0f, 0.0f); /// /// Shorthand for writing Vector3(0, 1, 0). /// - static initonly Vector3 Up = Vector3(0.0, 1.0, 0.0); + static initonly Vector3 Up = Vector3(0.0f, 1.0f, 0.0f); /// /// Shorthand for writing Vector3(0, 0, 0). /// - static initonly Vector3 Zero = Vector3(0.0, 0.0, 0.0); + static initonly Vector3 Zero = Vector3(0.0f, 0.0f, 0.0f); #pragma endregion /*-----------------------------------------------------------------------------*/ @@ -87,39 +87,39 @@ namespace SHADE /// /// X-component of the Vector3. /// - double x; + float x; /// /// Y-component of the Vector3. /// - double y; + float y; /// /// Z-component of the Vector3. /// - double z; + float z; /*-----------------------------------------------------------------------------*/ /* Constructors */ /*-----------------------------------------------------------------------------*/ /// /// Constructor to construct a Vector3 with the specified components with the - /// Y and Z-component set to 0.0. + /// Y and Z-component set to 0.0f. /// /// X-coordinate to set. - Vector3(double _x); + Vector3(float _x); /// /// Constructor to construct a Vector3 with the specified components with the - /// Z-component set to 0.0. + /// Z-component set to 0.0f. /// /// X-coordinate to set. /// Y-coordinate to set. - Vector3(double _x, double _y); + Vector3(float _x, float _y); /// /// Constructor to construct a Vector3 with the specified components. /// /// X-coordinate to set. /// Y-coordinate to set. /// Z-coordinate to set. - Vector3(double _x, double _y, double _z); + Vector3(float _x, float _y, float _z); /// /// Conversion constructor to construct a Vector3 using a Vector2. /// @@ -149,24 +149,24 @@ namespace SHADE /// need the precise magnitude, consider using GetSqrMagnitude() instead. /// /// Returns the length of this Vector3. - double GetMagnitude(); + float GetMagnitude(); /// /// Calculates and returns the squared magnitude of this Vector3. /// /// Returns the squared length of this Vector3. - double GetSqrMagnitude(); + float GetSqrMagnitude(); /// /// Calculates and returns the angle of this vector from the right vector. This /// function returns values between -Math.PI and Math.PI. /// /// Returns the angle of this vector from the right vector in radians. - double Angle2DFromRightRadians(); + float Angle2DFromRightRadians(); /// /// Calculates and returns the angle of this vector from the right vector. This - /// function returns values between -180.0 and 180.0. + /// function returns values between -180.0f and 180.0f. /// /// Returns the angle of this vector from the right vector in degrees. - double Angle2DFromRightDegrees(); + float Angle2DFromRightDegrees(); /// /// Checks if a specified point is near this Vector3 that represents a point with /// a tolerance value of PLS_EPSILON. @@ -188,7 +188,7 @@ namespace SHADE /// True if this Vector3 representing a point and the specified point are within /// the range of the specified tolerance. False otherwise. /// - bool IsNearPoint(Vector3 point, double tolerance); + bool IsNearPoint(Vector3 point, float tolerance); /*-----------------------------------------------------------------------------*/ /* IEquatable */ @@ -208,12 +208,12 @@ namespace SHADE /// /// The unboxed object to compare with. /// True if both objects are the same. - bool Equals(Object^ o) override; + bool Equals(Object^ o) override; /// /// Gets a unique hash for this object. /// /// Unique hash for this object. - int GetHashCode() override; + int GetHashCode() override; /*-----------------------------------------------------------------------------*/ /* Static Functions */ @@ -236,14 +236,14 @@ namespace SHADE /// /// True if the two Vector3s are within the tolerance value specified /// - static bool IsNear(Vector3 lhs, Vector3 rhs, double tolerance); + static bool IsNear(Vector3 lhs, Vector3 rhs, float tolerance); /// /// Computes and returns the dot product of 2 specified Vector3s. /// /// Vector3 to calculate dot product with. /// Another Vector3 to calculate dot product with. /// Scalar value representing the dot product of the two Vector3s. - static double Dot(Vector3 lhs, Vector3 rhs); + static float Dot(Vector3 lhs, Vector3 rhs); /// /// Computes and returns the cross product of 2 specified Vector3s. /// @@ -274,7 +274,7 @@ namespace SHADE /// Angle to rotate the vector by in an anti-clockwise direction in radians. /// /// The Vector3 that represents the rotated vector. - static Vector3 RotateRadians(Vector3 vec, double radians); + static Vector3 RotateRadians(Vector3 vec, float radians); /// /// Rotates a Vector3 on the Z-axis by a specified angle in an anti-clockwise /// direction. @@ -284,7 +284,7 @@ namespace SHADE /// Angle to rotate the vector by in an anti-clockwise direction in degrees. /// /// The Vector3 that represents the rotated vector. - static Vector3 RotateDegrees(Vector3 vec, double degrees); + static Vector3 RotateDegrees(Vector3 vec, float degrees); /// /// Computes and returns a Vector3 that is made from the smallest components of /// the two specified Vector3s. @@ -312,25 +312,25 @@ namespace SHADE /// This is most commonly used to find a point some fraction of the way along a /// line between two endpoints. /// - /// The start Vector3, returned when t = 0.0. - /// The end Vector3, returned when t = 1.0. + /// The start Vector3, returned when t = 0.0f. + /// The end Vector3, returned when t = 1.0f. /// /// Value used to interpolate between a and b which is clamped to /// the range[0, 1]. /// /// The interpolated Vector3. - static Vector3 Lerp(Vector3 a, Vector3 b, double t); + static Vector3 Lerp(Vector3 a, Vector3 b, float t); /// /// Linearly interpolates between two specified points. /// This is most commonly used to find a point some fraction of the way along a /// line between two endpoints. /// Unlike Lerp(), t is not clamped to a range at all. /// - /// The start Vector3, returned when t = 0.0. - /// The end Vector3, returned when t = 1.0. + /// The start Vector3, returned when t = 0.0f. + /// The end Vector3, returned when t = 1.0f. /// Value used to interpolate between a and b. /// The interpolated Vector3. - static Vector3 LerpUnclamped(Vector3 a, Vector3 b, double t); + static Vector3 LerpUnclamped(Vector3 a, Vector3 b, float t); /// /// Moves a point current towards target. /// Similar to Lerp(), however, the function will ensure that the distance never @@ -341,7 +341,7 @@ namespace SHADE /// The target position to move to. /// Maximum distance moved per call. /// Vector representing the moved point. - static Vector3 MoveTowards(Vector3 current, Vector3 target, double maxDistanceDelta); + static Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta); /*-----------------------------------------------------------------------------*/ /* Overloaded Operators */ @@ -375,7 +375,7 @@ namespace SHADE /// Vector3 to multiply with. /// Scalar to multiply with. /// The result of the scalar multiplication. - static Vector3 operator*(Vector3 lhs, double rhs); + static Vector3 operator*(Vector3 lhs, float rhs); /// /// Calculates the division of a Vector3 with a scalar value and returns /// the result. @@ -383,7 +383,7 @@ namespace SHADE /// Scalar to divide with. /// Vector3 to divide with. /// The result of the scalar division. - static Vector3 operator/(Vector3 lhs, double rhs); + static Vector3 operator/(Vector3 lhs, float rhs); /// /// Checks if two Vector3s are approximately equal. This is equivalent to /// calling Vector3.IsNear() with default tolerance values. diff --git a/SHADE_Managed/src/Utility/Convert.cxx b/SHADE_Managed/src/Utility/Convert.cxx index 661eb3e4..4646194b 100644 --- a/SHADE_Managed/src/Utility/Convert.cxx +++ b/SHADE_Managed/src/Utility/Convert.cxx @@ -35,10 +35,7 @@ namespace SHADE /*---------------------------------------------------------------------------------*/ SHVec3 Convert::ToNative(Vector3 vec) { - const double X = vec.x; - const double Y = vec.y; - const double Z = vec.z; - return SHVec3(X, Y, Z); + return SHVec3(vec.x, vec.y, vec.z); } Vector3 Convert::ToCLI(const SHVec3& vec) { @@ -46,9 +43,7 @@ namespace SHADE } SHVec2 Convert::ToNative(Vector2 vec) { - const double X = vec.x; - const double Y = vec.y; - return SHVec2(X, Y); + return SHVec2(vec.x, vec.y); } Vector2 Convert::ToCLI(const SHVec2& vec) @@ -56,6 +51,16 @@ namespace SHADE return Vector2(vec.x, vec.y); } + SHQuaternion Convert::ToNative(Quaternion quat) + { + return SHQuaternion{ quat.x, quat.y, quat.z, quat.w }; + } + + Quaternion Convert::ToCLI(const SHQuaternion& quat) + { + return Quaternion{ quat.x, quat.y, quat.z, quat.w }; + } + /*---------------------------------------------------------------------------------*/ /* String Conversions */ /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Utility/Convert.hxx b/SHADE_Managed/src/Utility/Convert.hxx index f04cbf4b..d694ca6a 100644 --- a/SHADE_Managed/src/Utility/Convert.hxx +++ b/SHADE_Managed/src/Utility/Convert.hxx @@ -18,10 +18,12 @@ of DigiPen Institute of Technology is prohibited. #include "ECS_Base/Entity/SHEntity.h" #include "Math/Vector/SHVec2.h" #include "Math/Vector/SHVec3.h" +#include "Math/SHQuaternion.h" // Project Includes #include "Engine/Entity.hxx" #include "Math/Vector2.hxx" #include "Math/Vector3.hxx" +#include "Math/Quaternion.hxx" namespace SHADE { @@ -74,6 +76,18 @@ namespace SHADE /// The native Vector2 to convert from. /// Managed copy of a native Vector2. static Vector2 ToCLI(const SHVec2& vec); + /// + /// Converts from a managed Quaternion to a native Quaternion. + /// + /// The managed Quaternion to convert from. + /// Native copy of a managed Quaternion. + static SHQuaternion ToNative(Quaternion quat); + /// + /// Converts from a native Quaternion to a managed Quaternion. + /// + /// The native Quaternion to convert from. + /// Managed copy of a native Quaternion. + static Quaternion ToCLI(const SHQuaternion& quat); /*-----------------------------------------------------------------------------*/ /* String Conversions */ From 26eb4ad18cf98d7d9b8f8b7806a52e97ce2f8c97 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Mon, 24 Oct 2022 16:18:18 +0800 Subject: [PATCH 18/28] Fix command registrations and mouse pick polling when using transform gizmo --- Assets/Editor/Layouts/UserLayout.ini | 54 ----- .../src/Application/SBApplication.cpp | 10 +- .../HierarchyPanel/SHHierarchyPanel.cpp | 2 +- .../Inspector/SHEditorComponentView.hpp | 4 + .../ViewportWindow/SHEditorViewport.cpp | 2 +- .../src/Editor/Gizmos/SHTransformGizmo.cpp | 65 +++--- .../src/Editor/Gizmos/SHTransformGizmo.h | 6 + SHADE_Engine/src/Editor/SHEditor.cpp | 2 +- SHADE_Engine/src/Editor/SHEditorWidgets.hpp | 191 +++++++++--------- 9 files changed, 151 insertions(+), 185 deletions(-) delete mode 100644 Assets/Editor/Layouts/UserLayout.ini diff --git a/Assets/Editor/Layouts/UserLayout.ini b/Assets/Editor/Layouts/UserLayout.ini deleted file mode 100644 index baced6b8..00000000 --- a/Assets/Editor/Layouts/UserLayout.ini +++ /dev/null @@ -1,54 +0,0 @@ -[Window][MainStatusBar] -Pos=0,1060 -Size=1920,20 -Collapsed=0 - -[Window][SHEditorMenuBar] -Pos=0,48 -Size=1920,1012 -Collapsed=0 - -[Window][Hierarchy Panel] -Pos=0,142 -Size=387,918 -Collapsed=0 -DockId=0x00000004,0 - -[Window][Debug##Default] -Pos=60,60 -Size=400,400 -Collapsed=0 - -[Window][Inspector] -Pos=1649,48 -Size=271,1012 -Collapsed=0 -DockId=0x00000006,0 - -[Window][Profiler] -Pos=0,48 -Size=387,92 -Collapsed=0 -DockId=0x00000003,0 - -[Window][Viewport] -Pos=648,48 -Size=2519,1319 -Collapsed=0 -DockId=0x00000002,0 - -[Window][ Viewport] -Pos=389,48 -Size=1258,1012 -Collapsed=0 -DockId=0x00000002,0 - -[Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X - DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=387,1036 Split=Y Selected=0x1E6EB881 - DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 - DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1258,1036 CentralNode=1 Selected=0xB41284E7 - DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252 - diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index a93148d5..54dc0ccf 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -56,8 +56,8 @@ namespace Sandbox _In_ INT nCmdShow ) { - // Set working directory - SHFileUtilities::SetWorkDirToExecDir(); + // Set working directory + SHFileUtilities::SetWorkDirToExecDir(); window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); @@ -152,16 +152,16 @@ namespace Sandbox SHSceneManager::SceneUpdate(0.016f); #endif SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f); - //editor->PollPicking(); + editor->PollPicking(); } // Finish all graphics jobs first - graphicsSystem->AwaitGraphicsExecution(); + graphicsSystem->AwaitGraphicsExecution(); } void SBApplication::Exit(void) { - #ifdef SHEDITOR + #ifdef SHEDITOR SDL_DestroyWindow(sdlWindow); SDL_Quit(); #endif diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index 27e46d98..972d4ae3 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -94,7 +94,7 @@ namespace SHADE if (ImGui::BeginMenuBar()) { - ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 35.0f); + ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 40.0f); if(ImGui::SmallButton(ICON_MD_DESELECT)) { auto editor = SHSystemManager::GetSystem(); diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 08f5695b..0bbbe0dd 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -39,6 +39,10 @@ namespace SHADE { SHComponentManager::RemoveComponent(component->GetEID()); } + if (ImGui::Selectable(std::format("{} Reset {}", ICON_MD_RESTART_ALT, componentName.data()).data())) + { + *component = T(); + } ImGui::EndPopup(); } } diff --git a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp index b06c37c7..cb30fa81 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp @@ -24,7 +24,7 @@ namespace SHADE void SHEditorViewport::Init() { SHEditorWindow::Init(); - + transformGizmo.Init(); } void SHEditorViewport::Update() diff --git a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp index a53b8c10..3c984051 100644 --- a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp +++ b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.cpp @@ -13,6 +13,12 @@ #include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h" namespace SHADE { + void SHTransformGizmo::Init() + { + auto& style = ImGuizmo::GetStyle(); + style.RotationLineThickness = 2.5f; + } + void SHTransformGizmo::Draw() { bool justChangedTfm = false; @@ -26,9 +32,12 @@ namespace SHADE SHMatrix view = SHMatrix::Transpose(editorCamera->GetViewMatrix()); SHMatrix proj = SHMatrix::Transpose(editorCamera->GetProjMatrix()); + + //Invert projection y-axis proj(1, 1) *= -1; + static SHMatrix gridMat = SHMatrix::Translate(0, -0.5f, 0.f) * SHMatrix::Identity; - //ImGuizmo::DrawGrid(&view._11, &proj._11, &gridMat._11, 100.f); + if (selectedEntityTransformComponent == nullptr) { SHEditor* editor = SHSystemManager::GetSystem(); @@ -55,31 +64,37 @@ namespace SHADE return; SHMatrix mat = selectedEntityTransformComponent->GetTRS(); - isManipulating = ImGuizmo::Manipulate(&view._11, &proj._11, static_cast(operation), ImGuizmo::MODE::WORLD, &mat._11); - if (!justChangedTfm) + useSnap = ImGui::IsKeyDown(ImGuiKey_LeftCtrl); + if(useSnap) { - if (ImGui::IsItemClicked()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx) - { - if (!tfm) - return; - SHVec3 translate{}, rotate{}, scale{}; - mtx.Decompose(translate, rotate, scale); - tfm->SetWorldPosition(translate); - tfm->SetWorldRotation(rotate); - tfm->SetWorldScale(scale); - }))); - else if (ImGui::IsItemHovered(ImGuiMouseButton_Left) && ImGui::IsMouseDown(ImGuiMouseButton_Left) && isManipulating) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx) - { - if (!tfm) - return; - SHVec3 translate{}, rotate{}, scale{}; - mtx.Decompose(translate, rotate, scale); - tfm->SetWorldPosition(translate); - tfm->SetWorldRotation(rotate); - tfm->SetWorldScale(scale); - })), true); + switch (operation) + { + case Operation::TRANSLATE: snap = &translationSnap.x; break; + case Operation::ROTATE: snap = &rotationSnap; break; + case Operation::SCALE: snap = &scaleSnap; break; + default: snap = &translationSnap.x; + } } + ImGuizmo::Manipulate(&view._11, &proj._11, static_cast(operation), ImGuizmo::MODE::WORLD, &mat._11, nullptr, useSnap ? snap : nullptr); + static bool startRecording = false; + if (!justChangedTfm && ImGuizmo::IsUsing()) + { + + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = (selectedEntityTransformComponent)](SHMatrix const& mtx) + { + if (!tfm) + return; + SHVec3 translate{}, rotate{}, scale{}; + mtx.Decompose(translate, rotate, scale); + tfm->SetWorldPosition(translate); + tfm->SetWorldRotation(rotate); + tfm->SetWorldScale(scale); + })), startRecording); + if(!startRecording) + startRecording = true; + } + isManipulating = ImGuizmo::IsUsing() || startRecording; + if(startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + startRecording = false; } } diff --git a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h index 2565575f..fd847335 100644 --- a/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h +++ b/SHADE_Engine/src/Editor/Gizmos/SHTransformGizmo.h @@ -37,11 +37,17 @@ namespace SHADE UNIVERSAL = TRANSLATE | ROTATE | SCALEU }; + void Init(); void Draw(); bool isManipulating = false; + bool useSnap = false; Mode mode = Mode::WORLD; Operation operation = Operation::TRANSLATE; private: + float scaleSnap = 0.25f; + float rotationSnap = 1.0f; + SHVec3 translationSnap = SHVec3(0.25f, 0.25f, 0.25f); + float* snap = nullptr; SHTransformComponent* selectedEntityTransformComponent{nullptr}; SHCameraComponent* editorCamera{nullptr}; }; diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index aff1eaad..912f9d0f 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -134,7 +134,7 @@ namespace SHADE } } - PollPicking(); + //PollPicking(); if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z)) { diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp index 5788dc15..dc65d6c2 100644 --- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp +++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp @@ -40,7 +40,6 @@ namespace SHADE { ImGui::BeginGroup(); - auto cursorPos = ImGui::GetCursorScreenPos(); auto itemSpacing = ImGui::GetStyle().ItemSpacing; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); @@ -175,7 +174,7 @@ namespace SHADE ImGui::SetColumnWidth(-1, 80.0f); ImGui::Text(fieldLabel.c_str()); if (isHovered) - *isHovered = ImGui::IsItemHovered(); + *isHovered = ImGui::IsItemHovered(); ImGui::NextColumn(); for (std::size_t i = 0; i < N; ++i) { @@ -208,21 +207,16 @@ namespace SHADE ImGuiSliderFlags flags = 0) { SHVec2 values = get(); - bool changed = false; - if (DragN(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags)) - { - changed = true; - } - + bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags); + static bool startRecording = false; if (changed) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), startRecording); + if (!startRecording) + startRecording = true; } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + startRecording = false; return changed; } @@ -232,20 +226,20 @@ namespace SHADE ImGuiSliderFlags flags = 0) { SHVec3 values = get(); - bool changed = false; - if (DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags)) - { - changed = true; - } + bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags); + + static bool startRecording = false; if (changed) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHVec3 old = get(); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(old, values, set)), startRecording); + if (!startRecording) + startRecording = true; + } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; } return changed; @@ -256,20 +250,17 @@ namespace SHADE ImGuiSliderFlags flags = 0) { SHVec4 values = get(); - bool changed = false; - if (DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags)) - { - changed = true; - } - + bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags); + static bool startRecording = false; if (changed) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), false); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), values, set)), startRecording); + if (!startRecording) + startRecording = true; + } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; } return changed; @@ -325,112 +316,116 @@ namespace SHADE float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { T value = get(); - std::cout << value << " \n"; - //bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags); - - if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags)) + const bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - - return true; + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; } - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + return hasChange; } static bool DragFloat(const std::string& fieldLabel, std::function get, std::function set, float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); - //bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); - if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags)) + const bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - - return true; + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + return hasChange; } static bool DragInt(const std::string& fieldLabel, std::function get, std::function set, float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { int value = get(); - //bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); - if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags)) + const bool hasChange = ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); + static bool startRecording = false; + if (hasChange) { - if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - else if (ImGui::IsItemDeactivatedAfterEdit()) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - - return true; + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + return hasChange; } template static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function get, std::function set, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { T value = get(); - if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags)) + bool const changed = ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags); + static bool startRecording = false; + if (changed) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; - return true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + return changed; } static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function get, std::function set, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); - if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags)) + bool const changed = ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags); + static bool startRecording = false; + if (changed) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; - - return true; } - - return false; + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; + } + return changed; } static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function get, std::function set, const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { int value = get(); - if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags)) + bool const changed = ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags); + static bool startRecording = false; + if (changed) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); - else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), true); - return true; + SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); + if (!startRecording) + startRecording = true; + } + if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) + { + startRecording = false; } - return false; } From 24c591ec27b186431ea145e7053d2d8542d23031 Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 24 Oct 2022 20:07:59 +0800 Subject: [PATCH 19/28] Modified Managed Transform Interface to use Quaternions --- SHADE_Managed/src/Components/Transform.cxx | 16 ++++++++-------- SHADE_Managed/src/Components/Transform.hxx | 21 ++++++++++----------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/SHADE_Managed/src/Components/Transform.cxx b/SHADE_Managed/src/Components/Transform.cxx index 0f0716dc..41298c21 100644 --- a/SHADE_Managed/src/Components/Transform.cxx +++ b/SHADE_Managed/src/Components/Transform.cxx @@ -29,13 +29,13 @@ namespace SHADE { GetNativeComponent()->SetLocalPosition(Convert::ToNative(val)); } - Vector3 Transform::LocalRotation::get() + Quaternion Transform::LocalRotation::get() { - return Convert::ToCLI(GetNativeComponent()->GetLocalRotation()); + return Convert::ToCLI(GetNativeComponent()->GetLocalOrientation()); } - void Transform::LocalRotation::set(Vector3 val) + void Transform::LocalRotation::set(Quaternion val) { - GetNativeComponent()->SetLocalRotation(Convert::ToNative(val)); + GetNativeComponent()->SetLocalOrientation(Convert::ToNative(val)); } Vector3 Transform::LocalScale::get() { @@ -54,13 +54,13 @@ namespace SHADE { GetNativeComponent()->SetWorldPosition(Convert::ToNative(val)); } - Vector3 Transform::GlobalRotation::get() + Quaternion Transform::GlobalRotation::get() { - return Convert::ToCLI(GetNativeComponent()->GetWorldRotation()); + return Convert::ToCLI(GetNativeComponent()->GetLocalOrientation()); } - void Transform::GlobalRotation::set(Vector3 val) + void Transform::GlobalRotation::set(Quaternion val) { - GetNativeComponent()->SetWorldRotation(Convert::ToNative(val)); + GetNativeComponent()->SetWorldOrientation(Convert::ToNative(val)); } Vector3 Transform::GlobalScale::get() { diff --git a/SHADE_Managed/src/Components/Transform.hxx b/SHADE_Managed/src/Components/Transform.hxx index 9efd2927..43118b1f 100644 --- a/SHADE_Managed/src/Components/Transform.hxx +++ b/SHADE_Managed/src/Components/Transform.hxx @@ -17,14 +17,14 @@ of DigiPen Institute of Technology is prohibited. // Project Includes #include "Components/Component.hxx" #include "Math/Vector3.hxx" -#include "Utility/Convert.hxx" +#include "Math/Quaternion.hxx" // External Dependencies #include "Math/Transform/SHTransformComponent.h" namespace SHADE { /// - /// CLR version of the the SHADE Engine's TransformComponent. + /// CLR version of the SHADE Engine's TransformComponent. /// public ref class Transform : public Component { @@ -52,12 +52,12 @@ namespace SHADE void set(Vector3 val); } /// - /// Local Z-axis rotation angle stored by this Transform in Radians. + /// Local rotation quaternion stored by this Transform. /// - property Vector3 LocalRotation + property Quaternion LocalRotation { - Vector3 get(); - void set(Vector3 val); + Quaternion get(); + void set(Quaternion val); } /// /// Local scale stored by this Transform. @@ -76,16 +76,15 @@ namespace SHADE void set(Vector3 val); } /// - /// Global Z-axis rotation angle stored by this Transform in Radians. + /// Global rotation quaternion stored by this Transform. /// - property Vector3 GlobalRotation + property Quaternion GlobalRotation { - Vector3 get(); - void set(Vector3 val); + Quaternion get(); + void set(Quaternion val); } /// /// Global scale stored by this Transform. - /// Note that this operation is expensive. /// property Vector3 GlobalScale { From ff025f212cc93e3668dd435015c8bab632b7889f Mon Sep 17 00:00:00 2001 From: Diren D Bharwani Date: Mon, 24 Oct 2022 22:41:36 +0800 Subject: [PATCH 20/28] Added Euler Angles properties to Managed Transforms --- SHADE_Managed/src/Components/Transform.cxx | 16 ++++++++++++++++ SHADE_Managed/src/Components/Transform.hxx | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/SHADE_Managed/src/Components/Transform.cxx b/SHADE_Managed/src/Components/Transform.cxx index 41298c21..98f0da4f 100644 --- a/SHADE_Managed/src/Components/Transform.cxx +++ b/SHADE_Managed/src/Components/Transform.cxx @@ -37,6 +37,14 @@ namespace SHADE { GetNativeComponent()->SetLocalOrientation(Convert::ToNative(val)); } + Vector3 Transform::LocalEulerAngles::get() + { + return Convert::ToCLI(GetNativeComponent()->GetLocalRotation()); + } + void Transform::LocalEulerAngles::set(Vector3 val) + { + GetNativeComponent()->SetLocalRotation(Convert::ToNative(val)); + } Vector3 Transform::LocalScale::get() { return Convert::ToCLI(GetNativeComponent()->GetLocalScale()); @@ -62,6 +70,14 @@ namespace SHADE { GetNativeComponent()->SetWorldOrientation(Convert::ToNative(val)); } + Vector3 Transform::GlobalEulerAngles::get() + { + return Convert::ToCLI(GetNativeComponent()->GetWorldRotation()); + } + void Transform::GlobalEulerAngles::set(Vector3 val) + { + GetNativeComponent()->SetWorldRotation(Convert::ToNative(val)); + } Vector3 Transform::GlobalScale::get() { return Convert::ToCLI(GetNativeComponent()->GetWorldScale()); diff --git a/SHADE_Managed/src/Components/Transform.hxx b/SHADE_Managed/src/Components/Transform.hxx index 43118b1f..bbe9fd19 100644 --- a/SHADE_Managed/src/Components/Transform.hxx +++ b/SHADE_Managed/src/Components/Transform.hxx @@ -60,6 +60,14 @@ namespace SHADE void set(Quaternion val); } /// + /// Local euler angle rotations stored by this Transform. + /// + property Vector3 LocalEulerAngles + { + Vector3 get(); + void set(Vector3 val); + } + /// /// Local scale stored by this Transform. /// property Vector3 LocalScale @@ -84,6 +92,14 @@ namespace SHADE void set(Quaternion val); } /// + /// Global euler angle rotations stored by this Transform. + /// + property Vector3 GlobalEulerAngles + { + Vector3 get(); + void set(Vector3 val); + } + /// /// Global scale stored by this Transform. /// property Vector3 GlobalScale From c2e51dc603118eb025aa95b4fcf64f44cc5cfca9 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 25 Oct 2022 14:31:28 +0800 Subject: [PATCH 21/28] Fixed deletion crash caused by Renderables --- .../Graphics/MiddleEnd/Batching/SHBatch.cpp | 74 ++++++++++++------- .../src/Graphics/MiddleEnd/Batching/SHBatch.h | 2 +- .../MiddleEnd/Interface/SHGraphicsSystem.cpp | 4 +- .../MiddleEnd/Interface/SHRenderable.cpp | 24 +++--- .../MiddleEnd/Interface/SHRenderable.h | 4 +- 5 files changed, 67 insertions(+), 41 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 40826047..24dd76c5 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -59,7 +59,7 @@ namespace SHADE } // Add renderable in - subBatch->Renderables.insert(renderable); + subBatch->Renderables.insert(renderable->GetEID()); // Also add material instance in referencedMatInstances.insert(renderable->GetMaterial()); @@ -80,27 +80,34 @@ namespace SHADE if (subBatch == subBatches.end()) return; - subBatch->Renderables.erase(renderable); + subBatch->Renderables.erase(renderable->GetEID()); // Check if other renderables in subBatches contain the same material instance bool matUnused = true; for (const auto& sb : subBatches) - for (const auto& rend : sb.Renderables) + for (const auto& rendId : sb.Renderables) { - if (rend->GetMaterial() == renderable->GetMaterial()) + auto rend = SHComponentManager::GetComponent(rendId); + if (rend) { - matUnused = false; - break; + if (rend->GetMaterial() == renderable->GetMaterial()) + { + matUnused = false; + break; + } + } + else + { + SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!"); } } // Material is no longer in this library, so we remove it if (matUnused) - referencedMatInstances.erase(renderable->GetMaterial()); + referencedMatInstances.erase(renderable->WasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial()); // Mark all as dirty - for (bool& dirt : isDirty) - dirt = true; + setAllDirtyFlags(); } void SHBatch::Clear() @@ -162,9 +169,17 @@ namespace SHADE // Build CPU Buffer char* propsCurrPtr = matPropsData.get(); for (auto& subBatch : subBatches) - for (const SHRenderable* renderable : subBatch.Renderables) + for (auto rendId : subBatch.Renderables) { - renderable->GetMaterial()->ExportProperties(propsCurrPtr); + const SHRenderable* renderable = SHComponentManager::GetComponent(rendId); + if (renderable) + { + renderable->GetMaterial()->ExportProperties(propsCurrPtr); + } + else + { + SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!"); + } propsCurrPtr += singleMatPropAlignedSize; } @@ -188,18 +203,18 @@ namespace SHADE // Populate on the CPU for (auto& subBatch : subBatches) - for (const SHRenderable* renderable : subBatch.Renderables) + for (auto rendId : subBatch.Renderables) { // Transform - auto transform = SHComponentManager::GetComponent(renderable->GetEID()); - if (!transform) + auto transform = SHComponentManager::GetComponent(rendId); + if (transform) { - SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); - transformData.emplace_back(); + transformData.emplace_back(transform->GetTRS()); } else { - transformData.emplace_back(transform->GetTRS()); + SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); + transformData.emplace_back(); } } @@ -221,10 +236,10 @@ namespace SHADE // Populate on the CPU for (auto& subBatch : subBatches) - for (const SHRenderable* renderable : subBatch.Renderables) - { - eidData.emplace_back(renderable->GetEID()); - } + for (auto rendId : subBatch.Renderables) + { + eidData.emplace_back(rendId); + } // Transfer to GPU if (eidBuffer[frameIndex]) @@ -305,11 +320,10 @@ namespace SHADE }); // Fill in buffers (CPU) - for (const SHRenderable* renderable : subBatch.Renderables) + for (auto rendId : subBatch.Renderables) { // Transform - EntityID eid = renderable->GetEID(); - auto transform = SHComponentManager::GetComponent_s(eid); + auto transform = SHComponentManager::GetComponent_s(rendId); if (!transform) { SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!"); @@ -320,12 +334,20 @@ namespace SHADE transformData.emplace_back(transform->GetTRS()); } - eidData.emplace_back(eid); + eidData.emplace_back(rendId); // Material Properties if (!EMPTY_MAT_PROPS) { - renderable->GetMaterial()->ExportProperties(propsCurrPtr); + const SHRenderable* renderable = SHComponentManager::GetComponent(rendId); + if (renderable) + { + renderable->GetMaterial()->ExportProperties(propsCurrPtr); + } + else + { + SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!"); + } propsCurrPtr += singleMatPropAlignedSize; } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h index 193fff0d..fa18fad5 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h @@ -55,7 +55,7 @@ namespace SHADE /* Data Members */ /*-----------------------------------------------------------------------------*/ Handle Mesh; - std::unordered_set Renderables; + std::unordered_set Renderables; }; /***********************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 7ecd92d2..4280cafd 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -677,10 +677,10 @@ namespace SHADE continue; // Remove from old material's SuperBatch - Handle prevMaterial = renderable.GetPrevMaterial(); + Handle prevMaterial = renderable.GetPrevMaterial(); if (prevMaterial) { - Handle oldSuperBatch = prevMaterial->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); + Handle oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); oldSuperBatch->Remove(&renderable); } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index 0b1c1b66..9dcd391d 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -31,15 +31,16 @@ namespace SHADE void SHRenderable::OnDestroy() { + // Remove from SuperBatch + Handle superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); + superBatch->Remove(this); + + // Free resources if (material) { material.Free(); material = {}; } - - // Remove from SuperBatch - Handle superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); - superBatch->Remove(this); } /*-----------------------------------------------------------------------------------*/ @@ -51,20 +52,23 @@ namespace SHADE if (!material && sharedMaterial == materialInstance) return; + // Flag that material was changed + materialChanged = true; + // Free copies of materials if any if (material) { + oldMaterial = material; material.Free(); material = {}; } - - // Flag that material was changed - materialChanged = true; - if (sharedMaterial) - oldMaterial = sharedMaterial->GetBaseMaterial(); + else if (sharedMaterial) + { + oldMaterial = sharedMaterial; + } // Update the material - sharedMaterial = materialInstance; + sharedMaterial = materialInstance; } Handle SHRenderable::GetMaterial() const diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h index bc885ca2..5312cf82 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h @@ -55,7 +55,7 @@ namespace SHADE /* Getter Functions */ /*-------------------------------------------------------------------------------*/ bool WasMaterialChanged() const noexcept { return materialChanged; } - Handle GetPrevMaterial() const noexcept { return oldMaterial; } + Handle GetPrevMaterial() const noexcept { return oldMaterial; } /*-------------------------------------------------------------------------------*/ /* Batcher Dispatcher Functions */ @@ -74,7 +74,7 @@ namespace SHADE Handle sharedMaterial; Handle material; bool materialChanged = true; - Handle oldMaterial; + Handle oldMaterial; }; } From 9f98bed4d15b85bd8aae1a6909e4045030fc278e Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 25 Oct 2022 15:11:01 +0800 Subject: [PATCH 22/28] Fixed batching renedering the wrong number of instances --- SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 24dd76c5..012d9526 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -310,14 +310,16 @@ namespace SHADE for (auto& subBatch : subBatches) { // Create command + const uint32_t CURR_INSTANCES = static_cast(subBatch.Renderables.size()); drawData.emplace_back(vk::DrawIndexedIndirectCommand { .indexCount = subBatch.Mesh->IndexCount, - .instanceCount = static_cast(subBatch.Renderables.size()), + .instanceCount = CURR_INSTANCES, .firstIndex = subBatch.Mesh->FirstIndex, .vertexOffset = subBatch.Mesh->FirstVertex, - .firstInstance = nextInstanceIndex++ + .firstInstance = nextInstanceIndex }); + nextInstanceIndex += CURR_INSTANCES; // Fill in buffers (CPU) for (auto rendId : subBatch.Renderables) From da167ec3a58acff2152dd633edd86e994e59851f Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 25 Oct 2022 15:39:18 +0800 Subject: [PATCH 23/28] Added .editorconfig to enforce 2-spacing indentation --- .editorconfig | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..29c5e400 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[*.{c,cpp,h,hpp}] +indent_style = space +indent_size = 2 \ No newline at end of file From 0acd6a99a43fd3a3e51cf2abc5fb7d13ed6af725 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Tue, 25 Oct 2022 17:08:15 +0800 Subject: [PATCH 24/28] Tweaks to editor widgets --- .../HierarchyPanel/SHHierarchyPanel.cpp | 3 +- .../Inspector/SHEditorComponentView.hpp | 21 +++-- SHADE_Engine/src/Editor/SHEditorWidgets.hpp | 84 ++++++++++++++++--- 3 files changed, 87 insertions(+), 21 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp index 972d4ae3..f2f8d927 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/HierarchyPanel/SHHierarchyPanel.cpp @@ -93,8 +93,7 @@ namespace SHADE { if (ImGui::BeginMenuBar()) { - - ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 40.0f); + ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x * 0.75f); if(ImGui::SmallButton(ICON_MD_DESELECT)) { auto editor = SHSystemManager::GetSystem(); diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 0bbbe0dd..7fa39d74 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -52,7 +52,7 @@ namespace SHADE if (!component) return; const auto componentType = rttr::type::get(*component); - SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }); + SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active"); ImGui::SameLine(); if (ImGui::CollapsingHeader(componentType.get_name().data())) { @@ -93,7 +93,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin && metaMax) { - SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); }); + SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); }); } else { @@ -119,7 +119,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu"); } else { @@ -132,7 +132,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value(), metaMin.template get_value(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value(), metaMax.template get_value(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu"); } else { @@ -145,7 +145,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu"); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu"); } else { @@ -156,13 +156,18 @@ namespace SHADE { auto metaMin = property.get_metadata(META::min); auto metaMax = property.get_metadata(META::max); + float min{}, max{}; + if(metaMin.is_valid()) + min = std::max(metaMin.template get_value(), -FLT_MAX * 0.5f); + if(metaMax.is_valid()) + max = std::min(metaMax.template get_value(), FLT_MAX * 0.5f); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }); + SHEditorWidgets::SliderFloat(property.get_name().data(), min, max, [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }); } else { - SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }); + SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }, "Test"); } } else if (type == rttr::type::get()) @@ -171,7 +176,7 @@ namespace SHADE auto metaMax = property.get_metadata(META::max); if (metaMin.is_valid() && metaMax.is_valid()) { - SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value(), metaMin.template get_value(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); }); + SHEditorWidgets::SliderScalar(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value(), metaMax.template get_value(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); }); } else { diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp index dc65d6c2..4a299d25 100644 --- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp +++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp @@ -203,7 +203,7 @@ namespace SHADE } static bool DragVec2(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, - std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, + std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec2 values = get(); @@ -217,12 +217,20 @@ namespace SHADE } if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) startRecording = false; - + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return changed; } static bool DragVec3(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, - std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, + std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec3 values = get(); @@ -241,12 +249,20 @@ namespace SHADE { startRecording = false; } - + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return changed; } static bool DragVec4(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, - std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f, + std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec4 values = get(); @@ -262,7 +278,15 @@ namespace SHADE { startRecording = false; } - + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return changed; } @@ -270,14 +294,38 @@ namespace SHADE //|| Widget Extensions || //#==============================================================# - static bool CheckBox(std::string const& label, std::function get, std::function set) + static void TextLabel(std::string_view const& text, bool sameLine = true) + { + const ImVec2 textSize = ImGui::CalcTextSize(text.data(), NULL, true); + if(textSize.x > 0.0f) + { + ImGui::Text(text.data()); + ImGui::SameLine(); + } + } + + static bool CheckBox(std::string_view const& label, std::function get, std::function set, std::string_view const& tooltip = {}) { bool value = get(); - if (ImGui::Checkbox(label.c_str(), &value)) + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + if (ImGui::Checkbox("##", &value)) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), false); return true; } + ImGui::PopID(); + ImGui::EndGroup(); + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return false; } @@ -331,11 +379,14 @@ namespace SHADE return hasChange; } - static bool DragFloat(const std::string& fieldLabel, std::function get, std::function set, + static bool DragFloat(const std::string_view& label, std::function get, std::function set, std::string_view const& tooltip = {}, float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); - const bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + const bool hasChange = ImGui::DragFloat("##", &value, speed, p_min, p_max, displayFormat, flags); static bool startRecording = false; if (hasChange) { @@ -347,6 +398,17 @@ namespace SHADE { startRecording = false; } + ImGui::PopID(); + ImGui::EndGroup(); + if(!tooltip.empty()) + { + if(ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return hasChange; } @@ -389,7 +451,7 @@ namespace SHADE return changed; } - static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function get, std::function set, + static bool SliderFloat(const std::string& fieldLabel, float const& min, float const& max, std::function get, std::function set, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); From 416c571fd2259bb616a04648f249985ec6ee6f03 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 25 Oct 2022 17:40:13 +0800 Subject: [PATCH 25/28] Added proper deletion of VKSamplers --- SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp index 4300f2bd..7443b6e2 100644 --- a/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp +++ b/SHADE_Engine/src/Graphics/Images/SHVkSampler.cpp @@ -49,7 +49,7 @@ namespace SHADE SHVkSampler::~SHVkSampler() noexcept { if (vkSampler) - device->GetVkLogicalDevice().destroySampler(); + device->GetVkLogicalDevice().destroySampler(vkSampler); } /*-----------------------------------------------------------------------------------*/ From d1d64ec167ff76e727057d2e0725d36575ae459f Mon Sep 17 00:00:00 2001 From: Glence Date: Tue, 25 Oct 2022 18:48:45 +0800 Subject: [PATCH 26/28] added tooltips for the rest of the widgets --- SHADE_Engine/src/Editor/SHEditorWidgets.hpp | 178 ++++++++++++++++---- 1 file changed, 144 insertions(+), 34 deletions(-) diff --git a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp index 4a299d25..b54a6799 100644 --- a/SHADE_Engine/src/Editor/SHEditorWidgets.hpp +++ b/SHADE_Engine/src/Editor/SHEditorWidgets.hpp @@ -157,7 +157,7 @@ namespace SHADE } template - static bool DragN(const std::string& fieldLabel, std::vectorconst& componentLabels, + static bool DragN(const std::string& label, std::vectorconst& componentLabels, std::vector values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(), ImGuiSliderFlags flags = 0, bool* isHovered = nullptr) { @@ -168,11 +168,11 @@ namespace SHADE const ImGuiContext& g = *GImGui; bool valueChanged = false; ImGui::BeginGroup(); - ImGui::PushID(fieldLabel.c_str()); + ImGui::PushID(label.c_str()); PushMultiItemsWidthsAndLabels(componentLabels, 0.0f); ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize); ImGui::SetColumnWidth(-1, 80.0f); - ImGui::Text(fieldLabel.c_str()); + ImGui::Text(label.c_str()); if (isHovered) *isHovered = ImGui::IsItemHovered(); ImGui::NextColumn(); @@ -202,12 +202,12 @@ namespace SHADE return valueChanged; } - static bool DragVec2(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, + static bool DragVec2(const std::string& label, std::vectorconst& componentLabels, std::function get, std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec2 values = get(); - bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags); + bool const changed = DragN(label, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags); static bool startRecording = false; if (changed) { @@ -229,12 +229,12 @@ namespace SHADE return changed; } - static bool DragVec3(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, + static bool DragVec3(const std::string& label, std::vectorconst& componentLabels, std::function get, std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec3 values = get(); - bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags); + bool const changed = DragN(label, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags); static bool startRecording = false; @@ -261,12 +261,12 @@ namespace SHADE return changed; } - static bool DragVec4(const std::string& fieldLabel, std::vectorconst& componentLabels, std::function get, + static bool DragVec4(const std::string& label, std::vectorconst& componentLabels, std::function get, std::function set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f, ImGuiSliderFlags flags = 0) { SHVec4 values = get(); - bool const changed = DragN(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags); + bool const changed = DragN(label, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags); static bool startRecording = false; if (changed) { @@ -330,41 +330,72 @@ namespace SHADE } template - static bool RadioButton(std::vector const& listLabels, std::vector const& listTypes, std::function get, std::function set) + static bool RadioButton(std::vector const& label, std::vector const& listTypes, std::function get, std::function set ,std::string_view const& tooltip = {}) { T type = get(); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); for (size_t i = 0; i < listTypes.size(); i++) { - if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i])) + if (ImGui::RadioButton(label[i].c_str(), type == listTypes[i])) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), listTypes[i], set)), false); } ImGui::SameLine(); } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return true; } static bool InputText(const std::string& label, const std::function get, - const std::function set, ImGuiInputTextFlags flag = 0, - ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0) + const std::function set, std::string_view const& tooltip = {}, + ImGuiInputTextFlags flag = 0, ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0) { std::string text = get(); - if (ImGui::InputText(label.c_str(), &text, flag, callback, userData)) + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + if (ImGui::InputText("##", &text, flag, callback, userData)) { if (ImGui::IsItemDeactivatedAfterEdit()) SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), text, set)), false); return true; } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return false; } template - static bool DragScalar(const std::string& fieldLabel, ImGuiDataType data_type, std::function get, std::function set, - float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) + static bool DragScalar(const std::string& label, ImGuiDataType data_type, std::function get, std::function set, + float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, ImGuiSliderFlags flags = 0) { T value = get(); - const bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + const bool hasChange = ImGui::DragScalar("##", data_type, &value, speed, &p_min, &p_max, displayFormat, flags); static bool startRecording = false; if (hasChange) { @@ -376,6 +407,17 @@ namespace SHADE { startRecording = false; } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return hasChange; } @@ -412,11 +454,14 @@ namespace SHADE return hasChange; } - static bool DragInt(const std::string& fieldLabel, std::function get, std::function set, + static bool DragInt(const std::string& label, std::function get, std::function set, std::string_view const& tooltip = {}, float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { int value = get(); - const bool hasChange = ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + const bool hasChange = ImGui::DragInt("##", &value, speed, p_min, p_max, displayFormat, flags); static bool startRecording = false; if (hasChange) { @@ -428,16 +473,30 @@ namespace SHADE { startRecording = false; } + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return hasChange; } template - static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function get, std::function set, + static bool SliderScalar(const std::string& label, ImGuiDataType data_type, T min, T max, std::function get, std::function set, std::string_view const& tooltip = {}, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { T value = get(); - bool const changed = ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + bool const hasChange = ImGui::SliderScalar("##", data_type, &value, &min, &max, displayFormat, flags); static bool startRecording = false; - if (changed) + if (hasChange) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); if (!startRecording) @@ -448,16 +507,30 @@ namespace SHADE { startRecording = false; } - return changed; + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; } - static bool SliderFloat(const std::string& fieldLabel, float const& min, float const& max, std::function get, std::function set, + static bool SliderFloat(const std::string& label, float const& min, float const& max, std::function get, std::function set, std::string_view const& tooltip = {}, const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0) { float value = get(); - bool const changed = ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + bool const hasChange = ImGui::SliderFloat("##", &value, min, max, displayFormat, flags); static bool startRecording = false; - if (changed) + if (hasChange) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); if (!startRecording) @@ -468,16 +541,30 @@ namespace SHADE { startRecording = false; } - return changed; + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; } - static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function get, std::function set, + static bool SliderInt(const std::string& label, int min, int max, std::function get, std::function set, std::string_view const& tooltip = {}, const char* displayFormat = "%d", ImGuiSliderFlags flags = 0) { int value = get(); - bool const changed = ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags); + ImGui::BeginGroup(); + ImGui::PushID(label.data()); + TextLabel(label); + bool const hasChange = ImGui::SliderInt("##", &value, min, max, displayFormat, flags); static bool startRecording = false; - if (changed) + if (hasChange) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), value, set)), startRecording); @@ -488,21 +575,44 @@ namespace SHADE { startRecording = false; } - return false; + ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } + return hasChange; } - static bool ComboBox(const std::string& fieldLabel, std::vector list, std::function get, std::function set) + static bool ComboBox(const std::string& label, std::vector list, std::function get, std::function set, std::string_view const& tooltip = {}) { bool edited = false; int selected = get(); - ImGui::PushID(fieldLabel.c_str()); - ImGui::Text(fieldLabel.c_str()); ImGui::SameLine(); + ImGui::BeginGroup(); + ImGui::PushID(label.c_str()); + TextLabel(label); + ImGui::SameLine(); if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast(list.size()))) { SHCommandManager::PerformCommand(std::reinterpret_pointer_cast(std::make_shared>(get(), selected, set)), false); } ImGui::PopID(); + ImGui::EndGroup(); + if (!tooltip.empty()) + { + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text(tooltip.data()); + ImGui::EndTooltip(); + } + } return edited; } }; From 6d9a8e484c4b08a9642a6f6ff998efd036cafc33 Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Tue, 25 Oct 2022 20:55:46 +0800 Subject: [PATCH 27/28] Asset browser --- .../AssetBrowser/SHAssetBrowser.cpp | 84 +++++++++++++++++++ .../AssetBrowser/SHAssetBrowser.h | 24 ++++++ .../Inspector/SHEditorInspector.cpp | 4 +- .../EditorWindow/SHEditorWindowIncludes.h | 3 +- .../ViewportWindow/SHEditorViewport.cpp | 3 +- SHADE_Engine/src/Editor/SHEditor.cpp | 1 + 6 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp create mode 100644 SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp new file mode 100644 index 00000000..caad9b10 --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.cpp @@ -0,0 +1,84 @@ +#include "SHpch.h" +#include "SHAssetBrowser.h" + +#include "Editor/IconsMaterialDesign.h" +#include "Editor/SHImGuiHelpers.hpp" +#include + +#include "Assets/SHAssetManager.h" +#include "Editor/DragDrop/SHDragDrop.hpp" + +namespace SHADE +{ + SHAssetBrowser::SHAssetBrowser() + :SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar) + { + } + + void SHAssetBrowser::Init() + { + SHEditorWindow::Init(); + } + + void SHAssetBrowser::Update() + { + SHEditorWindow::Update(); + if(Begin()) + { + DrawMenuBar(); + auto const& assets = SHAssetManager::GetAllAssets(); + if(ImGui::BeginTable("AssetBrowserTable", 3)) + { + ImGui::TableNextColumn(); + ImGui::TableHeader("Asset ID"); + ImGui::TableNextColumn(); + ImGui::TableHeader("Name"); + ImGui::TableNextColumn(); + ImGui::TableHeader("Type"); + for(SHAsset const& asset : assets) + { + DrawAsset(asset); + } + ImGui::EndTable(); + } + } + ImGui::End(); + } + + void SHAssetBrowser::DrawMenuBar() + { + if(ImGui::BeginMenuBar()) + { + + ImGui::EndMenuBar(); + } + } + + void SHAssetBrowser::DrawAsset(SHAsset const& asset) + { + ImGui::PushID(asset.id); + ImGui::BeginGroup(); + + ImGui::TableNextColumn(); + ImGui::Selectable(std::format("{}", asset.id).data(), false, ImGuiSelectableFlags_SpanAllColumns); + if(SHDragDrop::BeginSource()) + { + auto id = asset.id; + ImGui::Text("Moving Asset: %zu", id); + SHDragDrop::SetPayload(DRAG_RESOURCE, &id); + SHDragDrop::EndSource(); + } + + ImGui::TableNextColumn(); + ImGui::Text("%s", asset.name.c_str()); + + ImGui::TableNextColumn(); + ImGui::Text("%s", "Type"); + + ImGui::EndGroup(); + ImGui::PopID(); + + + + } +} diff --git a/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h new file mode 100644 index 00000000..0e3053bc --- /dev/null +++ b/SHADE_Engine/src/Editor/EditorWindow/AssetBrowser/SHAssetBrowser.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Assets/SHAsset.h" +#include "Editor/EditorWindow/SHEditorWindow.h" + +namespace SHADE +{ + class SHAssetBrowser final : public SHEditorWindow + { + public: + SHAssetBrowser(); + + void Init(); + void Update(); + + void Refresh(); + private: + void DrawMenuBar(); + void DrawAsset(SHAsset const& asset); + + float idColumnWidth, nameColumnWidth, typeColumnWidth; + + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp index b59ce9cc..ada5a35a 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp @@ -84,8 +84,8 @@ namespace SHADE } ImGui::Separator(); // Render Scripts - SHScriptEngine* scriptEngine = static_cast(SHSystemManager::GetSystem()); - scriptEngine->RenderScriptsInInspector(eid); + SHScriptEngine* scriptEngine = static_cast(SHSystemManager::GetSystem()); + scriptEngine->RenderScriptsInInspector(eid); ImGui::Separator(); if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data())) { diff --git a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h index f0267b06..5208c6d9 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h +++ b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h @@ -3,4 +3,5 @@ #include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel #include "Inspector/SHEditorInspector.h" //Inspector #include "Profiling/SHEditorProfiler.h" //Profiler -#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport \ No newline at end of file +#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport +#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp index cb30fa81..f5170999 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/ViewportWindow/SHEditorViewport.cpp @@ -30,6 +30,7 @@ namespace SHADE void SHEditorViewport::Update() { SHEditorWindow::Update(); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f,0.0f)); if(Begin()) { ImGuizmo::SetDrawlist(); @@ -55,7 +56,7 @@ namespace SHADE ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y); transformGizmo.Draw(); ImGui::End(); - + ImGui::PopStyleVar(); } void SHEditorViewport::Exit() diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index 912f9d0f..06fadfee 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -92,6 +92,7 @@ namespace SHADE SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); + SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); io = &ImGui::GetIO(); From 534aeba06b4728e2f7a4e494e51b03ed903c34cb Mon Sep 17 00:00:00 2001 From: Sri Sham Haran Date: Tue, 25 Oct 2022 20:59:32 +0800 Subject: [PATCH 28/28] Latest Default Layout --- Assets/Editor/Layouts/Default.ini | 103 ++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 18 deletions(-) diff --git a/Assets/Editor/Layouts/Default.ini b/Assets/Editor/Layouts/Default.ini index 4ddc46c2..d7a7bf69 100644 --- a/Assets/Editor/Layouts/Default.ini +++ b/Assets/Editor/Layouts/Default.ini @@ -4,13 +4,13 @@ Size=1920,20 Collapsed=0 [Window][SHEditorMenuBar] -Pos=0,24 -Size=1920,1036 +Pos=0,48 +Size=1920,1012 Collapsed=0 [Window][Hierarchy Panel] -Pos=0,120 -Size=225,940 +Pos=0,197 +Size=308,863 Collapsed=0 DockId=0x00000004,0 @@ -20,29 +20,96 @@ Size=400,400 Collapsed=0 [Window][Inspector] -Pos=1686,24 -Size=234,1036 +Pos=1528,48 +Size=392,1012 Collapsed=0 DockId=0x00000006,0 [Window][Profiler] -Pos=0,24 -Size=225,94 +Pos=0,48 +Size=308,147 Collapsed=0 DockId=0x00000003,0 [Window][Viewport] -Pos=227,24 -Size=1457,1036 +Pos=227,48 +Size=1457,1012 Collapsed=0 -DockId=0x00000002,0 +DockId=0x0000000B,0 + +[Window][面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面o] +Pos=60,60 +Size=32,64 +Collapsed=0 + +[Window][面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面面] +Pos=60,60 +Size=999,581 +Collapsed=0 + +[Window][o] +Pos=60,60 +Size=32,64 +Collapsed=0 + +[Window][面面] +Pos=60,60 +Size=553,422 +Collapsed=0 + +[Window][] +Pos=60,60 +Size=770,394 +Collapsed=0 + +[Window][ Viewport] +Pos=227,48 +Size=1457,1012 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][ Viewport] +Pos=227,48 +Size=1457,1012 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][ Viewport] +Pos=310,48 +Size=1216,715 +Collapsed=0 +DockId=0x0000000B,0 + +[Window][V] +Pos=310,722 +Size=1501,338 +Collapsed=0 +DockId=0x00000008,0 + +[Window][p] +Pos=310,750 +Size=1501,310 +Collapsed=0 +DockId=0x0000000A,0 + +[Window][ Asset Browser] +Pos=310,765 +Size=1216,295 +Collapsed=0 +DockId=0x0000000C,0 [Docking][Data] -DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,55 Size=1920,1036 Split=X - DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1684,1036 Split=X - DockNode ID=0x00000001 Parent=0x00000005 SizeRef=225,1036 Split=Y Selected=0x1E6EB881 - DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881 - DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1293,1036 CentralNode=1 Selected=0x13926F0B - DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=234,1036 Selected=0xE7039252 +DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X + DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1526,1036 Split=X + DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881 + DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881 + DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,863 Selected=0xE096E5AE + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1216,1036 Split=Y Selected=0xB41284E7 + DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1501,672 Split=Y Selected=0xB41284E7 + DockNode ID=0x00000009 Parent=0x00000007 SizeRef=1501,700 Split=Y Selected=0xB41284E7 + DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,715 CentralNode=1 Selected=0xB41284E7 + DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,295 Selected=0xB128252A + DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6 + DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532 + DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=392,1036 Selected=0xE7039252