Separated Ortho and perspective matrices in camera #221

Merged
maverickdgg merged 5 commits from SP3-141-Camera-System into main 2022-11-18 12:24:19 +08:00
64 changed files with 1269 additions and 622 deletions
Showing only changes of commit 0b5ec34b00 - Show all commits

View File

@ -21,141 +21,6 @@
Layer: 4294967295
Strength: 0
Scripts: ~
- EID: 1
Name: Floor
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -1.440328, y: -4.41369677, z: -5}
Rotate: {x: -0, y: 0, z: -0}
Scale: {x: 49.4798889, y: 0.5, z: 17.5}
Renderable Component:
Mesh: 149697411
Material: 126974645
RigidBody Component:
Type: Static
Mass: 1
Drag: 0.00999999978
Angular Drag: 0.00999999978
Use Gravity: true
Interpolate: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
Collider Component:
Colliders:
- Is Trigger: false
Type: Box
Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Scripts: ~
- EID: 10
Name: Default
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -4.40482807, y: 2.57871056, z: -5.21213436}
Rotate: {x: -0.361265004, y: 1.11661232, z: -0.626627684}
Scale: {x: 0.999982238, y: 0.999987125, z: 0.999981165}
RigidBody Component:
Type: Dynamic
Mass: 1
Drag: 0
Angular Drag: 0
Use Gravity: true
Interpolate: true
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: false
Freeze Rotation Y: false
Freeze Rotation Z: false
Collider Component:
Colliders:
- Is Trigger: false
Type: Box
Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0, z: 0}
Scripts: ~
- EID: 3
Name: Empty
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -0.0094268322, y: 0, z: 0}
Rotate: {x: -0, y: 0, z: -0}
Scale: {x: 1, y: 1, z: 1}
Scripts: ~
- EID: 4
Name: Empty2
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 0, z: 0}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
Scripts: ~
- EID: 9
Name: Bag
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: 0, z: 0}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
Renderable Component:
Mesh: 144838771
Material: 123745521
Scripts: ~
- EID: 6
Name: AI
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: -8, y: -2, z: 2.5}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 1, y: 1, z: 1}
Renderable Component:
Mesh: 149697411
Material: 126974645
RigidBody Component:
Type: Dynamic
Mass: 1
Drag: 0
Angular Drag: 0
Use Gravity: true
Interpolate: false
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: true
Freeze Rotation Y: true
Freeze Rotation Z: true
Collider Component:
Colliders:
- Is Trigger: false
Type: Box
Half Extents: {x: 0.5, y: 0.5, z: 0.5}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
Scripts: ~
- EID: 7
Name: BigBoi
IsActive: true
@ -181,46 +46,4 @@
Color: {x: 1, y: 1, z: 1, w: 1}
Layer: 4294967295
Strength: 0.25
Scripts: ~
- EID: 5
Name: item
IsActive: true
NumberOfChildren: 0
Components:
Transform Component:
Translate: {x: 0, y: -2, z: -5}
Rotate: {x: 0, y: 0, z: 0}
Scale: {x: 2, y: 2, z: 2}
Renderable Component:
Mesh: 144838771
Material: 123745521
RigidBody Component:
Type: Dynamic
Mass: 1
Drag: 0
Angular Drag: 0
Use Gravity: true
Interpolate: false
Freeze Position X: false
Freeze Position Y: false
Freeze Position Z: false
Freeze Rotation X: true
Freeze Rotation Y: true
Freeze Rotation Z: true
Collider Component:
Colliders:
- Is Trigger: false
Type: Box
Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
- Is Trigger: true
Type: Box
Half Extents: {x: 2, y: 2, z: 2}
Friction: 0.400000006
Bounciness: 0
Density: 1
Position Offset: {x: 0, y: 0.5, z: 0}
Scripts: ~

View File

@ -0,0 +1,50 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#extension GL_EXT_nonuniform_qualifier : require
struct MatPropData
{
vec4 color;
int textureIndex;
float alpha;
vec3 beta;
};
layout(location = 0) in struct
{
vec4 vertPos; // location 0
vec2 uv; // location = 1
vec4 normal; // location = 2
} In;
// material stuff
layout(location = 3) flat in struct
{
int materialIndex;
uint eid;
uint lightLayerIndex;
} In2;
layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global)
layout (std430, set = 3, binding = 0) buffer MaterialProperties // For materials
{
MatPropData data[];
} MatProp;
layout(location = 0) out vec4 position;
layout(location = 1) out uint outEntityID;
layout(location = 2) out uint lightLayerIndices;
layout(location = 3) out vec4 normals;
layout(location = 4) out vec4 albedo;
void main()
{
position = In.vertPos;
normals = In.normal;
albedo = normals * texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) * MatProp.data[In2.materialIndex].color;
outEntityID = In2.eid;
lightLayerIndices = In2.lightLayerIndex;
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: Normals_FS
ID: 48689301
Type: 2

View File

@ -115,6 +115,7 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::GizmosDrawRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::PrepareRenderRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();

View File

@ -143,7 +143,29 @@ namespace SHADE
return result;
}
/****************************************************************************
AssetType SHAssetManager::GetType(AssetID id) noexcept
{
if (assetCollection.contains(id))
{
return assetCollection[id].type;
}
SHLOG_WARNING("AssetID {}, does not belong to an asset", id)
return AssetType::INVALID;
}
std::optional<SHADE::SHAsset> SHAssetManager::GetAsset(AssetID id) noexcept
{
if (assetCollection.contains(id))
{
return assetCollection[id];
}
return {};
}
/****************************************************************************
* \brief Create record for new asset. CAN ONLY CREATE FOR CUSTOM
* ASSETS CREATED BY THE ENGINE.
*

View File

@ -50,6 +50,9 @@ namespace SHADE
* \return const& to unordered_map<AssetName, AssetID>
****************************************************************************/
static std::vector<SHAsset> GetAllAssets() noexcept;
static std::optional<SHAsset> GetAsset(AssetID id) noexcept;
static AssetType GetType(AssetID id) noexcept;
/****************************************************************************
* \brief Create record for new resource. CAN ONLY CREATE FOR CUSTOM

View File

@ -5,6 +5,7 @@
namespace SHADE
{
bool SHDragDrop::hasDragDrop = false;
SHDragDrop::DragDropTag SHDragDrop::currentDragDropTag{};
bool SHDragDrop::BeginSource(ImGuiDragDropFlags const flags)
{ return ImGui::BeginDragDropSource(flags); }
@ -16,6 +17,10 @@ namespace SHADE
{ return ImGui::BeginDragDropTarget(); }
void SHDragDrop::EndTarget()
{ ImGui::EndDragDropTarget(); hasDragDrop = false;}
{
ImGui::EndDragDropTarget();
hasDragDrop = false;
currentDragDropTag = {};
}
}

View File

@ -19,9 +19,13 @@ namespace SHADE
static void EndSource();
template<typename T>
static bool SetPayload(std::string_view const type, T* object, ImGuiCond const cond = 0)
static bool SetPayload(DragDropTag const& type, T* object, ImGuiCond const cond = 0)
{
hasDragDrop = ImGui::SetDragDropPayload(type.data(), static_cast<void*>(object), sizeof(T), cond);
ImGui::SetDragDropPayload(type.data(), static_cast<void*>(object), sizeof(T), cond);
hasDragDrop = true;
currentDragDropTag = type;
return hasDragDrop;
}
@ -32,13 +36,16 @@ namespace SHADE
static void EndTarget();
template<typename T>
static T* AcceptPayload(std::string_view const type, ImGuiDragDropFlags const flags = 0)
static T* AcceptPayload(DragDropTag const& type, ImGuiDragDropFlags const flags = 0)
{
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(type.data(), flags))
{
return static_cast<T*>(payload->Data);
}
return nullptr;
}
static bool hasDragDrop;
static DragDropTag currentDragDropTag;
};
}

View File

@ -109,7 +109,7 @@ namespace SHADE
ImVec2 vertLineEnd = vertLineStart;
for (auto const& subFolder : subFolders)
{
const float horizontalLineSize = 8.0f;
const float horizontalLineSize = (subFolder->subFolders.empty() && subFolder->files.empty()) ? 25.0f : 8.0f;
const ImRect childRect = RecursivelyDrawTree(subFolder);
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
@ -117,7 +117,7 @@ namespace SHADE
}
for (auto& file : files)
{
const float horizontalLineSize = 25.0f;
const float horizontalLineSize = (file.assetMeta && !file.assetMeta->subAssets.empty()) ? 8.0f : 25.0f;
const ImRect childRect = DrawFile(file);
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
@ -182,7 +182,10 @@ namespace SHADE
return nodeRect;
}
if(file.assetMeta)
DrawAsset(file.assetMeta, file.ext);
{
const ImRect childRect = DrawAsset(file.assetMeta, file.ext);
return childRect;
}
}
ImRect SHAssetBrowser::DrawAsset(SHAsset const* const asset, FileExt const& ext /*= ""*/) noexcept

View File

@ -117,9 +117,12 @@ namespace SHADE
{
if(ImGui::IsDragDropActive())
{
ParentSelectedEntities(MAX_EID, draggingEntities);
draggingEntities.clear();
ImGui::ClearDragDrop();
if (SHDragDrop::currentDragDropTag == SHDragDrop::DRAG_EID)
{
ParentSelectedEntities(MAX_EID, draggingEntities);
draggingEntities.clear();
ImGui::ClearDragDrop();
}
}
}
ImGui::End();
@ -233,8 +236,9 @@ namespace SHADE
{
ParentSelectedEntities(eid, draggingEntities);
draggingEntities.clear();
SHDragDrop::EndTarget();
//ImGui::ClearDragDrop();
}
SHDragDrop::EndTarget();
}
//Context menu
@ -342,17 +346,12 @@ namespace SHADE
SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID);
}
void SHHierarchyPanel::ParentSelectedEntities(EntityID parentEID, std::vector<EntityID> const& entities) const noexcept
void SHHierarchyPanel::ParentSelectedEntities(EntityID parentEID, std::vector<EntityID> const& entities) noexcept
{
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
std::vector<EntityID> entitiesToParent{};
std::ranges::copy_if(entities, std::back_inserter(entitiesToParent), [&sceneGraph](EntityID const& eid)
{
if (sceneGraph.GetParent(eid)->GetEntityID() == MAX_EID)
return true;
return false;
});
std::vector<EntityID> entitiesToParent = CleanUpEIDList(entities);
//auto const editor = SHSystemManager::GetSystem<SHEditor>();
SHEntityParentCommand::EntityParentData entityParentData;
std::vector<EntityID> parentedEIDS;
@ -419,14 +418,7 @@ namespace SHADE
void SHHierarchyPanel::CopySelectedEntities()
{
const auto editor = SHSystemManager::GetSystem<SHEditor>();
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
std::vector<EntityID> entitiesToCopy{};
std::ranges::copy_if(editor->selectedEntities, std::back_inserter(entitiesToCopy), [&sceneGraph](EntityID const& eid)
{
if(sceneGraph.GetParent(eid)->GetEntityID() == MAX_EID)
return true;
return false;
});
std::vector<EntityID> entitiesToCopy = CleanUpEIDList(editor->selectedEntities);
SHClipboardUtilities::WriteToClipboard(SHSerialization::SerializeEntitiesToString(entitiesToCopy));
}
@ -439,19 +431,25 @@ namespace SHADE
void SHHierarchyPanel::DeleteSelectedEntities()
{
const auto editor = SHSystemManager::GetSystem<SHEditor>();
std::vector<EntityID> entitiesToDelete = CleanUpEIDList(editor->selectedEntities);
SHCommandManager::PerformCommand(std::make_shared<SHDeleteEntitiesCommand>(entitiesToDelete));
}
std::vector<EntityID> SHHierarchyPanel::CleanUpEIDList(std::vector<EntityID> const& entities)
{
std::vector<EntityID> result;
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
std::vector<EntityID> entitiesToDelete{};
std::ranges::copy_if(editor->selectedEntities, std::back_inserter(entitiesToDelete), [&sceneGraph, &selectedEntities = editor->selectedEntities](EntityID const& eid)
std::ranges::copy_if(entities, std::back_inserter(result), [&sceneGraph, &entities](EntityID const& eid)
{
EntityID parentEID = sceneGraph.GetParent(eid)->GetEntityID();
if (parentEID == MAX_EID)
return true;
else if(std::ranges::find(selectedEntities, parentEID) == selectedEntities.end())
if (std::ranges::find(entities, parentEID) == entities.end())
return true;
return false;
});
SHCommandManager::PerformCommand(std::make_shared<SHDeleteEntitiesCommand>(entitiesToDelete));
return result;
}
}//namespace SHADE

View File

@ -27,12 +27,13 @@ namespace SHADE
void DrawMenuBar() const noexcept;
ImRect RecursivelyDrawEntityNode(SHSceneNode* const);
void CreateChildEntity(EntityID parentEID) const noexcept;
void ParentSelectedEntities(EntityID parentEID, std::vector<EntityID> const& entities) const noexcept;
void ParentSelectedEntities(EntityID parentEID, std::vector<EntityID> const& entities) noexcept;
void SelectRangeOfEntities(EntityID beginEID, EntityID EndEID);
void SelectAllEntities();
void CopySelectedEntities();
void PasteEntities(EntityID parentEID = MAX_EID);
void DeleteSelectedEntities();
std::vector<EntityID> CleanUpEIDList(std::vector<EntityID> const& entities);
bool skipFrame = false;
std::string filter;
bool isAnyNodeSelected = false;

View File

@ -290,6 +290,7 @@ namespace SHADE
{
SHEditorWidgets::DragVec3("Force", { "X", "Y", "Z" }, [component] {return component->GetForce(); }, [](SHVec3 const& value) {}, false, "Force", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Torque", { "X", "Y", "Z" }, [component] {return component->GetTorque(); }, [](SHVec3 const& value) {}, false, "Torque", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::CheckBox("Is Asleep", [component] {return component->GetIsSleeping(); }, [](bool value) {}, "If the Rigid Body is asleep");
}
}
@ -446,27 +447,39 @@ namespace SHADE
DrawContextMenu(component);
Handle<SHMesh> const& mesh = component->GetMesh();
Handle<SHMaterialInstance> const& mat = component->GetMaterial();
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Mesh", std::to_string(SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0)).data(), [component]()
const auto MESH_NAME = SHResourceManager::GetAssetName<SHMesh>(mesh).value_or("");
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Mesh", MESH_NAME, [component]()
{
Handle<SHMesh> const& mesh = component->GetMesh();
return SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0);
},
[component](AssetID const& id)
{
if(SHAssetManager::GetType(id) != AssetType::MESH)
{
SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!")
return;
}
component->SetMesh(SHResourceManager::LoadOrGet<SHMesh>(id));
SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE);
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Material", mat ? std::to_string(SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0)).data() : "", [component]()
{
Handle<SHMaterialInstance> const& mat = component->GetMaterial();
if(!mat)
return static_cast<AssetID>(0);
return SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0);
},
const auto MAT_NAME = mat ? SHResourceManager::GetAssetName<SHMaterial>(mat->GetBaseMaterial()).value_or("") : "";
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Material", MAT_NAME,
[component]()
{
Handle<SHMaterialInstance> const& mat = component->GetMaterial();
if (!mat)
return static_cast<AssetID>(0);
return SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0);
},
[component](AssetID const& id)
{
if (SHAssetManager::GetType(id) != AssetType::MATERIAL)
{
SHLOG_WARNING("Attempted to assign non material asset to Renderable Mesh property!")
return;
}
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
component->SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(SHResourceManager::LoadOrGet<SHMaterial>(id)));
}, SHDragDrop::DRAG_RESOURCE);

View File

@ -78,7 +78,26 @@ namespace SHADE
ImGui::BeginDisabled(!isDirty);
if(ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data()))
{
//save
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
// Replace Material if it's been instantiated
auto matHandle = SHResourceManager::Get<SHMaterial>(currentViewedMaterial);
if (matHandle)
{
// - Get Shader Modules
auto vertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->vertexShader);
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->fragShader);
if (vertShader && fragShader && gfxSystem)
{
// - Retrieve pipeline from pipeline library
auto renderPass = gfxSystem->GetPrimaryRenderpass();
auto subPass = renderPass->GetSubpass(currentMatSpec->subpassName);
auto pipeline = renderPass->GetOrCreatePipeline({ vertShader, fragShader }, subPass);
// - Set Pipeline
matHandle->SetPipeline(pipeline);
}
}
// Save Properties
if(auto matAsset = SHAssetManager::GetData<SHMaterialAsset>(currentViewedMaterial))
{
YAML::Emitter out;
@ -102,7 +121,20 @@ namespace SHADE
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<float>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<int>());
{
Handle<SHTexture> texture = SHResourceManager::LoadOrGet<SHTexture>(PROP_NODE.as<int>());
// HACK: Need to split this out to a separate pass before loading the materials and subsequently, the scenes
gfxSystem->BuildTextures();
if (texture)
{
matHandle->SetProperty(VARIABLE->offset, texture->TextureArrayIndex);
}
else
{
SHLOG_WARNING("[] Attempted to load invalid texture! Setting to 0.");
matHandle->SetProperty(VARIABLE->offset, 0);
}
}
break;
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec2>());
@ -136,12 +168,38 @@ namespace SHADE
{
/*if(!shaderModule)
return;*/
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
auto interface = gfxSystem->GetDefaultMaterialInstance()->GetBaseMaterial()->GetShaderBlockInterface();
//auto interface = shaderModule->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA);
int const varCount = static_cast<int>(interface->GetVariableCount());
// Shader
bool shaderChanged = false;
const auto* SHADER_INFO = SHAssetManager::GetData<SHShaderAsset>(currentMatSpec->fragShader);
const std::string SHADER_NAME = SHADER_INFO ? SHADER_INFO->name : "Unknown Shader";
ImGui::BeginDisabled();
isDirty |= SHEditorWidgets::DragDropReadOnlyField<AssetID>
(
"Fragment Shader", SHADER_NAME.data(),
[this]() { return currentMatSpec->fragShader; },
[this](const AssetID& id) { currentMatSpec->fragShader = id; },
SHDragDrop::DRAG_RESOURCE
);
ImGui::EndDisabled();
// Load the shader to access it's data
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->fragShader);
if (!fragShader)
return;
// Get interface for the shader combination
auto interface = fragShader->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface
(
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
);
if (!interface)
return;
// Properties
int const varCount = static_cast<int>(interface->GetVariableCount());
for (int i = 0; i < varCount; ++i)
{
auto variable = interface->GetVariable(i);

View File

@ -14,6 +14,7 @@
#include "Camera/SHCameraSystem.h"
#include "FRC/SHFramerateController.h"
#include "../../SHEditorWidgets.hpp"
constexpr std::string_view windowName = "\xef\x80\x95 Viewport";
@ -193,6 +194,13 @@ namespace SHADE
if (isScale)
ImGui::PopStyleColor();
ImGui::EndDisabled();
auto camSystem = SHSystemManager::GetSystem<SHCameraSystem>();
auto editorCamera = camSystem->GetEditorCamera();
//ImGui::SetNextItemWidth(10.0f);
SHEditorWidgets::SliderFloat("CamSpeed", 0.0f, 5.0f, [editorCamera] {return editorCamera->movementSpeed; }, [editorCamera](float const& value) {editorCamera->movementSpeed = value; });
SHEditorWidgets::DragVec3("TurnSpeed", { "X", "Y", "Z" }, [editorCamera] {return editorCamera->turnSpeed; }, [editorCamera](SHVec3 const& value) {editorCamera->turnSpeed = value; });
ImGui::EndMenuBar();
}
}

View File

@ -422,7 +422,7 @@ namespace SHADE
ImGui::BeginGroup();
ImGui::PushID(label.data());
TextLabel(label);
bool changed = ImGui::InputText("##", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr);
bool changed = ImGui::InputText("##inputText", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr);
if(SHDragDrop::BeginTarget())
{
if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag))
@ -454,7 +454,7 @@ namespace SHADE
ImGui::BeginGroup();
ImGui::PushID(label.data());
TextLabel(label);
const bool hasChange = ImGui::DragScalar("##", data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
const bool hasChange = ImGui::DragScalar("##dragScalar", data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
static bool startRecording = false;
if (hasChange)
{
@ -487,7 +487,7 @@ namespace SHADE
ImGui::BeginGroup();
ImGui::PushID(label.data());
TextLabel(label);
const bool hasChange = ImGui::DragFloat("##", &value, speed, p_min, p_max, displayFormat, flags);
const bool hasChange = ImGui::DragFloat("##dragFloat", &value, speed, p_min, p_max, displayFormat, flags);
static bool startRecording = false;
if (hasChange)
{
@ -520,7 +520,7 @@ namespace SHADE
ImGui::BeginGroup();
ImGui::PushID(label.data());
TextLabel(label);
const bool hasChange = ImGui::DragInt("##", &value, speed, p_min, p_max, displayFormat, flags);
const bool hasChange = ImGui::DragInt("##dragInt", &value, speed, p_min, p_max, displayFormat, flags);
static bool startRecording = false;
if (hasChange)
{
@ -553,7 +553,7 @@ namespace SHADE
ImGui::BeginGroup();
ImGui::PushID(label.data());
TextLabel(label);
bool const hasChange = ImGui::SliderScalar("##", data_type, &value, &min, &max, displayFormat, flags);
bool const hasChange = ImGui::SliderScalar("##sliderScalar", data_type, &value, &min, &max, displayFormat, flags);
static bool startRecording = false;
if (hasChange)
{
@ -587,7 +587,8 @@ namespace SHADE
ImGui::BeginGroup();
ImGui::PushID(label.data());
TextLabel(label);
bool const hasChange = ImGui::SliderFloat("##", &value, min, max, displayFormat, flags);
ImGui::SetNextItemWidth(ImGui::CalcTextSize(displayFormat).x + ImGui::GetStyle().ItemInnerSpacing.x * 2.0f);
bool const hasChange = ImGui::SliderFloat("##sliderFloat", &value, min, max, displayFormat, flags);
static bool startRecording = false;
if (hasChange)
{
@ -621,7 +622,7 @@ namespace SHADE
ImGui::BeginGroup();
ImGui::PushID(label.data());
TextLabel(label);
bool const hasChange = ImGui::SliderInt("##", &value, min, max, displayFormat, flags);
bool const hasChange = ImGui::SliderInt("##sliderInt", &value, min, max, displayFormat, flags);
static bool startRecording = false;
if (hasChange)
{

View File

@ -38,11 +38,11 @@ namespace SHADE
/// </summary>
std::vector<vk::DescriptorPoolSize> Limits =
{
{ vk::DescriptorType::eCombinedImageSampler, 100 },
{ vk::DescriptorType::eUniformBuffer, 100 },
{ vk::DescriptorType::eUniformBufferDynamic, 100 },
{ vk::DescriptorType::eStorageImage, 100},
{ vk::DescriptorType::eStorageBufferDynamic, 100 }
{ vk::DescriptorType::eCombinedImageSampler, 1000 },
{ vk::DescriptorType::eUniformBuffer, 1000 },
{ vk::DescriptorType::eUniformBufferDynamic, 1000 },
{ vk::DescriptorType::eStorageImage, 1000 },
{ vk::DescriptorType::eStorageBufferDynamic, 1000 }
};
/// <summary>
/// Maximum number of descriptor sets allowed

View File

@ -43,6 +43,85 @@ namespace SHADE
setAllDirtyFlags();
}
SHBatch::SHBatch(SHBatch&& rhs)
: device { rhs.device }
, pipeline { rhs.pipeline }
, referencedMatInstances { std::move(rhs.referencedMatInstances) }
, matBufferDirty { std::move(rhs.matBufferDirty) }
, subBatches { std::move(rhs.subBatches) }
, drawData { std::move(drawData) }
, transformData { std::move(rhs.transformData) }
, instancedIntegerData { std::move(rhs.instancedIntegerData) }
, matPropsData { std::move(rhs.matPropsData) }
, matPropsDataSize { rhs.matPropsDataSize }
, singleMatPropAlignedSize { rhs.singleMatPropAlignedSize }
, singleMatPropSize { rhs.singleMatPropSize }
, isCPUBuffersDirty { rhs.isCPUBuffersDirty }
, drawDataBuffer { rhs.drawDataBuffer }
, transformDataBuffer { rhs.transformDataBuffer }
, instancedIntegerBuffer { rhs.instancedIntegerBuffer }
, matPropsBuffer { rhs.matPropsBuffer }
, matPropsDescSet { rhs.matPropsDescSet }
{
rhs.drawDataBuffer = {};
rhs.transformDataBuffer = {};
rhs.instancedIntegerBuffer = {};
rhs.matPropsBuffer = {};
rhs.matPropsDescSet = {};
}
SHBatch& SHBatch::operator=(SHBatch&& rhs)
{
if (this == &rhs)
return *this;
device = rhs.device ;
pipeline = rhs.pipeline ;
referencedMatInstances = std::move(rhs.referencedMatInstances);
matBufferDirty = std::move(rhs.matBufferDirty) ;
subBatches = std::move(rhs.subBatches) ;
drawData = std::move(drawData) ;
transformData = std::move(rhs.transformData) ;
instancedIntegerData = std::move(rhs.instancedIntegerData) ;
matPropsData = std::move(rhs.matPropsData) ;
matPropsDataSize = rhs.matPropsDataSize ;
singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ;
singleMatPropSize = rhs.singleMatPropSize ;
isCPUBuffersDirty = rhs.isCPUBuffersDirty ;
drawDataBuffer = rhs.drawDataBuffer ;
transformDataBuffer = rhs.transformDataBuffer ;
instancedIntegerBuffer = rhs.instancedIntegerBuffer ;
matPropsBuffer = rhs.matPropsBuffer ;
matPropsDescSet = rhs.matPropsDescSet ;
// Unset values
rhs.drawDataBuffer = {};
rhs.transformDataBuffer = {};
rhs.instancedIntegerBuffer = {};
rhs.matPropsBuffer = {};
rhs.matPropsDescSet = {};
return *this;
}
SHBatch::~SHBatch()
{
// Free GPU buffers
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
{
if (drawDataBuffer[i])
drawDataBuffer[i].Free();
if (transformDataBuffer[i])
transformDataBuffer[i].Free();
if (instancedIntegerBuffer[i])
instancedIntegerBuffer[i].Free();
if (matPropsBuffer[i])
matPropsBuffer[i].Free();
if (matPropsDescSet[i])
matPropsDescSet[i].Free();
}
}
void SHBatch::Add(const SHRenderable* renderable)
{
// Ignore if null

View File

@ -71,6 +71,11 @@ namespace SHADE
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
SHBatch(Handle<SHVkPipeline> pipeline);
SHBatch(const SHBatch&) = delete;
SHBatch(SHBatch&& rhs);
SHBatch& operator=(const SHBatch&) = delete;
SHBatch& operator=(SHBatch&& rhs);
~SHBatch();
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
@ -117,7 +122,7 @@ namespace SHADE
std::unique_ptr<char> matPropsData;
Byte matPropsDataSize = 0;
Byte singleMatPropAlignedSize = 0;
Byte singleMatPropSize = 0;
Byte singleMatPropSize = 0;
bool isCPUBuffersDirty = true;
// GPU Buffers
TripleBuffer drawDataBuffer;

View File

@ -69,9 +69,9 @@ namespace SHADE
batch->Remove(renderable);
// If batch is empty, remove batch
if (batch->IsEmpty())
batches.erase(batch);
// TODO: If the pipeline is unloaded, we remove the batch
/*if (batch->IsEmpty() && !batch->GetPipeline())
batches.erase(batch);*/
}
void SHSuperBatch::Clear() noexcept

View File

@ -570,13 +570,6 @@ namespace SHADE
return;
}
// Finalise all batches
for (auto vp : viewports)
for (auto renderer : vp->GetRenderers())
{
renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame(), descPool);
}
// Resize
auto windowDims = window->GetWindowSize();
if (renderContext.GetResizeAndReset())
@ -591,6 +584,13 @@ namespace SHADE
// #BackEndTest: For for the fence initialized by queue submit
renderContext.WaitForFence();
// Finalise all batches
for (auto vp : viewports)
for (auto renderer : vp->GetRenderers())
{
renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame(), descPool);
}
// #BackEndTest: Acquire the next image in the swapchain available
renderContext.AcquireNextIamge();
const uint32_t CURR_FRAME_IDX_2 = renderContext.GetCurrentFrame();
@ -602,8 +602,6 @@ namespace SHADE
if (currFrameData.cmdPoolHdls.empty())
throw std::runtime_error("No command pools available!");
currFrameData.cmdPoolHdls[0]->Reset();
}
/***************************************************************************/
@ -710,6 +708,11 @@ namespace SHADE
return resourceManager.Create<SHMaterialInstance>(materialInst->GetBaseMaterial());
}
std::pair<typename SHResourceHub::dense_iterator<SHMaterialInstance>, typename SHResourceHub::dense_iterator<SHMaterialInstance>> SHGraphicsSystem::GetAllMaterialInstances()
{
return resourceManager.GetDenseAccess<SHMaterialInstance>();
}
void SHGraphicsSystem::RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance)
{
resourceManager.Free(materialInstance);
@ -807,7 +810,7 @@ namespace SHADE
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
{
SHResourceManager::FinaliseChanges();
// Begin rendering
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
}
@ -833,8 +836,38 @@ namespace SHADE
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
// Reset all material isDirty
auto gfxSystem = reinterpret_cast<SHGraphicsSystem*>(system);
auto [matBegin, matEnd] = gfxSystem->resourceManager.GetDenseAccess<SHMaterial>();
for (auto iter = matBegin; iter != matEnd; ++iter)
{
iter->ClearChangeFlag();
}
}
SHGraphicsSystem::PrepareRenderRoutine::PrepareRenderRoutine()
: SHSystemRoutine("Graphics System Pre-Render", true)
{}
void SHGraphicsSystem::PrepareRenderRoutine::Execute(double) noexcept
{
// Finish up, loading, unloading any resources
SHResourceManager::FinaliseChanges();
// Clean up and update all materials
auto gfxSystem = reinterpret_cast<SHGraphicsSystem*>(system);
auto [matInstBegin, matInstEnd] = gfxSystem->resourceManager.GetDenseAccess<SHMaterialInstance>();
for (auto iter = matInstBegin; iter != matInstEnd; ++iter)
{
auto baseMat = iter->GetBaseMaterial();
if (baseMat && baseMat->HasPipelineChanged())
{
iter->ResetProperties();
}
}
}
/*-----------------------------------------------------------------------------------*/
/* System Routine Functions - BatcherDispatcherRoutine */
/*-----------------------------------------------------------------------------------*/
@ -844,11 +877,14 @@ namespace SHADE
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
{
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
for (auto& renderable : renderables)
{
// Check if the material instance is now unused
renderable.CleanUpMaterials();
if (!renderable.HasChanged())
continue;
continue;
// Remove from the SuperBatch it is previously in (prevMat if mat has changed)
Handle<SHMaterialInstance> prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial();
@ -857,9 +893,8 @@ namespace SHADE
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
oldSuperBatch->Remove(&renderable);
}
// Add to new SuperBatch if there is a material
// Add to new SuperBatch if there is a material and a mesh to render
// Add to new SuperBatch if there is a material and a mesh to render
Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial();
if (newMatInstance && renderable.GetMesh())
{

View File

@ -95,25 +95,31 @@ namespace SHADE
class SH_API BeginRoutine final : public SHSystemRoutine
{
public:
BeginRoutine();
BeginRoutine();
virtual void Execute(double dt) noexcept override final;
};
class SH_API RenderRoutine final : public SHSystemRoutine
{
public:
RenderRoutine();
RenderRoutine();
virtual void Execute(double dt) noexcept override final;
};
class SH_API EndRoutine final : public SHSystemRoutine
{
public:
EndRoutine();
EndRoutine();
virtual void Execute(double dt) noexcept override final;
};
class SH_API PrepareRenderRoutine final : public SHSystemRoutine
{
public:
PrepareRenderRoutine();
virtual void Execute(double dt) noexcept override final;
};
class SH_API BatcherDispatcherRoutine final : public SHSystemRoutine
{
public:
BatcherDispatcherRoutine();
BatcherDispatcherRoutine();
virtual void Execute(double dt) noexcept override final;
};
@ -156,6 +162,7 @@ namespace SHADE
Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance();
Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance(Handle<SHMaterial> material);
Handle<SHMaterialInstance> AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst);
std::pair<typename SHResourceHub::dense_iterator<SHMaterialInstance>, typename SHResourceHub::dense_iterator<SHMaterialInstance>> GetAllMaterialInstances();
void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance);
Handle<SHMaterial> GetDefaultMaterial() { return defaultMaterial; }
Handle<SHMaterialInstance> GetDefaultMaterialInstance() { return AddOrGetBaseMaterialInstance(defaultMaterial); }
@ -166,10 +173,10 @@ namespace SHADE
/*******************************************************************************/
/*!
\brief
Adds a mesh to the Mesh Library. But this does not mean that the meshes have
been added yet. A call to "BuildBuffers()" is required to transfer all
meshes into the GPU.
\brief
Adds a mesh to the Mesh Library. But this does not mean that the meshes have
been added yet. A call to "BuildBuffers()" is required to transfer all
meshes into the GPU.
\param vertexCount
Number of vertices in this Mesh.

View File

@ -6,91 +6,109 @@
#include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h"
#include "Math/Vector/SHVec3.h"
#include "Math/Vector/SHVec4.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "SHGraphicsSystem.h"
#include "SHMaterialInstance.h"
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Pipeline Functions */
/*---------------------------------------------------------------------------------*/
void SHMaterial::SetPipeline(Handle<SHVkPipeline> _pipeline)
{
pipeline = _pipeline;
/*-----------------------------------------------------------------------------------*/
/* Pipeline Functions */
/*-----------------------------------------------------------------------------------*/
void SHMaterial::SetPipeline(Handle<SHVkPipeline> _pipeline)
{
// Reassignment, we ignore
if (_pipeline == pipeline)
return;
// Set up properties based on the pipeline
if (!pipeline)
{
// Clear memory and all that
propMemory.reset();
return;
}
pipeline = _pipeline;
// Allocate memory for properties
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
if (propMemorySize <= 0)
{
propMemory.reset();
}
else
{
propMemory.reset(new char[propMemorySize]);
}
ResetProperties();
}
Handle<SHVkPipeline> SHMaterial::GetPipeline() const
{
return pipeline;
}
/*---------------------------------------------------------------------------------*/
/* Property Functions */
/*---------------------------------------------------------------------------------*/
void SHMaterial::ResetProperties()
// Set up properties based on the pipeline
if (pipeline)
{
// Reset all the properties to default values
if (propMemory)
memset(propMemory.get(), 0, propMemorySize);
// Allocate memory for properties
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
if (propMemorySize <= 0)
{
propMemory.reset();
}
else
{
propMemory.reset(new char[propMemorySize]);
}
}
// Reset since pipeline changed
ResetProperties();
// Initialize Vectors to all 1.0 by default
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
for (int i = 0; i < SHADER_INFO->GetVariableCount(); ++i)
{
const auto& VAR = SHADER_INFO->GetVariable(i);
switch (VAR->type)
{
case SHShaderBlockInterface::Variable::Type::VECTOR3:
setPropertyUnsafe(VAR->offset, SHVec3::One);
break;
case SHShaderBlockInterface::Variable::Type::VECTOR4:
setPropertyUnsafe(VAR->offset, SHVec4::One);
break;
}
}
// Mark changed so that we know to update dependent material instances
propertiesChanged = true;
}
Handle<SHVkPipeline> SHMaterial::GetPipeline() const
{
return pipeline;
}
/*-----------------------------------------------------------------------------------*/
/* Property Functions */
/*-----------------------------------------------------------------------------------*/
void SHMaterial::ResetProperties()
{
// Reset all the properties to default values
if (propMemory)
memset(propMemory.get(), 0, propMemorySize);
// Initialize Vectors to all 1.0 by default
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
for (int i = 0; i < SHADER_INFO->GetVariableCount(); ++i)
{
const auto& VAR = SHADER_INFO->GetVariable(i);
switch (VAR->type)
{
case SHShaderBlockInterface::Variable::Type::VECTOR3:
setPropertyUnsafe(VAR->offset, SHVec3::One);
break;
case SHShaderBlockInterface::Variable::Type::VECTOR4:
setPropertyUnsafe(VAR->offset, SHVec4::One);
break;
}
}
void SHMaterial::ExportProperties(void* dest) const noexcept
{
if (propMemory)
memcpy(dest, propMemory.get(), propMemorySize);
}
propertiesChanged = true;
}
size_t SHMaterial::GetPropertiesMemorySize() const noexcept
{
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
}
void SHMaterial::ExportProperties(void* dest) const noexcept
{
if (propMemory)
memcpy(dest, propMemory.get(), propMemorySize);
}
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> SHMaterial::GetShaderBlockInterface() const noexcept
{
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
(
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
vk::ShaderStageFlagBits::eFragment
);
}
size_t SHMaterial::GetPropertiesMemorySize() const noexcept
{
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
}
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> SHMaterial::GetShaderBlockInterface() const noexcept
{
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
(
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
vk::ShaderStageFlagBits::eFragment
);
}
/*-----------------------------------------------------------------------------------*/
/* Query Functions */
/*-----------------------------------------------------------------------------------*/
void SHMaterial::ClearChangeFlag() noexcept
{
propertiesChanged = false;
}
}

View File

@ -36,7 +36,7 @@ namespace SHADE
Describes a Pipeline along with it's associated properties for this instance.
*/
/***********************************************************************************/
class SH_API SHMaterial
class SH_API SHMaterial : public ISelfHandle<SHMaterial>
{
public:
/*-----------------------------------------------------------------------------*/
@ -68,6 +68,10 @@ namespace SHADE
/* Query Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> GetShaderBlockInterface() const noexcept;
bool HasPipelineChanged() const noexcept { return pipelineChanged; }
bool HasPropertiesChanged() const noexcept { return propertiesChanged; }
bool HasChanged() const noexcept { return pipelineChanged || propertiesChanged; }
void ClearChangeFlag() noexcept;
private:
/*-----------------------------------------------------------------------------*/
@ -76,6 +80,8 @@ namespace SHADE
Handle<SHVkPipeline> pipeline;
std::unique_ptr<char> propMemory;
Byte propMemorySize = 0;
bool propertiesChanged = true;
bool pipelineChanged = true;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */

View File

@ -33,8 +33,7 @@ namespace SHADE
}
// Get offset and modify the memory directly
T* dataPtr = reinterpret_cast<T*>(propMemory.get() + PROP_INFO->offset);
*dataPtr = value;
setPropertyUnsafe(PROP_INFO->offset, value);
}
template<typename T>
@ -85,6 +84,12 @@ namespace SHADE
template<typename T>
void SHMaterial::setPropertyUnsafe(uint32_t memOffset, const T& value)
{
// Size check
if (memOffset + sizeof(T) > propMemorySize)
{
throw std::runtime_error("Attempted to write to out of bounds MaterialInstance properties memory");
}
(*reinterpret_cast<T*>(propMemory.get() + memOffset)) = value;
propertiesChanged = true;
}
}

View File

@ -31,11 +31,11 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
void SHMaterialInstance::ResetProperties() noexcept
{
// Reset all the properties to default values
memset(dataStore.get(), 0, dataStoreSize);
overrideData.clear();
dataStore.reset();
dataWasChanged = true;
}
void SHMaterialInstance::ExportProperties(void* dest)
@ -65,9 +65,17 @@ namespace SHADE
dataWasChanged = false;
}
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Query Functions */
/*-----------------------------------------------------------------------------------*/
bool SHMaterialInstance::HasChanged() const noexcept
{
return dataWasChanged || (baseMaterial && baseMaterial->HasChanged());
}
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> SHMaterialInstance::getShaderBlockInterface() const noexcept
{
return baseMaterial->GetPipeline()->GetPipelineLayout()->GetShaderBlockInterface

View File

@ -69,7 +69,8 @@ namespace SHADE
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHMaterial> GetBaseMaterial() const noexcept { return baseMaterial; }
bool HasChanged() const noexcept { return dataWasChanged; }
bool HasChanged() const noexcept;
bool IsBlank() const noexcept { return overrideData.empty(); } // No overrides
private:
/*-----------------------------------------------------------------------------*/

View File

@ -59,6 +59,12 @@ namespace SHADE
od.StoredDataOffset = lastInsertedData.StoredDataOffset + lastInsertedData.DataSize;
}
// Size check
if (od.StoredDataOffset + sizeof(T) > dataStoreSize)
{
throw std::runtime_error("Attempted to write to out of bounds MaterialInstance properties memory");
}
// Save the override data information
overrideData.emplace_back(std::move(od));
existingOverride = overrideData.end() - 1;

View File

@ -97,6 +97,14 @@ namespace SHADE
return material;
}
void SHRenderable::CleanUpMaterials() noexcept
{
if (material && material->IsBlank())
{
SetMaterial(sharedMaterial);
}
}
/*-----------------------------------------------------------------------------------*/
/* Mesh Functions */
/*-----------------------------------------------------------------------------------*/
@ -115,6 +123,20 @@ namespace SHADE
return lightLayer;
}
bool SHRenderable::HasChanged() const noexcept
{
if (matChanged || meshChanged)
return true;
// If the underlying material has changed
auto mat = GetMaterial();
if (mat)
{
return mat->HasChanged();
}
return false;
}
/*-----------------------------------------------------------------------------------*/
/* Batcher Dispatcher Functions */
/*-----------------------------------------------------------------------------------*/

View File

@ -53,6 +53,10 @@ namespace SHADE
Handle<SHMaterialInstance> GetModifiableMaterial();
Handle<SHMaterialInstance> GetPrevMaterial() const noexcept { return oldMaterial; }
bool HasMaterialChanged() const noexcept { return matChanged; }
/// <summary>
/// Clears the modifiable material if it is unused.
/// </summary>
void CleanUpMaterials() noexcept;
/*-------------------------------------------------------------------------------*/
/* Mesh Functions */
@ -70,7 +74,7 @@ namespace SHADE
/*-------------------------------------------------------------------------------*/
/* Batcher Dispatcher Functions */
/*-------------------------------------------------------------------------------*/
bool HasChanged() const noexcept { return matChanged || meshChanged; } // Whether or not the mesh or material has changed
bool HasChanged() const noexcept; // Whether or not the mesh or material has changed
void ResetChangedFlag(); // TODO: Lock it so that only SHBatcherDispatcher can access this
private:

View File

@ -34,7 +34,7 @@ namespace SHADE
{
colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState
{
.blendEnable = SHVkUtil::IsBlendCompatible (subpass->GetFormatFromAttachmentReference(att.attachment)) ? true : false,
.blendEnable = SHVkUtil::IsBlendCompatible(subpass->GetFormatFromAttachmentReference(att.attachment)),
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.colorBlendOp = vk::BlendOp::eAdd,

View File

@ -129,11 +129,11 @@ namespace SHADE
for (auto& predResource : prereq->attResources)
{
// if a predecessor's resource is used by this node, we want to copy the final layout from the pred to the initial of this node
if (uint64_t resourceID = predResource.GetId().Raw; node->resourceAttachmentMapping.contains(resourceID))
if (uint64_t resourceID = predResource.GetId().Raw; node->resourceAttachmentMapping->contains(resourceID))
{
// Get the resource's attachment index in BOTH the predecessor and the current node
uint32_t prereqResourceAttIndex = prereq->resourceAttachmentMapping[resourceID];
uint32_t resourceAttIndex = node->resourceAttachmentMapping[resourceID];
uint32_t prereqResourceAttIndex = prereq->resourceAttachmentMapping->at(resourceID);
uint32_t resourceAttIndex = node->resourceAttachmentMapping->at(resourceID);
// Use the resource attachment index to get the attachment description in the renderpass
auto& attDesc = node->attachmentDescriptions[resourceAttIndex];

View File

@ -124,7 +124,7 @@ namespace SHADE
, framebuffers{}
, prereqNodes{ std::move(predecessors) }
, attachmentDescriptions{}
, resourceAttachmentMapping{}
, resourceAttachmentMapping { new std::unordered_map<uint64_t, uint32_t> }
, attResources{ }
, subpasses{}
, executed{ false }
@ -163,7 +163,7 @@ namespace SHADE
if (attResources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT))
containsSwapchainImage = true;
resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i);
resourceAttachmentMapping->try_emplace(attResources[i].GetId().Raw, i);
}
if (!containsSwapchainImage)
@ -254,7 +254,7 @@ namespace SHADE
(
subpassName,
graphStorage, GetHandle(), static_cast<uint32_t>(subpasses.size()),
&resourceAttachmentMapping
resourceAttachmentMapping.get()
)
);
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);

View File

@ -60,7 +60,7 @@ namespace SHADE
std::vector<vk::SubpassDependency> spDeps;
//! For indexing resources fast
std::unordered_map<uint64_t, uint32_t> resourceAttachmentMapping;
std::unique_ptr<std::unordered_map<uint64_t, uint32_t>> resourceAttachmentMapping;
//! For indexing subpasses
std::map<std::string, uint32_t> subpassIndexing;

View File

@ -97,7 +97,7 @@ namespace SHADE
colorReferences = std::move(rhs.colorReferences);
depthReferences = std::move(rhs.depthReferences);
inputReferences = std::move(rhs.inputReferences);
resourceAttachmentMapping = rhs.resourceAttachmentMapping;
resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping);
descriptorSetLayout = rhs.descriptorSetLayout;
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
graphStorage = rhs.graphStorage;

View File

@ -86,8 +86,16 @@ namespace SHADE
{
if (bufferHandle)
{
// Resize
bufferHandle->ResizeReplace(size, src, size);
// Resize if we need to resize
if (bufferHandle->GetSizeStored() < size)
{
bufferHandle->ResizeReplace(size, src, size);
}
// Otherwise just copy the data over
else
{
bufferHandle->MapWriteUnmap(src, size, 0, 0);
}
}
else
{
@ -113,8 +121,16 @@ namespace SHADE
{
if (bufferHandle)
{
// Resize
bufferHandle->ResizeReplace(size, src, size); // TODO: Set to host visible method?
// Resize if we need to resize
if (bufferHandle->GetSizeStored() < size)
{
bufferHandle->ResizeReplace(size, src, size);
}
// Otherwise just copy the data over
else
{
bufferHandle->MapWriteUnmap(src, size, 0, 0);
}
}
else
{

View File

@ -1,5 +1,5 @@
/****************************************************************************************
* \file SHBoundingBox.cpp
* \file SHBox.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a 3-Dimensional Axis Aligned Bounding Box
*

View File

@ -1,5 +1,5 @@
/****************************************************************************************
* \file SHBoundingBox.h
* \file SHBox.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a 3-Dimensional Axis Aligned Bounding Box
*
@ -79,17 +79,17 @@ namespace SHADE
[[nodiscard]] bool TestPoint (const SHVec3& point) noexcept override;
[[nodiscard]] bool Raycast (const SHRay& ray, float& distance) noexcept override;
[[nodiscard]] bool Contains (const SHBox& rhs) const noexcept;
[[nodiscard]] float Volume () const noexcept;
[[nodiscard]] float SurfaceArea () const noexcept;
[[nodiscard]] bool Contains (const SHBox& rhs) const noexcept;
[[nodiscard]] float Volume () const noexcept;
[[nodiscard]] float SurfaceArea () const noexcept;
/*---------------------------------------------------------------------------------*/
/* Static Function Members */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] static SHBox Combine (const SHBox& lhs, const SHBox& rhs) noexcept;
[[nodiscard]] static bool Intersect (const SHBox& lhs, const SHBox& rhs) noexcept;
[[nodiscard]] static SHBox BuildFromBoxes (const SHBox* boxes, size_t numBoxes) noexcept;
[[nodiscard]] static SHBox Combine (const SHBox& lhs, const SHBox& rhs) noexcept;
[[nodiscard]] static bool Intersect (const SHBox& lhs, const SHBox& rhs) noexcept;
[[nodiscard]] static SHBox BuildFromBoxes (const SHBox* boxes, size_t numBoxes) noexcept;
[[nodiscard]] static SHBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept;
private:

View File

@ -16,6 +16,7 @@
// Project Headers
#include "Physics/PhysicsObject/SHPhysicsObject.h"
#include "Physics/System/SHPhysicsSystem.h"
#include "Scene/SHSceneManager.h"
/*-------------------------------------------------------------------------------------*/
/* Local Helper Functions */
@ -80,10 +81,15 @@ namespace SHADE
{
for (auto eventIter = container.begin(); eventIter != container.end();)
{
const bool CLEAR_EVENT = eventIter->GetCollisionState() == SHCollisionInfo::State::EXIT
|| eventIter->GetCollisionState() == SHCollisionInfo::State::INVALID;
const SHCollisionInfo& C_INFO = *eventIter;
if (CLEAR_EVENT)
const bool CLEAR_EVENT = C_INFO.GetCollisionState() == SHCollisionInfo::State::EXIT
|| C_INFO.GetCollisionState() == SHCollisionInfo::State::INVALID;
const bool INACTIVE_OBJECT = !SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(C_INFO.GetEntityA())
|| !SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(C_INFO.GetEntityB());
if (CLEAR_EVENT || INACTIVE_OBJECT)
eventIter = container.erase(eventIter);
else
++eventIter;

View File

@ -304,6 +304,9 @@ namespace SHADE
const auto* RHS_BOX = reinterpret_cast<const SHBox*>(rhs);
shape = new SHBox{ positionOffset, RHS_BOX->GetWorldExtents() };
auto* lhsBox = reinterpret_cast<SHBox*>(shape);
lhsBox->SetRelativeExtents(RHS_BOX->GetRelativeExtents());
break;
}
case Type::SPHERE:
@ -311,6 +314,9 @@ namespace SHADE
const auto* RHS_SPHERE = reinterpret_cast<const SHSphere*>(rhs);
shape = new SHSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() };
auto* lhsSphere = reinterpret_cast<SHSphere*>(shape);
lhsSphere->SetRelativeRadius(RHS_SPHERE->GetRelativeRadius());
break;
}
default: break;

View File

@ -29,7 +29,6 @@ namespace SHADE
SHRigidBodyComponent::SHRigidBodyComponent() noexcept
: type { Type::DYNAMIC }
, interpolate { true }
, flags { 0 }
, dirtyFlags { std::numeric_limits<uint16_t>::max() }
, mass { 1.0f }
@ -40,6 +39,7 @@ namespace SHADE
// Initialise default flags
flags |= 1U << 0; // Gravity set to true
flags |= 1U << 1; // Sleeping allowed
flags |= 1U << 8; // Interpolate by default
}
/*-----------------------------------------------------------------------------------*/
@ -60,7 +60,16 @@ namespace SHADE
bool SHRigidBodyComponent::IsInterpolating() const noexcept
{
return interpolate;
static constexpr int FLAG_POS = 8;
return flags & (1U << FLAG_POS);
}
bool SHRigidBodyComponent::GetIsSleeping() const noexcept
{
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
return physicsObject->GetRigidBody()->isSleeping();
return false;
}
SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept
@ -68,21 +77,6 @@ namespace SHADE
return type;
}
float SHRigidBodyComponent::GetMass() const noexcept
{
return mass;
}
float SHRigidBodyComponent::GetDrag() const noexcept
{
return drag;
}
float SHRigidBodyComponent::GetAngularDrag() const noexcept
{
return angularDrag;
}
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
{
static constexpr int FLAG_POS = 2;
@ -119,6 +113,27 @@ namespace SHADE
return flags & (1U << FLAG_POS);
}
//bool SHRigidBodyComponent::GetAutoMass() const noexcept
//{
// static constexpr int FLAG_POS = 9;
// return flags & (1U << FLAG_POS);
//}
float SHRigidBodyComponent::GetMass() const noexcept
{
return mass;
}
float SHRigidBodyComponent::GetDrag() const noexcept
{
return drag;
}
float SHRigidBodyComponent::GetAngularDrag() const noexcept
{
return angularDrag;
}
SHVec3 SHRigidBodyComponent::GetForce() const noexcept
{
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
@ -295,9 +310,18 @@ namespace SHADE
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
{
interpolate = allowInterpolation;
static constexpr int FLAG_POS = 8;
allowInterpolation ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
}
//void SHRigidBodyComponent::SetAutoMass(bool autoMass) noexcept
//{
// static constexpr int FLAG_POS = 9;
// autoMass ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
// dirtyFlags |= 1U << FLAG_POS;
//}
void SHRigidBodyComponent::SetMass(float newMass) noexcept
{
static constexpr int FLAG_POS = 9;
@ -313,6 +337,9 @@ namespace SHADE
dirtyFlags |= 1U << FLAG_POS;
mass = newMass;
// Turn off automass
flags &= ~(1U << FLAG_POS);
}
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
@ -467,6 +494,8 @@ RTTR_REGISTRATION
.property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag )
.property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled )
.property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate )
.property("Sleeping Enabled" , &SHRigidBodyComponent::IsAllowedToSleep , &SHRigidBodyComponent::SetIsAllowedToSleep)
//.property("Auto Mass" , &SHRigidBodyComponent::GetAutoMass , &SHRigidBodyComponent::SetAutoMass )
.property("Freeze Position X" , &SHRigidBodyComponent::GetFreezePositionX , &SHRigidBodyComponent::SetFreezePositionX )
.property("Freeze Position Y" , &SHRigidBodyComponent::GetFreezePositionY , &SHRigidBodyComponent::SetFreezePositionY )
.property("Freeze Position Z" , &SHRigidBodyComponent::GetFreezePositionZ , &SHRigidBodyComponent::SetFreezePositionZ )

View File

@ -71,19 +71,23 @@ namespace SHADE
[[nodiscard]] bool IsAllowedToSleep () const noexcept;
[[nodiscard]] bool IsInterpolating () const noexcept;
[[nodiscard]] bool GetIsSleeping () const noexcept;
[[nodiscard]] Type GetType () const noexcept;
[[nodiscard]] float GetMass () const noexcept;
[[nodiscard]] float GetDrag () const noexcept;
[[nodiscard]] float GetAngularDrag () const noexcept;
[[nodiscard]] bool GetFreezePositionX () const noexcept;
[[nodiscard]] bool GetFreezePositionY () const noexcept;
[[nodiscard]] bool GetFreezePositionZ () const noexcept;
[[nodiscard]] bool GetFreezeRotationX () const noexcept;
[[nodiscard]] bool GetFreezeRotationY () const noexcept;
[[nodiscard]] bool GetFreezeRotationZ () const noexcept;
//[[nodiscard]] bool GetAutoMass () const noexcept;
[[nodiscard]] float GetMass () const noexcept;
[[nodiscard]] float GetDrag () const noexcept;
[[nodiscard]] float GetAngularDrag () const noexcept;
[[nodiscard]] SHVec3 GetForce () const noexcept;
[[nodiscard]] SHVec3 GetTorque () const noexcept;
[[nodiscard]] SHVec3 GetLinearVelocity () const noexcept;
@ -108,6 +112,7 @@ namespace SHADE
void SetFreezeRotationY (bool freezeRotationY) noexcept;
void SetFreezeRotationZ (bool freezeRotationZ) noexcept;
void SetInterpolate (bool allowInterpolation) noexcept;
//void SetAutoMass (bool autoMass) noexcept;
void SetMass (float newMass) noexcept;
void SetDrag (float newDrag) noexcept;
@ -144,8 +149,7 @@ namespace SHADE
Type type;
bool interpolate;
uint8_t flags; // aZ aY aX lZ lY lX slp g
uint16_t flags; // 0 0 0 0 0 0 am ip aZ aY aX lZ lY lX slp g
uint16_t dirtyFlags; // 0 0 0 0 aD d m t aZ aY aX lZ lY lX slp g
float mass;

View File

@ -109,8 +109,17 @@ namespace SHADE
{
// TODO(Diren): Add more collider shapes
case SHCollisionShape::Type::BOX: addBoxShape(collisionShape); break;
case SHCollisionShape::Type::SPHERE: addSphereShape(collisionShape); break;
case SHCollisionShape::Type::BOX:
{
addBoxShape(collisionShape);
break;
}
case SHCollisionShape::Type::SPHERE:
{
addSphereShape(collisionShape);
break;
}
default: break;
}
@ -245,9 +254,17 @@ namespace SHADE
}
case 9: // Mass
{
rp3dBody->setMass(component.mass);
rp3dBody->updateLocalCenterOfMassFromColliders();
rp3dBody->updateLocalInertiaTensorFromColliders();
//if (component.GetAutoMass())
//{
// rp3dBody->updateMassPropertiesFromColliders();
// component.mass = rp3dBody->getMass();
//}
//else
//{
rp3dBody->setMass(component.mass);
rp3dBody->updateLocalCenterOfMassFromColliders();
rp3dBody->updateLocalInertiaTensorFromColliders();
//}
break;
}

View File

@ -38,8 +38,8 @@ namespace SHADE
/*-------------------------------------------------------------------------------*/
SHVec3 gravity = SHVec3{ 0.0f, -9.81f, 0.0f };
uint16_t numVelocitySolverIterations = 15;
uint16_t numPositionSolverIterations = 8;
uint16_t numVelocitySolverIterations = 10;
uint16_t numPositionSolverIterations = 5;
bool sleepingEnabled = true;
};

View File

@ -24,7 +24,7 @@ namespace SHADE
/* Static Data Member Definitions */
/*-----------------------------------------------------------------------------------*/
const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[SHPhysicsDebugDrawSystem::NUM_FLAGS] =
const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[NUM_FLAGS] =
{
SHPhysicsDebugDrawSystem::drawColliders
, SHPhysicsDebugDrawSystem::drawColliderAABBs
@ -33,6 +33,8 @@ namespace SHADE
, SHPhysicsDebugDrawSystem::drawContactNormals
};
SHVec3 SHPhysicsDebugDrawSystem::boxVertices[NUM_BOX_VERTICES];
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
@ -42,7 +44,7 @@ namespace SHADE
, physicsSystem { nullptr }
, rp3dDebugRenderer { nullptr }
{
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER)] =
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER)] = SHColour::GREEN;
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB)] = SHColour::YELLOW;
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB)] = SHColour::CYAN;
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS)] = SHColour::RED;
@ -95,6 +97,9 @@ namespace SHADE
SHASSERT(physicsSystem == nullptr, "Non-existent physics system attached to the physics debug draw system!")
physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
// Generate shapes
generateBox();
}
void SHPhysicsDebugDrawSystem::Exit()
@ -159,21 +164,20 @@ namespace SHADE
}
void SHPhysicsDebugDrawSystem::generateBox() noexcept
{
boxVertices[0] = { 0.5f, 0.5f, -0.5f }; // TOP_RIGHT_BACK
boxVertices[1] = { -0.5f, 0.5f, -0.5f }; // TOP_LEFT_BACK
boxVertices[2] = { 0.5f, -0.5f, -0.5f }; // BTM_RIGHT_BACK
boxVertices[3] = { -0.5f, -0.5f, -0.5f }; // BTM_LEFT_BACK
boxVertices[4] = { 0.5f, 0.5f, 0.5f }; // TOP_RIGHT_FRONT
boxVertices[5] = { -0.5f, 0.5f, 0.5f }; // TOP_LEFT_FRONT
boxVertices[6] = { 0.5f, -0.5f, 0.5f }; // BTM_RIGHT_FRONT
boxVertices[7] = { -0.5f, -0.5f, 0.5f }; // BTM_LEFT_FRONT
}
void SHPhysicsDebugDrawSystem::debugDrawBox(const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
{
static constexpr uint32_t NUM_BOX_VERTICES = 8;
static const SHVec3 boxVertices[NUM_BOX_VERTICES]
{
{ 0.5f, 0.5f, -0.5f } // TOP_RIGHT_BACK
, { -0.5f, 0.5f, -0.5f } // TOP_LEFT_BACK
, { 0.5f, -0.5f, -0.5f } // BTM_RIGHT_BACK
, { -0.5f, -0.5f, -0.5f } // BTM_LEFT_BACK
, { 0.5f, 0.5f, 0.5f } // TOP_RIGHT_FRONT
, { -0.5f, 0.5f, 0.5f } // TOP_LEFT_FRONT
, { 0.5f, -0.5f, 0.5f } // BTM_RIGHT_FRONT
, { -0.5f, -0.5f, 0.5f } // BTM_LEFT_FRONT
};
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
if (debugDrawSystem == nullptr)
{
@ -184,10 +188,16 @@ namespace SHADE
auto* BOX = reinterpret_cast<const SHBox*>(collisionShape.GetShape());
// Calculate final position & orientation
const SHVec3 FINAL_POS = colliderComponent.GetPosition() + collisionShape.GetPositionOffset();
const SHQuaternion FINAL_ROT = colliderComponent.GetOrientation() * SHQuaternion::FromEuler(collisionShape.GetRotationOffset());
const SHVec3 COLLIDER_POS = colliderComponent.GetPosition();
const SHVec3 BOX_POS = collisionShape.GetPositionOffset();
const SHQuaternion COLLIDER_ROT = colliderComponent.GetOrientation();
const SHQuaternion BOX_ROT = SHQuaternion::FromEuler(collisionShape.GetRotationOffset());
const SHMatrix BOX_TRS = SHMatrix::Scale(BOX->GetWorldExtents() * 2.0f) * SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(FINAL_POS);
const SHMatrix COLLIDER_TR = SHMatrix::Rotate(COLLIDER_ROT) * SHMatrix::Translate(COLLIDER_POS);
const SHMatrix BOX_TRS = SHMatrix::Scale(BOX->GetWorldExtents() * 2.0f) * SHMatrix::Rotate(BOX_ROT) * SHMatrix::Translate(BOX_POS);
const SHMatrix FINAL_TRS = BOX_TRS * COLLIDER_TR;
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
@ -197,8 +207,8 @@ namespace SHADE
const uint32_t IDX1 = i;
const uint32_t IDX2 = i + NUM_BOX_VERTICES / 2;
transformedVertices[IDX1] = SHVec3::Transform(boxVertices[IDX1], BOX_TRS);
transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], BOX_TRS);
transformedVertices[IDX1] = SHVec3::Transform(boxVertices[IDX1], FINAL_TRS);
transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], FINAL_TRS);
// Draw 4 line to connect the quads
debugDrawSystem->DrawLine(COLLIDER_COLOUR, transformedVertices[IDX1], transformedVertices[IDX2]);
@ -207,6 +217,7 @@ namespace SHADE
// A, B, C, D
std::array backQuad { transformedVertices[0], transformedVertices[1], transformedVertices[3], transformedVertices[2] };
debugDrawSystem->DrawPoly(COLLIDER_COLOUR, backQuad.begin(), backQuad.end());
// E, F, G, H
std::array frontQuad { transformedVertices[4], transformedVertices[5], transformedVertices[7], transformedVertices[6] };
debugDrawSystem->DrawPoly(COLLIDER_COLOUR, frontQuad.begin(), frontQuad.end());
@ -226,8 +237,10 @@ namespace SHADE
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
// Calculate final position & orientation
const SHVec3 FINAL_POS = colliderComponent.GetPosition() + collisionShape.GetPositionOffset();
debugDrawSystem->DrawSphere(COLLIDER_COLOUR, FINAL_POS, SPHERE->GetWorldRadius());
const SHQuaternion FINAL_ROT = colliderComponent.GetOrientation() * SHQuaternion::FromEuler(collisionShape.GetRotationOffset());
const SHMatrix TR = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(colliderComponent.GetPosition());
debugDrawSystem->DrawSphere(COLLIDER_COLOUR, SHVec3::Transform(collisionShape.GetPositionOffset(), TR), SPHERE->GetWorldRadius());
}
} // namespace SHADE

View File

@ -97,25 +97,38 @@ namespace SHADE
/* Data Members */
/*---------------------------------------------------------------------------------*/
static constexpr int NUM_FLAGS = SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS);
static constexpr int NUM_FLAGS = SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS);
static const DebugDrawFunction drawFunctions[NUM_FLAGS];
uint8_t debugDrawFlags;
SHPhysicsSystem* physicsSystem;
rp3d::DebugRenderer* rp3dDebugRenderer;
SHColour debugColours[NUM_FLAGS];
// SHAPES INFO
static constexpr size_t NUM_BOX_VERTICES = 8;
static SHVec3 boxVertices[NUM_BOX_VERTICES];
uint8_t debugDrawFlags;
SHPhysicsSystem* physicsSystem;
rp3d::DebugRenderer* rp3dDebugRenderer;
SHColour debugColours[NUM_FLAGS];
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
// Generic Draw Functions
static void drawColliders (rp3d::DebugRenderer* debugRenderer) noexcept;
static void drawColliderAABBs (rp3d::DebugRenderer* debugRenderer) noexcept;
static void drawBroadPhaseAABBs (rp3d::DebugRenderer* debugRenderer) noexcept;
static void drawContactPoints (rp3d::DebugRenderer* debugRenderer) noexcept;
static void drawContactNormals (rp3d::DebugRenderer* debugRenderer) noexcept;
// Shape Generation Functions
static void generateBox () noexcept;
// Shape Draw Functions
static void debugDrawBox (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
static void debugDrawSphere (const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
};

View File

@ -154,14 +154,32 @@ namespace SHADE
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
postUpdateSyncTransforms
(
physicsObject
, transformComponent
, rigidBodyComponent
, colliderComponent
, 1.0 // We use 1.0 here to avoid any interpolation
);
const auto& CURRENT_TF = physicsObject.GetRigidBody()->getTransform();
const auto& RENDER_POS = CURRENT_TF.getPosition();
const auto& RENDER_ROT = CURRENT_TF.getOrientation();
// Cache transform
physicsObject.prevTransform = CURRENT_TF;
// Sync with physics components
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(entityID))
{
rigidBodyComponent->position = RENDER_POS;
rigidBodyComponent->orientation = RENDER_ROT;
}
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(entityID))
{
colliderComponent->position = RENDER_POS;
colliderComponent->orientation = RENDER_ROT;
}
// Set transform for rendering
if (transformComponent)
{
transformComponent->SetWorldPosition(RENDER_POS);
transformComponent->SetWorldOrientation(RENDER_ROT);
}
}
}
@ -337,93 +355,4 @@ namespace SHADE
return onStopEvent->handle;
}
void SHPhysicsSystem::preUpdateSyncTransform
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
) noexcept
{
if (!transformComponent)
return;
const SHVec3& WORLD_POS = transformComponent->GetWorldPosition();
const SHQuaternion& WORLD_ROT = transformComponent->GetWorldOrientation();
const SHVec3& WORLD_SCL = transformComponent->GetWorldScale();
const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT };
physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM);
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
{
rigidBodyComponent->position = WORLD_POS;
rigidBodyComponent->orientation = WORLD_ROT;
}
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
{
colliderComponent->position = WORLD_POS;
colliderComponent->orientation = WORLD_ROT;
colliderComponent->scale = WORLD_SCL;
colliderComponent->RecomputeCollisionShapes();
}
}
void SHPhysicsSystem::postUpdateSyncTransforms
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
, double interpolationFactor
) noexcept
{
const rp3d::Transform& CURRENT_TF = physicsObject.GetRigidBody()->getTransform();
auto renderPos = CURRENT_TF.getPosition();
auto renderRot = CURRENT_TF.getOrientation();
// Cache transforms
if (physicsObject.GetRigidBody()->isActive())
physicsObject.prevTransform = CURRENT_TF;
// Sync with rigid bodies
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
{
// Skip static bodies
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
return;
// Check if transform should be interpolated
if (rigidBodyComponent->IsInterpolating())
{
// Interpolate transforms between current and predicted next transform
const rp3d::Transform PREV_TF = physicsObject.prevTransform;
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(interpolationFactor));
renderPos = INTERPOLATED_TF.getPosition();
renderRot = INTERPOLATED_TF.getOrientation();
}
rigidBodyComponent->position = CURRENT_TF.getPosition();
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
}
// Sync with colliders
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
{
colliderComponent->position = CURRENT_TF.getPosition();
colliderComponent->orientation = CURRENT_TF.getOrientation();
}
// Set transform for rendering
if (transformComponent)
{
transformComponent->SetWorldPosition(renderPos);
transformComponent->SetWorldOrientation(renderRot);
}
}
} // namespace SHADE

View File

@ -113,6 +113,14 @@ namespace SHADE
void syncRigidBodyActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept;
void syncColliderActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept;
static void syncOnPlay (EntityID eid, SHPhysicsObject& physicsObject) noexcept;
static void preUpdateSyncTransform
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
) noexcept;
};
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
@ -145,6 +153,21 @@ namespace SHADE
/*-------------------------------------------------------------------------------*/
void Execute(double dt) noexcept override;
private:
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
static void postUpdateSyncTransforms
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
, double interpolationFactor
) noexcept;
};
private:
@ -178,24 +201,5 @@ namespace SHADE
SHEventHandle onPlay (SHEventPtr onPlayEvent);
SHEventHandle onStop (SHEventPtr onStopEvent);
static void preUpdateSyncTransform
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
) noexcept;
static void postUpdateSyncTransforms
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
, double interpolationFactor
) noexcept;
};
} // namespace SHADE

View File

@ -262,4 +262,94 @@ namespace SHADE
if (colliderComponent)
physicsObject.SyncColliders(*colliderComponent);
}
void SHPhysicsSystem::PhysicsPreUpdate::preUpdateSyncTransform
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
) noexcept
{
if (!transformComponent)
return;
const SHVec3& WORLD_POS = transformComponent->GetWorldPosition();
const SHQuaternion& WORLD_ROT = transformComponent->GetWorldOrientation();
const SHVec3& WORLD_SCL = transformComponent->GetWorldScale();
const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT };
physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM);
physicsObject.prevTransform = RP3D_TRANSFORM;
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
{
rigidBodyComponent->position = WORLD_POS;
rigidBodyComponent->orientation = WORLD_ROT;
}
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
{
colliderComponent->position = WORLD_POS;
colliderComponent->orientation = WORLD_ROT;
colliderComponent->scale = WORLD_SCL;
colliderComponent->RecomputeCollisionShapes();
}
}
void SHPhysicsSystem::PhysicsPostUpdate::postUpdateSyncTransforms
(
SHPhysicsObject& physicsObject
, SHTransformComponent* transformComponent
, SHRigidBodyComponent* rigidBodyComponent
, SHColliderComponent* colliderComponent
, double interpolationFactor
) noexcept
{
const rp3d::Transform& CURRENT_TF = physicsObject.GetRigidBody()->getTransform();
auto renderPos = CURRENT_TF.getPosition();
auto renderRot = CURRENT_TF.getOrientation();
// Cache transforms
if (physicsObject.GetRigidBody()->isActive())
physicsObject.prevTransform = CURRENT_TF;
// Sync with rigid bodies
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
{
// Skip static bodies
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
return;
// Check if transform should be interpolated
if (rigidBodyComponent->IsInterpolating())
{
// Interpolate transforms between current and predicted next transform
const rp3d::Transform PREV_TF = physicsObject.prevTransform;
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(interpolationFactor));
renderPos = INTERPOLATED_TF.getPosition();
renderRot = INTERPOLATED_TF.getOrientation();
}
rigidBodyComponent->position = CURRENT_TF.getPosition();
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
}
// Sync with colliders
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
{
colliderComponent->position = CURRENT_TF.getPosition();
colliderComponent->orientation = CURRENT_TF.getOrientation();
}
// Set transform for rendering
if (transformComponent)
{
transformComponent->SetWorldPosition(renderPos);
transformComponent->SetWorldOrientation(renderRot);
}
}
} // namespace SHADE

View File

@ -38,6 +38,11 @@ namespace SHADE
class SHResourceLibrary : public SHResourceLibraryBase
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
using dense_iterator = typename SparseSet<T>::dense_iterator;
/*-----------------------------------------------------------------------------*/
/* Constructor */
/*-----------------------------------------------------------------------------*/
@ -74,6 +79,16 @@ namespace SHADE
/// <returns>Read-only reference to the resource object.</returns>
const T& Get(Handle<T> handle) const;
/*-----------------------------------------------------------------------------*/
/* Direct Dense Access Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Provides access to the dense array of the SparseSet.
/// These iterators should not be used to manipulate the underlying vector.
/// </summary>
/// <returns>Pair of begin and end iterators to the dense vector.</returns>
std::pair<dense_iterator, dense_iterator> GetDenseAccess();
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
@ -96,6 +111,12 @@ namespace SHADE
class SHResourceHub final
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
template<typename T>
using dense_iterator = typename SHResourceLibrary<T>::dense_iterator;
/*-----------------------------------------------------------------------------*/
/* Constructors/Destructors */
/*-----------------------------------------------------------------------------*/
@ -138,6 +159,18 @@ namespace SHADE
template<typename T>
const T& Get(Handle<T> handle) const;
/*-----------------------------------------------------------------------------*/
/* Direct Dense Access Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Provides access to the dense array of the SparseSet.
/// These iterators should not be used to manipulate the underlying vector.
/// </summary>
/// <typeparam name="T">Type of resource to access.</typeparam>
/// <returns>Pair of begin and end iterators to the dense vector.</returns>
template <typename T>
std::pair<dense_iterator<T>, dense_iterator<T>> GetDenseAccess();
private:
/*-----------------------------------------------------------------------------*/
/* Type Definition */

View File

@ -79,6 +79,15 @@ namespace SHADE
return objects[handle.GetId().Data.Index];
}
/*---------------------------------------------------------------------------------*/
/* ResourceLibrary - Direct Dense Access Functions */
/*---------------------------------------------------------------------------------*/
template<typename T>
std::pair<typename SHResourceLibrary<T>::dense_iterator, typename SHResourceLibrary<T>::dense_iterator> SHResourceLibrary<T>::GetDenseAccess()
{
return objects.GetDenseAccess();
}
/*---------------------------------------------------------------------------------*/
/* ResourceLibrary - Helper Functions */
/*---------------------------------------------------------------------------------*/
@ -105,7 +114,7 @@ namespace SHADE
}
/*---------------------------------------------------------------------------------*/
/* ResourceManager - Usage Functions */
/* ResourceHub - Usage Functions */
/*---------------------------------------------------------------------------------*/
template <typename T, typename ... Args>
Handle<T> SHResourceHub::Create(Args&&... args)
@ -132,7 +141,7 @@ namespace SHADE
}
/*-----------------------------------------------------------------------------*/
/* ResourceManager - Helper Functions */
/* ResourceHub - Helper Functions */
/*-----------------------------------------------------------------------------*/
template <typename T>
SHResourceLibrary<T>& SHResourceHub::getLibrary()
@ -161,4 +170,13 @@ namespace SHADE
{
return const_cast<SHResourceHub*>(this).getLibrary<T>();
}
/*---------------------------------------------------------------------------------*/
/* ResourceHub - Direct Dense Access Functions */
/*---------------------------------------------------------------------------------*/
template <typename T>
std::pair<typename SHResourceHub::dense_iterator<T>, typename SHResourceHub::dense_iterator<T>> SHResourceHub::GetDenseAccess()
{
return getLibrary<T>().GetDenseAccess();
}
}

View File

@ -103,4 +103,17 @@ namespace SHADE
return {};
}
std::optional<std::string> SHResourceManager::GetAssetName(Handle<void> handle)
{
const Handle GENERIC_HANDLE = Handle(handle);
auto assetId = GetAssetID(GENERIC_HANDLE);
if (assetId.has_value())
{
const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value());
if (ASSET_INFO.has_value())
return ASSET_INFO.value().name;
}
return {};
}
}

View File

@ -13,8 +13,6 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes
#include <unordered_map>
namespace SHADE { class SHMaterial; }
// Project Includes
#include "SH_API.h"
#include "SHResourceLibrary.h"
@ -31,17 +29,26 @@ namespace SHADE { class SHMaterial; }
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHMaterial;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/// <summary>
/// Template structs that maps a resource to their loaded asset representation type.
/// </summary>
template<typename T = void>
struct SHResourceLoader { using AssetType = void; };
template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshData; };
template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshData; };
template<> struct SHResourceLoader<SHTexture> { using AssetType = SHTextureAsset; };
template<> struct SHResourceLoader<SHVkShaderModule> { using AssetType = SHShaderAsset; };
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
/// <summary>
/// <summary>
/// Static class responsible for loading and caching runtime resources from their
/// serialised Asset IDs.
/// </summary>
@ -57,9 +64,7 @@ namespace SHADE
/// Note that for specific types, the retrieved Handle may not be valid until after
/// FinaliseChanges() is called.
/// </summary>
/// <typeparam name="ResourceType">
/// Type of resource to load.
/// </typeparam>
/// <typeparam name="ResourceType">Type of resource to load.</typeparam>
/// <param name="assetId">Asset ID of the resource to load.</param>
/// <returns>Handle to a loaded runtime asset.</returns>
template<typename ResourceType>
@ -67,6 +72,17 @@ namespace SHADE
template<>
static inline Handle<SHMaterial> LoadOrGet<SHMaterial>(AssetID assetId);
/// <summary>
/// Retrieves an existing loaded object of the specified type if it has already been
/// loaded prior.
/// </summary>
/// <typeparam name="ResourceType">Type of resource to load.</typeparam>
/// <param name="assetId">Asset ID of the resource to retrieve.</param>
/// <returns>
/// Handle to a loaded runtime asset. Null handle if not loaded before.
/// </returns>
template<typename ResourceType>
static Handle<ResourceType> Get(AssetID assetId);
/// <summary>
/// Unloads an existing loaded asset. Attempting to unload an invalid Handle will
/// simply do nothing except emit a warning.
/// Faster than the untemplated version.
@ -114,6 +130,31 @@ namespace SHADE
/// value.
/// </return>
static std::optional<AssetID> GetAssetID(Handle<void> handle);
/// <summary>
/// Retrieves the name associated with the AssetID that is associated with the
/// specified Handle.
/// Faster than the untemplated version.
/// </summary>
/// <typeparam name="ResourceType">Type of resource to get the name of.</typeparam>
/// <param name="handle">Handle to get the name of.</param>
/// <return>
/// Name for the specified Handle. If the Handle is invalid, there will be no
/// value.
/// </return>
template<typename T>
static std::optional<std::string> GetAssetName(Handle<T> handle);
/// <summary>
/// Retrieves the name associated with the AssetID that is associated with the
/// specified Handle.
/// Compared to the templated version, this function is slower as it requires
/// searching through the storage of all resource types.
/// </summary>
/// <param name="handle">Handle to get the name of.</param>
/// <return>
/// Name for the specified Handle. If the Handle is invalid, there will be no
/// value.
/// </return>
static std::optional<std::string> GetAssetName(Handle<void> handle);
private:
/*---------------------------------------------------------------------------------*/

View File

@ -93,6 +93,16 @@ namespace SHADE
return handle;
}
template<typename ResourceType>
Handle<ResourceType> SHResourceManager::Get(AssetID assetId)
{
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<ResourceType>();
if (typedHandleMap.get().contains(assetId))
return Handle<ResourceType>(typedHandleMap.get()[assetId]);
else
return Handle<ResourceType>();
}
template<typename ResourceType>
void SHResourceManager::Unload(Handle<ResourceType> asset)
{
@ -139,6 +149,18 @@ namespace SHADE
return {};
}
template<typename T>
std::optional<std::string> SHADE::SHResourceManager::GetAssetName(Handle<T> handle)
{
auto assetId = GetAssetID<T>(handle);
if (assetId.has_value())
{
const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value());
if (ASSET_INFO.has_value())
return ASSET_INFO.value().name;
}
return {};
}
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */

View File

@ -49,6 +49,7 @@ namespace SHADE
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using dense_iterator = typename std::vector<T>::iterator;
/*-----------------------------------------------------------------------------*/
/* Constructors/Destructors */
@ -59,10 +60,6 @@ namespace SHADE
SparseSet();
~SparseSet() = default;
//// Disallow moving or copying
//SparseSet(const SparseSet&) = delete;
//SparseSet(SparseSet&&) = delete;
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
@ -192,6 +189,16 @@ namespace SHADE
/// </exception>
const T& operator[](index_type idx) const;
/*-----------------------------------------------------------------------------*/
/* Direct Dense Access Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Provides access to the dense array of the SparseSet.
/// These iterators should not be used to manipulate the underlying vector.
/// </summary>
/// <returns>Pair of begin and end iterators to the dense vector.</returns>
std::pair<dense_iterator, dense_iterator> GetDenseAccess();
protected:
/*-----------------------------------------------------------------------------*/
/* Constants */

View File

@ -143,4 +143,13 @@ namespace SHADE
{
return at(idx);
}
/*---------------------------------------------------------------------------------*/
/* Direct Dense Access Functions */
/*---------------------------------------------------------------------------------*/
template<typename T>
std::pair<typename SparseSet<T>::dense_iterator, typename SparseSet<T>::dense_iterator> SparseSet<T>::GetDenseAccess()
{
return { denseArray.begin(), denseArray.end() };
}
}

View File

@ -58,10 +58,9 @@ namespace SHADE
loadFunctions();
// Generate script assembly if it hasn't been before
if (!fileExists(std::string(MANAGED_SCRIPT_LIB_NAME) + ".dll"))
{
BuildScriptAssembly();
}
#ifndef _PUBLISH
BuildScriptAssembly();
#endif
// Initialise the CSharp Engine
csEngineInit();
@ -307,7 +306,7 @@ namespace SHADE
SHEventHandle SHScriptEngine::onEntityDestroyed(SHEventPtr eventPtr)
{
auto eventData = reinterpret_cast<const SHEventSpec<SHEntityDestroyedEvent>*>(eventPtr.get());
csScriptsRemoveAll(eventData->data->eid);
csScriptsRemoveAllImmediately(eventData->data->eid, true);
return eventData->handle;
}

View File

@ -12,8 +12,8 @@
#include "Assets/Asset Types/SHSceneAsset.h"
#include "Camera/SHCameraComponent.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Physics/Interface/SHRigidBodyComponent.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"

View File

@ -20,7 +20,7 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* ColliderBound - Constructors */
/* CollisionShape - Constructors */
/*---------------------------------------------------------------------------------*/
CollisionShape::CollisionShape(int arrayIdx, Entity attachedEntity)
: arrayIndex { arrayIdx }
@ -28,102 +28,183 @@ namespace SHADE
{}
/*---------------------------------------------------------------------------------*/
/* ColliderBound - Setter Functions */
/* CollisionShape - Properties */
/*---------------------------------------------------------------------------------*/
bool CollisionShape::IsTrigger::get()
{
return getNativeCollisionShape().IsTrigger();
}
void CollisionShape::IsTrigger::set(bool value)
{
getNativeCollisionShape().SetIsTrigger(value);
}
Vector3 CollisionShape::PositionOffset::get()
{
return Convert::ToCLI(getNativeCollisionShape().GetPositionOffset());
}
void CollisionShape::PositionOffset::set(Vector3 value)
{
getNativeCollisionShape().SetPositionOffset(Convert::ToNative(value));
}
Vector3 CollisionShape::RotationOffset::get()
{
return Convert::ToCLI(getNativeCollisionShape().GetRotationOffset());
}
void CollisionShape::RotationOffset::set(Vector3 value)
{
getNativeCollisionShape().SetRotationOffset(Convert::ToNative(value));
}
float CollisionShape::Friction::get()
{
return getNativeCollisionShape().GetFriction();
}
void CollisionShape::Friction::set(float value)
{
getNativeCollisionShape().SetFriction(value);
}
float CollisionShape::Bounciness::get()
{
return getNativeCollisionShape().GetBounciness();
}
void CollisionShape::Bounciness::set(float value)
{
getNativeCollisionShape().SetBounciness(value);
}
float CollisionShape::Density::get()
{
return getNativeCollisionShape().GetDensity();
}
void CollisionShape::Density::set(float value)
{
getNativeCollisionShape().SetDensity(value);
}
/*---------------------------------------------------------------------------------*/
/* CollisionShape - helper Functions */
/*---------------------------------------------------------------------------------*/
void CollisionShape::updateArrayIndex(int index)
{
arrayIndex = index;
}
SHCollisionShape& SHADE::CollisionShape::getNativeCollisionShape()
{
SHColliderComponent* collider = SHComponentManager::GetComponent_s<SHColliderComponent>(entity);
if (!collider)
throw gcnew System::InvalidOperationException("Unable to retrieve Collider component!");
try
{
auto& shape = collider->GetCollisionShape(arrayIndex);
return shape;
}
catch (std::invalid_argument&)
{
throw gcnew System::IndexOutOfRangeException("Attempted to retrieve out of range CollisionShape!");
}
}
/*---------------------------------------------------------------------------------*/
/* BoxColliderBound - Constructors */
/* BoxCollider - Constructors */
/*---------------------------------------------------------------------------------*/
BoxCollider::BoxCollider(int arrayIdx, Entity attachedEntity)
: CollisionShape { arrayIndex, attachedEntity }
{}
/*---------------------------------------------------------------------------------*/
/* BoxColliderBound - Properties */
/* BoxCollider - Properties */
/*---------------------------------------------------------------------------------*/
Vector3 BoxCollider::Center::get()
{
return Convert::ToCLI(getNativeBoundObject<SHBox>().GetCenter());
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetCenter());
}
void BoxCollider::Center::set(Vector3 value)
{
getNativeBoundObject<SHBox>().SetCenter(Convert::ToNative(value));
getNativeCollisionShape<SHBox>().SetCenter(Convert::ToNative(value));
}
Vector3 BoxCollider::HalfExtents::get()
{
return Convert::ToCLI(getNativeBoundObject<SHBox>().GetWorldExtents());
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetWorldExtents());
}
void BoxCollider::HalfExtents::set(Vector3 value)
{
getNativeBoundObject<SHBox>().SetWorldExtents(Convert::ToNative(value));
getNativeCollisionShape<SHBox>().SetWorldExtents(Convert::ToNative(value));
}
Vector3 BoxCollider::Min::get()
{
return Convert::ToCLI(getNativeBoundObject<SHBox>().GetMin());
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetMin());
}
void BoxCollider::Min::set(Vector3 value)
{
getNativeBoundObject<SHBox>().SetMin(Convert::ToNative(value));
getNativeCollisionShape<SHBox>().SetMin(Convert::ToNative(value));
}
Vector3 BoxCollider::Max::get()
{
return Convert::ToCLI(getNativeBoundObject<SHBox>().GetMax());
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetMax());
}
void BoxCollider::Max::set(Vector3 value)
{
getNativeBoundObject<SHBox>().SetMax(Convert::ToNative(value));
getNativeCollisionShape<SHBox>().SetMax(Convert::ToNative(value));
}
/*---------------------------------------------------------------------------------*/
/* BoxColliderBound - Usage Functions */
/* BoxCollider - Usage Functions */
/*---------------------------------------------------------------------------------*/
bool BoxCollider::TestPoint(Vector3 point)
{
return getNativeBoundObject<SHBox>().TestPoint(Convert::ToNative(point));
return getNativeCollisionShape<SHBox>().TestPoint(Convert::ToNative(point));
}
bool BoxCollider::Raycast(Ray ray, float maxDistance)
{
return getNativeBoundObject<SHBox>().Raycast(Convert::ToNative(ray), maxDistance);
return getNativeCollisionShape<SHBox>().Raycast(Convert::ToNative(ray), maxDistance);
}
/*---------------------------------------------------------------------------------*/
/* BoxColliderBound - Properties */
/* SphereCollider - Properties */
/*---------------------------------------------------------------------------------*/
Vector3 SphereCollider::Center::get()
{
return Convert::ToCLI(getNativeBoundObject<SHSphere>().GetCenter());
return Convert::ToCLI(getNativeCollisionShape<SHSphere>().GetCenter());
}
void SphereCollider::Center::set(Vector3 value)
{
getNativeBoundObject<SHSphere>().SetCenter(Convert::ToNative(value));
getNativeCollisionShape<SHSphere>().SetCenter(Convert::ToNative(value));
}
float SphereCollider::Radius::get()
{
return getNativeBoundObject<SHSphere>().GetWorldRadius();
return getNativeCollisionShape<SHSphere>().GetWorldRadius();
}
void SphereCollider::Radius::set(float value)
{
getNativeBoundObject<SHSphere>().SetWorldRadius(value);
getNativeCollisionShape<SHSphere>().SetWorldRadius(value);
}
/*---------------------------------------------------------------------------------*/
/* SphereColliderBound - Usage Functions */
/* SphereCollider - Usage Functions */
/*---------------------------------------------------------------------------------*/
bool SphereCollider::TestPoint(Vector3 point)
{
return getNativeBoundObject<SHBox>().TestPoint(Convert::ToNative(point));
return getNativeCollisionShape<SHBox>().TestPoint(Convert::ToNative(point));
}
bool SphereCollider::Raycast(Ray ray, float maxDistance)
{
return getNativeBoundObject<SHBox>().Raycast(Convert::ToNative(ray), maxDistance);
return getNativeCollisionShape<SHBox>().Raycast(Convert::ToNative(ray), maxDistance);
}
/*---------------------------------------------------------------------------------*/
/* SphereColliderBound - Constructors */
/* SphereCollider - Constructors */
/*---------------------------------------------------------------------------------*/
SphereCollider::SphereCollider(int arrayIndex, Entity attachedEntity)
: CollisionShape{ arrayIndex, attachedEntity }
@ -154,7 +235,7 @@ namespace SHADE
}
/*---------------------------------------------------------------------------------*/
/* Collider - ColliderBound Functions */
/* Collider - Collider Functions */
/*---------------------------------------------------------------------------------*/
CollisionShape^ Collider::GetCollisionShape(int index)
{
@ -166,7 +247,7 @@ namespace SHADE
// Check if valid
if (index < 0 || index >= subColliderList->Count)
throw gcnew System::ArgumentException("[Collider] Invalid index for Collider Bound retrieval.");
throw gcnew System::ArgumentException("[Collider] Invalid index for Collision Shape retrieval.");
// Return the bound
return subColliderList[index];
@ -217,7 +298,7 @@ namespace SHADE
{
collidersList->Remove(wr);
}
SAFE_NATIVE_CALL_END("Collider.OnColliderBoundChanged")
SAFE_NATIVE_CALL_END("Collider.OnCollisionShapeChanged")
}
void Collider::updateSubColliderList()

View File

@ -19,7 +19,7 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE
{
template<typename CollisionShapeType>
CollisionShapeType& SHADE::CollisionShape::getNativeBoundObject()
CollisionShapeType& SHADE::CollisionShape::getNativeCollisionShape()
{
SHColliderComponent* collider = SHComponentManager::GetComponent_s<SHColliderComponent>(entity);
if (!collider)
@ -29,13 +29,13 @@ namespace SHADE
{
auto& shape = collider->GetCollisionShape(arrayIndex);
if (shape.GetType() != SHCollisionShape::Type::BOX)
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid ColliderBound.");
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape.");
return reinterpret_cast<CollisionShapeType&>(shape);
}
catch (std::invalid_argument&)
{
throw gcnew System::IndexOutOfRangeException("Attempted to retrieve out of range ColliderBound!");
throw gcnew System::IndexOutOfRangeException("Attempted to retrieve out of range CollisionShape!");
}
}
}

View File

@ -30,6 +30,61 @@ namespace SHADE
public ref class CollisionShape abstract
{
public:
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Whether or not this CollisionShape is a trigger.
/// </summary>
property bool IsTrigger
{
bool get();
void set(bool value);
}
/// <summary>
/// The positional offset of this collision shape from the transform's position.
/// </summary>
property Vector3 PositionOffset
{
Vector3 get();
void set(Vector3 value);
}
/// <summary>
/// The rotational offset of this collision shape from the transform's rotation.
/// </summary>
property Vector3 RotationOffset
{
Vector3 get();
void set(Vector3 value);
}
// TODO(Diren): Swap this to Physics Materials once asset implementation for that is done
/// <summary>
/// The frictional coefficient of the shape. Clamped between 0 and 1.
/// </summary>
property float Friction
{
float get();
void set(float value);
}
/// <summary>
/// The bounciness factor of the shape. Clamped between 0 and 1.
/// </summary>
property float Bounciness
{
float get();
void set(float value);
}
/// <summary>
/// The mass density of this shape. Cannot be negative.
/// </summary>
property float Density
{
float get();
void set(float value);
}
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
@ -56,20 +111,25 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
int arrayIndex; // Index into the colliders vector on the native object
Entity entity; // Entity holding the collider component that this collider bounds is on
int arrayIndex; // Index into the colliders vector on the native object
Entity entity; // Entity holding the collider component that this collider bounds is on
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
template<typename CollisionShapeType>
CollisionShapeType& getNativeBoundObject();
CollisionShapeType& getNativeCollisionShape();
internal:
/*-----------------------------------------------------------------------------*/
/* Setter Functions */
/*-----------------------------------------------------------------------------*/
void updateArrayIndex(int index);
/*-----------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------*/
SHCollisionShape& getNativeCollisionShape();
};
/// <summary>
@ -205,18 +265,18 @@ namespace SHADE
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Retrieves a ColliderBound at the specified index in the ColliderBound list.
/// Retrieves a CollisionShape at the specified index in the CollisionShapes list.
/// </summary>
/// <param name="index">Index to retrieve a ColliderBound from.</param>
/// <returns>ColliderBound for the specified index.</returns>
CollisionShape^ GetCollisionShape(int index);
/// <summary>
/// Retrieves a ColliderBound at the specified index in the ColliderBound list
/// Retrieves a CollisionShape at the specified index in the CollisionShapes list
/// and casts it to the appropriate type.
/// </summary>
/// <typeparam name="T">Type of the ColliderBound to cast to.</typeparam>
/// <param name="index">Index to retrieve a ColliderBound from.</param>
/// <returns>ColliderBound for the specified index.</returns>
/// <typeparam name="T">Type of the CollisionShape to cast to.</typeparam>
/// <param name="index">Index to retrieve a CollisionShape from.</param>
/// <returns>CollisionShape for the specified index.</returns>
generic<typename T> where T:CollisionShape
T GetCollisionShape(int index);

View File

@ -402,8 +402,8 @@ namespace SHADE
System::Collections::Generic::List<Script^>^ scriptList = scripts[entity];
for each (Script ^ script in scriptList)
{
// Call OnDestroy only if indicated and also in play mode
if (callOnDestroy)
// Call OnDestroy only if indicated and also if the game has run
if (callOnDestroy && Application::IsPlaying || Application::IsPaused)
{
script->OnDestroy();
}
@ -469,7 +469,7 @@ namespace SHADE
script->OnDestroy();
}
auto entity = script->Owner.GetEntity();
auto scriptList = scripts[script->Owner.GetEntity()];
auto scriptList = scripts[script->Owner.GetEntity()]; // Unable to find here
scriptList->Remove(script);
if (scriptList->Count <= 0)
{

View File

@ -45,12 +45,22 @@ namespace SHADE
System::Collections::Generic::IEnumerable<FieldInfo^>^ fields = ReflectionUtilities::GetInstanceFields(object);
for each (FieldInfo^ field in fields)
{
// Ignore private and non-SerialiseField
if (!ReflectionUtilities::FieldIsSerialisable(field))
continue;
try
{
// Ignore private and non-SerialiseField
if (!ReflectionUtilities::FieldIsSerialisable(field))
continue;
// Serialise
writeFieldIntoYaml(field, object, scriptNode);
// Serialise
writeFieldIntoYaml(field, object, scriptNode);
}
catch (System::Exception^ e)
{
Debug::LogError
(
System::String::Format("[SerialisationUtilities] Failed to serialise field ({0}): {1}", field->Name, e->ToString())
);
}
}
scriptListNode.push_back(scriptNode);
@ -74,15 +84,25 @@ namespace SHADE
System::Collections::Generic::IEnumerable<FieldInfo^>^ fields = ReflectionUtilities::GetInstanceFields(object);
for each (FieldInfo^ field in fields)
{
// Ignore private and non-SerialiseField
if (!ReflectionUtilities::FieldIsSerialisable(field))
continue;
// Deserialise
const std::string FIELD_NAME = Convert::ToNative(field->Name);
if (yamlNode[FIELD_NAME])
try
{
writeYamlIntoField(field, object, yamlNode[FIELD_NAME]);
// Ignore private and non-SerialiseField
if (!ReflectionUtilities::FieldIsSerialisable(field))
continue;
// Deserialise
const std::string FIELD_NAME = Convert::ToNative(field->Name);
if (yamlNode[FIELD_NAME])
{
writeYamlIntoField(field, object, yamlNode[FIELD_NAME]);
}
}
catch (System::Exception^ e)
{
Debug::LogError
(
System::String::Format("[SerialisationUtilities] Failed to deserialise field ({0}): {1}", field->Name, e->ToString())
);
}
}
}

View File

@ -142,6 +142,31 @@ namespace SHADE
bool SerialisationUtilities::fieldAssignYaml(System::Reflection::FieldInfo^ fieldInfo, Object^ object, YAML::Node& node)
{
System::Object^ valueObj = fieldInfo->GetValue(object);
if (valueObj == nullptr)
{
if constexpr (std::is_same_v<FieldType, System::Enum>)
{
if (fieldInfo->FieldType->IsSubclassOf(System::Enum::typeid))
{
valueObj = 0;
}
}
else
{
if (fieldInfo->FieldType == FieldType::typeid)
{
if constexpr (std::is_same_v<FieldType, System::String>)
{
valueObj = "";
}
else
{
valueObj = FieldType();
}
}
}
}
if (varAssignYamlInternal<FieldType>(valueObj, node))
{
fieldInfo->SetValue(object, valueObj);