Added functionality for graphics system to render to swapchain image when SHEDITOR is disabled. #241

Merged
Xenosas1337 merged 6 commits from SP3-1-Rendering into main 2022-11-22 10:58:26 +08:00
37 changed files with 1078 additions and 177 deletions
Showing only changes of commit cd6edeeee4 - Show all commits

View File

@ -0,0 +1,20 @@
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12
12 13
13 14
14 15
15 16
note:
All collision tags should follow the above format "index<space>tag name".
If it fails to follow this, the default tag names will be used.

View File

@ -78,7 +78,10 @@ project "SHADE_Application"
"26451",
"26437",
"4275",
"4635"
"4633",
"4634",
"4635",
"4638"
}
linkoptions { "-IGNORE:4006" }

View File

@ -85,6 +85,7 @@ namespace Sandbox
SHSystemManager::CreateSystem<SHGraphicsSystem>();
SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
SHPhysicsSystem* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
// Link up SHDebugDraw
SHSystemManager::CreateSystem<SHDebugDrawSystem>();
@ -176,11 +177,16 @@ namespace Sandbox
#ifdef SHEDITOR
if(editor->editorState == SHEditor::State::PLAY)
SHSceneManager::SceneUpdate(0.016f);
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
editor->PollPicking();
#endif
#endif
SHSceneManager::SceneUpdate(0.016f);
#ifdef SHEDITOR
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, SHFrameRateController::GetRawDeltaTime());
editor->PollPicking();
#else
SHSystemManager::RunRoutines(false, SHFrameRateController::GetRawDeltaTime());
#endif
// TODO: Move into an Editor menu
static bool drawColliders = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
{
@ -193,6 +199,13 @@ namespace Sandbox
drawRays = !drawRays;
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays);
}
static bool drawContacts = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F9))
{
drawContacts = !drawContacts;
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_POINTS, drawContacts);
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_NORMALS, drawContacts);
}
}
// Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution();

View File

@ -7,6 +7,7 @@
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Physics/System/SHPhysicsSystem.h"
#include "Scripting/SHScriptEngine.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
@ -42,6 +43,28 @@ namespace Sandbox
void SBMainScene::Init()
{
sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID);
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (!physicsSystem)
{
SHLOGV_CRITICAL("Failed to get the physics system for building the scene!")
return;
}
physicsSystem->BuildScene(SHSceneManager::GetCurrentSceneGraph());
/*-----------------------------------------------------------------------*/
/* TESTING CODE */
/*-----------------------------------------------------------------------*/
//testText = SHEntityManager::CreateEntity<SHTransformComponent, SHTextRendererComponent>(MAX_EID, "Test Text");
//auto gfxSystem =SHSystemManager::GetSystem<SHGraphicsSystem>();
//auto textComp = SHComponentManager::GetComponent<SHTextRendererComponent>(testText);
//textComp->SetFont(gfxSystem->GetFontLibrary().GetFonts()[0]);
/*-----------------------------------------------------------------------*/
/* TESTING CODE */
/*-----------------------------------------------------------------------*/
}
void SBMainScene::Update(float dt)

View File

@ -79,7 +79,10 @@ project "SHADE_Engine"
"26451",
"26437",
"4275",
"4635"
"4633",
"4634",
"4635",
"4638"
}
linkoptions { "-IGNORE:4006" }

View File

@ -252,7 +252,7 @@ namespace SHADE
if(rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields
{
SHEditorWidgets::CheckBox("Use Gravity", [component]{return component->IsGravityEnabled();}, [component](bool const& value){component->SetGravityEnabled(value);}, "Gravity");
SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass");
//SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass");
}
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
{
@ -284,6 +284,7 @@ namespace SHADE
//Debug Info (Read-Only)
if(ImGui::CollapsingHeader("Debug Information", ImGuiTreeNodeFlags_DefaultOpen))//Dynamic or Kinematic only fields
{
SHEditorWidgets::DragFloat("Mass", [component] { return component->GetMass(); }, [](float value){}, "Mass", 0.1f, 0.0f, std::numeric_limits<float>::infinity(), "%.3f", ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component] {return component->GetPosition(); }, [](SHVec3 const& value) {}, false, "Position", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, [component] {return component->GetRotation(); }, [](SHVec3 const& value) {}, false, "Rotation", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields

View File

@ -4,9 +4,9 @@
\par email: kahwei.tng\@digipen.edu
\date Nov 7, 2021
\brief Contains the implementation of the EditorUI class.
Copyright (C) 2021 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
// Precompiled Header
@ -57,10 +57,10 @@ namespace SHADE
{
const bool OPENED = ImGui::CollapsingHeader(title.c_str(), ImGuiTreeNodeFlags_DefaultOpen);
if (isHovered)
*isHovered = ImGui::IsItemHovered();
*isHovered = ImGui::IsItemHovered();
return OPENED;
}
void SHEditorUI::SameLine()
{
ImGui::SameLine();
@ -98,7 +98,7 @@ namespace SHADE
void SHEditorUI::EndTooltip()
{
ImGui::EndTooltip();
ImGui::EndTooltip();
}
/*-----------------------------------------------------------------------------------*/
@ -146,7 +146,7 @@ namespace SHADE
bool SHEditorUI::Selectable(const std::string& label)
{
return ImGui::Selectable(label.data());
return ImGui::Selectable(label.data());
}
bool SHEditorUI::Selectable(const std::string& label, const char* icon)
@ -156,30 +156,41 @@ namespace SHADE
bool SHEditorUI::InputCheckbox(const std::string& label, bool& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
*isHovered = ImGui::IsItemHovered();
return ImGui::Checkbox("##", &value);
}
bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::DragInt("##", &value, 0.001f,
std::numeric_limits<int>::min(),
std::numeric_limits<int>::max(),
"%d",
ImGuiInputTextFlags_EnterReturnsTrue);
std::numeric_limits<int>::min(),
std::numeric_limits<int>::max(),
"%d",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered)
{
int signedVal = static_cast<int>(value);
ImGui::Text(label.c_str());
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
const bool CHANGED = InputInt("##", signedVal);
if (CHANGED)
@ -191,15 +202,19 @@ namespace SHADE
}
bool SHEditorUI::InputFloat(const std::string& label, float& value, bool* isHovered)
{
ImGui::Text(label.c_str());
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::DragFloat("##", &value, 0.001f,
std::numeric_limits<float>::lowest(),
std::numeric_limits<float>::max(),
"%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
std::numeric_limits<float>::lowest(),
std::numeric_limits<float>::max(),
"%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputDouble(const std::string& label, double& value, bool* isHovered)
{
@ -213,48 +228,56 @@ namespace SHADE
}
bool SHEditorUI::InputSlider(const std::string& label, int min, int max, int& value, bool* isHovered /*= nullptr*/)
{
if (!label.empty())
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::SliderInt("##", &value,
static_cast<float>(min), static_cast<float>(max), "%d",
ImGuiInputTextFlags_EnterReturnsTrue);
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::SliderInt("##", &value,
static_cast<float>(min), static_cast<float>(max), "%d",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputSlider(const std::string& label, unsigned int min, unsigned int max, unsigned int& value, bool* isHovered /*= nullptr*/)
{
int val = static_cast<int>(value);
const bool CHANGED = InputSlider(label, min, max, val, isHovered);
if (CHANGED)
{
value = static_cast<int>(val);
}
int val = static_cast<int>(value);
const bool CHANGED = InputSlider(label, min, max, val, isHovered);
if (CHANGED)
{
value = static_cast<int>(val);
}
return CHANGED;
return CHANGED;
}
bool SHEditorUI::InputSlider(const std::string& label, float min, float max, float& value, bool* isHovered)
{
if (!label.empty())
{
ImGui::Text(label.c_str());
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::SliderFloat("##", &value,
static_cast<float>(min), static_cast<float>(max), "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::SliderFloat("##", &value,
static_cast<float>(min), static_cast<float>(max), "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue);
}
bool SHEditorUI::InputSlider(const std::string& label, double min, double max, double& value, bool* isHovered /*= nullptr*/)
{
float val = static_cast<float>(value);
const bool CHANGED = InputSlider(label, min, max, val, isHovered);
if (CHANGED)
{
value = static_cast<double>(val);
}
float val = static_cast<float>(value);
const bool CHANGED = InputSlider(label, min, max, val, isHovered);
if (CHANGED)
{
value = static_cast<double>(val);
}
return CHANGED;
return CHANGED;
}
bool SHEditorUI::InputVec2(const std::string& label, SHVec2& value, bool* isHovered)
@ -264,7 +287,7 @@ namespace SHADE
}
bool SHEditorUI::InputVec3(const std::string& label, SHVec3& value, bool* isHovered)
{
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z"};
static const std::vector<std::string> COMPONENT_LABELS = { "X", "Y", "Z" };
return SHEditorWidgets::DragN<float, 3>(label, COMPONENT_LABELS, { &value.x, &value.y, &value.z }, 0.1f, "%.3f", float{}, float{}, 0, isHovered);
}
@ -272,9 +295,13 @@ namespace SHADE
{
std::array<char, TEXT_FIELD_MAX_LENGTH> buffer = { '\0' };
strcpy_s(buffer.data(), TEXT_FIELD_MAX_LENGTH, value.c_str());
ImGui::Text(label.c_str());
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
const bool CHANGED = ImGui::InputText("##", &buffer[0], TEXT_FIELD_MAX_LENGTH);
if (CHANGED)
@ -286,7 +313,11 @@ namespace SHADE
bool SHEditorUI::InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered, bool alwaysNull)
{
ImGui::Text(label.c_str());
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
@ -326,9 +357,13 @@ namespace SHADE
const std::string& INITIAL_NAME = v >= static_cast<int>(enumNames.size()) ? "Unknown" : enumNames[v];
bool b = false;
ImGui::Text(label.c_str());
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
if (ImGui::BeginCombo("##", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
{

View File

@ -55,7 +55,7 @@ namespace SHADE
void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept
{
Handle<SHMaterial> baseMat = renderable->GetMaterial()->GetBaseMaterial();
Handle<SHMaterial> baseMat = (renderable->HasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial())->GetBaseMaterial();
const Handle<SHVkPipeline> PIPELINE = baseMat->HasPipelineChanged() ? baseMat->GetPrevPipeline() : baseMat->GetPipeline();
// Check if we have a Batch with the same pipeline yet

View File

@ -119,15 +119,12 @@ namespace SHADE
SHFreetypeInstance::Init();
#ifdef _DEBUG
SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false);
SHAssetManager::CompileAsset("../../Assets/Shaders/Text_FS.glsl", false);
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl", false);
SHAssetManager::CompileAsset("../../Assets/Shaders/UI_VS.glsl", false);
SHAssetManager::CompileAsset("../../Assets/Shaders/UI_FS.glsl", false);
SHAssetManager::CompileAsset("../../Assets/Models/Quad.gltf", false);
#endif
//SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/Text_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/UI_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/UI_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Models/Quad.gltf", false);
// Load Built In Shaders

View File

@ -0,0 +1,223 @@
/****************************************************************************************
* \file SHCollisionTagMatrix.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for Collision Tag Matrix for handling sets of Collision Tags.
*
* \copyright 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 <fstream>
// Primary Header
#include "SHCollisionTagMatrix.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Static Data Member Definitions */
/*-----------------------------------------------------------------------------------*/
SHCollisionTag SHCollisionTagMatrix::collisionTags[SHCollisionTag::NUM_LAYERS];
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
const std::string& SHCollisionTagMatrix::GetTagName(int tagIndex)
{
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
return collisionTags[tagIndex].GetName();
}
int SHCollisionTagMatrix::GetTagIndex(const std::string& tagName) noexcept
{
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
{
if (collisionTags[i].GetName() == tagName)
return i;
}
SHLOGV_WARNING("Collision Tag {} cannot be found!", tagName)
return -1;
}
SHCollisionTag* SHCollisionTagMatrix::GetTag(int tagIndex)
{
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
return &collisionTags[tagIndex];
}
SHCollisionTag* SHCollisionTagMatrix::GetTag(const std::string& tagName) noexcept
{
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
{
if (collisionTags[i].GetName() == tagName)
return &collisionTags[i];
}
SHLOGV_WARNING("Collision Tag {} cannot be found!", tagName)
return nullptr;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollisionTagMatrix::SetTagName(const std::string& oldTagName, const std::string& newTagName) noexcept
{
for (auto& collisionTag : collisionTags)
{
if (collisionTag.GetName() != oldTagName)
continue;
collisionTag.SetName(newTagName);
return;
}
SHLOGV_WARNING("Collision tag {} cannot be found!", oldTagName)
}
void SHCollisionTagMatrix::SetTag(const std::string& tagName, const SHCollisionTag& newTag) noexcept
{
for (auto& collisionTag : collisionTags)
{
if (collisionTag.GetName() != tagName)
continue;
collisionTag = newTag;
return;
}
SHLOGV_WARNING("Collision tag {} cannot be found!", tagName)
}
void SHCollisionTagMatrix::SetTag(const std::string& tagName, uint16_t mask) noexcept
{
for (auto& collisionTag : collisionTags)
{
if (collisionTag.GetName() != tagName)
continue;
collisionTag.SetMask(mask);
return;
}
SHLOGV_WARNING("Collision tag {} cannot be found!", tagName)
}
void SHCollisionTagMatrix::SetTagName(int tagIndex, const std::string& newTagName)
{
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
collisionTags[tagIndex].SetName(newTagName);
}
void SHCollisionTagMatrix::SetTag(int tagIndex, const SHCollisionTag& newTag)
{
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
collisionTags[tagIndex] = newTag;
}
void SHCollisionTagMatrix::SetTag(int tagIndex, uint16_t mask)
{
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
collisionTags[tagIndex].SetMask(mask);
}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollisionTagMatrix::Init(const std::filesystem::path& tagNameFilePath) noexcept
{
/**
* I HATE FILE IO
*
* Each line in the file should be "index<space>tag name".
* If the line fails to follow this format, use the default tag name (index + 1)
*/
// Populate tag names with default
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
collisionTags[i].SetName(std::to_string(i + 1));
std::ifstream collisionTagNamesFile { tagNameFilePath };
if (!collisionTagNamesFile.is_open())
{
SHLOG_ERROR("Failed to open file for Collision Tag Names! Default tag names used!")
return;
}
std::stringstream ss;
std::string line;
int linesRead = 0;
while (std::getline(collisionTagNamesFile, line))
{
// Do not read anything beyond the first 16 lines
if (linesRead >= 16)
break;
ss << line;
++linesRead;
// First element is index.
int tagIndex;
ss >> tagIndex;
// Next element is name of the tag
std::string tagName;
ss >> tagName;
// If no tag name read, use default.
if (tagName.empty())
{
SHLOG_ERROR
(
"Collision tag file line {} does not match the required format of 'index<space>tag name'. Default tag used for index {}"
, linesRead + 1
, tagIndex
)
// Use default
collisionTags[tagIndex].SetName(std::to_string(tagIndex + 1));
continue;
}
collisionTags[tagIndex].SetName(tagName);
ss.clear();
}
collisionTagNamesFile.close();
}
void SHCollisionTagMatrix::Exit(const std::filesystem::path& tagNameFilePath) noexcept
{
std::ofstream collisionTagNamesFile { tagNameFilePath };
if (!collisionTagNamesFile.is_open())
{
SHLOG_ERROR("Failed to open file for Collision Tag Names! Tag names not saved!")
return;
}
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
collisionTagNamesFile << i << " " << collisionTags[i].GetName() << std::endl;
collisionTagNamesFile.close();
}
} // namespace SHADE

View File

@ -0,0 +1,67 @@
/****************************************************************************************
* \file SHCollisionTagMatrix.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for Collision Tag Matrix for handling sets of Collision Tags.
*
* \copyright 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 <filesystem>
// Project Includes
#include "SH_API.h"
#include "SHCollisionTags.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHCollisionTagMatrix
{
public:
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] static const std::string& GetTagName (int tagIndex);
[[nodiscard]] static int GetTagIndex (const std::string& tagName) noexcept;
[[nodiscard]] static SHCollisionTag* GetTag (int tagIndex);
[[nodiscard]] static SHCollisionTag* GetTag (const std::string& tagName) noexcept;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
static void SetTagName (const std::string& oldTagName, const std::string& newTagName) noexcept;
static void SetTag (const std::string& tagName, const SHCollisionTag& newTag) noexcept;
static void SetTag (const std::string& tagName, uint16_t mask) noexcept;
// Unsafe Setters: Can throw exceptions
static void SetTagName (int tagIndex, const std::string& newTagName);
static void SetTag (int tagIndex, const SHCollisionTag& newTag);
static void SetTag (int tagIndex, uint16_t mask);
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
static void Init (const std::filesystem::path& tagNameFilePath) noexcept;
static void Exit (const std::filesystem::path& tagNameFilePath) noexcept;
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
static SHCollisionTag collisionTags[SHCollisionTag::NUM_LAYERS];
};
}

View File

@ -0,0 +1,116 @@
/****************************************************************************************
* \file SHCollisionTags.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for Collision Tags for filtering collisions.
*
* \copyright 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 <fstream>
// Primary Header
#include "SHCollisionTags.h"
// Project Headers
#include "Tools/Utilities/SHUtilities.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHCollisionTag::SHCollisionTag() noexcept
: mask { SHUtilities::ConvertEnum(Layer::ALL) }
{}
SHCollisionTag::SHCollisionTag(uint16_t _mask) noexcept
: mask { _mask }
{}
SHCollisionTag::SHCollisionTag(Layer layer) noexcept
: mask { SHUtilities::ConvertEnum(layer) }
{}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
bool SHCollisionTag::operator==(const SHCollisionTag& rhs) const noexcept
{
return mask == rhs.mask;
}
bool SHCollisionTag::operator!=(const SHCollisionTag& rhs) const noexcept
{
return mask != rhs.mask;
}
SHCollisionTag::operator uint16_t() const noexcept
{
return mask;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
uint16_t SHCollisionTag::GetMask() const noexcept
{
return mask;
}
const std::string& SHCollisionTag::GetName() const noexcept
{
return name;
}
bool SHCollisionTag::GetLayerState(Layer layer) const noexcept
{
return (mask & SHUtilities::ConvertEnum(layer)) > 0;
}
bool SHCollisionTag::GetLayerState(int layerIndex) const
{
if (layerIndex < 0 || layerIndex > NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
return (mask & (1U << layerIndex)) > 0;
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHCollisionTag::SetMask(uint16_t newMask) noexcept
{
mask = newMask;
}
void SHCollisionTag::SetName(const std::string_view& newName) noexcept
{
name = newName;
}
void SHCollisionTag::SetLayerState(Layer layer, bool state) noexcept
{
const auto VALUE = SHUtilities::ConvertEnum(layer);
state ? mask |= VALUE : mask &= ~(VALUE);
}
void SHCollisionTag::SetLayerState(int layerIndex, bool state)
{
if (layerIndex < 0 || layerIndex > NUM_LAYERS)
throw std::invalid_argument("Index out of range!");
const auto VALUE = 1U << layerIndex;
state ? mask |= (VALUE) : mask &= ~(VALUE);
}
} // namespace SHADE
SHADE::SHCollisionTag::Layer operator|(SHADE::SHCollisionTag::Layer lhs, SHADE::SHCollisionTag::Layer rhs) noexcept
{
return static_cast<SHADE::SHCollisionTag::Layer>(SHADE::SHUtilities::ConvertEnum(lhs) | SHADE::SHUtilities::ConvertEnum(rhs));
}

View File

@ -0,0 +1,112 @@
/****************************************************************************************
* \file SHCollisionTags.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for Collision Tags for filtering collisions.
*
* \copyright 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 <string>
// Project Headers
#include "SH_API.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
class SH_API SHCollisionTag
{
public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
enum class Layer : uint16_t
{
_1 = 0x0001
, _2 = 0x0002
, _3 = 0x0004
, _4 = 0x0008
, _5 = 0x0010
, _6 = 0x0020
, _7 = 0x0040
, _8 = 0x0080
, _9 = 0x0100
, _10 = 0x0200
, _11 = 0x0400
, _12 = 0x0800
, _13 = 0x1000
, _14 = 0x2000
, _15 = 0x4000
, _16 = 0x8000
, ALL = 0xFFFF
};
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
static constexpr int NUM_LAYERS = 16;
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHCollisionTag () noexcept;
SHCollisionTag (uint16_t mask) noexcept;
SHCollisionTag (Layer layer) noexcept;
SHCollisionTag (const SHCollisionTag&) noexcept = default;
SHCollisionTag (SHCollisionTag&&) noexcept = default;
~SHCollisionTag () = default;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHCollisionTag& operator=(const SHCollisionTag&) noexcept = default;
SHCollisionTag& operator=(SHCollisionTag&&) noexcept = default;
[[nodiscard]] bool operator==(const SHCollisionTag& rhs) const noexcept;
[[nodiscard]] bool operator!=(const SHCollisionTag& rhs) const noexcept;
operator uint16_t() const noexcept;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] uint16_t GetMask () const noexcept;
[[nodiscard]] const std::string& GetName () const noexcept;
[[nodiscard]] bool GetLayerState (Layer layer) const noexcept;
[[nodiscard]] bool GetLayerState (int layerIndex) const;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
void SetMask (uint16_t newMask) noexcept;
void SetName (const std::string_view& newName) noexcept;
void SetLayerState (Layer layer, bool state) noexcept;
void SetLayerState (int layerIndex, bool state);
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
uint16_t mask;
std::string name;
};
} // namespace SHADE
SHADE::SHCollisionTag::Layer SH_API operator|(SHADE::SHCollisionTag::Layer lhs, SHADE::SHCollisionTag::Layer rhs) noexcept;

View File

@ -80,6 +80,14 @@ namespace SHADE
}
system = physicsSystem;
// Sync with transform if one already exists
if (auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(GetEID()); transformComponent)
{
position = transformComponent->GetWorldPosition();
orientation = transformComponent->GetWorldOrientation();
scale = transformComponent->GetWorldScale();
}
}
void SHColliderComponent::OnDestroy()

View File

@ -16,6 +16,7 @@
#include "Math/Geometry/SHBox.h"
#include "Math/Geometry/SHSphere.h"
#include "Math/SHMathHelpers.h"
#include "Physics/Collision/SHCollisionTagMatrix.h"
#include "Reflection/SHReflectionMetadata.h"
#include "SHColliderComponent.h"
@ -26,12 +27,13 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
SHCollisionShape::SHCollisionShape(EntityID eid, Type colliderType, const SHPhysicsMaterial& physicsMaterial)
: type { colliderType }
, entityID { eid }
, isTrigger { false }
, dirty { true }
, shape { nullptr }
, material { physicsMaterial }
: type { colliderType }
, entityID { eid }
, isTrigger { false }
, dirty { true }
, shape { nullptr }
, material { physicsMaterial }
, collisionTag { SHCollisionTagMatrix::GetTag(0) }
{
switch (type)
{
@ -57,6 +59,8 @@ namespace SHADE
, shape { nullptr }
, material { rhs.material }
, positionOffset { rhs.positionOffset }
, rotationOffset { rhs.rotationOffset }
, collisionTag { rhs.collisionTag }
{
CopyShape(rhs.shape);
}
@ -69,6 +73,8 @@ namespace SHADE
, shape { nullptr }
, material { rhs.material }
, positionOffset { rhs.positionOffset }
, rotationOffset { rhs.rotationOffset }
, collisionTag { rhs.collisionTag }
{
CopyShape(rhs.shape);
}
@ -93,6 +99,8 @@ namespace SHADE
dirty = true;
material = rhs.material;
positionOffset = rhs.positionOffset;
rotationOffset = rhs.rotationOffset;
collisionTag = rhs.collisionTag;
delete shape;
CopyShape(rhs.shape);
@ -108,6 +116,8 @@ namespace SHADE
dirty = true;
material = rhs.material;
positionOffset = rhs.positionOffset;
rotationOffset = rhs.rotationOffset;
collisionTag = rhs.collisionTag;
delete shape;
CopyShape(rhs.shape);
@ -134,6 +144,11 @@ namespace SHADE
return type;
}
const SHCollisionTag& SHCollisionShape::GetCollisionTag() const noexcept
{
return *collisionTag;
}
float SHCollisionShape::GetFriction() const noexcept
{
return material.GetFriction();
@ -240,6 +255,12 @@ namespace SHADE
isTrigger = trigger;
}
void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept
{
dirty = true;
collisionTag = newCollisionTag;
}
void SHCollisionShape::SetFriction(float friction) noexcept
{
dirty = true;

View File

@ -17,6 +17,7 @@
#include "Math/Geometry/SHShape.h"
#include "Math/SHQuaternion.h"
#include "SHPhysicsMaterial.h"
#include "Physics/Collision/SHCollisionTags.h"
namespace SHADE
{
@ -74,6 +75,8 @@ namespace SHADE
[[nodiscard]] Type GetType () const noexcept;
[[nodiscard]] const SHCollisionTag& GetCollisionTag () const noexcept;
[[nodiscard]] float GetFriction () const noexcept;
[[nodiscard]] float GetBounciness () const noexcept;
[[nodiscard]] float GetDensity () const noexcept;
@ -92,6 +95,7 @@ namespace SHADE
void SetBoundingSphere (float radius);
void SetIsTrigger (bool isTrigger) noexcept;
void SetCollisionTag (SHCollisionTag* newCollisionTag) noexcept;
void SetFriction (float friction) noexcept;
void SetBounciness (float bounciness) noexcept;
void SetDensity (float density) noexcept;
@ -109,11 +113,15 @@ namespace SHADE
EntityID entityID; // The entity this collider belongs to
bool isTrigger;
bool dirty;
SHShape* shape;
SHPhysicsMaterial material;
SHVec3 positionOffset;
SHVec3 rotationOffset;
SHCollisionTag* collisionTag;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/

View File

@ -322,25 +322,25 @@ namespace SHADE
// dirtyFlags |= 1U << FLAG_POS;
//}
void SHRigidBodyComponent::SetMass(float newMass) noexcept
{
static constexpr int FLAG_POS = 9;
//void SHRigidBodyComponent::SetMass(float newMass) noexcept
//{
// static constexpr int FLAG_POS = 9;
if (newMass < 0.0f)
return;
// if (newMass < 0.0f)
// return;
if (type != Type::DYNAMIC)
{
SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
return;
}
// if (type != Type::DYNAMIC)
// {
// SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
// return;
// }
dirtyFlags |= 1U << FLAG_POS;
mass = newMass;
// dirtyFlags |= 1U << FLAG_POS;
// mass = newMass;
// Turn off automass
flags &= ~(1U << FLAG_POS);
}
// // Turn off automass
// flags &= ~(1U << FLAG_POS);
//}
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
{
@ -411,6 +411,13 @@ namespace SHADE
}
system = physicsSystem;
// Sync with transform if one already exists
if (auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(GetEID()); transformComponent)
{
position = transformComponent->GetWorldPosition();
orientation = transformComponent->GetWorldOrientation();
}
}
void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept
@ -489,7 +496,7 @@ RTTR_REGISTRATION
registration::class_<SHRigidBodyComponent>("RigidBody Component")
.property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType )
.property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass )
//.property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass )
.property("Drag" , &SHRigidBodyComponent::GetDrag , &SHRigidBodyComponent::SetDrag )
.property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag )
.property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled )

View File

@ -114,7 +114,7 @@ namespace SHADE
void SetInterpolate (bool allowInterpolation) noexcept;
//void SetAutoMass (bool autoMass) noexcept;
void SetMass (float newMass) noexcept;
//void SetMass (float newMass) noexcept;
void SetDrag (float newDrag) noexcept;
void SetAngularDrag (float newAngularDrag) noexcept;

View File

@ -94,7 +94,7 @@ namespace SHADE
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
int SHPhysicsObject::AddCollisionShape(int index) const
int SHPhysicsObject::AddCollisionShape(int index)
{
// Get collider component
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
@ -123,13 +123,19 @@ namespace SHADE
default: break;
}
rp3dBody->updateLocalCenterOfMassFromColliders();
rp3dBody->updateLocalInertiaTensorFromColliders();
if (rp3dBody->getType() == rp3d::BodyType::DYNAMIC)
{
rp3dBody->updateMassPropertiesFromColliders();
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
if (rigidBodyComponent)
rigidBodyComponent->mass = rp3dBody->getMass();
}
return index;
}
void SHPhysicsObject::RemoveCollisionShape(int index) const
void SHPhysicsObject::RemoveCollisionShape(int index)
{
const int NUM_COLLIDERS = static_cast<int>(rp3dBody->getNbColliders());
if (NUM_COLLIDERS == 0)
@ -140,6 +146,15 @@ namespace SHADE
auto* collider = rp3dBody->getCollider(index);
rp3dBody->removeCollider(collider);
if (rp3dBody->getType() == rp3d::BodyType::DYNAMIC)
{
rp3dBody->updateMassPropertiesFromColliders();
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
if (rigidBodyComponent)
rigidBodyComponent->mass = rp3dBody->getMass();
}
}
void SHPhysicsObject::RemoveAllCollisionShapes() const noexcept
@ -254,6 +269,8 @@ namespace SHADE
}
case 9: // Mass
{
//rp3dBody->setMass(component.mass);
//if (component.GetAutoMass())
//{
// rp3dBody->updateMassPropertiesFromColliders();
@ -261,9 +278,9 @@ namespace SHADE
//}
//else
//{
rp3dBody->setMass(component.mass);
rp3dBody->updateLocalCenterOfMassFromColliders();
rp3dBody->updateLocalInertiaTensorFromColliders();
// rp3dBody->setMass(component.mass);
// rp3dBody->updateLocalCenterOfMassFromColliders();
// rp3dBody->updateLocalInertiaTensorFromColliders();
//}
break;
@ -309,7 +326,18 @@ namespace SHADE
default: break;
}
syncMaterial(i, collisionShape);
// Sync material
auto* rp3dCollider = rp3dBody->getCollider(i);
auto& rp3dMaterial = rp3dCollider->getMaterial();
rp3dMaterial.setFrictionCoefficient(collisionShape.GetFriction());
rp3dMaterial.setBounciness(collisionShape.GetBounciness());
rp3dMaterial.setMassDensity(collisionShape.GetDensity());
// Sync tags
const unsigned short MASK_BITS = collisionShape.GetCollisionTag();
rp3dCollider->setCollisionCategoryBits(MASK_BITS);
rp3dCollider->setCollideWithMaskBits(MASK_BITS);
collisionShape.dirty = false;
}
@ -319,14 +347,6 @@ namespace SHADE
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsObject::syncMaterial(int colliderIndex, SHCollisionShape& collisionShape) const noexcept
{
auto& rp3dMaterial = rp3dBody->getCollider(colliderIndex)->getMaterial();
rp3dMaterial.setFrictionCoefficient(collisionShape.GetFriction());
rp3dMaterial.setBounciness(collisionShape.GetBounciness());
rp3dMaterial.setMassDensity(collisionShape.GetDensity());
}
void SHPhysicsObject::addBoxShape(SHCollisionShape& boxShape) const noexcept
{
const rp3d::Transform OFFSETS

View File

@ -71,8 +71,8 @@ namespace SHADE
/* Function Members */
/*---------------------------------------------------------------------------------*/
int AddCollisionShape (int index) const;
void RemoveCollisionShape (int index) const;
int AddCollisionShape (int index);
void RemoveCollisionShape (int index);
void RemoveAllCollisionShapes () const noexcept;
void SyncRigidBody (SHRigidBodyComponent& component) const noexcept;
@ -96,16 +96,14 @@ namespace SHADE
/* Function Members */
/*---------------------------------------------------------------------------------*/
void syncMaterial (int colliderIndex, SHCollisionShape& collisionShape) const noexcept;
// Box Shapes
void addBoxShape (SHCollisionShape& boxShape) const noexcept;
void syncBoxShape (int index, SHCollisionShape& boxShape) const noexcept;
void addBoxShape (SHCollisionShape& boxShape) const noexcept;
void syncBoxShape (int index, SHCollisionShape& boxShape) const noexcept;
// Sphere Shapes
void addSphereShape (SHCollisionShape& sphereShape) const noexcept;
void syncSphereShape (int index, SHCollisionShape& sphereShape) const noexcept;
void addSphereShape (SHCollisionShape& sphereShape) const noexcept;
void syncSphereShape (int index, SHCollisionShape& sphereShape) const noexcept;
};
} // namespace SHADE

View File

@ -15,6 +15,7 @@
// Project Headers
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.h"
#include "Scene/SHSceneManager.h"
namespace SHADE
@ -118,11 +119,22 @@ namespace SHADE
return;
}
rp3d::DebugRenderer* rp3dRenderer = nullptr;
#ifdef SHEDITOR
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
{
rp3dRenderer = &system->physicsSystem->worldState.world->getDebugRenderer();
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, false);
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, false);
}
#endif
for (int i = 0; i < SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); ++i)
{
const bool DRAW = (system->debugDrawFlags & (1U << i)) > 0;
if (DRAW)
drawFunctions[i](debugDrawSystem);
drawFunctions[i](debugDrawSystem, rp3dRenderer);
}
// Automatically clear the container of raycasts despite debug drawing state
@ -134,7 +146,7 @@ namespace SHADE
/* Private Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
void SHPhysicsDebugDrawSystem::drawColliders(SHDebugDrawSystem* debugRenderer) noexcept
void SHPhysicsDebugDrawSystem::drawColliders(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{
const auto& COLLIDER_SET = SHComponentManager::GetDense<SHColliderComponent>();
for (const auto& COLLIDER : COLLIDER_SET)
@ -155,27 +167,53 @@ namespace SHADE
}
}
void SHPhysicsDebugDrawSystem::drawColliderAABBs(SHDebugDrawSystem* debugRenderer) noexcept
void SHPhysicsDebugDrawSystem::drawColliderAABBs(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{
}
void SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs(SHDebugDrawSystem* debugRenderer) noexcept
void SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{
}
void SHPhysicsDebugDrawSystem::drawContactPoints(SHDebugDrawSystem* debugRenderer) noexcept
void SHPhysicsDebugDrawSystem::drawContactPoints(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{
#ifdef SHEDITOR
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
{
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, true);
const int NUM_TRIS = static_cast<int>(rp3dRenderer->getNbTriangles());
if (NUM_TRIS == 0)
return;
const auto& TRI_ARRAY = rp3dRenderer->getTrianglesArray();
for (int i = 0; i < NUM_TRIS; ++i)
debugRenderer->DrawTri(SHColour::RED, TRI_ARRAY[i].point1, TRI_ARRAY[i].point2, TRI_ARRAY[i].point3);
}
#endif
}
void SHPhysicsDebugDrawSystem::drawContactNormals(SHDebugDrawSystem* debugRenderer) noexcept
void SHPhysicsDebugDrawSystem::drawContactNormals(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{
#ifdef SHEDITOR
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
{
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, true);
const int NUM_LINES = static_cast<int>(rp3dRenderer->getNbLines());
if (NUM_LINES == 0)
return;
const auto& LINE_ARRAY = rp3dRenderer->getLinesArray();
for (int i = 0; i < NUM_LINES; ++i)
debugRenderer->DrawLine(SHColour::RED, LINE_ARRAY[i].point1, LINE_ARRAY[i].point2);
}
#endif
}
void SHPhysicsDebugDrawSystem::drawRaycasts(SHDebugDrawSystem* debugRenderer) noexcept
void SHPhysicsDebugDrawSystem::drawRaycasts(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
{
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (!physicsSystem)

View File

@ -93,7 +93,7 @@ namespace SHADE
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
using DebugDrawFunction = void(*)(SHDebugDrawSystem*) noexcept;
using DebugDrawFunction = void(*)(SHDebugDrawSystem*, rp3d::DebugRenderer*) noexcept;
/*---------------------------------------------------------------------------------*/
/* Data Members */
@ -118,12 +118,12 @@ namespace SHADE
// Generic Draw Functions
static void drawColliders (SHDebugDrawSystem* debugRenderer) noexcept;
static void drawColliderAABBs (SHDebugDrawSystem* debugRenderer) noexcept;
static void drawBroadPhaseAABBs (SHDebugDrawSystem* debugRenderer) noexcept;
static void drawContactPoints (SHDebugDrawSystem* debugRenderer) noexcept;
static void drawContactNormals (SHDebugDrawSystem* debugRenderer) noexcept;
static void drawRaycasts (SHDebugDrawSystem* debugRenderer) noexcept;
static void drawColliders (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
static void drawColliderAABBs (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
static void drawBroadPhaseAABBs (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
static void drawContactPoints (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
static void drawContactNormals (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
static void drawRaycasts (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
// Shape Generation Functions

View File

@ -14,10 +14,12 @@
#include "SHPhysicsSystem.h"
// Project Headers
#include "Assets/SHAssetMacros.h"
#include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/SHEditor.h"
#include "Physics/Collision/SHCollisionTagMatrix.h"
#include "Physics/SHPhysicsEvents.h"
#include "Scene/SHSceneManager.h"
#include "Scripting/SHScriptEngine.h"
@ -90,6 +92,18 @@ namespace SHADE
void SHPhysicsSystem::Init()
{
// Initialise collision tags
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig");
SHCollisionTagMatrix::Init(defaultCollisionTagNameFilePath);
// Link Physics Object Manager with System & Raycaster
objectManager.SetFactory(factory);
raycaster.SetObjectManager(&objectManager);
// Link Collision Listener with System
collisionListener.BindToSystem(this);
// Subscribe to component events
const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::addPhysicsComponent) };
const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ADD_COMPONENT_RECEIVER);
@ -111,17 +125,66 @@ namespace SHADE
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, ON_STOP_RECEIVER_PTR);
#endif
// Link Physics Object Manager with System & Raycaster
objectManager.SetFactory(factory);
raycaster.SetObjectManager(&objectManager);
// Link Collision Listener with System
collisionListener.BindToSystem(this);
}
void SHPhysicsSystem::Exit()
{
worldState.DestroyWorld(factory);
// Write collision tag names to file
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig");
SHCollisionTagMatrix::Exit(defaultCollisionTagNameFilePath);
}
void SHPhysicsSystem::BuildScene(SHSceneGraph& sceneGraph)
{
static const auto BUILD_NEW_SCENE_PHYSICS_OBJECT = [&](SHSceneNode* node)
{
const EntityID EID = node->GetEntityID();
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(EID))
objectManager.AddRigidBody(EID);
if (SHComponentManager::HasComponent<SHColliderComponent>(EID))
objectManager.AddCollider(EID);
};
////////////////////////////////
// Destroy an existing world
if (worldState.world != nullptr)
{
objectManager.RemoveAllObjects();
objectManager.SetWorld(nullptr);
collisionListener.ClearContainers();
raycaster.ClearFrame();
worldState.DestroyWorld(factory);
}
worldState.CreateWorld(factory);
#ifdef _PUBLISH
worldState.world->setIsDebugRenderingEnabled(false);
#else
worldState.world->setIsDebugRenderingEnabled(true);
#endif
// Link Collision Listener & Raycaster
collisionListener.BindToWorld(worldState.world);
raycaster.BindToWorld(worldState.world);
// Link with object manager & create all physics objects
objectManager.SetWorld(worldState.world);
// When building a scene, clear the object manager command queue and build scene objects again.
// This is done to avoid duplicate adds.
while (!objectManager.commandQueue.empty())
objectManager.commandQueue.pop();
sceneGraph.Traverse(BUILD_NEW_SCENE_PHYSICS_OBJECT);
}
void SHPhysicsSystem::ForceUpdate()
@ -216,10 +279,13 @@ namespace SHADE
{
objectManager.AddCollisionShape(entityID, index);
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
auto& collisionShape = colliderComponent->GetCollisionShape(index);
const SHPhysicsColliderAddedEvent COLLIDER_ADDED_EVENT_DATA
{
.entityID = entityID
, .colliderType = SHComponentManager::GetComponent<SHColliderComponent>(entityID)->GetCollisionShape(index).GetType()
, .colliderType = collisionShape.GetType()
, .colliderIndex = index
};
@ -355,6 +421,11 @@ namespace SHADE
return onPlayEvent->handle;
worldState.CreateWorld(factory);
#ifdef _PUBLISH
worldState.world->setIsDebugRenderingEnabled(false);
#else
worldState.world->setIsDebugRenderingEnabled(true);
#endif
// Link Collision Listener & Raycaster
collisionListener.BindToWorld(worldState.world);
@ -363,8 +434,8 @@ namespace SHADE
// Link with object manager & create all physics objects
objectManager.SetWorld(worldState.world);
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
SCENE_GRAPH.Traverse(BUILD_PHYSICS_OBJECT);
// Build scene
SHSceneManager::GetCurrentSceneGraph().Traverse(BUILD_PHYSICS_OBJECT);
return onPlayEvent->handle;
}
@ -378,11 +449,11 @@ namespace SHADE
// Clear all collision info
// Collision listener is automatically unbound when world is destroyed
collisionListener.ClearContainers();
raycaster.ClearFrame();
// Destroy the world
worldState.DestroyWorld(factory);
return onStopEvent->handle;
}
} // namespace SHADE

View File

@ -27,7 +27,7 @@
#include "Physics/Interface/SHColliderComponent.h"
#include "Physics/PhysicsObject/SHPhysicsObjectManager.h"
#include "Physics/SHPhysicsWorld.h"
#include "Scene/SHSceneGraph.h"
namespace SHADE
{
@ -74,10 +74,12 @@ namespace SHADE
/* Function Members */
/*---------------------------------------------------------------------------------*/
void Init () override;
void Exit () override;
void Init () override;
void Exit () override;
void BuildScene (SHSceneGraph& sceneGraph);
void ForceUpdate ();
void ForceUpdate ();
/**
* @brief Casts a ray into the world.
@ -280,11 +282,11 @@ namespace SHADE
/* Function Members */
/*---------------------------------------------------------------------------------*/
SHEventHandle addPhysicsComponent (SHEventPtr addComponentEvent) noexcept;
SHEventHandle removePhysicsComponent (SHEventPtr removeComponentEvent) noexcept;
SHEventHandle onPlay (SHEventPtr onPlayEvent);
SHEventHandle onStop (SHEventPtr onStopEvent);
SHEventHandle addPhysicsComponent (SHEventPtr addComponentEvent) noexcept;
SHEventHandle removePhysicsComponent (SHEventPtr removeComponentEvent) noexcept;
SHEventHandle onPlay (SHEventPtr onPlayEvent);
SHEventHandle onStop (SHEventPtr onStopEvent);
SHEventHandle buildScene (SHEventPtr onSceneChangeEvent);
};
} // namespace SHADE

View File

@ -1,7 +1,7 @@
/****************************************************************************************
* \file SHSceneGraphEvents.h
* \file SHSceneEvents.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for Scene Graph Events.
* \brief Interface for Scene Events.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
@ -21,21 +21,21 @@ namespace SHADE
struct SHSceneGraphChangeParentEvent
{
SHSceneNode* node;
SHSceneNode* oldParent;
SHSceneNode* newParent;
SHSceneNode* node = nullptr;
SHSceneNode* oldParent = nullptr;
SHSceneNode* newParent = nullptr;
};
struct SHSceneGraphAddChildEvent
{
SHSceneNode* parent;
SHSceneNode* childAdded;
SHSceneNode* parent = nullptr;
SHSceneNode* childAdded = nullptr;
};
struct SHSceneGraphRemoveChildEvent
{
SHSceneNode* parent;
SHSceneNode* childRemoved;
SHSceneNode* parent = nullptr;
SHSceneNode* childRemoved = nullptr;
};
} // namespace SHADE

View File

@ -16,7 +16,7 @@
#include "ECS_Base/Entity/SHEntity.h"
#include "SH_API.h"
#include "SHSceneNode.h"
#include "SHSceneGraphEvents.h"
#include "SHSceneEvents.h"
namespace SHADE
{

View File

@ -85,7 +85,6 @@ namespace SHADE
currentScene->Load();
currentScene->Init();
}
}
else // restarting scene
{

View File

@ -27,7 +27,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Events/SHEventManager.hpp"
#include "Physics/System/SHPhysicsSystem.h"
#include "Physics/SHPhysicsEvents.h"
#include "Scene/SHSceneGraphEvents.h"
#include "Scene/SHSceneEvents.h"
#include "Assets/SHAssetMacros.h"

View File

@ -116,6 +116,7 @@ namespace YAML
static constexpr const char* Bounciness = "Bounciness";
static constexpr const char* Density = "Density";
static constexpr const char* PositionOffset = "Position Offset";
static constexpr const char* RotationOffset = "Rotation Offset";
static Node encode(SHCollisionShape& rhs)
{
@ -151,6 +152,7 @@ namespace YAML
node[Bounciness] = rhs.GetBounciness();
node[Density] = rhs.GetDensity();
node[PositionOffset] = rhs.GetPositionOffset();
node[RotationOffset] = rhs.GetRotationOffset();
return node;
}
@ -191,6 +193,8 @@ namespace YAML
rhs.SetDensity(node[Density].as<float>());
if (node[PositionOffset].IsDefined())
rhs.SetPositionOffset(node[PositionOffset].as<SHVec3>());
if (node[RotationOffset].IsDefined())
rhs.SetRotationOffset(node[RotationOffset].as<SHVec3>());
return true;
}

View File

@ -62,7 +62,11 @@ project "SHADE_Managed"
disablewarnings
{
"4251"
"4251",
"4633",
"4634",
"4635",
"4638"
}
defines

View File

@ -58,7 +58,7 @@ namespace SHADE
}
void RigidBody::Mass::set(float value)
{
return GetNativeComponent()->SetMass(value);
/*return GetNativeComponent()->SetMass(value);*/
}
float RigidBody::Drag::get()
{

View File

@ -117,6 +117,12 @@ namespace SHADE
// Header
SHEditorUI::PushID(index);
bool enabled = script->Enabled;
if (SHEditorUI::InputCheckbox("", enabled))
{
script->Enabled = enabled;
}
SHEditorUI::SameLine();
if (SHEditorUI::CollapsingHeader(LABEL))
{
SHEditorUI::PushID(LABEL);

View File

@ -54,6 +54,14 @@ namespace SHADE
return GameObject(ENTITY_ID);
}
/*---------------------------------------------------------------------------------*/
/* Static Properties */
/*---------------------------------------------------------------------------------*/
GameObject GameObject::Null::get()
{
return GameObject();
}
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/

View File

@ -62,6 +62,17 @@ namespace SHADE
/// <returns>GameObject that has the specified name. Null if not found.</returns>
static System::Nullable<GameObject> Find(System::String^ name);
/*-----------------------------------------------------------------------------*/
/* Static Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Default empty GameObject.
/// </summary>
static property GameObject Null
{
GameObject get();
}
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/

View File

@ -22,6 +22,36 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Properties */
/*---------------------------------------------------------------------------------*/
GameObject Script::Owner::get()
{
return owner;
}
GameObject Script::GameObject::get()
{
return owner;
}
bool Script::Enabled::get()
{
return enabled;
}
void Script::Enabled::set(bool value)
{
// Same, don't set
if (value == enabled)
return;
enabled = value;
// There's a change, so call the appropriate function
if (enabled)
OnEnable();
else
OnDisable();
}
/*---------------------------------------------------------------------------------*/
/* Component Access Functions */
/*---------------------------------------------------------------------------------*/
@ -104,11 +134,10 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* "All-time" Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
void Script::Initialize(GameObject newOwner)
void Script::Initialize(SHADE::GameObject newOwner)
{
owner = newOwner;
}
void Script::OnAttached()
{
SAFE_NATIVE_CALL_BEGIN
@ -131,6 +160,12 @@ namespace SHADE
awake();
SAFE_NATIVE_CALL_END(this)
}
void Script::OnEnable()
{
SAFE_NATIVE_CALL_BEGIN
onEnable();
SAFE_NATIVE_CALL_END(this)
}
void Script::Start()
{
SAFE_NATIVE_CALL_BEGIN
@ -162,6 +197,12 @@ namespace SHADE
onDrawGizmos();
SAFE_NATIVE_CALL_END(this)
}
void Script::OnDisable()
{
SAFE_NATIVE_CALL_BEGIN
onDisable();
SAFE_NATIVE_CALL_END(this)
}
void Script::OnDestroy()
{
SAFE_NATIVE_CALL_BEGIN
@ -228,6 +269,7 @@ namespace SHADE
/* Virtual Lifecycle Functions */
/*---------------------------------------------------------------------------------*/
void Script::awake() {}
void Script::onEnable() {}
void Script::start() {}
void Script::fixedUpdate() {}
void Script::update() {}
@ -236,6 +278,7 @@ namespace SHADE
{
OnGizmosDrawOverriden = false;
}
void Script::onDisable() {}
void Script::onDestroy() {}
/*---------------------------------------------------------------------------------*/

View File

@ -38,11 +38,28 @@ namespace SHADE
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// GameObject that this Script belongs to. This is a legacy interface, use
/// GameObject instead.
/// </summary>
[System::ObsoleteAttribute("Use GameObject instead.", false)]
property SHADE::GameObject Owner
{
SHADE::GameObject get();
}
/// <summary>
/// GameObject that this Script belongs to.
/// </summary>
property GameObject Owner
property SHADE::GameObject GameObject
{
GameObject get() { return owner; }
SHADE::GameObject get();
}
/// <summary>
/// Whether or not this Script should have it's update functions be executed.
/// </summary>
property bool Enabled
{
bool get();
void set(bool value);
}
/*-----------------------------------------------------------------------------*/
@ -127,7 +144,7 @@ namespace SHADE
/// </summary>
/// <typeparam name="T">
/// Type of script to get.
/// This needs to be a default constructable Script.
/// This needs to be a default constructible Script.
/// </typeparam>
/// <returns>Reference to the script added</returns>
generic<typename T> where T : ref class, Script
@ -206,7 +223,7 @@ namespace SHADE
/// <summary>
/// Used to initialize a Script with a GameObject.
/// </summary>
void Initialize(GameObject newOwner);
void Initialize(SHADE::GameObject newOwner);
/// <summary>
/// Used to call onAttached(). This is called immediately when this script is
/// attached to a GameObject.
@ -232,6 +249,11 @@ namespace SHADE
/// </summary>
void Start();
/// <summary>
/// Used to call onEnable. This should be called right when a script is enabled
/// directly.
/// </summary>
void OnEnable();
/// <summary>
/// Used to call fixedUpdate(). This should be called in sync with Physics
/// update steps and thus in most cases will execute more than Update() will.
/// This will be called immediately before a Physics update step.
@ -253,6 +275,11 @@ namespace SHADE
/// </summary>
void OnDrawGizmos();
/// <summary>
/// Used to call onDisable. This should be called right when a script is disabled
/// directly.
/// </summary>
void OnDisable();
/// <summary>
/// Used to call onDestroy(). This should be called at the end of the frame
/// where the attached GameObject or this script is destroyed directly or
/// indirectly due to destruction of the owner.
@ -329,6 +356,10 @@ namespace SHADE
/// </summary>
virtual void awake();
/// <summary>
/// Called when this script is enabled.
/// </summary>
virtual void onEnable();
/// <summary>
/// Called on the first frame that the attached GameObject is active but always
/// after Awake().
/// </summary>
@ -353,6 +384,10 @@ namespace SHADE
/// </summary>
virtual void onDrawGizmos();
/// <summary>
/// Called when this script is disabled.
/// </summary>
virtual void onDisable();
/// <summary>
/// Called just before the end of the frame where the attached GameObject or
/// this script is destroyed directly or indirectly due to destruction of the
/// owner.
@ -403,7 +438,8 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
GameObject owner;
SHADE::GameObject owner;
bool enabled = true;
};
}

View File

@ -528,7 +528,8 @@ namespace SHADE
ScriptList^ scripts = entity.Value;
for (int i = 0; i < scripts->Count; ++i)
{
scripts[i]->FixedUpdate();
if (scripts[i]->Enabled)
scripts[i]->FixedUpdate();
}
}
SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
@ -546,7 +547,8 @@ namespace SHADE
ScriptList^ scripts = entity.Value;
for (int i = 0; i < scripts->Count; ++i)
{
scripts[i]->Update();
if (scripts[i]->Enabled)
scripts[i]->Update();
}
}
SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
@ -564,7 +566,8 @@ namespace SHADE
ScriptList^ scripts = entity.Value;
for (int i = 0; i < scripts->Count; ++i)
{
scripts[i]->LateUpdate();
if (scripts[i]->Enabled)
scripts[i]->LateUpdate();
}
}
SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")
@ -583,7 +586,8 @@ namespace SHADE
ScriptList^ scripts = entity.Value;
for (int i = 0; i < scripts->Count; ++i)
{
scripts[i]->OnDrawGizmos();
if (scripts[i]->Enabled)
scripts[i]->OnDrawGizmos();
}
}
SAFE_NATIVE_CALL_END_N("SHADE_Managed.ScriptStore")