Lighting WIP. Some bug fixes. #119
|
@ -0,0 +1,5 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*.{c,cpp,h,hpp}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
|
@ -1,3 +1,3 @@
|
||||||
Name: Cube.003
|
Name: Cube.003
|
||||||
ID: 110152941
|
ID: 110152941
|
||||||
Type:
|
Type: 6
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Name: Cube.012
|
Name: Cube.012
|
||||||
ID: 107348815
|
ID: 107348815
|
||||||
Type:
|
Type: 6
|
||||||
|
|
|
@ -4,13 +4,13 @@ Size=1920,20
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][SHEditorMenuBar]
|
[Window][SHEditorMenuBar]
|
||||||
Pos=0,24
|
Pos=0,48
|
||||||
Size=1920,1036
|
Size=1920,1012
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Hierarchy Panel]
|
[Window][Hierarchy Panel]
|
||||||
Pos=0,120
|
Pos=0,197
|
||||||
Size=225,940
|
Size=308,863
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,0
|
DockId=0x00000004,0
|
||||||
|
|
||||||
|
@ -20,29 +20,96 @@ Size=400,400
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Inspector]
|
[Window][Inspector]
|
||||||
Pos=1686,24
|
Pos=1528,48
|
||||||
Size=234,1036
|
Size=392,1012
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,0
|
DockId=0x00000006,0
|
||||||
|
|
||||||
[Window][Profiler]
|
[Window][Profiler]
|
||||||
Pos=0,24
|
Pos=0,48
|
||||||
Size=225,94
|
Size=308,147
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000003,0
|
DockId=0x00000003,0
|
||||||
|
|
||||||
[Window][Viewport]
|
[Window][Viewport]
|
||||||
Pos=227,24
|
Pos=227,48
|
||||||
Size=1457,1036
|
Size=1457,1012
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌð‡Žoû]
|
||||||
|
Pos=60,60
|
||||||
|
Size=32,64
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ]
|
||||||
|
Pos=60,60
|
||||||
|
Size=999,581
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ð‡–oû]
|
||||||
|
Pos=60,60
|
||||||
|
Size=32,64
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ÌÌÌÌ]
|
||||||
|
Pos=60,60
|
||||||
|
Size=553,422
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][]
|
||||||
|
Pos=60,60
|
||||||
|
Size=770,394
|
||||||
|
Collapsed=0
|
||||||
|
|
||||||
|
[Window][ Viewport]
|
||||||
|
Pos=227,48
|
||||||
|
Size=1457,1012
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][ Viewport]
|
||||||
|
Pos=227,48
|
||||||
|
Size=1457,1012
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][î<>‹ Viewport]
|
||||||
|
Pos=310,48
|
||||||
|
Size=1216,715
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000B,0
|
||||||
|
|
||||||
|
[Window][V]
|
||||||
|
Pos=310,722
|
||||||
|
Size=1501,338
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000008,0
|
||||||
|
|
||||||
|
[Window][p›£€Ê]
|
||||||
|
Pos=310,750
|
||||||
|
Size=1501,310
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000A,0
|
||||||
|
|
||||||
|
[Window][ Asset Browser]
|
||||||
|
Pos=310,765
|
||||||
|
Size=1216,295
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x0000000C,0
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,55 Size=1920,1036 Split=X
|
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
||||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1684,1036 Split=X
|
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1526,1036 Split=X
|
||||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=225,1036 Split=Y Selected=0x1E6EB881
|
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881
|
||||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
|
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881
|
||||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,863 Selected=0xE096E5AE
|
||||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1293,1036 CentralNode=1 Selected=0x13926F0B
|
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1216,1036 Split=Y Selected=0xB41284E7
|
||||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=234,1036 Selected=0xE7039252
|
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1501,672 Split=Y Selected=0xB41284E7
|
||||||
|
DockNode ID=0x00000009 Parent=0x00000007 SizeRef=1501,700 Split=Y Selected=0xB41284E7
|
||||||
|
DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,715 CentralNode=1 Selected=0xB41284E7
|
||||||
|
DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,295 Selected=0xB128252A
|
||||||
|
DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6
|
||||||
|
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532
|
||||||
|
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=392,1036 Selected=0xE7039252
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,9 @@ Collapsed=0
|
||||||
|
|
||||||
[Window][Hierarchy Panel]
|
[Window][Hierarchy Panel]
|
||||||
Pos=0,142
|
Pos=0,142
|
||||||
Size=494,918
|
Size=494,690
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,0
|
DockId=0x00000007,0
|
||||||
|
|
||||||
[Window][Debug##Default]
|
[Window][Debug##Default]
|
||||||
Pos=60,60
|
Pos=60,60
|
||||||
|
@ -43,12 +43,20 @@ Size=1151,1012
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x00000002,0
|
||||||
|
|
||||||
[Docking][Data]
|
[Window][ Asset Browser]
|
||||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
Pos=0,834
|
||||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X
|
Size=494,226
|
||||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=494,1036 Split=Y Selected=0x1E6EB881
|
Collapsed=0
|
||||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
|
DockId=0x00000008,0
|
||||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Selected=0xE096E5AE
|
|
||||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1151,1036 CentralNode=1 Selected=0xB41284E7
|
[Docking][Data]
|
||||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252
|
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
||||||
|
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1992,1036 Split=X
|
||||||
|
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=494,1036 Split=Y Selected=0x1E6EB881
|
||||||
|
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,94 Selected=0x1E6EB881
|
||||||
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,940 Split=Y Selected=0xE096E5AE
|
||||||
|
DockNode ID=0x00000007 Parent=0x00000004 SizeRef=494,690 Selected=0xE096E5AE
|
||||||
|
DockNode ID=0x00000008 Parent=0x00000004 SizeRef=494,226 Selected=0xB128252A
|
||||||
|
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1151,1036 CentralNode=1 Selected=0xB41284E7
|
||||||
|
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=271,1036 Selected=0xE7039252
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Name: RaccoonPreTexturedVer1_Base9
|
Name: RaccoonPreTexturedVer1_Base9
|
||||||
ID: 91918845
|
ID: 91918845
|
||||||
Type:
|
Type: 4
|
||||||
|
|
|
@ -56,8 +56,8 @@ namespace Sandbox
|
||||||
_In_ INT nCmdShow
|
_In_ INT nCmdShow
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Set working directory
|
// Set working directory
|
||||||
SHFileUtilities::SetWorkDirToExecDir();
|
SHFileUtilities::SetWorkDirToExecDir();
|
||||||
|
|
||||||
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
||||||
|
|
||||||
|
@ -83,11 +83,13 @@ namespace Sandbox
|
||||||
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::LateUpdateRoutine>();
|
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::LateUpdateRoutine>();
|
||||||
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::FrameCleanUpRoutine>();
|
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::FrameCleanUpRoutine>();
|
||||||
|
|
||||||
|
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostLogicUpdate>();
|
||||||
|
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
|
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
|
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
|
||||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
|
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
|
||||||
|
|
||||||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformUpdateRoutine>();
|
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
|
||||||
|
|
||||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
|
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
|
||||||
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
|
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();
|
||||||
|
@ -150,16 +152,16 @@ namespace Sandbox
|
||||||
SHSceneManager::SceneUpdate(0.016f);
|
SHSceneManager::SceneUpdate(0.016f);
|
||||||
#endif
|
#endif
|
||||||
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
|
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
|
||||||
//editor->PollPicking();
|
editor->PollPicking();
|
||||||
}
|
}
|
||||||
// Finish all graphics jobs first
|
// Finish all graphics jobs first
|
||||||
graphicsSystem->AwaitGraphicsExecution();
|
graphicsSystem->AwaitGraphicsExecution();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SBApplication::Exit(void)
|
void SBApplication::Exit(void)
|
||||||
{
|
{
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
SDL_DestroyWindow(sdlWindow);
|
SDL_DestroyWindow(sdlWindow);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace Sandbox
|
||||||
if (asset.name == "Cube.012")
|
if (asset.name == "Cube.012")
|
||||||
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
|
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
|
||||||
break;
|
break;
|
||||||
case AssetType::TEXTURE:
|
case AssetType::IMAGE:
|
||||||
texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
|
texHandles.emplace_back(SHResourceManager::LoadOrGet<SHTexture>(asset.id));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -68,9 +68,9 @@ namespace Sandbox
|
||||||
customMat->SetProperty("data.alpha", 0.1f);
|
customMat->SetProperty("data.alpha", 0.1f);
|
||||||
|
|
||||||
// Create Stress Test Objects
|
// Create Stress Test Objects
|
||||||
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One * 0.5f;
|
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One;
|
||||||
constexpr int NUM_ROWS = 0;
|
constexpr int NUM_ROWS = 3;
|
||||||
constexpr int NUM_COLS = 0;
|
constexpr int NUM_COLS = 1;
|
||||||
static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f };
|
static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f };
|
||||||
static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f };
|
static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f };
|
||||||
|
|
||||||
|
@ -92,13 +92,13 @@ namespace Sandbox
|
||||||
//Set initial positions
|
//Set initial positions
|
||||||
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) });
|
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) });
|
||||||
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
|
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
|
||||||
transform.SetWorldRotation(SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber(), SHMath::GenerateRandomNumber());
|
transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f));
|
||||||
transform.SetWorldScale(TEST_OBJ_SCALE);
|
transform.SetWorldScale(TEST_OBJ_SCALE);
|
||||||
|
|
||||||
if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
|
//if (const bool IS_EVEN = (y * NUM_ROWS + x) % 2; IS_EVEN)
|
||||||
collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero);
|
collider.AddBoundingBox(SHVec3::One * 0.5f, SHVec3::Zero);
|
||||||
else
|
//else
|
||||||
collider.AddBoundingSphere(0.5f, SHVec3::Zero);
|
// collider.AddBoundingSphere(0.5f, SHVec3::Zero);
|
||||||
|
|
||||||
stressTestObjects.emplace_back(entity);
|
stressTestObjects.emplace_back(entity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAnimationAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <assimp/anim.h>
|
||||||
|
#include "SH_API.power h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SH_API SHAnimationAsset
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
std::vector<aiNodeAnim*> nodeChannels;
|
||||||
|
std::vector<aiMeshAnim*> meshChannels;
|
||||||
|
std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
||||||
|
|
||||||
|
double duration;
|
||||||
|
double ticksPerSecond;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAnimationAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <assimp/anim.h>
|
||||||
|
#include "SHAssetData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SH_API SHAnimationAsset : SHAssetData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
std::vector<aiNodeAnim*> nodeChannels;
|
||||||
|
std::vector<aiMeshAnim*> meshChannels;
|
||||||
|
std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
||||||
|
|
||||||
|
double duration;
|
||||||
|
double ticksPerSecond;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAssetDataBase.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHAssetData
|
||||||
|
{
|
||||||
|
virtual ~SHAssetData(){}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SHMeshAsset.h"
|
||||||
|
#include "SHTextureAsset.h"
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHInternalAsset.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SHAsset.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHInternalAsset : SHAsset
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Math/SHMath.h"
|
#include "Math/SHMath.h"
|
||||||
#include "SH_API.h"
|
#include "SHAssetData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -22,10 +22,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
uint32_t vertexCount;
|
uint32_t vertexCount;
|
||||||
uint32_t indexCount;
|
uint32_t indexCount;
|
||||||
std::string meshName;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SH_API SHMeshAsset
|
struct SH_API SHMeshAsset : SHAssetData
|
||||||
{
|
{
|
||||||
bool compiled;
|
bool compiled;
|
||||||
bool changed;
|
bool changed;
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
#include "tinyddsloader.h"
|
#include "tinyddsloader.h"
|
||||||
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
||||||
|
#include "SHAssetData.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SHTextureAsset
|
struct SHTextureAsset : SHAssetData
|
||||||
{
|
{
|
||||||
bool compiled;
|
bool compiled;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAssetLoader.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Assets/Asset Types/SHAssetData.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHAssetLoader
|
||||||
|
{
|
||||||
|
virtual SHAssetData* Load(AssetPath path) = 0;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAssimpLibrary.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHAssimpLibrary.h"
|
||||||
|
#include <assimp/postprocess.h>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
Assimp::Importer SHAssimpLibrary::aiImporter;
|
||||||
|
|
||||||
|
void SHAssimpLibrary::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept
|
||||||
|
{
|
||||||
|
for (size_t i {0}; i < node.mNumMeshes; ++i)
|
||||||
|
{
|
||||||
|
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
|
||||||
|
meshes.push_back(ProcessMesh(*mesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
|
||||||
|
{
|
||||||
|
ProcessNode(*node.mChildren[i], scene, meshes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssimpLibrary::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
|
||||||
|
{
|
||||||
|
if (scene.HasAnimations())
|
||||||
|
{
|
||||||
|
std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
|
||||||
|
for (auto i{0}; i < scene.mNumAnimations; ++i)
|
||||||
|
{
|
||||||
|
auto const& anim {*scene.mAnimations[i]};
|
||||||
|
|
||||||
|
anims[i].name = anim.mName.C_Str();
|
||||||
|
|
||||||
|
anims[i].duration = anim.mDuration;
|
||||||
|
anims[i].ticksPerSecond = anim.mTicksPerSecond;
|
||||||
|
|
||||||
|
std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data());
|
||||||
|
std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data());
|
||||||
|
std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SHMeshAsset* SHAssimpLibrary::ProcessMesh(aiMesh const& mesh) noexcept
|
||||||
|
{
|
||||||
|
SHMeshAsset* result = new SHMeshAsset();
|
||||||
|
result->compiled = false;
|
||||||
|
result->changed = false;
|
||||||
|
|
||||||
|
for (size_t i{0}; i < mesh.mNumVertices; ++i)
|
||||||
|
{
|
||||||
|
// Vertex position
|
||||||
|
SHVec3 vertex;
|
||||||
|
vertex.x = mesh.mVertices[i].x;
|
||||||
|
vertex.y = mesh.mVertices[i].y;
|
||||||
|
vertex.z = mesh.mVertices[i].z;
|
||||||
|
result->vertexPosition.push_back(vertex);
|
||||||
|
|
||||||
|
// Tex coords
|
||||||
|
SHVec2 texCoord{0.f, 0.f};
|
||||||
|
if (mesh.mTextureCoords[0])
|
||||||
|
{
|
||||||
|
texCoord.x = mesh.mTextureCoords[0][i].x;
|
||||||
|
texCoord.y = mesh.mTextureCoords[0][i].y;
|
||||||
|
}
|
||||||
|
result->texCoords.push_back(texCoord);
|
||||||
|
|
||||||
|
// Normals
|
||||||
|
SHVec3 normal{0.f, 0.f, 0.f};
|
||||||
|
if (mesh.mNormals)
|
||||||
|
{
|
||||||
|
normal.x = mesh.mNormals[i].x;
|
||||||
|
normal.y = mesh.mNormals[i].y;
|
||||||
|
normal.z = mesh.mNormals[i].z;
|
||||||
|
}
|
||||||
|
result->vertexNormal.push_back(normal);
|
||||||
|
|
||||||
|
// Tangent
|
||||||
|
SHVec3 tangent{0.f, 0.f, 0.f};
|
||||||
|
if (mesh.mTangents)
|
||||||
|
{
|
||||||
|
tangent.x = mesh.mTangents[i].x;
|
||||||
|
tangent.y = mesh.mTangents[i].y;
|
||||||
|
tangent.z = mesh.mTangents[i].z;
|
||||||
|
}
|
||||||
|
result->vertexTangent.push_back(tangent);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i {0}; i < mesh.mNumFaces; ++i)
|
||||||
|
{
|
||||||
|
aiFace face = mesh.mFaces[i];
|
||||||
|
for (size_t j{0}; j < face.mNumIndices; ++j)
|
||||||
|
{
|
||||||
|
result->indices.push_back(face.mIndices[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result->header.vertexCount = static_cast<uint32_t>(result->vertexPosition.size());
|
||||||
|
result->header.indexCount = static_cast<uint32_t>(result->indices.size());
|
||||||
|
result->header.name = mesh.mName.C_Str();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssimpLibrary::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept
|
||||||
|
{
|
||||||
|
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
||||||
|
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
||||||
|
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
||||||
|
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
|
||||||
|
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
|
||||||
|
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
|
||||||
|
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
|
||||||
|
| aiProcess_RemoveRedundantMaterials // remove redundant materials
|
||||||
|
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
||||||
|
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!scene || !scene->HasMeshes())
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtractAnimations(*scene, anims);
|
||||||
|
|
||||||
|
ProcessNode(*scene->mRootNode, *scene, meshes);
|
||||||
|
|
||||||
|
aiImporter.FreeScene();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*************************************************************************//**
|
||||||
|
* \file SHAssimpLibrary.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date October 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||||
|
* disclosure of this file or its contents without the prior written consent
|
||||||
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
#include <vector>
|
||||||
|
#include "../SHAssetMacros.h"
|
||||||
|
#include "../Asset Types/SHMeshAsset.h"
|
||||||
|
#include "../Asset Types/SHAnimationAsset.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHAssimpLibrary
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
using MeshVectorRef = std::vector<SHMeshAsset*>&;
|
||||||
|
using AnimVectorRef = std::vector<SHAnimationAsset*>&;
|
||||||
|
|
||||||
|
static Assimp::Importer aiImporter;
|
||||||
|
static void ProcessNode(aiNode const& node, aiScene const& scene,MeshVectorRef meshes) noexcept;
|
||||||
|
static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
|
||||||
|
static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept;
|
||||||
|
};
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ std::string SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, A
|
||||||
{
|
{
|
||||||
std::string newPath{ path.string() };
|
std::string newPath{ path.string() };
|
||||||
newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
|
newPath = newPath.substr(0, newPath.find_last_of('/') + 1);
|
||||||
newPath += asset.header.meshName + MESH_EXTENSION;
|
newPath += asset.header.name + MESH_EXTENSION.data();
|
||||||
|
|
||||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
||||||
if (!file.is_open())
|
if (!file.is_open())
|
||||||
|
|
|
@ -12,129 +12,11 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
#include "SHMeshLoader.h"
|
#include "SHMeshLoader.h"
|
||||||
#include <assimp/postprocess.h>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
Assimp::Importer SHMeshLoader::aiImporter;
|
void SHMeshLoader::LoadSHMesh(AssetPath path, SHMeshAsset& mesh) noexcept
|
||||||
|
|
||||||
void SHMeshLoader::ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept
|
|
||||||
{
|
|
||||||
for (size_t i {0}; i < node.mNumMeshes; ++i)
|
|
||||||
{
|
|
||||||
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
|
|
||||||
meshes.push_back(ProcessMesh(*mesh, scene));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
|
|
||||||
{
|
|
||||||
ProcessNode(*node.mChildren[i], scene, meshes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SHMeshAsset SHMeshLoader::ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept
|
|
||||||
{
|
|
||||||
(void)scene;
|
|
||||||
|
|
||||||
SHMeshAsset result
|
|
||||||
{
|
|
||||||
.compiled { false},
|
|
||||||
.changed { false }
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i{0}; i < mesh.mNumVertices; ++i)
|
|
||||||
{
|
|
||||||
// Vertex position
|
|
||||||
SHVec3 vertex;
|
|
||||||
vertex.x = mesh.mVertices[i].x;
|
|
||||||
vertex.y = mesh.mVertices[i].y;
|
|
||||||
vertex.z = mesh.mVertices[i].z;
|
|
||||||
result.vertexPosition.push_back(vertex);
|
|
||||||
|
|
||||||
// Tex coords
|
|
||||||
SHVec2 texCoord{0.f, 0.f};
|
|
||||||
if (mesh.mTextureCoords[0])
|
|
||||||
{
|
|
||||||
texCoord.x = mesh.mTextureCoords[0][i].x;
|
|
||||||
texCoord.y = mesh.mTextureCoords[0][i].y;
|
|
||||||
}
|
|
||||||
result.texCoords.push_back(texCoord);
|
|
||||||
|
|
||||||
// Normals
|
|
||||||
SHVec3 normal{0.f, 0.f, 0.f};
|
|
||||||
if (mesh.mNormals)
|
|
||||||
{
|
|
||||||
normal.x = mesh.mNormals[i].x;
|
|
||||||
normal.y = mesh.mNormals[i].y;
|
|
||||||
normal.z = mesh.mNormals[i].z;
|
|
||||||
}
|
|
||||||
result.vertexNormal.push_back(normal);
|
|
||||||
|
|
||||||
// Tangent
|
|
||||||
SHVec3 tangent{0.f, 0.f, 0.f};
|
|
||||||
if (mesh.mTangents)
|
|
||||||
{
|
|
||||||
tangent.x = mesh.mTangents[i].x;
|
|
||||||
tangent.y = mesh.mTangents[i].y;
|
|
||||||
tangent.z = mesh.mTangents[i].z;
|
|
||||||
}
|
|
||||||
result.vertexTangent.push_back(tangent);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i {0}; i < mesh.mNumFaces; ++i)
|
|
||||||
{
|
|
||||||
aiFace face = mesh.mFaces[i];
|
|
||||||
for (size_t j{0}; j < face.mNumIndices; ++j)
|
|
||||||
{
|
|
||||||
result.indices.push_back(face.mIndices[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.header.vertexCount = static_cast<uint32_t>(result.vertexPosition.size());
|
|
||||||
result.header.indexCount = static_cast<uint32_t>(result.indices.size());
|
|
||||||
result.header.meshName = mesh.mName.C_Str();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHMeshLoader::LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
|
|
||||||
{
|
|
||||||
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
|
||||||
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
|
||||||
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
|
||||||
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
|
|
||||||
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
|
|
||||||
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
|
|
||||||
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
|
|
||||||
| aiProcess_RemoveRedundantMaterials // remove redundant materials
|
|
||||||
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
|
||||||
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!scene || !scene->HasMeshes())
|
|
||||||
{
|
|
||||||
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO MATERIALS FROM MESHES
|
|
||||||
//if (scene->HasMaterials())
|
|
||||||
//{
|
|
||||||
// for (int i{0}; i < scene->mNumMaterials; ++i)
|
|
||||||
// {
|
|
||||||
// if (scene->mMaterials[i]->mNumProperties > 0)
|
|
||||||
// {
|
|
||||||
// for (int j{0}; j < scene->mMaterials[i]->mProperties[j].)
|
|
||||||
// }
|
|
||||||
//std::cout << scene->mMaterials[i]->;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
ProcessNode(*scene->mRootNode, *scene, meshes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHMeshLoader::LoadSHMesh(SHMeshAsset& mesh, AssetPath path) noexcept
|
|
||||||
{
|
{
|
||||||
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
||||||
if (!file.is_open())
|
if (!file.is_open())
|
||||||
|
@ -168,45 +50,13 @@ namespace SHADE
|
||||||
file.read(reinterpret_cast<char *>(vertNorm.data()), vertexVec3Byte);
|
file.read(reinterpret_cast<char *>(vertNorm.data()), vertexVec3Byte);
|
||||||
file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
|
file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
|
||||||
file.read(reinterpret_cast<char *>(indices.data()), sizeof(uint32_t) * indexCount);
|
file.read(reinterpret_cast<char *>(indices.data()), sizeof(uint32_t) * indexCount);
|
||||||
|
|
||||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
|
||||||
//{
|
|
||||||
// file >> vertPos[i].x;
|
|
||||||
// file >> vertPos[i].y;
|
|
||||||
// file >> vertPos[i].z;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
|
||||||
//{
|
|
||||||
// file >> vertTan[i].x;
|
|
||||||
// file >> vertTan[i].y;
|
|
||||||
// file >> vertTan[i].z;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
|
||||||
//{
|
|
||||||
// file >> vertNorm[i].x;
|
|
||||||
// file >> vertNorm[i].y;
|
|
||||||
// file >> vertNorm[i].z;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//for (auto i{ 0 }; i < vertCount; ++i)
|
|
||||||
//{
|
|
||||||
// file >> texCoord[i].x;
|
|
||||||
// file >> texCoord[i].y;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//for (auto i{ 0 }; i < indexCount; ++i)
|
|
||||||
//{
|
|
||||||
// file >> indices[i];
|
|
||||||
//}
|
|
||||||
|
|
||||||
mesh.compiled = true;
|
mesh.compiled = true;
|
||||||
mesh.changed = false;
|
mesh.changed = false;
|
||||||
|
|
||||||
mesh.header.indexCount = indexCount;
|
mesh.header.indexCount = indexCount;
|
||||||
mesh.header.vertexCount = vertCount;
|
mesh.header.vertexCount = vertCount;
|
||||||
mesh.header.meshName = name;
|
mesh.header.name = name;
|
||||||
|
|
||||||
mesh.vertexPosition = std::move(vertPos);
|
mesh.vertexPosition = std::move(vertPos);
|
||||||
mesh.vertexTangent = std::move(vertTan);
|
mesh.vertexTangent = std::move(vertTan);
|
||||||
|
@ -217,15 +67,12 @@ namespace SHADE
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHMeshLoader::LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept
|
SHAssetData* SHMeshLoader::Load(AssetPath path)
|
||||||
{
|
{
|
||||||
if (path.extension().string() == GLTF_EXTENSION)
|
auto result = new SHMeshAsset();
|
||||||
{
|
|
||||||
LoadExternal(meshes, path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
meshes.emplace_back();
|
LoadSHMesh(path, *result);
|
||||||
LoadSHMesh(meshes.back(), path);
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,27 +10,15 @@
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <assimp/Importer.hpp>
|
|
||||||
#include <assimp/scene.h>
|
|
||||||
#include "../SHAssetMacros.h"
|
#include "../SHAssetMacros.h"
|
||||||
#include "../Asset Types/SHMeshAsset.h"
|
#include "../Asset Types/SHMeshAsset.h"
|
||||||
#include <vector>
|
#include "SHAssetLoader.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHMeshLoader
|
struct SHMeshLoader : public SHAssetLoader
|
||||||
{
|
{
|
||||||
private:
|
void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept;
|
||||||
static Assimp::Importer aiImporter;
|
SHAssetData* Load(AssetPath path) override;
|
||||||
|
|
||||||
static void ProcessNode(aiNode const& node, aiScene const& scene, std::vector<SHMeshAsset>& meshes) noexcept;
|
|
||||||
|
|
||||||
static SHMeshAsset ProcessMesh(aiMesh const& mesh, aiScene const& scene) noexcept;
|
|
||||||
|
|
||||||
static void LoadExternal(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void LoadMesh(std::vector<SHMeshAsset>& meshes, AssetPath path) noexcept;
|
|
||||||
static void LoadSHMesh(SHMeshAsset& meshes, AssetPath path) noexcept;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -133,6 +133,15 @@ namespace SHADE
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHAssetData* SHTextureLoader::Load(AssetPath path)
|
||||||
|
{
|
||||||
|
auto result = new SHTextureAsset();
|
||||||
|
|
||||||
|
LoadImageAsset(path, *result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
|
void SHTextureLoader::LoadImageAsset(AssetPath path, SHTextureAsset& asset)
|
||||||
{
|
{
|
||||||
if (path.extension().string() == DDS_EXTENSION)
|
if (path.extension().string() == DDS_EXTENSION)
|
||||||
|
|
|
@ -15,19 +15,20 @@
|
||||||
#include "../SHAssetMacros.h"
|
#include "../SHAssetMacros.h"
|
||||||
#include "../Asset Types/SHTextureAsset.h"
|
#include "../Asset Types/SHTextureAsset.h"
|
||||||
#include "tinyddsloader.h"
|
#include "tinyddsloader.h"
|
||||||
|
#include "SHAssetLoader.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
class SHTextureLoader
|
class SHTextureLoader : public SHAssetLoader
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static std::string TinyDDSResultToString(tinyddsloader::Result value);
|
std::string TinyDDSResultToString(tinyddsloader::Result value);
|
||||||
static vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
vk::Format ddsLoaderToVkFormat(tinyddsloader::DDSFile::DXGIFormat format, bool isLinear);
|
||||||
|
|
||||||
|
void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||||
static void LoadTinyDDS(AssetPath path, SHTextureAsset& asset) noexcept;
|
|
||||||
public:
|
public:
|
||||||
static void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
|
void LoadImageAsset(AssetPath paths, SHTextureAsset& image);
|
||||||
static void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
|
void LoadSHTexture(AssetPath path, SHTextureAsset& asset) noexcept;
|
||||||
|
SHAssetData* Load(AssetPath path) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Filesystem/SHFileSystem.h"
|
#include "Filesystem/SHFileSystem.h"
|
||||||
#include "SHAssetMacros.h"
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
#include "SH_API.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
struct SHAsset
|
struct SH_API SHAsset
|
||||||
{
|
{
|
||||||
AssetName name;
|
AssetName name;
|
||||||
AssetID id;
|
AssetID id;
|
||||||
|
|
|
@ -32,12 +32,12 @@ typedef std::filesystem::path AssetPath;
|
||||||
typedef unsigned char* AssetData;
|
typedef unsigned char* AssetData;
|
||||||
typedef std::string AssetMetaVersion;
|
typedef std::string AssetMetaVersion;
|
||||||
typedef std::string AssetExtension;
|
typedef std::string AssetExtension;
|
||||||
typedef unsigned char AssetTypeMeta;
|
typedef size_t AssetTypeMeta;
|
||||||
|
|
||||||
typedef FMOD::Sound* SHSound;
|
typedef FMOD::Sound* SHSound;
|
||||||
|
|
||||||
// Asset Meta Version
|
// Asset Meta Version
|
||||||
#define ASSET_META_VER "1.0"
|
constexpr std::string_view ASSET_META_VER { "1.0" };
|
||||||
|
|
||||||
// Asset type enum
|
// Asset type enum
|
||||||
enum class AssetType : AssetTypeMeta
|
enum class AssetType : AssetTypeMeta
|
||||||
|
@ -53,34 +53,35 @@ enum class AssetType : AssetTypeMeta
|
||||||
SCENE,
|
SCENE,
|
||||||
PREFAB,
|
PREFAB,
|
||||||
AUDIO_WAV,
|
AUDIO_WAV,
|
||||||
DDS
|
DDS,
|
||||||
|
MAX_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
//Directory
|
//Directory
|
||||||
#ifdef _PUBLISH
|
#ifdef _PUBLISH
|
||||||
#define ASSET_ROOT "Assets"
|
constexpr std::string_view ASSET_ROOT {"Assets"};
|
||||||
#else
|
#else
|
||||||
#define ASSET_ROOT "../../Assets"
|
constexpr std::string_view ASSET_ROOT {"../../Assets"};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// ASSET EXTENSIONS
|
// ASSET EXTENSIONS
|
||||||
#define META_EXTENSION ".shmeta"
|
constexpr std::string_view META_EXTENSION {".shmeta"};
|
||||||
#define IMAGE_EXTENSION ".png"
|
constexpr std::string_view IMAGE_EXTENSION {".png"};
|
||||||
#define AUDIO_EXTENSION ".ogg"
|
constexpr std::string_view AUDIO_EXTENSION {".ogg"};
|
||||||
#define AUDIO_WAV_EXTENSION ".wav"
|
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
|
||||||
#define SHADER_EXTENSION ".glsl"
|
constexpr std::string_view SHADER_EXTENSION {".glsl"};
|
||||||
#define SCRIPT_EXTENSION ".cs"
|
constexpr std::string_view SCRIPT_EXTENSION {".cs"};
|
||||||
#define SCENE_EXTENSION ".SHADE"
|
constexpr std::string_view SCENE_EXTENSION {".SHADE"};
|
||||||
#define PREFAB_EXTENSION ".SHPrefab"
|
constexpr std::string_view PREFAB_EXTENSION {".SHPrefab"};
|
||||||
#define MATERIAL_EXTENSION ".SHMat"
|
constexpr std::string_view MATERIAL_EXTENSION {".SHMat"};
|
||||||
#define TEXTURE_EXTENSION ".shtex"
|
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
||||||
#define DDS_EXTENSION ".dds"
|
constexpr std::string_view DDS_EXTENSION {".dds"};
|
||||||
#define FBX_EXTENSION ".fbx"
|
constexpr std::string_view FBX_EXTENSION {".fbx"};
|
||||||
#define GLTF_EXTENSION ".gltf"
|
constexpr std::string_view GLTF_EXTENSION {".gltf"};
|
||||||
#define MESH_EXTENSION ".shmesh"
|
constexpr std::string_view MESH_EXTENSION {".shmesh"};
|
||||||
|
|
||||||
std::string const EXTENSIONS[] = {
|
constexpr std::string_view EXTENSIONS[] = {
|
||||||
AUDIO_EXTENSION,
|
AUDIO_EXTENSION,
|
||||||
SHADER_EXTENSION,
|
SHADER_EXTENSION,
|
||||||
MATERIAL_EXTENSION,
|
MATERIAL_EXTENSION,
|
||||||
|
@ -96,10 +97,12 @@ std::string const EXTENSIONS[] = {
|
||||||
GLTF_EXTENSION
|
GLTF_EXTENSION
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr size_t TYPE_COUNT {static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||||
|
|
||||||
// Error flags
|
// Error flags
|
||||||
#define FILE_NOT_FOUND_ERR "FILE NOT FOUND"
|
constexpr std::string_view FILE_NOT_FOUND_ERR {"FILE NOT FOUND"};
|
||||||
#define META_NOT_FOUND_ERR "META NOT FOUND"
|
constexpr std::string_view META_NOT_FOUND_ERR {"META NOT FOUND"};
|
||||||
#define ASSET_NOT_FOUND_ERR "ASSET NOT FOUND"
|
constexpr std::string_view ASSET_NOT_FOUND_ERR {"ASSET NOT FOUND"};
|
||||||
#define EXT_DOES_NOT_EXIST "TYPE DOES NOT HAVE EXTENSION DEFINED"
|
constexpr std::string_view EXT_DOES_NOT_EXIST {"TYPE DOES NOT HAVE EXTENSION DEFINED"};
|
||||||
|
|
||||||
#endif // !SH_ASSET_MACROS_H
|
#endif // !SH_ASSET_MACROS_H
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "SHAssetMetaHandler.h"
|
#include "SHAssetMetaHandler.h"
|
||||||
#include "Filesystem/SHFileSystem.h"
|
#include "Filesystem/SHFileSystem.h"
|
||||||
|
|
||||||
|
#include "Libraries/SHAssimpLibrary.h"
|
||||||
#include "Libraries/SHMeshLoader.h"
|
#include "Libraries/SHMeshLoader.h"
|
||||||
#include "Libraries/SHTextureLoader.h"
|
#include "Libraries/SHTextureLoader.h"
|
||||||
|
|
||||||
|
@ -25,11 +26,10 @@ namespace SHADE
|
||||||
FMOD::System* SHAssetManager::audioSystem;
|
FMOD::System* SHAssetManager::audioSystem;
|
||||||
std::unordered_map<AssetID, SHSound >* SHAssetManager::audioSoundList;
|
std::unordered_map<AssetID, SHSound >* SHAssetManager::audioSoundList;
|
||||||
|
|
||||||
std::vector<SHAsset> SHAssetManager::assetCollection;
|
std::vector<SHAssetLoader*> SHAssetManager::loaders(TYPE_COUNT);
|
||||||
std::unordered_map<AssetID, SHAsset> SHAssetManager::assetRegistry;
|
|
||||||
|
|
||||||
std::unordered_map<AssetID, SHMeshAsset> SHAssetManager::meshCollection;
|
std::vector<SHAsset> SHAssetManager::assetCollection;
|
||||||
std::unordered_map<AssetID, SHTextureAsset> SHAssetManager::textureCollection;
|
std::unordered_map<AssetID, SHAssetData * const> SHAssetManager::assetData;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Static function to generate asset ID.
|
* \brief Static function to generate asset ID.
|
||||||
|
@ -56,18 +56,15 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::Unload() noexcept
|
void SHAssetManager::Unload() noexcept
|
||||||
{
|
{
|
||||||
for (auto const& asset : assetCollection)
|
|
||||||
{
|
|
||||||
SHAssetMetaHandler::WriteMetaData(asset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::Unload(AssetID assetId) noexcept
|
void SHAssetManager::Unload(AssetID assetId) noexcept
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
|
AssetPath SHAssetManager::GenerateLocalPath(AssetPath path) noexcept
|
||||||
{
|
{
|
||||||
if (!IsRecognised(path.extension().string().c_str()))
|
if (!IsRecognised(path.extension().string().c_str()))
|
||||||
{
|
{
|
||||||
|
@ -85,7 +82,37 @@ namespace SHADE
|
||||||
// return std::filesystem::path();
|
// return std::filesystem::path();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
return std::filesystem::path(ASSET_ROOT + folder + path.filename().string());
|
return std::filesystem::path(std::string(ASSET_ROOT) + folder + path.filename().string());
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetPath SHAssetManager::GenerateNewPath(AssetName name, AssetType type)
|
||||||
|
{
|
||||||
|
std::string folder;
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case AssetType::SCENE:
|
||||||
|
folder = "scenes/";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssetType::PREFAB:
|
||||||
|
folder = "prefabs/";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssetType::MATERIAL:
|
||||||
|
folder = "materials/";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
folder = "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::filesystem::path{
|
||||||
|
std::string(ASSET_ROOT) +
|
||||||
|
folder +
|
||||||
|
name +
|
||||||
|
std::string(EXTENSIONS[static_cast<size_t>(type)])
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -121,7 +148,7 @@ namespace SHADE
|
||||||
// folder = "";
|
// folder = "";
|
||||||
// break;
|
// break;
|
||||||
//}
|
//}
|
||||||
AssetPath path{ ASSET_ROOT + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
|
AssetPath path{ std::string{ASSET_ROOT} + folder + name + SHAssetMetaHandler::GetExtensionFromType(type) };
|
||||||
|
|
||||||
SHAssetMetaHandler::WriteMetaData(meta);
|
SHAssetMetaHandler::WriteMetaData(meta);
|
||||||
|
|
||||||
|
@ -130,6 +157,19 @@ namespace SHADE
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssetID SHAssetManager::CreateAsset(AssetName name, AssetType type) noexcept
|
||||||
|
{
|
||||||
|
AssetID id = GenerateAssetID(type);
|
||||||
|
|
||||||
|
assetCollection.emplace_back(
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
GenerateNewPath(name, type),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Import new asset from outside editor window.
|
* \brief Import new asset from outside editor window.
|
||||||
*
|
*
|
||||||
|
@ -138,7 +178,10 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
AssetID SHAssetManager::ImportNewAsset(char const* p) noexcept
|
AssetID SHAssetManager::ImportNewAsset(char const* p) noexcept
|
||||||
{
|
{
|
||||||
std::filesystem::path const path{ p };
|
std::filesystem::path const path{ p };
|
||||||
|
|
||||||
|
auto const type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
|
||||||
|
auto const id = GenerateAssetID(type);
|
||||||
|
|
||||||
std::filesystem::path const newPath{ GenerateLocalPath(path) };
|
std::filesystem::path const newPath{ GenerateLocalPath(path) };
|
||||||
if (newPath.empty())
|
if (newPath.empty())
|
||||||
|
@ -149,11 +192,7 @@ namespace SHADE
|
||||||
|
|
||||||
std::filesystem::copy(path, newPath);
|
std::filesystem::copy(path, newPath);
|
||||||
|
|
||||||
AssetID id{ RetrieveAsset(newPath.string().c_str()) };
|
assetCollection.push_back(CreateAssetFromPath(newPath));
|
||||||
if (id != 0)
|
|
||||||
{
|
|
||||||
LoadData(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -164,158 +203,14 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::RefreshAllAssets() noexcept
|
void SHAssetManager::RefreshAllAssets() noexcept
|
||||||
{
|
{
|
||||||
std::vector<AssetPath> metaFiles;
|
|
||||||
std::vector<AssetPath> AssetFiles;
|
|
||||||
|
|
||||||
//SHFileSystem::LoadAllFiles(metaFiles, AssetFiles);
|
|
||||||
//std::vector<AssetPath> AssetFilesVerified;
|
|
||||||
std::vector<AssetPath> AssetFilesNew;
|
|
||||||
|
|
||||||
for (auto const& asset : AssetFiles)
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
for (auto it {metaFiles.begin()}; it != metaFiles.end(); ++it)
|
|
||||||
{
|
|
||||||
std::string fileExtCheck{ asset.filename().string() };
|
|
||||||
fileExtCheck += META_EXTENSION;
|
|
||||||
if (it->filename().string() == fileExtCheck)
|
|
||||||
{
|
|
||||||
metaFiles.erase(it);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found && IsRecognised(asset.extension().string().c_str()))
|
|
||||||
{
|
|
||||||
AssetFilesNew.push_back(asset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SHAsset> newLoad;
|
|
||||||
newLoad.reserve(AssetFilesNew.size());
|
|
||||||
|
|
||||||
//TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
|
|
||||||
for (auto const& file : AssetFilesNew)
|
|
||||||
{
|
|
||||||
newLoad.push_back(RegisterAssetNew(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
//UpdateAllSpriteSets();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHAssetManager::LoadDataTemp(std::string p) noexcept
|
|
||||||
{
|
|
||||||
AssetPath path{ p };
|
|
||||||
|
|
||||||
if (path.extension().string() == FBX_EXTENSION
|
|
||||||
|| path.extension().string() == GLTF_EXTENSION
|
|
||||||
|| path.extension().string() == MESH_EXTENSION)
|
|
||||||
{
|
|
||||||
LoadGLTF(
|
|
||||||
{
|
|
||||||
.name {path.filename().string()},
|
|
||||||
.id {0},
|
|
||||||
.type {AssetType::MESH},
|
|
||||||
.path {path},
|
|
||||||
.location {0}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (path.extension().string() == DDS_EXTENSION
|
|
||||||
|| path.extension().string() == TEXTURE_EXTENSION)
|
|
||||||
{
|
|
||||||
LoadDDS(
|
|
||||||
{
|
|
||||||
.name {path.filename().string()},
|
|
||||||
.id {0},
|
|
||||||
.type {AssetType::DDS},
|
|
||||||
.path {path},
|
|
||||||
.location {0}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SHMeshAsset> SHAssetManager::GetAllMeshes() noexcept
|
|
||||||
{
|
|
||||||
std::vector<SHMeshAsset> result;
|
|
||||||
for (auto const& mesh : meshCollection)
|
|
||||||
{
|
|
||||||
result.push_back(mesh.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SHTextureAsset> SHAssetManager::GetAllTextures() noexcept
|
|
||||||
{
|
|
||||||
std::vector<SHTextureAsset> result;
|
|
||||||
for (auto const& dds : textureCollection)
|
|
||||||
{
|
|
||||||
result.push_back(dds.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHMeshAsset const* SHAssetManager::GetMesh(AssetID id) noexcept
|
|
||||||
{
|
|
||||||
if (meshCollection.find(id) == meshCollection.end())
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &meshCollection[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
SHTextureAsset const* SHAssetManager::GetTexture(AssetID id) noexcept
|
|
||||||
{
|
|
||||||
if (textureCollection.find(id) == textureCollection.end())
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &textureCollection[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* \param Path for meta data file
|
|
||||||
* \param Path for asset file
|
|
||||||
|
|
||||||
* \brief Links meta data to asset in registries. Meta data should
|
|
||||||
* already exist
|
|
||||||
****************************************************************************/
|
|
||||||
void SHAssetManager::RegisterAsset(AssetPath const& metaPath, AssetPath const& path) noexcept
|
|
||||||
{
|
|
||||||
SHAsset const meta = SHAssetMetaHandler::RetrieveMetaData(metaPath);
|
|
||||||
|
|
||||||
assetCollection.push_back(meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* \param Path for asset file
|
|
||||||
|
|
||||||
* \brief Creates new meta data for new asset.
|
|
||||||
****************************************************************************/
|
|
||||||
SHAsset SHAssetManager::RegisterAssetNew(AssetPath const& asset) noexcept
|
|
||||||
{
|
|
||||||
SHAsset meta;
|
|
||||||
meta.type = SHAssetMetaHandler::GetTypeFromExtension(asset.extension().string());
|
|
||||||
meta.id = GenerateAssetID(meta.type);
|
|
||||||
|
|
||||||
assetCollection.push_back(meta);
|
|
||||||
|
|
||||||
SHAssetMetaHandler::WriteMetaData(meta);
|
|
||||||
return assetCollection.back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHAssetManager::IsRecognised(char const* ext) noexcept
|
bool SHAssetManager::IsRecognised(char const* ext) noexcept
|
||||||
{
|
{
|
||||||
for (auto const& e : EXTENSIONS)
|
for (auto const& e : EXTENSIONS)
|
||||||
{
|
{
|
||||||
if (strcmp(ext, e.c_str()) == 0)
|
if (strcmp(ext, e.data()) == 0)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -324,54 +219,31 @@ namespace SHADE
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::LoadGLTF(SHAsset asset) noexcept
|
SHAsset SHAssetManager::CreateAssetFromPath(AssetPath path) noexcept
|
||||||
{
|
{
|
||||||
std::vector<SHMeshAsset> meshes;
|
SHAsset result;
|
||||||
|
|
||||||
SHMeshLoader::LoadMesh(meshes, asset.path);
|
result.name = path.stem().string();
|
||||||
|
result.type = SHAssetMetaHandler::GetTypeFromExtension(path.extension().string());
|
||||||
|
result.id = GenerateAssetID(result.type);
|
||||||
|
result.path = path;
|
||||||
|
|
||||||
for (auto const& mesh : meshes)
|
return result;
|
||||||
{
|
|
||||||
auto id{ GenerateAssetID(AssetType::MESH) };
|
|
||||||
meshCollection.emplace(id, mesh);
|
|
||||||
|
|
||||||
AssetPath path;
|
|
||||||
if (!mesh.compiled)
|
|
||||||
{
|
|
||||||
path = SHMeshCompiler::CompileMeshBinary(mesh, asset.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
assetCollection.emplace_back(
|
|
||||||
mesh.header.meshName,
|
|
||||||
id,
|
|
||||||
AssetType::MESH,
|
|
||||||
path,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::LoadDDS(SHAsset asset) noexcept
|
void SHAssetManager::InitLoaders() noexcept
|
||||||
{
|
{
|
||||||
SHTextureAsset image;
|
loaders[static_cast<size_t>(AssetType::AUDIO)] = nullptr;
|
||||||
|
loaders[static_cast<size_t>(AssetType::SHADER)] = nullptr;
|
||||||
SHTextureLoader::LoadImageAsset(asset.path, image);
|
loaders[static_cast<size_t>(AssetType::MATERIAL)] = nullptr;
|
||||||
|
loaders[static_cast<size_t>(AssetType::IMAGE)] = dynamic_cast<SHAssetLoader*>(new SHTextureLoader());
|
||||||
if (!image.compiled)
|
loaders[static_cast<size_t>(AssetType::TEXTURE)] = nullptr;
|
||||||
{
|
loaders[static_cast<size_t>(AssetType::MESH)] = dynamic_cast<SHAssetLoader*>(new SHMeshLoader());
|
||||||
auto id{ GenerateAssetID(AssetType::TEXTURE) };
|
loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
|
||||||
textureCollection.emplace(id, image);
|
loaders[static_cast<size_t>(AssetType::SCENE)] = nullptr;
|
||||||
|
loaders[static_cast<size_t>(AssetType::PREFAB)] = nullptr;
|
||||||
auto path{ SHTextureCompiler::CompileTextureBinary(image, asset.path) };
|
loaders[static_cast<size_t>(AssetType::AUDIO_WAV)] = nullptr;
|
||||||
|
loaders[static_cast<size_t>(AssetType::DDS)] = nullptr;
|
||||||
assetCollection.emplace_back(
|
|
||||||
image.name,
|
|
||||||
id,
|
|
||||||
AssetType::TEXTURE,
|
|
||||||
path,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -379,8 +251,9 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::Load() noexcept
|
void SHAssetManager::Load() noexcept
|
||||||
{
|
{
|
||||||
RetrieveAssets();
|
InitLoaders();
|
||||||
LoadAllData();
|
BuildAssetCollection();
|
||||||
|
//LoadAllData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -388,143 +261,40 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void SHAssetManager::LoadAllData() noexcept
|
void SHAssetManager::LoadAllData() noexcept
|
||||||
{
|
{
|
||||||
//TODO Remove when on demand loading is done
|
|
||||||
for (auto const& asset : assetCollection)
|
for (auto const& asset : assetCollection)
|
||||||
{
|
{
|
||||||
switch (asset.type)
|
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||||
{
|
assetData.emplace(asset.id, data);
|
||||||
case AssetType::MESH:
|
|
||||||
meshCollection.emplace(asset.id, SHMeshAsset());
|
|
||||||
SHMeshLoader::LoadSHMesh(meshCollection[asset.id], asset.path);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AssetType::TEXTURE:
|
|
||||||
textureCollection.emplace(asset.id, SHTextureAsset());
|
|
||||||
SHTextureLoader::LoadSHTexture(asset.path, textureCollection[asset.id]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
void;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetManager::LoadData(AssetID id) noexcept
|
SHAssetData* SHAssetManager::LoadData(SHAsset const& asset) noexcept
|
||||||
{
|
{
|
||||||
(void)id;
|
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
if (data == nullptr)
|
||||||
* \brief Retrieve all asset files and meta files from filesystem
|
|
||||||
****************************************************************************/
|
|
||||||
void SHAssetManager::RetrieveAssets() noexcept
|
|
||||||
{
|
|
||||||
std::vector<AssetPath> metaFiles;
|
|
||||||
std::vector<AssetPath> AssetFiles;
|
|
||||||
|
|
||||||
for (auto const dir : std::filesystem::recursive_directory_iterator(ASSET_ROOT))
|
|
||||||
{
|
{
|
||||||
if (dir.path().extension().string() == META_EXTENSION)
|
SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string());
|
||||||
{
|
|
||||||
auto meta{ SHAssetMetaHandler::RetrieveMetaData(dir.path()) };
|
|
||||||
|
|
||||||
assetCollection.push_back(meta);
|
|
||||||
assetRegistry.emplace(meta.id, meta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Write new function for file manager to loop through all files
|
|
||||||
//SHFileSystem::StartupFillDirectories(ASSET_ROOT);
|
|
||||||
//FolderPointer rootFolder = SHFileSystem::GetRoot();
|
|
||||||
|
|
||||||
//for (auto const& meta : metaFiles)
|
|
||||||
//{
|
|
||||||
// for (std::vector<AssetPath>::const_iterator it{ AssetFiles.cbegin() };
|
|
||||||
// it != AssetFiles.cend();
|
|
||||||
// ++it)
|
|
||||||
// {
|
|
||||||
// // Asset exists for meta file
|
|
||||||
// std::string fileExtCheck{ it->filename().string() };
|
|
||||||
// fileExtCheck += META_EXTENSION;
|
|
||||||
// if (meta.filename().string() == fileExtCheck)
|
|
||||||
// {
|
|
||||||
// RegisterAsset(meta, *it);
|
|
||||||
// AssetFiles.erase(it);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//TODO: Handle if meta does not match all assets (if meta exist and asset doesnt, vice versa)
|
|
||||||
//for (auto const& file : AssetFiles)
|
|
||||||
//{
|
|
||||||
// if (IsRecognised(file.extension().string().c_str()))
|
|
||||||
// {
|
|
||||||
// SHAssetMetaHandler::WriteMetaData(RegisterAssetNew(file));
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// std::cout << "Unsupported File Format: " << file.filename() << "\n";
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
AssetID SHAssetManager::RetrieveAsset(char const* path) noexcept
|
|
||||||
{
|
|
||||||
std::filesystem::path p{ path };
|
|
||||||
if (IsRecognised(p.extension().string().c_str()))
|
|
||||||
{
|
|
||||||
SHAsset const& meta{ RegisterAssetNew(p) };
|
|
||||||
SHAssetMetaHandler::WriteMetaData(meta);
|
|
||||||
return meta.id;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Unsupported File Format: " << p.filename() << "\n";
|
assetData.emplace(asset.id, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert that file imported is not recognised
|
return data;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
void SHAssetManager::BuildAssetCollection() noexcept
|
||||||
* \param Full path of file
|
|
||||||
|
|
||||||
* \brief Extracts file name from path. Formats file name into readable
|
|
||||||
* with spaces and capitalises first letter of every word
|
|
||||||
****************************************************************************/
|
|
||||||
AssetName SHAssetManager::GetNameFromPath(AssetPath filepath) noexcept
|
|
||||||
{
|
{
|
||||||
std::string name{ filepath.filename().string() };
|
for (auto const& dir : std::filesystem::recursive_directory_iterator{ASSET_ROOT})
|
||||||
name = name.substr(0, name.find_last_of('.'));
|
{
|
||||||
|
if (dir.is_regular_file())
|
||||||
//if (name[0] <= 122 && name[0] >= 97)
|
{
|
||||||
//{
|
if (dir.path().extension().string() == META_EXTENSION.data())
|
||||||
// name[0] -= 32;
|
{
|
||||||
//}
|
assetCollection.push_back(SHAssetMetaHandler::RetrieveMetaData(dir.path()));
|
||||||
|
}
|
||||||
//for (size_t i{ 1 }; i < name.length(); ++i)
|
}
|
||||||
//{
|
}
|
||||||
// // Replace all underscores with spaces
|
|
||||||
// if (name[i] == '_')
|
|
||||||
// {
|
|
||||||
// name[i] = ' ';
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (name[i + 1] <= 'Z' && name[i + 1] >= 'A'
|
|
||||||
// && name[i] <= 'z' && name[i] >= 'a')
|
|
||||||
// {
|
|
||||||
// name.insert(i + 1, 1, ' ');
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (name[i - 1] == ' ' && name[i] <= 'z' && name[i] >= 'a')
|
|
||||||
// {
|
|
||||||
// name[i] -= 32;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "tinyddsloader.h"
|
#include "tinyddsloader.h"
|
||||||
#include "SHAsset.h"
|
#include "SHAsset.h"
|
||||||
|
#include "Asset Types/SHAssetData.h"
|
||||||
|
#include "Libraries/SHAssetLoader.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "Asset Types/SHMeshAsset.h"
|
|
||||||
#include "Asset Types/SHTextureAsset.h"
|
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -28,6 +29,8 @@ namespace SHADE
|
||||||
|
|
||||||
static AssetPath GenerateLocalPath(AssetPath path) noexcept;
|
static AssetPath GenerateLocalPath(AssetPath path) noexcept;
|
||||||
|
|
||||||
|
static AssetPath GenerateNewPath(AssetName name, AssetType type);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Deallocate all memory used by resource data
|
* \brief Deallocate all memory used by resource data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -55,6 +58,7 @@ namespace SHADE
|
||||||
* \return resource id generated for new asset
|
* \return resource id generated for new asset
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static AssetID CreateNewAsset(AssetType, AssetName) noexcept;
|
static AssetID CreateNewAsset(AssetType, AssetName) noexcept;
|
||||||
|
static AssetID CreateAsset(AssetName name, AssetType type) noexcept;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Import new resource from outside editor window.
|
* \brief Import new resource from outside editor window.
|
||||||
|
@ -71,66 +75,33 @@ namespace SHADE
|
||||||
static void RefreshAllAssets() noexcept;
|
static void RefreshAllAssets() noexcept;
|
||||||
// -------------------------------------------------------------------------/
|
// -------------------------------------------------------------------------/
|
||||||
|
|
||||||
//TODO: TEMPORARY FOR TESTING GLTF & DDS
|
template<typename T>
|
||||||
static void LoadDataTemp(std::string path) noexcept;
|
static std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> GetData(AssetID id) noexcept;
|
||||||
static std::vector<SHMeshAsset> GetAllMeshes() noexcept;
|
|
||||||
static std::vector<SHTextureAsset> GetAllTextures() noexcept;
|
|
||||||
|
|
||||||
static SHMeshAsset const* GetMesh(AssetID id) noexcept;
|
|
||||||
static SHTextureAsset const* GetTexture(AssetID id) noexcept;
|
|
||||||
private:
|
private:
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* \brief Load resource data into memory
|
* \brief Load resource data into memory
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
static void LoadAllData() noexcept;
|
static void LoadAllData() noexcept;
|
||||||
|
|
||||||
static void LoadData(AssetID id) noexcept;
|
static SHAssetData* LoadData(SHAsset const& asset) noexcept;
|
||||||
|
|
||||||
/****************************************************************************
|
inline static void BuildAssetCollection() noexcept;
|
||||||
* \brief Retrieve all resource files and meta files from filesystem
|
|
||||||
****************************************************************************/
|
|
||||||
static void RetrieveAssets() noexcept;
|
|
||||||
|
|
||||||
static AssetID RetrieveAsset(char const* path) noexcept;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* \param Full path of file
|
|
||||||
|
|
||||||
* \brief Extracts file name from path. Formats file name into readable
|
|
||||||
* with spaces and capitalises first letter of every word
|
|
||||||
****************************************************************************/
|
|
||||||
static AssetName GetNameFromPath(AssetPath) noexcept;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* \param Path for meta data file
|
|
||||||
* \param Path for resource file
|
|
||||||
|
|
||||||
* \brief Links meta data to resource in registries. Meta data should
|
|
||||||
* already exist
|
|
||||||
****************************************************************************/
|
|
||||||
static void RegisterAsset(AssetPath const&, AssetPath const&) noexcept;
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* \param Path for resource file
|
|
||||||
|
|
||||||
* \brief Creates new meta data for new resource.
|
|
||||||
****************************************************************************/
|
|
||||||
static SHAsset RegisterAssetNew(AssetPath const&) noexcept;
|
|
||||||
|
|
||||||
static bool IsRecognised(char const*) noexcept;
|
static bool IsRecognised(char const*) noexcept;
|
||||||
|
|
||||||
|
static SHAsset CreateAssetFromPath(AssetPath path) noexcept;
|
||||||
|
|
||||||
// Specialised load calls
|
static void InitLoaders() noexcept;
|
||||||
static void LoadGLTF(SHAsset asset) noexcept;
|
|
||||||
static void LoadDDS(SHAsset asset) noexcept;
|
|
||||||
|
|
||||||
static FMOD::System* audioSystem;
|
static FMOD::System* audioSystem;
|
||||||
static std::unordered_map<AssetID,SHSound>* audioSoundList;
|
static std::unordered_map<AssetID,SHSound>* audioSoundList;
|
||||||
|
|
||||||
|
static std::vector<SHAssetLoader*> loaders;
|
||||||
|
|
||||||
// For all resources
|
// For all resources
|
||||||
static std::vector<SHAsset> assetCollection;
|
static std::vector<SHAsset> assetCollection;
|
||||||
static std::unordered_map<AssetID, SHAsset> assetRegistry;
|
static std::unordered_map<AssetID, SHAssetData * const> assetData;
|
||||||
|
|
||||||
static std::unordered_map<AssetID, SHMeshAsset> meshCollection;
|
|
||||||
static std::unordered_map<AssetID, SHTextureAsset> textureCollection;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "SHAssetManager.hpp"
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
#include "SHAssetManager.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T const* const> SHAssetManager::GetData(AssetID id) noexcept
|
||||||
|
{
|
||||||
|
if (!assetData.contains(id))
|
||||||
|
{
|
||||||
|
for (auto const& asset : assetCollection)
|
||||||
|
{
|
||||||
|
if (asset.id == id)
|
||||||
|
{
|
||||||
|
assetData.emplace(id, LoadData(asset));
|
||||||
|
return dynamic_cast<T const* const>(assetData[id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SHLOG_ERROR("Asset ID provided does not exist: {}", id);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dynamic_cast<T const* const>(assetData[id]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,7 +37,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
for (int i{0}; i < EXTENSIONS->size(); ++i)
|
for (int i{0}; i < EXTENSIONS->size(); ++i)
|
||||||
{
|
{
|
||||||
if (ext == EXTENSIONS[i])
|
if (strcmp(ext.c_str(), EXTENSIONS[i].data()) == 0)
|
||||||
{
|
{
|
||||||
return static_cast<AssetType>(i);
|
return static_cast<AssetType>(i);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ namespace SHADE
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
AssetExtension SHAssetMetaHandler::GetExtensionFromType(AssetType type) noexcept
|
AssetExtension SHAssetMetaHandler::GetExtensionFromType(AssetType type) noexcept
|
||||||
{
|
{
|
||||||
return EXTENSIONS[static_cast<size_t>(type)];
|
return AssetExtension(EXTENSIONS[static_cast<size_t>(type)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -124,16 +124,6 @@ namespace SHADE
|
||||||
metaFile << "ID: " << meta.id << "\n";
|
metaFile << "ID: " << meta.id << "\n";
|
||||||
metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl;
|
metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl;
|
||||||
|
|
||||||
////TODO Add in information that is specific to types like mesh
|
|
||||||
//switch(meta.type)
|
|
||||||
//{
|
|
||||||
//case AssetType::MESH:
|
|
||||||
// break;
|
|
||||||
|
|
||||||
//default:
|
|
||||||
// break;
|
|
||||||
//}
|
|
||||||
|
|
||||||
metaFile.close();
|
metaFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHAssetBrowser.h"
|
||||||
|
|
||||||
|
#include "Editor/IconsMaterialDesign.h"
|
||||||
|
#include "Editor/SHImGuiHelpers.hpp"
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "Assets/SHAssetManager.h"
|
||||||
|
#include "Editor/DragDrop/SHDragDrop.hpp"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHAssetBrowser::SHAssetBrowser()
|
||||||
|
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::Init()
|
||||||
|
{
|
||||||
|
SHEditorWindow::Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::Update()
|
||||||
|
{
|
||||||
|
SHEditorWindow::Update();
|
||||||
|
if(Begin())
|
||||||
|
{
|
||||||
|
DrawMenuBar();
|
||||||
|
auto const& assets = SHAssetManager::GetAllAssets();
|
||||||
|
if(ImGui::BeginTable("AssetBrowserTable", 3))
|
||||||
|
{
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableHeader("Asset ID");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableHeader("Name");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TableHeader("Type");
|
||||||
|
for(SHAsset const& asset : assets)
|
||||||
|
{
|
||||||
|
DrawAsset(asset);
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::DrawMenuBar()
|
||||||
|
{
|
||||||
|
if(ImGui::BeginMenuBar())
|
||||||
|
{
|
||||||
|
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::DrawAsset(SHAsset const& asset)
|
||||||
|
{
|
||||||
|
ImGui::PushID(asset.id);
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Selectable(std::format("{}", asset.id).data(), false, ImGuiSelectableFlags_SpanAllColumns);
|
||||||
|
if(SHDragDrop::BeginSource())
|
||||||
|
{
|
||||||
|
auto id = asset.id;
|
||||||
|
ImGui::Text("Moving Asset: %zu", id);
|
||||||
|
SHDragDrop::SetPayload<AssetID>(DRAG_RESOURCE, &id);
|
||||||
|
SHDragDrop::EndSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s", asset.name.c_str());
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s", "Type");
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Assets/SHAsset.h"
|
||||||
|
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHAssetBrowser final : public SHEditorWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SHAssetBrowser();
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
void Refresh();
|
||||||
|
private:
|
||||||
|
void DrawMenuBar();
|
||||||
|
void DrawAsset(SHAsset const& asset);
|
||||||
|
|
||||||
|
float idColumnWidth, nameColumnWidth, typeColumnWidth;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
|
@ -93,8 +93,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if (ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
{
|
{
|
||||||
|
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x * 0.75f);
|
||||||
ImGui::SetCursorPosX(ImGui::GetContentRegionAvail().x - 35.0f);
|
|
||||||
if(ImGui::SmallButton(ICON_MD_DESELECT))
|
if(ImGui::SmallButton(ICON_MD_DESELECT))
|
||||||
{
|
{
|
||||||
auto editor = SHSystemManager::GetSystem<SHEditor>();
|
auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
|
|
@ -39,6 +39,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHComponentManager::RemoveComponent<T>(component->GetEID());
|
SHComponentManager::RemoveComponent<T>(component->GetEID());
|
||||||
}
|
}
|
||||||
|
if (ImGui::Selectable(std::format("{} Reset {}", ICON_MD_RESTART_ALT, componentName.data()).data()))
|
||||||
|
{
|
||||||
|
*component = T();
|
||||||
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,7 +52,7 @@ namespace SHADE
|
||||||
if (!component)
|
if (!component)
|
||||||
return;
|
return;
|
||||||
const auto componentType = rttr::type::get(*component);
|
const auto componentType = rttr::type::get(*component);
|
||||||
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; });
|
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
if (ImGui::CollapsingHeader(componentType.get_name().data()))
|
||||||
{
|
{
|
||||||
|
@ -89,7 +93,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin && metaMax)
|
if (metaMin && metaMax)
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value<int>(), metaMin.template get_value<int>(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); });
|
SHEditorWidgets::SliderInt(property.get_name().data(), metaMin.template get_value<int>(), metaMax.template get_value<int>(), [component, property] {return property.get_value(component).to_int(); }, [component, property](int const& result) {property.set_value(component, result); });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -115,7 +119,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), metaMin.template get_value<uint16_t>(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu");
|
SHEditorWidgets::SliderScalar<uint16_t>(property.get_name().data(), ImGuiDataType_U16, metaMin.template get_value<uint16_t>(), metaMax.template get_value<uint16_t>(), [component, property] {return property.get_value(component).to_uint16(); }, [component, property](uint16_t const& result) {property.set_value(component, result); }, "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -128,7 +132,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), metaMin.template get_value<uint32_t>(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu");
|
SHEditorWidgets::SliderScalar<uint32_t>(property.get_name().data(), ImGuiDataType_U32, metaMin.template get_value<uint32_t>(), metaMax.template get_value<uint32_t>(), [component, property] { return property.get_value(component).to_uint32(); }, [component, property](uint32_t const& result) {property.set_value(component, result); }, "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -141,7 +145,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), metaMin.template get_value<uint64_t>(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu");
|
SHEditorWidgets::SliderScalar<uint64_t>(property.get_name().data(), ImGuiDataType_U64, metaMin.template get_value<uint64_t>(), metaMax.template get_value<uint64_t>(), [component, property] {return property.get_value(component).to_uint64(); }, [component, property](uint64_t const& result) {property.set_value(component, result); }, "%zu");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -152,13 +156,18 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
auto metaMin = property.get_metadata(META::min);
|
auto metaMin = property.get_metadata(META::min);
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
|
float min{}, max{};
|
||||||
|
if(metaMin.is_valid())
|
||||||
|
min = std::max(metaMin.template get_value<float>(), -FLT_MAX * 0.5f);
|
||||||
|
if(metaMax.is_valid())
|
||||||
|
max = std::min(metaMax.template get_value<float>(), FLT_MAX * 0.5f);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderFloat(property.get_name().data(), metaMin.template get_value<float>(), metaMin.template get_value<float>(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); });
|
SHEditorWidgets::SliderFloat(property.get_name().data(), min, max, [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); });
|
SHEditorWidgets::DragFloat(property.get_name().data(), [component, property] {return property.get_value(component).to_float(); }, [component, property](float const& result) {property.set_value(component, result); }, "Test");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == rttr::type::get<double>())
|
else if (type == rttr::type::get<double>())
|
||||||
|
@ -167,7 +176,7 @@ namespace SHADE
|
||||||
auto metaMax = property.get_metadata(META::max);
|
auto metaMax = property.get_metadata(META::max);
|
||||||
if (metaMin.is_valid() && metaMax.is_valid())
|
if (metaMin.is_valid() && metaMax.is_valid())
|
||||||
{
|
{
|
||||||
SHEditorWidgets::SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMin.template get_value<double>(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); });
|
SHEditorWidgets::SliderScalar<double>(property.get_name().data(), ImGuiDataType_Double, metaMin.template get_value<double>(), metaMax.template get_value<double>(), [component, property] {return property.get_value(component).to_double(); }, [component, property](double const& result) {property.set_value(component, result); });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,8 +84,8 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
// Render Scripts
|
// Render Scripts
|
||||||
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||||
scriptEngine->RenderScriptsInInspector(eid);
|
scriptEngine->RenderScriptsInInspector(eid);
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
if(ImGui::BeginMenu(std::format("{} Add Component", ICON_MD_LIBRARY_ADD).data()))
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,4 +3,5 @@
|
||||||
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
|
#include "HierarchyPanel/SHHierarchyPanel.h" //Hierarchy Panel
|
||||||
#include "Inspector/SHEditorInspector.h" //Inspector
|
#include "Inspector/SHEditorInspector.h" //Inspector
|
||||||
#include "Profiling/SHEditorProfiler.h" //Profiler
|
#include "Profiling/SHEditorProfiler.h" //Profiler
|
||||||
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
|
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
|
||||||
|
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
|
|
@ -24,12 +24,13 @@ namespace SHADE
|
||||||
void SHEditorViewport::Init()
|
void SHEditorViewport::Init()
|
||||||
{
|
{
|
||||||
SHEditorWindow::Init();
|
SHEditorWindow::Init();
|
||||||
|
transformGizmo.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditorViewport::Update()
|
void SHEditorViewport::Update()
|
||||||
{
|
{
|
||||||
SHEditorWindow::Update();
|
SHEditorWindow::Update();
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f,0.0f));
|
||||||
if(Begin())
|
if(Begin())
|
||||||
{
|
{
|
||||||
ImGuizmo::SetDrawlist();
|
ImGuizmo::SetDrawlist();
|
||||||
|
@ -55,7 +56,7 @@ namespace SHADE
|
||||||
ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
ImGuizmo::SetRect(beginCursorPos.x , beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
||||||
transformGizmo.Draw();
|
transformGizmo.Draw();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
ImGui::PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditorViewport::Exit()
|
void SHEditorViewport::Exit()
|
||||||
|
|
|
@ -13,6 +13,12 @@
|
||||||
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
void SHTransformGizmo::Init()
|
||||||
|
{
|
||||||
|
auto& style = ImGuizmo::GetStyle();
|
||||||
|
style.RotationLineThickness = 2.5f;
|
||||||
|
}
|
||||||
|
|
||||||
void SHTransformGizmo::Draw()
|
void SHTransformGizmo::Draw()
|
||||||
{
|
{
|
||||||
bool justChangedTfm = false;
|
bool justChangedTfm = false;
|
||||||
|
@ -26,9 +32,12 @@ namespace SHADE
|
||||||
|
|
||||||
SHMatrix view = SHMatrix::Transpose(editorCamera->GetViewMatrix());
|
SHMatrix view = SHMatrix::Transpose(editorCamera->GetViewMatrix());
|
||||||
SHMatrix proj = SHMatrix::Transpose(editorCamera->GetProjMatrix());
|
SHMatrix proj = SHMatrix::Transpose(editorCamera->GetProjMatrix());
|
||||||
|
|
||||||
|
//Invert projection y-axis
|
||||||
proj(1, 1) *= -1;
|
proj(1, 1) *= -1;
|
||||||
|
|
||||||
static SHMatrix gridMat = SHMatrix::Translate(0, -0.5f, 0.f) * SHMatrix::Identity;
|
static SHMatrix gridMat = SHMatrix::Translate(0, -0.5f, 0.f) * SHMatrix::Identity;
|
||||||
//ImGuizmo::DrawGrid(&view._11, &proj._11, &gridMat._11, 100.f);
|
|
||||||
if (selectedEntityTransformComponent == nullptr)
|
if (selectedEntityTransformComponent == nullptr)
|
||||||
{
|
{
|
||||||
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
|
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
@ -55,31 +64,37 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SHMatrix mat = selectedEntityTransformComponent->GetTRS();
|
SHMatrix mat = selectedEntityTransformComponent->GetTRS();
|
||||||
isManipulating = ImGuizmo::Manipulate(&view._11, &proj._11, static_cast<ImGuizmo::OPERATION>(operation), ImGuizmo::MODE::WORLD, &mat._11);
|
useSnap = ImGui::IsKeyDown(ImGuiKey_LeftCtrl);
|
||||||
if (!justChangedTfm)
|
if(useSnap)
|
||||||
{
|
{
|
||||||
if (ImGui::IsItemClicked())
|
switch (operation)
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHMatrix>>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx)
|
{
|
||||||
{
|
case Operation::TRANSLATE: snap = &translationSnap.x; break;
|
||||||
if (!tfm)
|
case Operation::ROTATE: snap = &rotationSnap; break;
|
||||||
return;
|
case Operation::SCALE: snap = &scaleSnap; break;
|
||||||
SHVec3 translate{}, rotate{}, scale{};
|
default: snap = &translationSnap.x;
|
||||||
mtx.Decompose(translate, rotate, scale);
|
}
|
||||||
tfm->SetWorldPosition(translate);
|
|
||||||
tfm->SetWorldRotation(rotate);
|
|
||||||
tfm->SetWorldScale(scale);
|
|
||||||
})));
|
|
||||||
else if (ImGui::IsItemHovered(ImGuiMouseButton_Left) && ImGui::IsMouseDown(ImGuiMouseButton_Left) && isManipulating)
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHMatrix>>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = std::move(selectedEntityTransformComponent)](SHMatrix const& mtx)
|
|
||||||
{
|
|
||||||
if (!tfm)
|
|
||||||
return;
|
|
||||||
SHVec3 translate{}, rotate{}, scale{};
|
|
||||||
mtx.Decompose(translate, rotate, scale);
|
|
||||||
tfm->SetWorldPosition(translate);
|
|
||||||
tfm->SetWorldRotation(rotate);
|
|
||||||
tfm->SetWorldScale(scale);
|
|
||||||
})), true);
|
|
||||||
}
|
}
|
||||||
|
ImGuizmo::Manipulate(&view._11, &proj._11, static_cast<ImGuizmo::OPERATION>(operation), ImGuizmo::MODE::WORLD, &mat._11, nullptr, useSnap ? snap : nullptr);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (!justChangedTfm && ImGuizmo::IsUsing())
|
||||||
|
{
|
||||||
|
|
||||||
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHMatrix>>(selectedEntityTransformComponent->GetTRS(), mat, [tfm = (selectedEntityTransformComponent)](SHMatrix const& mtx)
|
||||||
|
{
|
||||||
|
if (!tfm)
|
||||||
|
return;
|
||||||
|
SHVec3 translate{}, rotate{}, scale{};
|
||||||
|
mtx.Decompose(translate, rotate, scale);
|
||||||
|
tfm->SetWorldPosition(translate);
|
||||||
|
tfm->SetWorldRotation(rotate);
|
||||||
|
tfm->SetWorldScale(scale);
|
||||||
|
})), startRecording);
|
||||||
|
if(!startRecording)
|
||||||
|
startRecording = true;
|
||||||
|
}
|
||||||
|
isManipulating = ImGuizmo::IsUsing() || startRecording;
|
||||||
|
if(startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
|
startRecording = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,11 +37,17 @@ namespace SHADE
|
||||||
UNIVERSAL = TRANSLATE | ROTATE | SCALEU
|
UNIVERSAL = TRANSLATE | ROTATE | SCALEU
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void Init();
|
||||||
void Draw();
|
void Draw();
|
||||||
bool isManipulating = false;
|
bool isManipulating = false;
|
||||||
|
bool useSnap = false;
|
||||||
Mode mode = Mode::WORLD;
|
Mode mode = Mode::WORLD;
|
||||||
Operation operation = Operation::TRANSLATE;
|
Operation operation = Operation::TRANSLATE;
|
||||||
private:
|
private:
|
||||||
|
float scaleSnap = 0.25f;
|
||||||
|
float rotationSnap = 1.0f;
|
||||||
|
SHVec3 translationSnap = SHVec3(0.25f, 0.25f, 0.25f);
|
||||||
|
float* snap = nullptr;
|
||||||
SHTransformComponent* selectedEntityTransformComponent{nullptr};
|
SHTransformComponent* selectedEntityTransformComponent{nullptr};
|
||||||
SHCameraComponent* editorCamera{nullptr};
|
SHCameraComponent* editorCamera{nullptr};
|
||||||
};
|
};
|
||||||
|
|
|
@ -92,6 +92,7 @@ namespace SHADE
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
|
||||||
|
SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
||||||
|
|
||||||
io = &ImGui::GetIO();
|
io = &ImGui::GetIO();
|
||||||
|
@ -134,7 +135,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PollPicking();
|
//PollPicking();
|
||||||
|
|
||||||
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,7 +40,6 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
|
|
||||||
auto cursorPos = ImGui::GetCursorScreenPos();
|
|
||||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||||
|
@ -158,7 +157,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
static bool DragN(const std::string& fieldLabel, std::vector<std::string>const& componentLabels,
|
static bool DragN(const std::string& label, std::vector<std::string>const& componentLabels,
|
||||||
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
|
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
|
||||||
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
|
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
|
||||||
{
|
{
|
||||||
|
@ -169,13 +168,13 @@ namespace SHADE
|
||||||
const ImGuiContext& g = *GImGui;
|
const ImGuiContext& g = *GImGui;
|
||||||
bool valueChanged = false;
|
bool valueChanged = false;
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::PushID(fieldLabel.c_str());
|
ImGui::PushID(label.c_str());
|
||||||
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
|
PushMultiItemsWidthsAndLabels(componentLabels, 0.0f);
|
||||||
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
|
ImGui::BeginColumns("DragVecCol", 2, ImGuiOldColumnFlags_NoBorder | ImGuiOldColumnFlags_NoResize);
|
||||||
ImGui::SetColumnWidth(-1, 80.0f);
|
ImGui::SetColumnWidth(-1, 80.0f);
|
||||||
ImGui::Text(fieldLabel.c_str());
|
ImGui::Text(label.c_str());
|
||||||
if (isHovered)
|
if (isHovered)
|
||||||
*isHovered = ImGui::IsItemHovered();
|
*isHovered = ImGui::IsItemHovered();
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
for (std::size_t i = 0; i < N; ++i)
|
for (std::size_t i = 0; i < N; ++i)
|
||||||
{
|
{
|
||||||
|
@ -203,75 +202,91 @@ namespace SHADE
|
||||||
return valueChanged;
|
return valueChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec2(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
|
static bool DragVec2(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec2(void)> get,
|
||||||
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec2)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec2 values = get();
|
SHVec2 values = get();
|
||||||
bool changed = false;
|
bool const changed = DragN<float, 2>(label, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags);
|
||||||
if (DragN<float, 2>(fieldLabel, componentLabels, { &values.x, &values.y }, speed, displayFormat, valueMin, valueMax, flags))
|
static bool startRecording = false;
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), true);
|
}
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec2>>(get(), values, set)), false);
|
startRecording = false;
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec3(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
|
static bool DragVec3(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec3(void)> get,
|
||||||
std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec3)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec3 values = get();
|
SHVec3 values = get();
|
||||||
bool changed = false;
|
bool const changed = DragN<float, 3>(label, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags);
|
||||||
if (DragN<float, 3>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z }, speed, displayFormat, valueMin, valueMax, flags))
|
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
static bool startRecording = false;
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHVec3 old = get();
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(old, values, set)), startRecording);
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
if (!startRecording)
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), true);
|
startRecording = true;
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
}
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec3>>(get(), values, set)), false);
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragVec4(const std::string& fieldLabel, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
|
static bool DragVec4(const std::string& label, std::vector<std::string>const& componentLabels, std::function<SHVec4(void)> get,
|
||||||
std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", float valueMin = 0.0f, float valueMax = 0.0f,
|
std::function<void(SHVec4)> set, float speed = 0.1f, const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, float valueMin = 0.0f, float valueMax = 0.0f,
|
||||||
ImGuiSliderFlags flags = 0)
|
ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
SHVec4 values = get();
|
SHVec4 values = get();
|
||||||
bool changed = false;
|
bool const changed = DragN<float, 4>(label, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags);
|
||||||
if (DragN<float, 4>(fieldLabel, componentLabels, { &values.x, &values.y, &values.z, &values.w }, speed, displayFormat, valueMin, valueMax, flags))
|
static bool startRecording = false;
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), true);
|
}
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<SHVec4>>(get(), values, set)), false);
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,173 +294,325 @@ namespace SHADE
|
||||||
//|| Widget Extensions ||
|
//|| Widget Extensions ||
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
|
|
||||||
static bool CheckBox(std::string const& label, std::function<bool(void)> get, std::function<void(bool const&)> set)
|
static void TextLabel(std::string_view const& text, bool sameLine = true)
|
||||||
|
{
|
||||||
|
const ImVec2 textSize = ImGui::CalcTextSize(text.data(), NULL, true);
|
||||||
|
if(textSize.x > 0.0f)
|
||||||
|
{
|
||||||
|
ImGui::Text(text.data());
|
||||||
|
ImGui::SameLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool CheckBox(std::string_view const& label, std::function<bool(void)> get, std::function<void(bool const&)> set, std::string_view const& tooltip = {})
|
||||||
{
|
{
|
||||||
bool value = get();
|
bool value = get();
|
||||||
if (ImGui::Checkbox(label.c_str(), &value))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
if (ImGui::Checkbox("##", &value))
|
||||||
{
|
{
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<bool>>(get(), value, set)), false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static bool RadioButton(std::vector<std::string> const& listLabels, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set)
|
static bool RadioButton(std::vector<std::string> const& label, std::vector<T> const& listTypes, std::function<T(void)> get, std::function<void(T const&)> set ,std::string_view const& tooltip = {})
|
||||||
{
|
{
|
||||||
T type = get();
|
T type = get();
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
for (size_t i = 0; i < listTypes.size(); i++)
|
for (size_t i = 0; i < listTypes.size(); i++)
|
||||||
{
|
{
|
||||||
if (ImGui::RadioButton(listLabels[i].c_str(), type == listTypes[i]))
|
if (ImGui::RadioButton(label[i].c_str(), type == listTypes[i]))
|
||||||
{
|
{
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), listTypes[i], set)), false);
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
}
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool InputText(const std::string& label, const std::function<std::string(void)> get,
|
static bool InputText(const std::string& label, const std::function<std::string(void)> get,
|
||||||
const std::function<void(std::string)> set, ImGuiInputTextFlags flag = 0,
|
const std::function<void(std::string)> set, std::string_view const& tooltip = {},
|
||||||
ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
|
ImGuiInputTextFlags flag = 0, ImGuiInputTextCallback callback = (ImGuiInputTextCallback)0, void* userData = (void*)0)
|
||||||
{
|
{
|
||||||
std::string text = get();
|
std::string text = get();
|
||||||
if (ImGui::InputText(label.c_str(), &text, flag, callback, userData))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
if (ImGui::InputText("##", &text, flag, callback, userData))
|
||||||
{
|
{
|
||||||
if (ImGui::IsItemDeactivatedAfterEdit())
|
if (ImGui::IsItemDeactivatedAfterEdit())
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<std::string>>(get(), text, set)), false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
ImGui::PopID();
|
||||||
}
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
template <typename T>
|
|
||||||
static bool DragScalar(const std::string& fieldLabel, ImGuiDataType data_type, std::function<T(void)> get, std::function<void(T const&)> set,
|
|
||||||
float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
|
||||||
{
|
|
||||||
T value = get();
|
|
||||||
std::cout << value << " \n";
|
|
||||||
//bool hasChange = ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
|
|
||||||
|
|
||||||
if (ImGui::DragScalar(fieldLabel.c_str(), data_type, &value, speed, &p_min, &p_max, displayFormat, flags))
|
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
if (ImGui::IsItemHovered())
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
{
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
ImGui::BeginTooltip();
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
ImGui::Text(tooltip.data());
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
ImGui::EndTooltip();
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragFloat(const std::string& fieldLabel, std::function<float(void)> get, std::function<void(float const&)> set,
|
template <typename T>
|
||||||
|
static bool DragScalar(const std::string& label, ImGuiDataType data_type, std::function<T(void)> get, std::function<void(T const&)> set,
|
||||||
|
float speed = 1.0f, T p_min = T(), T p_max = T(), const char* displayFormat = "%.3f", std::string_view const& tooltip = {}, ImGuiSliderFlags flags = 0)
|
||||||
|
{
|
||||||
|
T value = get();
|
||||||
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
const bool hasChange = ImGui::DragScalar("##", data_type, &value, speed, &p_min, &p_max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
|
{
|
||||||
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), startRecording);
|
||||||
|
if (!startRecording)
|
||||||
|
startRecording = true;
|
||||||
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool DragFloat(const std::string_view& label, std::function<float(void)> get, std::function<void(float const&)> set, std::string_view const& tooltip = {},
|
||||||
float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
float speed = 0.1f, float p_min = float(), float p_max = float(), const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
float value = get();
|
float value = get();
|
||||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
ImGui::BeginGroup();
|
||||||
if (ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
const bool hasChange = ImGui::DragFloat("##", &value, speed, p_min, p_max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
|
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if(!tooltip.empty())
|
||||||
|
{
|
||||||
|
if(ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DragInt(const std::string& fieldLabel, std::function<int(void)> get, std::function<void(int const&)> set,
|
static bool DragInt(const std::string& label, std::function<int(void)> get, std::function<void(int const&)> set, std::string_view const& tooltip = {},
|
||||||
float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
float speed = 1.0f, int p_min = int(), int p_max = int(), const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
int value = get();
|
int value = get();
|
||||||
//bool hasChange = ImGui::DragFloat(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags);
|
ImGui::BeginGroup();
|
||||||
if (ImGui::DragInt(fieldLabel.c_str(), &value, speed, p_min, p_max, displayFormat, flags))
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
const bool hasChange = ImGui::DragInt("##", &value, speed, p_min, p_max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
|
|
||||||
else if (ImGui::IsItemDeactivatedAfterEdit())
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static bool SliderScalar(const std::string& fieldLabel, ImGuiDataType data_type, T min, T max, std::function<T(void)> get, std::function<void(T const&)> set,
|
static bool SliderScalar(const std::string& label, ImGuiDataType data_type, T min, T max, std::function<T(void)> get, std::function<void(T const&)> set, std::string_view const& tooltip = {},
|
||||||
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
T value = get();
|
T value = get();
|
||||||
if (ImGui::SliderScalar(fieldLabel.c_str(), data_type, &value, &min, &max, displayFormat, flags))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
bool const hasChange = ImGui::SliderScalar("##", data_type, &value, &min, &max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), value, set)), true);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SliderFloat(const std::string& fieldLabel, float min, float max, std::function<float(void)> get, std::function<void(float const&)> set,
|
static bool SliderFloat(const std::string& label, float const& min, float const& max, std::function<float(void)> get, std::function<void(float const&)> set, std::string_view const& tooltip = {},
|
||||||
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
const char* displayFormat = "%.3f", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
float value = get();
|
float value = get();
|
||||||
if (ImGui::SliderFloat(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
bool const hasChange = ImGui::SliderFloat("##", &value, min, max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), startRecording);
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), false);
|
if (!startRecording)
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
startRecording = true;
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<float>>(get(), value, set)), true);
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SliderInt(const std::string& fieldLabel, int min, int max, std::function<int(void)> get, std::function<void(int const&)> set,
|
static bool SliderInt(const std::string& label, int min, int max, std::function<int(void)> get, std::function<void(int const&)> set, std::string_view const& tooltip = {},
|
||||||
const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
const char* displayFormat = "%d", ImGuiSliderFlags flags = 0)
|
||||||
{
|
{
|
||||||
int value = get();
|
int value = get();
|
||||||
if (ImGui::SliderInt(fieldLabel.c_str(), &value, min, max, displayFormat, flags))
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID(label.data());
|
||||||
|
TextLabel(label);
|
||||||
|
bool const hasChange = ImGui::SliderInt("##", &value, min, max, displayFormat, flags);
|
||||||
|
static bool startRecording = false;
|
||||||
|
if (hasChange)
|
||||||
{
|
{
|
||||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left, false) && !ImGui::IsMouseDragging(ImGuiMouseButton_Left, -0.2f))
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), false);
|
|
||||||
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), true);
|
|
||||||
|
|
||||||
return true;
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), value, set)), startRecording);
|
||||||
|
if (!startRecording)
|
||||||
|
startRecording = true;
|
||||||
}
|
}
|
||||||
|
if (startRecording && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
return false;
|
{
|
||||||
|
startRecording = false;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ComboBox(const std::string& fieldLabel, std::vector<const char*> list, std::function<int(void)> get, std::function<void(int const&)> set)
|
static bool ComboBox(const std::string& label, std::vector<const char*> list, std::function<int(void)> get, std::function<void(int const&)> set, std::string_view const& tooltip = {})
|
||||||
{
|
{
|
||||||
bool edited = false;
|
bool edited = false;
|
||||||
int selected = get();
|
int selected = get();
|
||||||
ImGui::PushID(fieldLabel.c_str());
|
ImGui::BeginGroup();
|
||||||
ImGui::Text(fieldLabel.c_str()); ImGui::SameLine();
|
ImGui::PushID(label.c_str());
|
||||||
|
TextLabel(label);
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast<int>(list.size())))
|
if (edited = ImGui::Combo("##Combo", &selected, list.data(), static_cast<int>(list.size())))
|
||||||
{
|
{
|
||||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false);
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<int>>(get(), selected, set)), false);
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
|
ImGui::EndGroup();
|
||||||
|
if (!tooltip.empty())
|
||||||
|
{
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text(tooltip.data());
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
return edited;
|
return edited;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,8 +5,9 @@ typedef uint32_t SHEventIdentifier;
|
||||||
typedef uint32_t SHEventHandle;
|
typedef uint32_t SHEventHandle;
|
||||||
|
|
||||||
//Add your event identifiers here:
|
//Add your event identifiers here:
|
||||||
constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0};
|
constexpr SHEventIdentifier SH_EXAMPLE_EVENT { 0 };
|
||||||
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT{ 1 };
|
constexpr SHEventIdentifier SH_ENTITY_DESTROYED_EVENT { 1 };
|
||||||
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT{ 2 };
|
constexpr SHEventIdentifier SH_ENTITY_CREATION_EVENT { 2 };
|
||||||
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT{ 3 };
|
constexpr SHEventIdentifier SH_COMPONENT_ADDED_EVENT { 3 };
|
||||||
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT{ 4 };
|
constexpr SHEventIdentifier SH_COMPONENT_REMOVED_EVENT { 4 };
|
||||||
|
constexpr SHEventIdentifier SH_SCENEGRAPH_CHANGE_PARENT_EVENT { 5 };
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace SHADE
|
||||||
SHVkSampler::~SHVkSampler() noexcept
|
SHVkSampler::~SHVkSampler() noexcept
|
||||||
{
|
{
|
||||||
if (vkSampler)
|
if (vkSampler)
|
||||||
device->GetVkLogicalDevice().destroySampler();
|
device->GetVkLogicalDevice().destroySampler(vkSampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -30,184 +30,199 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* SHBatch - Usage Functions */
|
/* SHBatch - Usage Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
SHBatch::SHBatch(Handle<SHVkPipeline> pipeline)
|
||||||
: pipeline{ pipeline }
|
: pipeline{ pipeline }
|
||||||
{
|
{
|
||||||
if (!pipeline)
|
if (!pipeline)
|
||||||
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
throw std::invalid_argument("Attempted to create a SHBatch with an invalid SHPipeline!");
|
||||||
|
|
||||||
// Mark all as dirty
|
// Mark all as dirty
|
||||||
setAllDirtyFlags();
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::Add(const SHRenderable* renderable)
|
||||||
|
{
|
||||||
|
// Check if we have a SubBatch with the same mesh yet
|
||||||
|
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
||||||
|
{
|
||||||
|
return batch.Mesh == renderable->Mesh;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create one if not found
|
||||||
|
if (subBatch == subBatches.end())
|
||||||
|
{
|
||||||
|
subBatches.emplace_back(renderable->Mesh);
|
||||||
|
subBatch = subBatches.end() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Add(const SHRenderable* renderable)
|
// Add renderable in
|
||||||
{
|
subBatch->Renderables.insert(renderable->GetEID());
|
||||||
// Check if we have a SubBatch with the same mesh yet
|
|
||||||
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
|
||||||
{
|
|
||||||
return batch.Mesh == renderable->Mesh;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create one if not found
|
// Also add material instance in
|
||||||
if (subBatch == subBatches.end())
|
referencedMatInstances.insert(renderable->GetMaterial());
|
||||||
|
|
||||||
|
// Mark all as dirty
|
||||||
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::Remove(const SHRenderable* renderable)
|
||||||
|
{
|
||||||
|
// Check if we have a SubBatch with the same mesh yet
|
||||||
|
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
||||||
|
{
|
||||||
|
return batch.Mesh == renderable->Mesh;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attempt to remove if it exists
|
||||||
|
if (subBatch == subBatches.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
subBatch->Renderables.erase(renderable->GetEID());
|
||||||
|
|
||||||
|
// Check if other renderables in subBatches contain the same material instance
|
||||||
|
bool matUnused = true;
|
||||||
|
for (const auto& sb : subBatches)
|
||||||
|
for (const auto& rendId : sb.Renderables)
|
||||||
|
{
|
||||||
|
auto rend = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
if (rend)
|
||||||
{
|
{
|
||||||
subBatches.emplace_back(renderable->Mesh);
|
if (rend->GetMaterial() == renderable->GetMaterial())
|
||||||
subBatch = subBatches.end() - 1;
|
{
|
||||||
|
matUnused = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add renderable in
|
// Material is no longer in this library, so we remove it
|
||||||
subBatch->Renderables.insert(renderable);
|
if (matUnused)
|
||||||
|
referencedMatInstances.erase(renderable->WasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial());
|
||||||
|
|
||||||
// Also add material instance in
|
// Mark all as dirty
|
||||||
referencedMatInstances.insert(renderable->GetMaterial());
|
setAllDirtyFlags();
|
||||||
|
}
|
||||||
|
|
||||||
// Mark all as dirty
|
void SHBatch::Clear()
|
||||||
setAllDirtyFlags();
|
{
|
||||||
|
subBatches.clear();
|
||||||
|
|
||||||
|
// Clear CPU buffers
|
||||||
|
drawData.clear();
|
||||||
|
transformData.clear();
|
||||||
|
instancedIntegerData.clear();
|
||||||
|
matPropsData.reset();
|
||||||
|
matPropsDataSize = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Clear GPU buffers
|
||||||
|
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
||||||
|
{
|
||||||
|
drawDataBuffer[i].Free();
|
||||||
|
transformDataBuffer[i].Free();
|
||||||
|
instancedIntegerBuffer[i].Free();
|
||||||
|
matPropsBuffer[i].Free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Remove(const SHRenderable* renderable)
|
// Check if there are even material properties to update
|
||||||
|
if (!matPropsData)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if any materials have changed
|
||||||
|
bool hasChanged = false;
|
||||||
|
for (const auto& material : referencedMatInstances)
|
||||||
{
|
{
|
||||||
// Check if we have a SubBatch with the same mesh yet
|
if (material->HasChanged())
|
||||||
auto subBatch = std::find_if(subBatches.begin(), subBatches.end(), [&](const SHSubBatch& batch)
|
{
|
||||||
{
|
hasChanged = true;
|
||||||
return batch.Mesh == renderable->Mesh;
|
break;
|
||||||
});
|
}
|
||||||
|
|
||||||
// Attempt to remove if it exists
|
|
||||||
if (subBatch == subBatches.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
subBatch->Renderables.erase(renderable);
|
|
||||||
|
|
||||||
// Check if other renderables in subBatches contain the same material instance
|
|
||||||
bool matUnused = true;
|
|
||||||
for (const auto& sb : subBatches)
|
|
||||||
for (const auto& rend : sb.Renderables)
|
|
||||||
{
|
|
||||||
if (rend->GetMaterial() == renderable->GetMaterial())
|
|
||||||
{
|
|
||||||
matUnused = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Material is no longer in this library, so we remove it
|
|
||||||
if (matUnused)
|
|
||||||
referencedMatInstances.erase(renderable->GetMaterial());
|
|
||||||
|
|
||||||
// Mark all as dirty
|
|
||||||
for (bool& dirt : isDirty)
|
|
||||||
dirt = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Clear()
|
// We need to update all the material buffers if the materials have changed
|
||||||
|
if (hasChanged)
|
||||||
{
|
{
|
||||||
subBatches.clear();
|
for (auto& dirt : matBufferDirty)
|
||||||
|
dirt = true;
|
||||||
// Clear CPU buffers
|
|
||||||
drawData.clear();
|
|
||||||
transformData.clear();
|
|
||||||
instancedIntegerData.clear();
|
|
||||||
matPropsData.reset();
|
|
||||||
matPropsDataSize = 0;
|
|
||||||
|
|
||||||
|
|
||||||
// Clear GPU buffers
|
|
||||||
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
|
|
||||||
{
|
|
||||||
drawDataBuffer[i].Free();
|
|
||||||
transformDataBuffer[i].Free();
|
|
||||||
instancedIntegerBuffer[i].Free();
|
|
||||||
matPropsBuffer[i].Free();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
// Check if this frame's buffer is dirty
|
||||||
{
|
if (!matBufferDirty[frameIndex])
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
return;
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there are even material properties to update
|
// Build CPU Buffer
|
||||||
if (!matPropsData)
|
char* propsCurrPtr = matPropsData.get();
|
||||||
return;
|
for (auto& subBatch : subBatches)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
// Check if any materials have changed
|
{
|
||||||
bool hasChanged = false;
|
const SHRenderable* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
for (const auto& material : referencedMatInstances)
|
if (renderable)
|
||||||
{
|
{
|
||||||
if (material->HasChanged())
|
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||||
{
|
|
||||||
hasChanged = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// We need to update all the material buffers if the materials have changed
|
|
||||||
if (hasChanged)
|
|
||||||
{
|
{
|
||||||
for (auto& dirt : matBufferDirty)
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
dirt = true;
|
|
||||||
}
|
}
|
||||||
|
propsCurrPtr += singleMatPropAlignedSize;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if this frame's buffer is dirty
|
// Transfer to GPU
|
||||||
if (!matBufferDirty[frameIndex])
|
rebuildMaterialBuffers(frameIndex, descPool);
|
||||||
return;
|
|
||||||
|
|
||||||
// Build CPU Buffer
|
// This frame is updated
|
||||||
char* propsCurrPtr = matPropsData.get();
|
matBufferDirty[frameIndex] = false;
|
||||||
for (auto& subBatch : subBatches)
|
}
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
|
||||||
propsCurrPtr += singleMatPropAlignedSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer to GPU
|
|
||||||
rebuildMaterialBuffers(frameIndex, descPool);
|
|
||||||
|
|
||||||
// This frame is updated
|
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
|
||||||
matBufferDirty[frameIndex] = false;
|
{
|
||||||
}
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
|
||||||
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
|
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
||||||
{
|
return;
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset Transform Data
|
|
||||||
transformData.clear();
|
|
||||||
|
|
||||||
// Populate on the CPU
|
|
||||||
for (auto& subBatch : subBatches)
|
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
// Transform
|
|
||||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(renderable->GetEID());
|
|
||||||
if (!transform)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
|
||||||
transformData.emplace_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transformData.emplace_back(transform->GetTRS());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer to GPU
|
|
||||||
if (transformDataBuffer[frameIndex])
|
|
||||||
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset Transform Data
|
||||||
|
transformData.clear();
|
||||||
|
|
||||||
|
// Populate on the CPU
|
||||||
|
for (auto& subBatch : subBatches)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
{
|
||||||
|
// Transform
|
||||||
|
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(rendId);
|
||||||
|
if (transform)
|
||||||
|
{
|
||||||
|
transformData.emplace_back(transform->GetTRS());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
||||||
|
transformData.emplace_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer to GPU
|
||||||
|
if (transformDataBuffer[frameIndex])
|
||||||
|
transformDataBuffer[frameIndex]->WriteToMemory(transformData.data(), static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix)), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void SHBatch::UpdateInstancedIntegerBuffer(uint32_t frameIndex)
|
void SHBatch::UpdateInstancedIntegerBuffer(uint32_t frameIndex)
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
@ -221,11 +236,12 @@ namespace SHADE
|
||||||
|
|
||||||
// Populate on the CPU
|
// Populate on the CPU
|
||||||
for (auto& subBatch : subBatches)
|
for (auto& subBatch : subBatches)
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
for (auto rendId : subBatch.Renderables)
|
||||||
{
|
{
|
||||||
|
auto* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
||||||
{
|
{
|
||||||
renderable->GetEID(),
|
rendId,
|
||||||
renderable->GetLightLayer()
|
renderable->GetLightLayer()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -238,213 +254,222 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
void SHBatch::Build(Handle<SHVkLogicalDevice> _device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
{
|
{
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index.");
|
||||||
{
|
return;
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to update build batch buffers with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save logical device
|
|
||||||
device = _device;
|
|
||||||
|
|
||||||
// No need to build as there are no changes
|
|
||||||
if (!isDirty[frameIndex])
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Count number of elements
|
|
||||||
size_t numTotalElements = 0;
|
|
||||||
for (const auto& subBatch : subBatches)
|
|
||||||
{
|
|
||||||
numTotalElements += subBatch.Renderables.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate CPU buffers if there are changes
|
|
||||||
if (isCPUBuffersDirty)
|
|
||||||
{
|
|
||||||
// - Draw data
|
|
||||||
drawData.reserve(subBatches.size());
|
|
||||||
drawData.clear();
|
|
||||||
// - Transform data
|
|
||||||
transformData.reserve(numTotalElements);
|
|
||||||
transformData.clear();
|
|
||||||
// - EID data
|
|
||||||
instancedIntegerData.reserve(numTotalElements);
|
|
||||||
instancedIntegerData.clear();
|
|
||||||
|
|
||||||
|
|
||||||
// - Material Properties Data
|
|
||||||
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
|
||||||
(
|
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
|
||||||
vk::ShaderStageFlagBits::eFragment
|
|
||||||
);
|
|
||||||
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
|
|
||||||
Byte matPropTotalBytes = 0;
|
|
||||||
if (!EMPTY_MAT_PROPS)
|
|
||||||
{
|
|
||||||
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
|
||||||
singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
|
|
||||||
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
|
|
||||||
if (matPropsDataSize < matPropTotalBytes)
|
|
||||||
{
|
|
||||||
matPropsData.reset(new char[matPropTotalBytes]);
|
|
||||||
matPropsDataSize = matPropTotalBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build Sub Batches
|
|
||||||
uint32_t nextInstanceIndex = 0;
|
|
||||||
char* propsCurrPtr = matPropsData.get();
|
|
||||||
for (auto& subBatch : subBatches)
|
|
||||||
{
|
|
||||||
// Create command
|
|
||||||
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
|
||||||
{
|
|
||||||
.indexCount = subBatch.Mesh->IndexCount,
|
|
||||||
.instanceCount = static_cast<uint32_t>(subBatch.Renderables.size()),
|
|
||||||
.firstIndex = subBatch.Mesh->FirstIndex,
|
|
||||||
.vertexOffset = subBatch.Mesh->FirstVertex,
|
|
||||||
.firstInstance = nextInstanceIndex++
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fill in buffers (CPU)
|
|
||||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
|
||||||
{
|
|
||||||
// Transform
|
|
||||||
EntityID eid = renderable->GetEID();
|
|
||||||
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
|
||||||
if (!transform)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
|
||||||
transformData.emplace_back();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transformData.emplace_back(transform->GetTRS());
|
|
||||||
}
|
|
||||||
|
|
||||||
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
|
||||||
{
|
|
||||||
eid,
|
|
||||||
renderable->GetLightLayer()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Material Properties
|
|
||||||
if (!EMPTY_MAT_PROPS)
|
|
||||||
{
|
|
||||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
|
||||||
propsCurrPtr += singleMatPropAlignedSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Successfully update CPU buffers
|
|
||||||
isCPUBuffersDirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send all buffered data to the GPU buffers
|
|
||||||
using BuffUsage = vk::BufferUsageFlagBits;
|
|
||||||
// - Draw Data
|
|
||||||
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
|
|
||||||
BuffUsage::eIndirectBuffer
|
|
||||||
);
|
|
||||||
// - Transform Buffer
|
|
||||||
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
|
||||||
BuffUsage::eVertexBuffer
|
|
||||||
);
|
|
||||||
const uint32_t EID_DATA_BYTES = static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData));
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, instancedIntegerBuffer[frameIndex], instancedIntegerData.data(), EID_DATA_BYTES,
|
|
||||||
BuffUsage::eVertexBuffer
|
|
||||||
);
|
|
||||||
// - Material Properties Buffer
|
|
||||||
rebuildMaterialBuffers(frameIndex, descPool);
|
|
||||||
|
|
||||||
// Mark this frame as no longer dirty
|
|
||||||
isDirty[frameIndex] = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
// Save logical device
|
||||||
/* SHBatch - Usage Functions */
|
device = _device;
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
|
||||||
{
|
|
||||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
|
||||||
{
|
|
||||||
SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind all required objects before drawing
|
// No need to build as there are no changes
|
||||||
static std::array<uint32_t, 1> dynamicOffset { 0 };
|
if (!isDirty[frameIndex])
|
||||||
cmdBuffer->BindPipeline(pipeline);
|
return;
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
|
||||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
|
// Count number of elements
|
||||||
if (matPropsDescSet[frameIndex])
|
size_t numTotalElements = 0;
|
||||||
|
for (const auto& subBatch : subBatches)
|
||||||
|
{
|
||||||
|
numTotalElements += subBatch.Renderables.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate CPU buffers if there are changes
|
||||||
|
if (isCPUBuffersDirty)
|
||||||
|
{
|
||||||
|
// - Draw data
|
||||||
|
drawData.reserve(subBatches.size());
|
||||||
|
drawData.clear();
|
||||||
|
// - Transform data
|
||||||
|
transformData.reserve(numTotalElements);
|
||||||
|
transformData.clear();
|
||||||
|
// - EID data
|
||||||
|
instancedIntegerData.reserve(numTotalElements);
|
||||||
|
instancedIntegerData.clear();
|
||||||
|
|
||||||
|
|
||||||
|
// - Material Properties Data
|
||||||
|
const Handle<SHShaderBlockInterface> SHADER_INFO = pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
||||||
|
vk::ShaderStageFlagBits::eFragment
|
||||||
|
);
|
||||||
|
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
|
||||||
|
Byte matPropTotalBytes = 0;
|
||||||
|
if (!EMPTY_MAT_PROPS)
|
||||||
|
{
|
||||||
|
singleMatPropSize = SHADER_INFO->GetBytesRequired();
|
||||||
|
singleMatPropAlignedSize = device->PadSSBOSize(static_cast<uint32_t>(singleMatPropSize));
|
||||||
|
matPropTotalBytes = numTotalElements * singleMatPropAlignedSize;
|
||||||
|
if (matPropsDataSize < matPropTotalBytes)
|
||||||
{
|
{
|
||||||
cmdBuffer->BindDescriptorSet
|
matPropsData.reset(new char[matPropTotalBytes]);
|
||||||
(
|
matPropsDataSize = matPropTotalBytes;
|
||||||
matPropsDescSet[frameIndex],
|
}
|
||||||
SH_PIPELINE_TYPE::GRAPHICS,
|
}
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
dynamicOffset
|
// Build Sub Batches
|
||||||
|
uint32_t nextInstanceIndex = 0;
|
||||||
|
char* propsCurrPtr = matPropsData.get();
|
||||||
|
for (auto& subBatch : subBatches)
|
||||||
|
{
|
||||||
|
// Create command
|
||||||
|
const uint32_t CURR_INSTANCES = static_cast<uint32_t>(subBatch.Renderables.size());
|
||||||
|
drawData.emplace_back(vk::DrawIndexedIndirectCommand
|
||||||
|
{
|
||||||
|
.indexCount = subBatch.Mesh->IndexCount,
|
||||||
|
.instanceCount = CURR_INSTANCES,
|
||||||
|
.firstIndex = subBatch.Mesh->FirstIndex,
|
||||||
|
.vertexOffset = subBatch.Mesh->FirstVertex,
|
||||||
|
.firstInstance = nextInstanceIndex
|
||||||
|
});
|
||||||
|
nextInstanceIndex += CURR_INSTANCES;
|
||||||
|
|
||||||
|
// Fill in buffers (CPU)
|
||||||
|
for (auto rendId : subBatch.Renderables)
|
||||||
|
{
|
||||||
|
// Transform
|
||||||
|
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(rendId);
|
||||||
|
if (!transform)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
|
||||||
|
transformData.emplace_back();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transformData.emplace_back(transform->GetTRS());
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHRenderable* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
|
||||||
|
instancedIntegerData.emplace_back(SHInstancedIntegerData
|
||||||
|
{
|
||||||
|
rendId,
|
||||||
|
renderable->GetLightLayer()
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
// Material Properties
|
||||||
/* SHBatch - Helper Functions */
|
if (!EMPTY_MAT_PROPS)
|
||||||
/*---------------------------------------------------------------------------------*/
|
{
|
||||||
void SHBatch::setAllDirtyFlags()
|
if (renderable)
|
||||||
{
|
|
||||||
for (bool& dirt : isDirty)
|
|
||||||
dirt = true;
|
|
||||||
isCPUBuffersDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHBatch::rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
|
||||||
{
|
|
||||||
if (matPropsData)
|
|
||||||
{
|
|
||||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
|
||||||
(
|
|
||||||
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
|
||||||
vk::BufferUsageFlagBits::eStorageBuffer
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!matPropsDescSet[frameIndex])
|
|
||||||
{
|
{
|
||||||
matPropsDescSet[frameIndex] = descPool->Allocate
|
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||||
(
|
|
||||||
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] },
|
|
||||||
{ 0 }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
|
else
|
||||||
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer
|
{
|
||||||
(
|
SHLOG_WARNING("[SHBatch] Entity with a missing SHRenderable found!");
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
}
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
propsCurrPtr += singleMatPropAlignedSize;
|
||||||
bufferList,
|
}
|
||||||
0, static_cast<uint32_t>(matPropsDataSize)
|
|
||||||
);
|
|
||||||
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
|
||||||
(
|
|
||||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
|
||||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Successfully update CPU buffers
|
||||||
|
isCPUBuffersDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send all buffered data to the GPU buffers
|
||||||
|
using BuffUsage = vk::BufferUsageFlagBits;
|
||||||
|
// - Draw Data
|
||||||
|
const uint32_t DRAW_DATA_BYTES = static_cast<uint32_t>(drawData.size() * sizeof(vk::DrawIndexedIndirectCommand));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, drawDataBuffer[frameIndex], drawData.data(), DRAW_DATA_BYTES,
|
||||||
|
BuffUsage::eIndirectBuffer
|
||||||
|
);
|
||||||
|
// - Transform Buffer
|
||||||
|
const uint32_t TF_DATA_BYTES = static_cast<uint32_t>(transformData.size() * sizeof(SHMatrix));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, transformDataBuffer[frameIndex], transformData.data(), TF_DATA_BYTES,
|
||||||
|
BuffUsage::eVertexBuffer
|
||||||
|
);
|
||||||
|
const uint32_t EID_DATA_BYTES = static_cast<uint32_t>(instancedIntegerData.size() * sizeof(SHInstancedIntegerData));
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, instancedIntegerBuffer[frameIndex], instancedIntegerData.data(), EID_DATA_BYTES,
|
||||||
|
BuffUsage::eVertexBuffer
|
||||||
|
);
|
||||||
|
// - Material Properties Buffer
|
||||||
|
rebuildMaterialBuffers(frameIndex, descPool);
|
||||||
|
|
||||||
|
// Mark this frame as no longer dirty
|
||||||
|
isDirty[frameIndex] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* SHBatch - Usage Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
||||||
|
{
|
||||||
|
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING("[SHBatch] Attempted to draw a batch with an invalid frame index.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind all required objects before drawing
|
||||||
|
static std::array<uint32_t, 1> dynamicOffset{ 0 };
|
||||||
|
cmdBuffer->BindPipeline(pipeline);
|
||||||
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
||||||
|
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
|
||||||
|
if (matPropsDescSet[frameIndex])
|
||||||
|
{
|
||||||
|
cmdBuffer->BindDescriptorSet
|
||||||
|
(
|
||||||
|
matPropsDescSet[frameIndex],
|
||||||
|
SH_PIPELINE_TYPE::GRAPHICS,
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
dynamicOffset
|
||||||
|
);
|
||||||
|
}
|
||||||
|
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* SHBatch - Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
void SHBatch::setAllDirtyFlags()
|
||||||
|
{
|
||||||
|
for (bool& dirt : isDirty)
|
||||||
|
dirt = true;
|
||||||
|
isCPUBuffersDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHBatch::rebuildMaterialBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool)
|
||||||
|
{
|
||||||
|
if (matPropsData)
|
||||||
|
{
|
||||||
|
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||||
|
(
|
||||||
|
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||||
|
vk::BufferUsageFlagBits::eStorageBuffer
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!matPropsDescSet[frameIndex])
|
||||||
|
{
|
||||||
|
matPropsDescSet[frameIndex] = descPool->Allocate
|
||||||
|
(
|
||||||
|
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE] },
|
||||||
|
{ 0 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
std::array<Handle<SHVkBuffer>, 1> bufferList = { matPropsBuffer[frameIndex] };
|
||||||
|
matPropsDescSet[frameIndex]->ModifyWriteDescBuffer
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
||||||
|
bufferList,
|
||||||
|
0, static_cast<uint32_t>(matPropsDataSize)
|
||||||
|
);
|
||||||
|
matPropsDescSet[frameIndex]->UpdateDescriptorSetBuffer
|
||||||
|
(
|
||||||
|
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||||
|
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace SHADE
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
Handle<SHMesh> Mesh;
|
Handle<SHMesh> Mesh;
|
||||||
std::unordered_set<const SHRenderable*> Renderables;
|
std::unordered_set<EntityID> Renderables;
|
||||||
};
|
};
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -700,10 +700,10 @@ namespace SHADE
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Remove from old material's SuperBatch
|
// Remove from old material's SuperBatch
|
||||||
Handle<SHMaterial> prevMaterial = renderable.GetPrevMaterial();
|
Handle<SHMaterialInstance> prevMaterial = renderable.GetPrevMaterial();
|
||||||
if (prevMaterial)
|
if (prevMaterial)
|
||||||
{
|
{
|
||||||
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||||
oldSuperBatch->Remove(&renderable);
|
oldSuperBatch->Remove(&renderable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,15 +33,16 @@ namespace SHADE
|
||||||
|
|
||||||
void SHRenderable::OnDestroy()
|
void SHRenderable::OnDestroy()
|
||||||
{
|
{
|
||||||
|
// Remove from SuperBatch
|
||||||
|
Handle<SHSuperBatch> superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||||
|
superBatch->Remove(this);
|
||||||
|
|
||||||
|
// Free resources
|
||||||
if (material)
|
if (material)
|
||||||
{
|
{
|
||||||
material.Free();
|
material.Free();
|
||||||
material = {};
|
material = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from SuperBatch
|
|
||||||
Handle<SHSuperBatch> superBatch = sharedMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
|
||||||
superBatch->Remove(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -53,20 +54,23 @@ namespace SHADE
|
||||||
if (!material && sharedMaterial == materialInstance)
|
if (!material && sharedMaterial == materialInstance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Flag that material was changed
|
||||||
|
materialChanged = true;
|
||||||
|
|
||||||
// Free copies of materials if any
|
// Free copies of materials if any
|
||||||
if (material)
|
if (material)
|
||||||
{
|
{
|
||||||
|
oldMaterial = material;
|
||||||
material.Free();
|
material.Free();
|
||||||
material = {};
|
material = {};
|
||||||
}
|
}
|
||||||
|
else if (sharedMaterial)
|
||||||
// Flag that material was changed
|
{
|
||||||
materialChanged = true;
|
oldMaterial = sharedMaterial;
|
||||||
if (sharedMaterial)
|
}
|
||||||
oldMaterial = sharedMaterial->GetBaseMaterial();
|
|
||||||
|
|
||||||
// Update the material
|
// Update the material
|
||||||
sharedMaterial = materialInstance;
|
sharedMaterial = materialInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<SHMaterialInstance> SHRenderable::GetMaterial() const
|
Handle<SHMaterialInstance> SHRenderable::GetMaterial() const
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace SHADE
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
bool WasMaterialChanged() const noexcept { return materialChanged; }
|
bool WasMaterialChanged() const noexcept { return materialChanged; }
|
||||||
Handle<SHMaterial> GetPrevMaterial() const noexcept { return oldMaterial; }
|
Handle<SHMaterialInstance> GetPrevMaterial() const noexcept { return oldMaterial; }
|
||||||
uint8_t GetLightLayer (void) const noexcept;
|
uint8_t GetLightLayer (void) const noexcept;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
@ -75,7 +75,7 @@ namespace SHADE
|
||||||
Handle<SHMaterialInstance> sharedMaterial;
|
Handle<SHMaterialInstance> sharedMaterial;
|
||||||
Handle<SHMaterialInstance> material;
|
Handle<SHMaterialInstance> material;
|
||||||
bool materialChanged = true;
|
bool materialChanged = true;
|
||||||
Handle<SHMaterial> oldMaterial;
|
Handle<SHMaterialInstance> oldMaterial;
|
||||||
uint8_t lightLayer;
|
uint8_t lightLayer;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,32 +295,33 @@ namespace SHADE
|
||||||
) != 0;
|
) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHMatrix::operator XMMATRIX() const noexcept
|
||||||
|
{
|
||||||
|
return XMLoadFloat4x4(this);
|
||||||
|
}
|
||||||
|
|
||||||
SHMatrix operator*(float lhs, const SHMatrix& rhs) noexcept
|
SHMatrix operator*(float lhs, const SHMatrix& rhs) noexcept
|
||||||
{
|
{
|
||||||
return rhs * lhs;
|
return rhs * lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Function Member Definitions */
|
/* Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHMatrix::Transpose() noexcept
|
void SHMatrix::Transpose() noexcept
|
||||||
{
|
{
|
||||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
XMStoreFloat4x4(this, XMMatrixTranspose(*this));
|
||||||
XMStoreFloat4x4(this, XMMatrixTranspose(M));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHMatrix::Invert() noexcept
|
void SHMatrix::Invert() noexcept
|
||||||
{
|
{
|
||||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
XMStoreFloat4x4(this, XMMatrixInverse(nullptr, *this));
|
||||||
XMStoreFloat4x4(this, XMMatrixInverse(nullptr, M));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHMatrix::Determinant() const noexcept
|
float SHMatrix::Determinant() const noexcept
|
||||||
{
|
{
|
||||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
return XMVectorGetX(XMMatrixDeterminant(*this));
|
||||||
return XMVectorGetX(XMMatrixDeterminant(M));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SHMatrix::ToString() const noexcept
|
std::string SHMatrix::ToString() const noexcept
|
||||||
|
@ -337,9 +338,8 @@ namespace SHADE
|
||||||
bool SHMatrix::Decompose(SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept
|
bool SHMatrix::Decompose(SHVec3& translation, SHVec3& rotation, SHVec3& scale) const noexcept
|
||||||
{
|
{
|
||||||
XMVECTOR s, r, t;
|
XMVECTOR s, r, t;
|
||||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
|
||||||
|
|
||||||
if (!XMMatrixDecompose(&s, &r, &t, M))
|
if (!XMMatrixDecompose(&s, &r, &t, *this))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SHQuaternion orientation;
|
SHQuaternion orientation;
|
||||||
|
@ -356,9 +356,8 @@ namespace SHADE
|
||||||
bool SHMatrix::Decompose(SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept
|
bool SHMatrix::Decompose(SHVec3& translation, SHQuaternion& orientation, SHVec3& scale) const noexcept
|
||||||
{
|
{
|
||||||
XMVECTOR s, r, t;
|
XMVECTOR s, r, t;
|
||||||
const XMMATRIX M = XMLoadFloat4x4(this);
|
|
||||||
|
|
||||||
if (!XMMatrixDecompose(&s, &r, &t, M))
|
if (!XMMatrixDecompose(&s, &r, &t, *this))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
XMStoreFloat3(&scale, s);
|
XMStoreFloat3(&scale, s);
|
||||||
|
@ -376,8 +375,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMMATRIX M = XMLoadFloat4x4(&matrix);
|
XMStoreFloat4x4(&result, XMMatrixTranspose(matrix));
|
||||||
XMStoreFloat4x4(&result, XMMatrixTranspose(M));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,8 +383,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMMATRIX M = XMLoadFloat4x4(&matrix);
|
XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, matrix));
|
||||||
XMStoreFloat4x4(&result, XMMatrixInverse(nullptr, M));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,8 +398,8 @@ namespace SHADE
|
||||||
SHMatrix SHMatrix::Translate(const SHVec3& pos) noexcept
|
SHMatrix SHMatrix::Translate(const SHVec3& pos) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixTranslation(pos.x, pos.y, pos.z));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,25 +407,23 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMVECTOR A = XMLoadFloat3(&axis);
|
XMStoreFloat4x4(&result, XMMatrixRotationAxis(axis, angleInRad));
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationAxis(A, angleInRad));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::Rotate(float yaw, float pitch, float roll) noexcept
|
SHMatrix SHMatrix::Rotate(float yaw, float pitch, float roll) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(pitch, yaw, roll));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::Rotate(const SHVec3& eulerAngles) noexcept
|
SHMatrix SHMatrix::Rotate(const SHVec3& eulerAngles) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYaw(eulerAngles.x, eulerAngles.y, eulerAngles.z));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixRotationRollPitchYawFromVector(eulerAngles));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,57 +431,55 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(q));
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationQuaternion(Q));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::RotateX(float angleInRad) noexcept
|
SHMatrix SHMatrix::RotateX(float angleInRad) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixRotationX(angleInRad));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::RotateY(float angleInRad) noexcept
|
SHMatrix SHMatrix::RotateY(float angleInRad) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixRotationY(angleInRad));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::RotateZ(float angleInRad) noexcept
|
SHMatrix SHMatrix::RotateZ(float angleInRad) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixRotationZ(angleInRad));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::Scale(float uniformScaleFactor) noexcept
|
SHMatrix SHMatrix::Scale(float uniformScaleFactor) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixScaling(uniformScaleFactor, uniformScaleFactor, uniformScaleFactor));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::Scale(float x, float y, float z) noexcept
|
SHMatrix SHMatrix::Scale(float x, float y, float z) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixScaling(x, y, z));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHMatrix SHMatrix::Scale(const SHVec3& scale) noexcept
|
SHMatrix SHMatrix::Scale(const SHVec3& scale) noexcept
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
XMStoreFloat4x4(&result, XMMatrixScaling(scale.x, scale.y, scale.z));
|
|
||||||
|
|
||||||
|
XMStoreFloat4x4(&result, XMMatrixScalingFromVector(scale));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,12 +487,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMVECTOR EYE = XMLoadFloat3(&eye);
|
XMStoreFloat4x4(&result, XMMatrixLookAtRH(eye, target, up));
|
||||||
const XMVECTOR TGT = XMLoadFloat3(&target);
|
|
||||||
const XMVECTOR UP = XMLoadFloat3(&up);
|
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixLookAtRH(EYE, TGT, UP));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,12 +495,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
const XMVECTOR EYE = XMLoadFloat3(&eye);
|
XMStoreFloat4x4(&result, XMMatrixLookAtLH(eye, target, up));
|
||||||
const XMVECTOR TGT = XMLoadFloat3(&target);
|
|
||||||
const XMVECTOR UP = XMLoadFloat3(&up);
|
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixLookAtLH(EYE, TGT, UP));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,8 +505,8 @@ namespace SHADE
|
||||||
|
|
||||||
const SHVec3 FWD_HAT = SHVec3::Normalise(-forward);
|
const SHVec3 FWD_HAT = SHVec3::Normalise(-forward);
|
||||||
|
|
||||||
const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT));
|
const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT);
|
||||||
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT));
|
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT));
|
||||||
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
|
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
|
||||||
|
|
||||||
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
|
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
|
||||||
|
@ -543,8 +526,8 @@ namespace SHADE
|
||||||
|
|
||||||
const SHVec3 FWD_HAT = SHVec3::Normalise(forward);
|
const SHVec3 FWD_HAT = SHVec3::Normalise(forward);
|
||||||
|
|
||||||
const XMVECTOR Z_HAT = XMVector3Normalize(XMLoadFloat3(&FWD_HAT));
|
const XMVECTOR Z_HAT = XMVector3Normalize(FWD_HAT);
|
||||||
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(XMLoadFloat3(&up), Z_HAT));
|
const XMVECTOR X_HAT = XMVector3Normalize(XMVector3Cross(up, Z_HAT));
|
||||||
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
|
const XMVECTOR Y_HAT = XMVector3Cross(Z_HAT, X_HAT);
|
||||||
|
|
||||||
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
|
XMStoreFloat3(reinterpret_cast<XMFLOAT3*>(&result._11), X_HAT);
|
||||||
|
@ -563,7 +546,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovRH(fov, aspectRatio, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovRH(fov, aspectRatio, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,7 +554,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovLH(fov, aspectRatio, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixPerspectiveFovLH(fov, aspectRatio, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,7 +562,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveRH(width, height, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixPerspectiveRH(width, height, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +570,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixPerspectiveLH(width, height, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixPerspectiveLH(width, height, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,7 +578,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixOrthographicRH(width, height, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixOrthographicRH(width, height, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,7 +586,6 @@ namespace SHADE
|
||||||
SHMatrix result;
|
SHMatrix result;
|
||||||
|
|
||||||
XMStoreFloat4x4(&result, XMMatrixOrthographicLH(width, height, nearPlane, farPlane));
|
XMStoreFloat4x4(&result, XMMatrixOrthographicLH(width, height, nearPlane, farPlane));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,8 @@ namespace SHADE
|
||||||
SHMatrix& operator= (const SHMatrix& rhs) = default;
|
SHMatrix& operator= (const SHMatrix& rhs) = default;
|
||||||
SHMatrix& operator= (SHMatrix&& rhs) = default;
|
SHMatrix& operator= (SHMatrix&& rhs) = default;
|
||||||
|
|
||||||
|
operator DirectX::XMMATRIX () const noexcept;
|
||||||
|
|
||||||
SHMatrix& operator+= (const SHMatrix& rhs) noexcept;
|
SHMatrix& operator+= (const SHMatrix& rhs) noexcept;
|
||||||
SHMatrix& operator-= (const SHMatrix& rhs) noexcept;
|
SHMatrix& operator-= (const SHMatrix& rhs) noexcept;
|
||||||
SHMatrix& operator*= (const SHMatrix& rhs) noexcept;
|
SHMatrix& operator*= (const SHMatrix& rhs) noexcept;
|
||||||
|
|
|
@ -36,44 +36,18 @@ namespace SHADE
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
SHQuaternion::SHQuaternion(const SHVec4& vec4) noexcept
|
||||||
|
: XMFLOAT4( vec4.x, vec4.y, vec4.z, vec4.w )
|
||||||
|
{}
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(float _x, float _y, float _z, float _w) noexcept
|
SHQuaternion::SHQuaternion(float _x, float _y, float _z, float _w) noexcept
|
||||||
: XMFLOAT4( _x, _y, _z, _w )
|
: XMFLOAT4( _x, _y, _z, _w )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(float yaw, float pitch, float roll) noexcept
|
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
|
||||||
{
|
|
||||||
XMStoreFloat4(this, XMQuaternionRotationRollPitchYaw(pitch, yaw, roll));
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(const SHVec3& eulerAngles) noexcept
|
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
|
||||||
{
|
|
||||||
const XMVECTOR V = XMLoadFloat3(&eulerAngles);
|
|
||||||
XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V));
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(const SHVec3& axis, float angleInRad) noexcept
|
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
|
||||||
{
|
|
||||||
const XMVECTOR AXIS = XMLoadFloat3(&axis);
|
|
||||||
XMStoreFloat4(this, XMQuaternionRotationAxis(AXIS, angleInRad));
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(const SHMatrix& rotationMatrix) noexcept
|
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
|
||||||
{
|
|
||||||
const XMMATRIX M = XMLoadFloat4x4(&rotationMatrix);
|
|
||||||
XMStoreFloat4(this, XMQuaternionRotationMatrix(M));
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(const reactphysics3d::Vector3& rp3dEuler) noexcept
|
SHQuaternion::SHQuaternion(const reactphysics3d::Vector3& rp3dEuler) noexcept
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f )
|
||||||
{
|
{
|
||||||
const SHVec3& SHADE_VEC{ rp3dEuler };
|
XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(SHVec3 { rp3dEuler }));
|
||||||
|
|
||||||
const XMVECTOR V = XMLoadFloat3(&SHADE_VEC);
|
|
||||||
XMStoreFloat4(this, XMQuaternionRotationRollPitchYawFromVector(V));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept
|
SHQuaternion::SHQuaternion(const reactphysics3d::Quaternion& rp3dQuat) noexcept
|
||||||
|
@ -113,10 +87,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMVectorAdd(*this, rhs));
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMVectorAdd(Q1, Q2));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,10 +95,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMVectorSubtract(*this, rhs));
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMVectorSubtract(Q1, Q2));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,9 +103,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMVectorNegate(*this));
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMVectorNegate(Q));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,10 +111,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMQuaternionMultiply(*this, rhs));
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,9 +119,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMVectorScale(*this, rhs));
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMVectorScale(Q, rhs));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,27 +127,18 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
XMStoreFloat4(&result, XMQuaternionMultiply(*this, XMQuaternionInverse(rhs)));
|
||||||
const XMVECTOR Q2 = XMQuaternionInverse(XMLoadFloat4(&rhs));
|
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMQuaternionMultiply(Q1, Q2));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHQuaternion::operator==(const SHQuaternion& rhs) const noexcept
|
bool SHQuaternion::operator==(const SHQuaternion& rhs) const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
return XMQuaternionEqual(*this, rhs);
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
return XMQuaternionEqual(Q1, Q2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHQuaternion::operator!=(const SHQuaternion& rhs) const noexcept
|
bool SHQuaternion::operator!=(const SHQuaternion& rhs) const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
return XMQuaternionNotEqual(*this, rhs);
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
return XMQuaternionNotEqual(Q1, Q2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHQuaternion::operator reactphysics3d::Quaternion() const noexcept
|
SHQuaternion::operator reactphysics3d::Quaternion() const noexcept
|
||||||
|
@ -199,6 +151,11 @@ namespace SHADE
|
||||||
return reactphysics3d::Vector3{ ToEuler() };
|
return reactphysics3d::Vector3{ ToEuler() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHQuaternion::operator XMVECTOR() const noexcept
|
||||||
|
{
|
||||||
|
return XMLoadFloat4(this);
|
||||||
|
}
|
||||||
|
|
||||||
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept
|
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept
|
||||||
{
|
{
|
||||||
return rhs * lhs;
|
return rhs * lhs;
|
||||||
|
@ -213,8 +170,7 @@ namespace SHADE
|
||||||
XMVECTOR axis;
|
XMVECTOR axis;
|
||||||
float angle;
|
float angle;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
XMQuaternionToAxisAngle(&axis, &angle, *this);
|
||||||
XMQuaternionToAxisAngle(&axis, &angle, Q);
|
|
||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,8 +179,7 @@ namespace SHADE
|
||||||
XMVECTOR axis;
|
XMVECTOR axis;
|
||||||
float angle;
|
float angle;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
XMQuaternionToAxisAngle(&axis, &angle, *this);
|
||||||
XMQuaternionToAxisAngle(&axis, &angle, Q);
|
|
||||||
|
|
||||||
|
|
||||||
return SHVec4{XMVectorGetX(axis), XMVectorGetY(axis), XMVectorGetZ(axis), angle};
|
return SHVec4{XMVectorGetX(axis), XMVectorGetY(axis), XMVectorGetZ(axis), angle};
|
||||||
|
@ -238,64 +193,49 @@ namespace SHADE
|
||||||
|
|
||||||
void SHQuaternion::Invert() noexcept
|
void SHQuaternion::Invert() noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
XMStoreFloat4(this, XMQuaternionInverse(*this));
|
||||||
XMStoreFloat4(this, XMQuaternionInverse(Q));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHQuaternion::Length() const noexcept
|
float SHQuaternion::Length() const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
return XMVectorGetX(XMQuaternionLength(*this));
|
||||||
return XMVectorGetX(XMQuaternionLength(Q));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHQuaternion::LengthSquared() const noexcept
|
float SHQuaternion::LengthSquared() const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q = XMLoadFloat4(this);
|
return XMVectorGetX(XMQuaternionLengthSq(*this));
|
||||||
return XMVectorGetX(XMQuaternionLengthSq(Q));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float SHQuaternion::Dot(const SHQuaternion& rhs) const noexcept
|
float SHQuaternion::Dot(const SHQuaternion& rhs) const noexcept
|
||||||
{
|
{
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(this);
|
return XMVectorGetX(XMQuaternionDot(*this, rhs));
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&rhs);
|
|
||||||
|
|
||||||
return XMVectorGetX(XMQuaternionDot(Q1, Q2));
|
|
||||||
}
|
|
||||||
|
|
||||||
SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion&, float) const noexcept
|
|
||||||
{
|
|
||||||
SHQuaternion result;
|
|
||||||
|
|
||||||
// TODO (Diren)
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SHVec3 SHQuaternion::ToEuler() const noexcept
|
SHVec3 SHQuaternion::ToEuler() const noexcept
|
||||||
{
|
{
|
||||||
const float xx = x * x;
|
const float XX = x * x;
|
||||||
const float yy = y * y;
|
const float YY = y * y;
|
||||||
const float zz = z * z;
|
const float ZZ = z * z;
|
||||||
|
|
||||||
const float m31 = 2.f * x * z + 2.f * y * w;
|
const float M_31 = 2.f * x * z + 2.f * y * w;
|
||||||
const float m32 = 2.f * y * z - 2.f * x * w;
|
const float M_32 = 2.f * y * z - 2.f * x * w;
|
||||||
const float m33 = 1.f - 2.f * xx - 2.f * yy;
|
const float M_33 = 1.f - 2.f * XX - 2.f * YY;
|
||||||
|
|
||||||
const float cy = sqrtf(m33 * m33 + m31 * m31);
|
const float CY = sqrtf(M_33 * M_33 + M_31 * M_31);
|
||||||
const float cx = atan2f(-m32, cy);
|
const float CX = atan2f(-M_32, CY);
|
||||||
if (cy > 16.0f * SHMath::EPSILON)
|
if (CY > 16.0f * SHMath::EPSILON)
|
||||||
{
|
{
|
||||||
const float m12 = 2.f * x * y + 2.f * z * w;
|
const float M_12 = 2.f * x * y + 2.f * z * w;
|
||||||
const float m22 = 1.f - 2.f * xx - 2.f * zz;
|
const float M_22 = 1.f - 2.f * XX - 2.f * ZZ;
|
||||||
|
|
||||||
return SHVec3(cx, atan2f(m31, m33), atan2f(m12, m22));
|
return SHVec3(CX, atan2f(M_31, M_33), atan2f(M_12, M_22));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const float m11 = 1.f - 2.f * yy - 2.f * zz;
|
const float m11 = 1.f - 2.f * YY - 2.f * ZZ;
|
||||||
const float m21 = 2.f * x * y - 2.f * z * w;
|
const float m21 = 2.f * x * y - 2.f * z * w;
|
||||||
|
|
||||||
return SHVec3(cx, 0.f, atan2f(-m21, m11));
|
return SHVec3(CX, 0.f, atan2f(-m21, m11));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,13 +251,43 @@ namespace SHADE
|
||||||
/* Static Function Member Definitions */
|
/* Static Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::FromEuler(const SHVec3& eulerAngles) noexcept
|
||||||
|
{
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionRotationRollPitchYawFromVector(eulerAngles));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::FromPitchYawRoll(float pitch, float yaw, float roll) noexcept
|
||||||
|
{
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionRotationRollPitchYaw(pitch, yaw, roll));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::FromAxisAngle(const SHVec3& axis, float angle) noexcept
|
||||||
|
{
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionRotationAxis(axis, angle));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept
|
||||||
|
{
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionRotationMatrix(rotationMatrix));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
SHQuaternion SHQuaternion::Normalise(const SHQuaternion& q) noexcept
|
SHQuaternion SHQuaternion::Normalise(const SHQuaternion& q) noexcept
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
XMStoreFloat4(&result, XMQuaternionNormalize(q));
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMQuaternionNormalize(Q));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,9 +295,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
XMStoreFloat4(&result, XMQuaternionConjugate(q));
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMQuaternionConjugate(Q));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,26 +303,37 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q = XMLoadFloat4(&q);
|
XMStoreFloat4(&result, XMQuaternionInverse(q));
|
||||||
XMStoreFloat4(&result, XMQuaternionInverse(Q));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float SHQuaternion::Angle(const SHQuaternion&, const SHQuaternion&) noexcept
|
float SHQuaternion::Angle(const SHQuaternion& q1, const SHQuaternion& q2) noexcept
|
||||||
{
|
{
|
||||||
// TODO (Diren)
|
XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(q1), q2);
|
||||||
|
|
||||||
return 0.0f;
|
const float RS = XMVectorGetW(R);
|
||||||
|
R = XMVector3Length(R);
|
||||||
|
return 2.0f * atan2f(XMVectorGetX(R), RS);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHQuaternion SHQuaternion::Lerp(const SHQuaternion&, const SHQuaternion&, float) noexcept
|
SHQuaternion SHQuaternion::Lerp(const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
// TODO (Diren)
|
XMVECTOR R = XMVectorZero();
|
||||||
|
if (XMVector4GreaterOrEqual(XMVector4Dot(q1, q2), R))
|
||||||
|
{
|
||||||
|
R = XMVectorLerp(q1, q2, t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const XMVECTOR X0 = XMVectorMultiply(q1, XMVectorReplicate(1.f - t));
|
||||||
|
const XMVECTOR X1 = XMVectorMultiply(q2, XMVectorReplicate(t));
|
||||||
|
R = XMVectorSubtract(X0, X1);
|
||||||
|
}
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionNormalize(R));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,19 +341,105 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
const XMVECTOR Q1 = XMLoadFloat4(&q1);
|
XMStoreFloat4(&result, XMQuaternionSlerp(q1, q2, t));
|
||||||
const XMVECTOR Q2 = XMLoadFloat4(&q2);
|
|
||||||
|
|
||||||
XMStoreFloat4(&result, XMQuaternionSlerp(Q1, Q2, t));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHQuaternion SHQuaternion::Rotate(const SHVec3& , const SHVec3&) noexcept
|
SHQuaternion SHQuaternion::ClampedLerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept
|
||||||
|
{
|
||||||
|
return Lerp(q1, q2, std::clamp(t, tMin, tMax));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::ClampedSlerp(const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin, float tMax) noexcept
|
||||||
|
{
|
||||||
|
return Slerp(q1, q2, std::clamp(t, tMin, tMax));
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::FromToRotation(const SHVec3& from, const SHVec3& to) noexcept
|
||||||
|
{
|
||||||
|
// Melax, "The Shortest Arc Quaternion", Game Programming Gems
|
||||||
|
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
const XMVECTOR F = XMVector3Normalize(from);
|
||||||
|
const XMVECTOR T = XMVector3Normalize(to);
|
||||||
|
|
||||||
|
const float dot = XMVectorGetX(XMVector3Dot(F, T));
|
||||||
|
if (dot >= 1.f)
|
||||||
|
{
|
||||||
|
result = Identity;
|
||||||
|
}
|
||||||
|
else if (dot <= -1.f)
|
||||||
|
{
|
||||||
|
XMVECTOR axis = XMVector3Cross(F, SHVec3::Right);
|
||||||
|
if (XMVector3NearEqual(XMVector3LengthSq(axis), g_XMZero, g_XMEpsilon))
|
||||||
|
{
|
||||||
|
axis = XMVector3Cross(F, SHVec3::Up);
|
||||||
|
}
|
||||||
|
|
||||||
|
const XMVECTOR Q = XMQuaternionRotationAxis(axis, XM_PI);
|
||||||
|
XMStoreFloat4(&result, Q);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const XMVECTOR C = XMVector3Cross(F, T);
|
||||||
|
XMStoreFloat4(&result, C);
|
||||||
|
|
||||||
|
const float s = sqrtf((1.f + dot) * 2.f);
|
||||||
|
result.x /= s;
|
||||||
|
result.y /= s;
|
||||||
|
result.z /= s;
|
||||||
|
result.w = s * 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::LookRotation(const SHVec3& forward, const SHVec3& up) noexcept
|
||||||
{
|
{
|
||||||
SHQuaternion result;
|
SHQuaternion result;
|
||||||
|
|
||||||
// TODO (Diren)
|
const SHQuaternion Q1 = FromToRotation(SHVec3::Forward, forward);
|
||||||
|
|
||||||
|
const XMVECTOR C = XMVector3Cross(forward, up);
|
||||||
|
if (XMVector3NearEqual(XMVector3LengthSq(C), g_XMZero, g_XMEpsilon))
|
||||||
|
{
|
||||||
|
// forward and up are co-linear
|
||||||
|
return Q1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHVec3 qU;
|
||||||
|
XMStoreFloat3(&qU, XMQuaternionMultiply(Q1, SHVec3::Up));
|
||||||
|
|
||||||
|
const SHQuaternion Q2 = FromToRotation(qU, up);
|
||||||
|
|
||||||
|
XMStoreFloat4(&result, XMQuaternionMultiply(Q2, Q1));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHQuaternion SHQuaternion::RotateTowards(const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept
|
||||||
|
{
|
||||||
|
SHQuaternion result;
|
||||||
|
|
||||||
|
// We can use the conjugate here instead of inverse assuming q1 & q2 are normalized.
|
||||||
|
const XMVECTOR R = XMQuaternionMultiply(XMQuaternionConjugate(from), to);
|
||||||
|
|
||||||
|
const float RS = XMVectorGetW(R);
|
||||||
|
const XMVECTOR L = XMVector3Length(R);
|
||||||
|
const float angle = 2.f * atan2f(XMVectorGetX(L), RS);
|
||||||
|
if (angle > maxAngleInRad)
|
||||||
|
{
|
||||||
|
const XMVECTOR delta = XMQuaternionRotationAxis(R, maxAngleInRad);
|
||||||
|
const XMVECTOR Q = XMQuaternionMultiply(delta, from);
|
||||||
|
XMStoreFloat4(&result, Q);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Don't overshoot.
|
||||||
|
result = to;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,11 +49,8 @@ namespace SHADE
|
||||||
SHQuaternion (SHQuaternion&& rhs) = default;
|
SHQuaternion (SHQuaternion&& rhs) = default;
|
||||||
|
|
||||||
SHQuaternion () noexcept;
|
SHQuaternion () noexcept;
|
||||||
|
SHQuaternion (const SHVec4& vec4) noexcept;
|
||||||
SHQuaternion (float x, float y, float z, float w) noexcept;
|
SHQuaternion (float x, float y, float z, float w) noexcept;
|
||||||
SHQuaternion (float yaw, float pitch, float roll) noexcept;
|
|
||||||
SHQuaternion (const SHVec3& eulerAngles) noexcept;
|
|
||||||
SHQuaternion (const SHVec3& axis, float angleInRad) noexcept;
|
|
||||||
SHQuaternion (const SHMatrix& rotationMatrix) noexcept;
|
|
||||||
|
|
||||||
// Conversion from other math types
|
// Conversion from other math types
|
||||||
|
|
||||||
|
@ -87,6 +84,7 @@ namespace SHADE
|
||||||
|
|
||||||
operator reactphysics3d::Quaternion () const noexcept;
|
operator reactphysics3d::Quaternion () const noexcept;
|
||||||
operator reactphysics3d::Vector3 () const noexcept;
|
operator reactphysics3d::Vector3 () const noexcept;
|
||||||
|
operator DirectX::XMVECTOR () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
|
@ -99,29 +97,37 @@ namespace SHADE
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void Invert () noexcept;
|
void Invert () noexcept;
|
||||||
|
|
||||||
[[nodiscard]] float Length () const noexcept;
|
[[nodiscard]] float Length () const noexcept;
|
||||||
[[nodiscard]] float LengthSquared () const noexcept;
|
[[nodiscard]] float LengthSquared () const noexcept;
|
||||||
[[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept;
|
[[nodiscard]] float Dot (const SHQuaternion& rhs) const noexcept;
|
||||||
[[nodiscard]] SHQuaternion RotateTowards (const SHQuaternion& target, float maxAngleInRad) const noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] SHVec3 ToEuler () const noexcept;
|
[[nodiscard]] SHVec3 ToEuler () const noexcept;
|
||||||
[[nodiscard]] std::string ToString () const noexcept;
|
[[nodiscard]] std::string ToString () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Static Function Members */
|
/* Static Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
[[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept;
|
[[nodiscard]] static SHQuaternion FromEuler (const SHVec3& eulerAngles) noexcept;
|
||||||
[[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept;
|
[[nodiscard]] static SHQuaternion FromPitchYawRoll (float pitch, float yaw, float roll) noexcept;
|
||||||
[[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept;
|
[[nodiscard]] static SHQuaternion FromAxisAngle (const SHVec3& axis, float angle) noexcept;
|
||||||
[[nodiscard]] static float Angle (const SHQuaternion& q1, const SHQuaternion& q2) noexcept;
|
[[nodiscard]] static SHQuaternion FromRotationMatrix(const SHMatrix& rotationMatrix) noexcept;
|
||||||
|
|
||||||
[[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
|
[[nodiscard]] static SHQuaternion Normalise (const SHQuaternion& q) noexcept;
|
||||||
[[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
|
[[nodiscard]] static SHQuaternion Conjugate (const SHQuaternion& q) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion Inverse (const SHQuaternion& q) noexcept;
|
||||||
|
[[nodiscard]] static float Angle (const SHQuaternion& q1, const SHQuaternion& q2) noexcept;
|
||||||
|
|
||||||
[[nodiscard]] static SHQuaternion Rotate (const SHVec3& from, const SHVec3& to) noexcept;
|
[[nodiscard]] static SHQuaternion Lerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion Slerp (const SHQuaternion& q1, const SHQuaternion& q2, float t) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion ClampedLerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion ClampedSlerp (const SHQuaternion& q1, const SHQuaternion& q2, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] static SHQuaternion FromToRotation (const SHVec3& from, const SHVec3& to) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion LookRotation (const SHVec3& forward, const SHVec3& up) noexcept;
|
||||||
|
[[nodiscard]] static SHQuaternion RotateTowards (const SHQuaternion& from, const SHQuaternion& to, float maxAngleInRad) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept;
|
SHQuaternion operator*(float lhs, const SHQuaternion& rhs) noexcept;
|
||||||
|
|
|
@ -26,15 +26,15 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHTransform::SHTransform() noexcept
|
SHTransform::SHTransform() noexcept
|
||||||
: position { SHVec3::Zero }
|
: position { SHVec3::Zero }
|
||||||
, rotation { SHVec3::Zero }
|
, orientation { SHQuaternion::Identity }
|
||||||
, scale { SHVec3::One }
|
, scale { SHVec3::One }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SHTransform::SHTransform(const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept
|
SHTransform::SHTransform(const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept
|
||||||
: position { pos }
|
: position { pos }
|
||||||
, rotation { rot }
|
, orientation { SHQuaternion::FromEuler(rot) }
|
||||||
, scale { scl }
|
, scale { scl }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -43,12 +43,12 @@ namespace SHADE
|
||||||
|
|
||||||
bool SHTransform::operator==(const SHTransform& rhs) const noexcept
|
bool SHTransform::operator==(const SHTransform& rhs) const noexcept
|
||||||
{
|
{
|
||||||
return !(position != rhs.position || rotation != rhs.rotation || scale != rhs.scale);
|
return !(position != rhs.position || orientation != rhs.orientation || scale != rhs.scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHTransform::operator!=(const SHTransform& rhs) const noexcept
|
bool SHTransform::operator!=(const SHTransform& rhs) const noexcept
|
||||||
{
|
{
|
||||||
return (position != rhs.position || rotation != rhs.rotation || scale != rhs.scale);
|
return (position != rhs.position || orientation != rhs.orientation || scale != rhs.scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -59,7 +59,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
|
|
||||||
const SHMatrix T = SHMatrix::Translate(position);
|
const SHMatrix T = SHMatrix::Translate(position);
|
||||||
const SHMatrix R = SHMatrix::Rotate(rotation);
|
const SHMatrix R = SHMatrix::Rotate(orientation);
|
||||||
const SHMatrix S = SHMatrix::Scale(scale);
|
const SHMatrix S = SHMatrix::Scale(scale);
|
||||||
|
|
||||||
trs = S * R * T;
|
trs = S * R * T;
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
#include "Math/Vector/SHVec2.h"
|
|
||||||
#include "Math/Vector/SHVec3.h"
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/SHQuaternion.h"
|
||||||
#include "Math/SHMatrix.h"
|
#include "Math/SHMatrix.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -31,22 +31,23 @@ namespace SHADE
|
||||||
|
|
||||||
static const SHTransform Identity;
|
static const SHTransform Identity;
|
||||||
|
|
||||||
SHVec3 position;
|
SHVec3 position;
|
||||||
SHVec3 rotation;
|
SHQuaternion orientation;
|
||||||
SHVec3 scale;
|
SHVec3 scale;
|
||||||
|
|
||||||
SHMatrix trs;
|
SHMatrix trs;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Constructors & Destructor */
|
/* Constructors & Destructor */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHTransform (const SHTransform&) = default;
|
SHTransform (const SHTransform&) = default;
|
||||||
SHTransform (SHTransform&&) = default;
|
SHTransform (SHTransform&&) = default;
|
||||||
~SHTransform () = default;
|
~SHTransform () = default;
|
||||||
|
|
||||||
SHTransform () noexcept;
|
SHTransform () noexcept;
|
||||||
SHTransform (const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept;
|
SHTransform (const SHVec3& pos, const SHVec3& rot, const SHVec3& scl) noexcept;
|
||||||
|
SHTransform (const SHVec3& pos, const SHQuaternion& quat, const SHVec3& scl) noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Operator Overloads */
|
/* Operator Overloads */
|
||||||
|
@ -63,7 +64,6 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
const SHMatrix& ComputeTRS();
|
const SHMatrix& ComputeTRS();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
// Primary Header
|
// Primary Header
|
||||||
#include "SHTransformComponent.h"
|
#include "SHTransformComponent.h"
|
||||||
|
// Project Headers
|
||||||
|
#include "Math/SHMathHelpers.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -40,7 +42,12 @@ namespace SHADE
|
||||||
|
|
||||||
const SHVec3& SHTransformComponent::GetLocalRotation() const noexcept
|
const SHVec3& SHTransformComponent::GetLocalRotation() const noexcept
|
||||||
{
|
{
|
||||||
return local.rotation;
|
return localRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHQuaternion& SHTransformComponent::GetLocalOrientation() const noexcept
|
||||||
|
{
|
||||||
|
return local.orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHVec3& SHTransformComponent::GetLocalScale() const noexcept
|
const SHVec3& SHTransformComponent::GetLocalScale() const noexcept
|
||||||
|
@ -55,7 +62,12 @@ namespace SHADE
|
||||||
|
|
||||||
const SHVec3& SHTransformComponent::GetWorldRotation() const noexcept
|
const SHVec3& SHTransformComponent::GetWorldRotation() const noexcept
|
||||||
{
|
{
|
||||||
return world.rotation;
|
return worldRotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHQuaternion& SHTransformComponent::GetWorldOrientation() const noexcept
|
||||||
|
{
|
||||||
|
return world.orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SHVec3& SHTransformComponent::GetWorldScale() const noexcept
|
const SHVec3& SHTransformComponent::GetWorldScale() const noexcept
|
||||||
|
@ -91,16 +103,28 @@ namespace SHADE
|
||||||
void SHTransformComponent::SetLocalRotation(const SHVec3& newLocalRotation) noexcept
|
void SHTransformComponent::SetLocalRotation(const SHVec3& newLocalRotation) noexcept
|
||||||
{
|
{
|
||||||
dirty = true;
|
dirty = true;
|
||||||
local.rotation = newLocalRotation;
|
|
||||||
|
localRotation = newLocalRotation;
|
||||||
|
updateQueue.push({ UpdateCommandType::LOCAL_ROTATION, newLocalRotation });
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHTransformComponent::SetLocalRotation(float pitch, float yaw, float roll) noexcept
|
void SHTransformComponent::SetLocalRotation(float pitch, float yaw, float roll) noexcept
|
||||||
{
|
{
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
|
||||||
local.rotation.x = pitch;
|
localRotation.x = pitch;
|
||||||
local.rotation.y = yaw;
|
localRotation.y = yaw;
|
||||||
local.rotation.z = roll;
|
localRotation.z = roll;
|
||||||
|
|
||||||
|
updateQueue.push({ UpdateCommandType::LOCAL_ROTATION, SHVec3{pitch, yaw, roll} });
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHTransformComponent::SetLocalOrientation(const SHQuaternion& newLocalOrientation) noexcept
|
||||||
|
{
|
||||||
|
dirty = true;
|
||||||
|
|
||||||
|
local.orientation = newLocalOrientation;
|
||||||
|
updateQueue.push({ UpdateCommandType::LOCAL_ORIENTATION, newLocalOrientation });
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHTransformComponent::SetLocalScale(const SHVec3& newLocalScale) noexcept
|
void SHTransformComponent::SetLocalScale(const SHVec3& newLocalScale) noexcept
|
||||||
|
@ -121,7 +145,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
|
||||||
world.rotation = newWorldRotation;
|
worldRotation = newWorldRotation;
|
||||||
updateQueue.push({ UpdateCommandType::WORLD_ROTATION, newWorldRotation });
|
updateQueue.push({ UpdateCommandType::WORLD_ROTATION, newWorldRotation });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,13 +153,21 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
|
||||||
world.rotation.x = pitch;
|
worldRotation.x = pitch;
|
||||||
world.rotation.y = yaw;
|
worldRotation.y = yaw;
|
||||||
world.rotation.z = roll;
|
worldRotation.z = roll;
|
||||||
|
|
||||||
updateQueue.push({ UpdateCommandType::WORLD_ROTATION, SHVec3{ pitch, yaw, roll} });
|
updateQueue.push({ UpdateCommandType::WORLD_ROTATION, SHVec3{ pitch, yaw, roll} });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHTransformComponent::SetWorldOrientation(const SHQuaternion& newWorldOrientation) noexcept
|
||||||
|
{
|
||||||
|
dirty = true;
|
||||||
|
|
||||||
|
world.orientation = newWorldOrientation;
|
||||||
|
updateQueue.push({ UpdateCommandType::WORLD_ORIENTATION, newWorldOrientation });
|
||||||
|
}
|
||||||
|
|
||||||
void SHTransformComponent::SetWorldScale(const SHVec3& newWorldScale) noexcept
|
void SHTransformComponent::SetWorldScale(const SHVec3& newWorldScale) noexcept
|
||||||
{
|
{
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
@ -153,6 +185,6 @@ RTTR_REGISTRATION
|
||||||
|
|
||||||
registration::class_<SHTransformComponent>("Transform Component")
|
registration::class_<SHTransformComponent>("Transform Component")
|
||||||
.property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition )
|
.property("Translate" , &SHTransformComponent::GetLocalPosition , &SHTransformComponent::SetLocalPosition )
|
||||||
.property("Rotate" , &SHTransformComponent::GetLocalRotation , select_overload<void(SHVec3 const&)>(&SHTransformComponent::SetLocalRotation) )
|
.property("Rotate" , &SHTransformComponent::GetLocalRotation , select_overload<void(const SHVec3&)>(&SHTransformComponent::SetLocalRotation) )
|
||||||
.property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale );
|
.property("Scale" , &SHTransformComponent::GetLocalScale , &SHTransformComponent::SetLocalScale );
|
||||||
}
|
}
|
|
@ -56,42 +56,52 @@ namespace SHADE
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
[[nodiscard]] bool HasChanged () const noexcept;
|
[[nodiscard]] bool HasChanged () const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] const SHVec3& GetLocalPosition () const noexcept;
|
[[nodiscard]] const SHVec3& GetLocalPosition () const noexcept;
|
||||||
[[nodiscard]] const SHVec3& GetLocalRotation () const noexcept;
|
[[nodiscard]] const SHVec3& GetLocalRotation () const noexcept;
|
||||||
[[nodiscard]] const SHVec3& GetLocalScale () const noexcept;
|
[[nodiscard]] const SHQuaternion& GetLocalOrientation () const noexcept;
|
||||||
[[nodiscard]] const SHVec3& GetWorldPosition () const noexcept;
|
[[nodiscard]] const SHVec3& GetLocalScale () const noexcept;
|
||||||
[[nodiscard]] const SHVec3& GetWorldRotation () const noexcept;
|
[[nodiscard]] const SHVec3& GetWorldPosition () const noexcept;
|
||||||
[[nodiscard]] const SHVec3& GetWorldScale () const noexcept;
|
[[nodiscard]] const SHVec3& GetWorldRotation () const noexcept;
|
||||||
|
[[nodiscard]] const SHQuaternion& GetWorldOrientation () const noexcept;
|
||||||
|
[[nodiscard]] const SHVec3& GetWorldScale () const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] const SHMatrix& GetLocalToWorld () const noexcept;
|
[[nodiscard]] const SHMatrix& GetLocalToWorld () const noexcept;
|
||||||
[[nodiscard]] SHMatrix GetWorldToLocal () const noexcept;
|
[[nodiscard]] SHMatrix GetWorldToLocal () const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] const SHMatrix& GetTRS () const noexcept;
|
[[nodiscard]] const SHMatrix& GetTRS () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SetLocalPosition (const SHVec3& newLocalPosition) noexcept;
|
void SetLocalPosition (const SHVec3& newLocalPosition) noexcept;
|
||||||
void SetLocalRotation (const SHVec3& newLocalRotation) noexcept;
|
void SetLocalRotation (const SHVec3& newLocalRotation) noexcept;
|
||||||
void SetLocalRotation (float pitch, float yaw, float roll) noexcept;
|
void SetLocalRotation (float pitch, float yaw, float roll) noexcept;
|
||||||
void SetLocalScale (const SHVec3& newLocalScale) noexcept;
|
void SetLocalOrientation (const SHQuaternion& newLocalOrientation) noexcept;
|
||||||
void SetWorldPosition (const SHVec3& newWorldPosition) noexcept;
|
void SetLocalScale (const SHVec3& newLocalScale) noexcept;
|
||||||
void SetWorldRotation (const SHVec3& newWorldRotation) noexcept;
|
void SetWorldPosition (const SHVec3& newWorldPosition) noexcept;
|
||||||
void SetWorldRotation (float pitch, float yaw, float roll) noexcept;
|
void SetWorldRotation (const SHVec3& newWorldRotation) noexcept;
|
||||||
void SetWorldScale (const SHVec3& newWorldScale) noexcept;
|
void SetWorldRotation (float pitch, float yaw, float roll) noexcept;
|
||||||
|
void SetWorldOrientation (const SHQuaternion& newWorldOrientation) noexcept;
|
||||||
|
void SetWorldScale (const SHVec3& newWorldScale) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Differentiate between rotation and orientation for setters
|
||||||
|
// Setting a quaternion directly is different from using euler angle rotations.
|
||||||
|
|
||||||
enum class UpdateCommandType
|
enum class UpdateCommandType
|
||||||
{
|
{
|
||||||
WORLD_POSITION
|
LOCAL_ROTATION
|
||||||
|
, LOCAL_ORIENTATION
|
||||||
|
, WORLD_POSITION
|
||||||
, WORLD_ROTATION
|
, WORLD_ROTATION
|
||||||
|
, WORLD_ORIENTATION
|
||||||
, WORLD_SCALE
|
, WORLD_SCALE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,7 +113,7 @@ namespace SHADE
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
UpdateCommandType type;
|
UpdateCommandType type;
|
||||||
SHVec3 data;
|
SHVec4 data;
|
||||||
};
|
};
|
||||||
|
|
||||||
using UpdateQueue = std::queue<UpdateCommand>;
|
using UpdateQueue = std::queue<UpdateCommand>;
|
||||||
|
@ -114,6 +124,12 @@ namespace SHADE
|
||||||
|
|
||||||
bool dirty;
|
bool dirty;
|
||||||
|
|
||||||
|
// We store euler angle rotations separately to interface with transform quaternions.
|
||||||
|
// Reading quaternions are unreliable.
|
||||||
|
|
||||||
|
SHVec3 localRotation; // Stored in Radians
|
||||||
|
SHVec3 worldRotation; // Stored in Radians
|
||||||
|
|
||||||
SHTransform local; // Local TRS holds Local To World Transform
|
SHTransform local; // Local TRS holds Local To World Transform
|
||||||
SHTransform world;
|
SHTransform world;
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
#include "Scene/SHSceneManager.h"
|
#include "Scene/SHSceneManager.h"
|
||||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||||
#include "Tools/SHException.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
#include "Math/SHMathHelpers.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -29,8 +30,12 @@ namespace SHADE
|
||||||
/* Constructors & Destructor Definitions */
|
/* Constructors & Destructor Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHTransformSystem::TransformUpdateRoutine::TransformUpdateRoutine()
|
SHTransformSystem::TransformPostLogicUpdate::TransformPostLogicUpdate()
|
||||||
: SHSystemRoutine { "Transform Update", true }
|
: SHSystemRoutine { "Transform Post-Logic Update", true }
|
||||||
|
{}
|
||||||
|
|
||||||
|
SHTransformSystem::TransformPostPhysicsUpdate::TransformPostPhysicsUpdate()
|
||||||
|
: SHSystemRoutine { "Transform Post-Physics Update", false }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,16 +43,27 @@ namespace SHADE
|
||||||
/* Public Function Member Definitions */
|
/* Public Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHTransformSystem::TransformUpdateRoutine::Execute(double) noexcept
|
void SHTransformSystem::TransformPostLogicUpdate::Execute(double) noexcept
|
||||||
{
|
{
|
||||||
// Get the current scene graph to traverse and update
|
// Get the current scene graph to traverse and update
|
||||||
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
|
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
|
||||||
UpdateEntity(SCENE_GRAPH.GetRoot());
|
|
||||||
|
// TODO(Diren): Consider how to clear dirty in pause / stop mode and update physics, but do not clear in play mode.
|
||||||
|
UpdateEntity(SCENE_GRAPH.GetRoot(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHTransformSystem::TransformPostPhysicsUpdate::Execute(double) noexcept
|
||||||
|
{
|
||||||
|
// Get the current scene graph to traverse and update
|
||||||
|
const auto& SCENE_GRAPH = SHSceneManager::GetCurrentSceneGraph();
|
||||||
|
UpdateEntity(SCENE_GRAPH.GetRoot(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHTransformSystem::Init()
|
void SHTransformSystem::Init()
|
||||||
{
|
{
|
||||||
|
std::shared_ptr thisReceiver { std::make_shared<SHEventReceiverSpec<SHTransformSystem>>(this, &SHTransformSystem::ChangeParent) };
|
||||||
|
ReceiverPtr receiver = std::dynamic_pointer_cast<SHEventReceiver>(thisReceiver);
|
||||||
|
SHEventManager::SubscribeTo(SH_SCENEGRAPH_CHANGE_PARENT_EVENT, receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHTransformSystem::Exit()
|
void SHTransformSystem::Exit()
|
||||||
|
@ -59,7 +75,97 @@ namespace SHADE
|
||||||
/* Private Function Member Definitions */
|
/* Private Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHTransformSystem::UpdateEntity(const SHSceneNode* node)
|
SHEventHandle SHTransformSystem::ChangeParent(SHEventPtr changeParentEvent)
|
||||||
|
{
|
||||||
|
const auto& eventData = reinterpret_cast<const SHEventSpec<SHSceneGraphChangeParentEvent>*>(changeParentEvent.get());
|
||||||
|
|
||||||
|
auto* node = eventData->data->node;
|
||||||
|
auto* tf = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID());
|
||||||
|
|
||||||
|
// Recompute local transform and store localToWorld Matrix
|
||||||
|
SHMatrix localToWorld = SHMatrix::Identity;
|
||||||
|
SHMatrix worldToLocal = SHMatrix::Identity;
|
||||||
|
|
||||||
|
auto* newParent = eventData->data->newParent;
|
||||||
|
const auto* PARENT_TF = SHComponentManager::GetComponent_s<SHTransformComponent>(newParent->GetEntityID());
|
||||||
|
if (PARENT_TF != nullptr) // Not the root
|
||||||
|
{
|
||||||
|
localToWorld = PARENT_TF->GetTRS();
|
||||||
|
worldToLocal = SHMatrix::Inverse(localToWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maintain World Transform and recompute Local Transform
|
||||||
|
|
||||||
|
// Compute Local Position
|
||||||
|
tf->local.position = SHVec3::Transform(tf->world.position, worldToLocal);
|
||||||
|
|
||||||
|
|
||||||
|
tf->localRotation = tf->worldRotation;
|
||||||
|
tf->local.scale = tf->world.scale;
|
||||||
|
|
||||||
|
if (PARENT_TF != nullptr)
|
||||||
|
{
|
||||||
|
// Compute Local Rotation
|
||||||
|
tf->localRotation -= PARENT_TF->GetLocalRotation();
|
||||||
|
|
||||||
|
// Compute Local Scale
|
||||||
|
tf->local.scale /= PARENT_TF->GetLocalScale();
|
||||||
|
}
|
||||||
|
|
||||||
|
tf->local.trs = localToWorld;
|
||||||
|
|
||||||
|
// Propagate maintaining world transform down the branch
|
||||||
|
UpdateChildrenLocalTransforms(node);
|
||||||
|
return eventData->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHTransformSystem::UpdateChildrenLocalTransforms(SHSceneNode* node)
|
||||||
|
{
|
||||||
|
// Structure is similar to update entity, albeit without a queue to do being a forced update
|
||||||
|
for (const auto* child : node->GetChildren())
|
||||||
|
{
|
||||||
|
if (auto* childTransform = SHComponentManager::GetComponent_s<SHTransformComponent>(child->GetEntityID()); childTransform)
|
||||||
|
{
|
||||||
|
const bool IS_NODE_ACTIVE = child->IsActive();
|
||||||
|
if (IS_NODE_ACTIVE && childTransform->isActive)
|
||||||
|
{
|
||||||
|
// Recompute local transform and store localToWorld Matrix
|
||||||
|
SHMatrix localToWorld = SHMatrix::Identity;
|
||||||
|
SHMatrix worldToLocal = SHMatrix::Identity;
|
||||||
|
|
||||||
|
const auto* parent = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID());
|
||||||
|
|
||||||
|
if (parent != nullptr) // Not the root
|
||||||
|
{
|
||||||
|
localToWorld = parent->GetTRS();
|
||||||
|
worldToLocal = SHMatrix::Inverse(localToWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maintain World Transform and recompute Local Transform
|
||||||
|
|
||||||
|
// Compute Local Position
|
||||||
|
childTransform->local.position = SHVec3::Transform(childTransform->world.position, worldToLocal);
|
||||||
|
|
||||||
|
|
||||||
|
childTransform->localRotation = childTransform->worldRotation;
|
||||||
|
childTransform->local.scale = childTransform->world.scale;
|
||||||
|
|
||||||
|
if (parent)
|
||||||
|
{
|
||||||
|
// Compute Local Rotation
|
||||||
|
childTransform->localRotation -= parent->GetLocalRotation();
|
||||||
|
|
||||||
|
// Compute Local Scale
|
||||||
|
childTransform->local.scale /= parent->GetLocalScale();
|
||||||
|
}
|
||||||
|
|
||||||
|
childTransform->local.trs = localToWorld;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHTransformSystem::UpdateEntity(const SHSceneNode* node, bool clearDirtyFlag)
|
||||||
{
|
{
|
||||||
const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID());
|
const auto* NODE_TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(node->GetEntityID());
|
||||||
const bool HAS_PARENT_CHANGED = NODE_TRANSFORM && NODE_TRANSFORM->dirty;
|
const bool HAS_PARENT_CHANGED = NODE_TRANSFORM && NODE_TRANSFORM->dirty;
|
||||||
|
@ -74,14 +180,17 @@ namespace SHADE
|
||||||
if (IS_NODE_ACTIVE && childTransform->isActive)
|
if (IS_NODE_ACTIVE && childTransform->isActive)
|
||||||
{
|
{
|
||||||
if (childTransform->dirty || HAS_PARENT_CHANGED)
|
if (childTransform->dirty || HAS_PARENT_CHANGED)
|
||||||
|
{
|
||||||
UpdateTransform(*childTransform, NODE_TRANSFORM);
|
UpdateTransform(*childTransform, NODE_TRANSFORM);
|
||||||
|
childTransform->dirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateEntity(child);
|
UpdateEntity(child, clearDirtyFlag);
|
||||||
|
|
||||||
// Clear dirty flag after all children are updated
|
// Clear dirty flag after all children are updated
|
||||||
if (childTransform)
|
if (childTransform && clearDirtyFlag)
|
||||||
childTransform->dirty = false;
|
childTransform->dirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,6 +200,8 @@ namespace SHADE
|
||||||
SHMatrix localToWorld = SHMatrix::Identity;
|
SHMatrix localToWorld = SHMatrix::Identity;
|
||||||
SHMatrix worldToLocal = SHMatrix::Identity;
|
SHMatrix worldToLocal = SHMatrix::Identity;
|
||||||
|
|
||||||
|
bool convertRotation = true;
|
||||||
|
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
localToWorld = parent->GetTRS();
|
localToWorld = parent->GetTRS();
|
||||||
|
@ -103,22 +214,44 @@ namespace SHADE
|
||||||
|
|
||||||
switch (UPDATE_COMMAND.type)
|
switch (UPDATE_COMMAND.type)
|
||||||
{
|
{
|
||||||
|
case SHTransformComponent::UpdateCommandType::LOCAL_ROTATION:
|
||||||
|
{
|
||||||
|
convertRotation = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SHTransformComponent::UpdateCommandType::LOCAL_ORIENTATION:
|
||||||
|
{
|
||||||
|
convertRotation = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SHTransformComponent::UpdateCommandType::WORLD_POSITION:
|
case SHTransformComponent::UpdateCommandType::WORLD_POSITION:
|
||||||
{
|
{
|
||||||
tf.local.position = SHVec3::Transform(UPDATE_COMMAND.data, worldToLocal);
|
tf.local.position = SHVec3::Transform(UPDATE_COMMAND.data.ToVec3(), worldToLocal);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SHTransformComponent::UpdateCommandType::WORLD_ROTATION:
|
case SHTransformComponent::UpdateCommandType::WORLD_ROTATION:
|
||||||
{
|
{
|
||||||
tf.local.rotation = tf.world.rotation;
|
tf.localRotation = UPDATE_COMMAND.data.ToVec3();
|
||||||
if (parent)
|
if (parent)
|
||||||
tf.local.rotation -= parent->GetLocalRotation();
|
tf.localRotation -= parent->GetLocalRotation();
|
||||||
|
|
||||||
|
convertRotation = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SHTransformComponent::UpdateCommandType::WORLD_ORIENTATION:
|
||||||
|
{
|
||||||
|
tf.local.orientation = UPDATE_COMMAND.data;
|
||||||
|
if (parent)
|
||||||
|
tf.local.orientation /= parent->GetLocalOrientation();
|
||||||
|
|
||||||
|
convertRotation = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SHTransformComponent::UpdateCommandType::WORLD_SCALE:
|
case SHTransformComponent::UpdateCommandType::WORLD_SCALE:
|
||||||
{
|
{
|
||||||
tf.local.scale = tf.world.scale;
|
tf.local.scale = UPDATE_COMMAND.data.ToVec3();
|
||||||
if (parent)
|
if (parent)
|
||||||
tf.local.scale /= parent->GetLocalScale();
|
tf.local.scale /= parent->GetLocalScale();
|
||||||
|
|
||||||
|
@ -133,15 +266,38 @@ namespace SHADE
|
||||||
|
|
||||||
tf.local.trs = localToWorld;
|
tf.local.trs = localToWorld;
|
||||||
|
|
||||||
|
// Compute world transforms
|
||||||
tf.world.position = SHVec3::Transform(tf.local.position, localToWorld);
|
tf.world.position = SHVec3::Transform(tf.local.position, localToWorld);
|
||||||
tf.world.rotation = tf.local.rotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero);
|
|
||||||
tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One);
|
tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One);
|
||||||
|
|
||||||
tf.world.ComputeTRS();
|
|
||||||
|
|
||||||
// Transpose TRS to column major
|
if (convertRotation)
|
||||||
//tf.local.trs.Transpose();
|
{
|
||||||
//tf.world.trs.Transpose();
|
tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero);
|
||||||
|
|
||||||
|
// Set the orientation
|
||||||
|
// Wrap rotations between -360 and 360 and convert to radians
|
||||||
|
SHVec3 worldRotRad, localRotRad;
|
||||||
|
for (size_t i = 0; i < SHVec3::SIZE; ++i)
|
||||||
|
{
|
||||||
|
worldRotRad[i] = SHMath::Wrap(tf.worldRotation[i], -SHMath::TWO_PI, SHMath::TWO_PI);
|
||||||
|
localRotRad[i] = SHMath::Wrap(tf.localRotation[i], -SHMath::TWO_PI, SHMath::TWO_PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
tf.world.orientation = SHQuaternion::FromEuler(worldRotRad);
|
||||||
|
tf.local.orientation = SHQuaternion::FromEuler(localRotRad);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tf.world.orientation = (parent ? parent->GetLocalOrientation() : SHQuaternion::Identity) * tf.local.orientation;
|
||||||
|
|
||||||
|
// Set the euler angle rotations
|
||||||
|
tf.worldRotation = tf.world.orientation.ToEuler();
|
||||||
|
tf.localRotation = tf.local.orientation.ToEuler();
|
||||||
|
}
|
||||||
|
|
||||||
|
tf.world.ComputeTRS();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -45,25 +45,52 @@ namespace SHADE
|
||||||
/* System Routines */
|
/* System Routines */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class SH_API TransformUpdateRoutine final: public SHSystemRoutine
|
class SH_API TransformPostLogicUpdate final: public SHSystemRoutine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Constructors & Destructor */
|
/* Constructors & Destructor */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
TransformUpdateRoutine ();
|
TransformPostLogicUpdate ();
|
||||||
~TransformUpdateRoutine () = default;
|
~TransformPostLogicUpdate () = default;
|
||||||
|
|
||||||
TransformUpdateRoutine (const TransformUpdateRoutine&) = delete;
|
TransformPostLogicUpdate (const TransformPostLogicUpdate&) = delete;
|
||||||
TransformUpdateRoutine (TransformUpdateRoutine&&) = delete;
|
TransformPostLogicUpdate (TransformPostLogicUpdate&&) = delete;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Operator Overloads */
|
/* Operator Overloads */
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
TransformUpdateRoutine& operator= (const TransformUpdateRoutine&) = delete;
|
TransformPostLogicUpdate& operator= (const TransformPostLogicUpdate&) = delete;
|
||||||
TransformUpdateRoutine& operator= (TransformUpdateRoutine&&) = delete;
|
TransformPostLogicUpdate& operator= (TransformPostLogicUpdate&&) = delete;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void Execute(double dt) noexcept override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SH_API TransformPostPhysicsUpdate final: public SHSystemRoutine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
TransformPostPhysicsUpdate ();
|
||||||
|
~TransformPostPhysicsUpdate () = default;
|
||||||
|
|
||||||
|
TransformPostPhysicsUpdate (const TransformPostPhysicsUpdate&) = delete;
|
||||||
|
TransformPostPhysicsUpdate (TransformPostPhysicsUpdate&&) = delete;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
/* Operator Overloads */
|
||||||
|
/*-------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
TransformPostPhysicsUpdate& operator= (const TransformPostPhysicsUpdate&) = delete;
|
||||||
|
TransformPostPhysicsUpdate& operator= (TransformPostPhysicsUpdate&&) = delete;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
|
@ -84,8 +111,11 @@ namespace SHADE
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void UpdateEntity (const SHSceneNode* node);
|
SHEventHandle ChangeParent (SHEventPtr changeParentEvent);
|
||||||
static void UpdateTransform(SHTransformComponent& tf, const SHTransformComponent* parent = nullptr);
|
static void UpdateChildrenLocalTransforms (SHSceneNode* node);
|
||||||
|
|
||||||
|
static void UpdateEntity (const SHSceneNode* node, bool clearDirtyFlag);
|
||||||
|
static void UpdateTransform (SHTransformComponent& tf, const SHTransformComponent* parent = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,10 @@ namespace SHADE
|
||||||
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f )
|
: XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
SHVec4::SHVec4(const SHVec3& vec3) noexcept
|
||||||
|
: XMFLOAT4( vec3.x, vec3.y, vec3.z, 1.0f )
|
||||||
|
{}
|
||||||
|
|
||||||
SHVec4::SHVec4(const XMFLOAT4& xmfloat4) noexcept
|
SHVec4::SHVec4(const XMFLOAT4& xmfloat4) noexcept
|
||||||
: XMFLOAT4( xmfloat4.x, xmfloat4.y, xmfloat4.z, xmfloat4.w )
|
: XMFLOAT4( xmfloat4.x, xmfloat4.y, xmfloat4.z, xmfloat4.w )
|
||||||
{}
|
{}
|
||||||
|
@ -271,6 +275,11 @@ namespace SHADE
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHVec3 SHVec4::ToVec3() const noexcept
|
||||||
|
{
|
||||||
|
return SHVec3{ x, y, z };
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Static Function Member Definitions */
|
/* Static Function Member Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
#include "SHVec3.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -53,6 +54,7 @@ namespace SHADE
|
||||||
~SHVec4 () = default;
|
~SHVec4 () = default;
|
||||||
|
|
||||||
SHVec4 () noexcept;
|
SHVec4 () noexcept;
|
||||||
|
SHVec4 (const SHVec3& vec3) noexcept;
|
||||||
SHVec4 (const XMFLOAT4& xmfloat4) noexcept;
|
SHVec4 (const XMFLOAT4& xmfloat4) noexcept;
|
||||||
SHVec4 (float x, float y, float z, float w) noexcept;
|
SHVec4 (float x, float y, float z, float w) noexcept;
|
||||||
|
|
||||||
|
@ -102,16 +104,18 @@ namespace SHADE
|
||||||
[[nodiscard]] float Dot3D (const SHVec4& rhs) const noexcept;
|
[[nodiscard]] float Dot3D (const SHVec4& rhs) const noexcept;
|
||||||
[[nodiscard]] SHVec4 Cross3D (const SHVec4& rhs) const noexcept;
|
[[nodiscard]] SHVec4 Cross3D (const SHVec4& rhs) const noexcept;
|
||||||
[[nodiscard]] SHVec4 Cross (const SHVec4& v1, const SHVec4& v2) const noexcept;
|
[[nodiscard]] SHVec4 Cross (const SHVec4& v1, const SHVec4& v2) const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] SHVec3 ToVec3 () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Static Function Members */
|
/* Static Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
[[nodiscard]] static SHVec4 Normalise (const SHVec4& v) noexcept;
|
[[nodiscard]] static SHVec4 Normalise (const SHVec4& v) noexcept;
|
||||||
[[nodiscard]] static SHVec4 Normalise3D (const SHVec4& v) noexcept;
|
[[nodiscard]] static SHVec4 Normalise3D (const SHVec4& v) noexcept;
|
||||||
[[nodiscard]] static SHVec4 Abs (const SHVec4& v) noexcept;
|
[[nodiscard]] static SHVec4 Abs (const SHVec4& v) noexcept;
|
||||||
[[nodiscard]] static SHVec4 Min (const std::initializer_list<SHVec4>& vs) noexcept;
|
[[nodiscard]] static SHVec4 Min (const std::initializer_list<SHVec4>& vs) noexcept;
|
||||||
[[nodiscard]] static SHVec4 Max (const std::initializer_list<SHVec4>& vs) noexcept;
|
[[nodiscard]] static SHVec4 Max (const std::initializer_list<SHVec4>& vs) noexcept;
|
||||||
[[nodiscard]] static SHVec4 Clamp (const SHVec4& v, const SHVec4& vMin, const SHVec4& vMax) noexcept;
|
[[nodiscard]] static SHVec4 Clamp (const SHVec4& v, const SHVec4& vMin, const SHVec4& vMax) noexcept;
|
||||||
[[nodiscard]] static SHVec4 Lerp (const SHVec4& a, const SHVec4& b, float t) noexcept;
|
[[nodiscard]] static SHVec4 Lerp (const SHVec4& a, const SHVec4& b, float t) noexcept;
|
||||||
[[nodiscard]] static SHVec4 ClampedLerp (const SHVec4& a, const SHVec4& b, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept;
|
[[nodiscard]] static SHVec4 ClampedLerp (const SHVec4& a, const SHVec4& b, float t, float tMin = 0.0f, float tMax = 1.0f) noexcept;
|
||||||
|
|
|
@ -140,12 +140,12 @@ namespace SHADE
|
||||||
isRigidBody = true;
|
isRigidBody = true;
|
||||||
|
|
||||||
rb->position = tf->GetWorldPosition();
|
rb->position = tf->GetWorldPosition();
|
||||||
rb->orientation = tf->GetWorldRotation();
|
rb->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation());
|
||||||
|
|
||||||
if (hasColliders)
|
if (hasColliders)
|
||||||
{
|
{
|
||||||
c->position = tf->GetWorldPosition();
|
c->position = tf->GetWorldPosition();
|
||||||
c->orientation = tf->GetWorldRotation();
|
c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation());
|
||||||
// Get array of colliders and add them back into the rigidbody
|
// Get array of colliders and add them back into the rigidbody
|
||||||
for (auto& collider : c->colliders | std::views::keys)
|
for (auto& collider : c->colliders | std::views::keys)
|
||||||
AddCollider(&collider);
|
AddCollider(&collider);
|
||||||
|
@ -160,7 +160,7 @@ namespace SHADE
|
||||||
hasColliders = true;
|
hasColliders = true;
|
||||||
|
|
||||||
c->position = tf->GetWorldPosition();
|
c->position = tf->GetWorldPosition();
|
||||||
c->orientation = tf->GetWorldRotation();
|
c->orientation = SHQuaternion::FromEuler(tf->GetWorldRotation());
|
||||||
|
|
||||||
for (auto& collider : c->colliders | std::views::keys)
|
for (auto& collider : c->colliders | std::views::keys)
|
||||||
AddCollider(&collider);
|
AddCollider(&collider);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||||
|
#include "Math/SHMathHelpers.h"
|
||||||
#include "Scene/SHSceneManager.h"
|
#include "Scene/SHSceneManager.h"
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
|
|
||||||
|
@ -315,7 +316,7 @@ namespace SHADE
|
||||||
if (TF->HasChanged())
|
if (TF->HasChanged())
|
||||||
{
|
{
|
||||||
physicsObject.SetPosition(TF->GetWorldPosition());
|
physicsObject.SetPosition(TF->GetWorldPosition());
|
||||||
physicsObject.SetRotation(TF->GetWorldRotation());
|
physicsObject.SetOrientation(TF->GetWorldOrientation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,8 +493,7 @@ namespace SHADE
|
||||||
// Convert RP3D Transform to SHADE
|
// Convert RP3D Transform to SHADE
|
||||||
auto* tfComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
|
auto* tfComponent = SHComponentManager::GetComponent<SHTransformComponent>(entityID);
|
||||||
tfComponent->SetWorldPosition(rp3dPos);
|
tfComponent->SetWorldPosition(rp3dPos);
|
||||||
tfComponent->SetWorldRotation(SHQuaternion{ rp3dRot }.ToEuler());
|
tfComponent->SetWorldOrientation(SHQuaternion{ rp3dRot });
|
||||||
|
|
||||||
|
|
||||||
// Cache transforms
|
// Cache transforms
|
||||||
physicsObject.prevTransform = CURRENT_TF;
|
physicsObject.prevTransform = CURRENT_TF;
|
||||||
|
|
|
@ -15,6 +15,7 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "SHResourceManager.h"
|
#include "SHResourceManager.h"
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Assets/SHAssetManager.h"
|
#include "Assets/SHAssetManager.h"
|
||||||
|
#include "Assets/Asset Types/SHAssetIncludes.h"
|
||||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Tools/SHLog.h"
|
#include "Tools/SHLog.h"
|
||||||
|
@ -48,7 +49,7 @@ namespace SHADE
|
||||||
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
|
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
const SHMeshAsset* assetData = SHAssetManager::GetMesh(assetId);
|
const SHMeshAsset* assetData = SHAssetManager::GetData<SHMeshAsset>(assetId);
|
||||||
if (assetData == nullptr)
|
if (assetData == nullptr)
|
||||||
{
|
{
|
||||||
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
|
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
|
||||||
|
@ -80,7 +81,7 @@ namespace SHADE
|
||||||
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
|
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
const SHTextureAsset* assetData = SHAssetManager::GetTexture(assetId);
|
const SHTextureAsset* assetData = SHAssetManager::GetData<SHTextureAsset>(assetId);
|
||||||
if (assetData == nullptr)
|
if (assetData == nullptr)
|
||||||
{
|
{
|
||||||
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
|
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
|
||||||
|
@ -133,7 +134,7 @@ namespace SHADE
|
||||||
/* Query Functions */
|
/* Query Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static std::optional<AssetID> SHResourceManager::GetAssetID(Handle<T> handle)
|
std::optional<AssetID> SHResourceManager::GetAssetID(Handle<T> handle)
|
||||||
{
|
{
|
||||||
const Handle GENERIC_HANDLE = Handle(handle);
|
const Handle GENERIC_HANDLE = Handle(handle);
|
||||||
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<T>();
|
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<T>();
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||||
|
#include "Events/SHEventManager.hpp"
|
||||||
#include "Tools/SHLogger.h"
|
#include "Tools/SHLogger.h"
|
||||||
#include "Tools/SHException.h"
|
#include "Tools/SHException.h"
|
||||||
|
|
||||||
|
@ -317,6 +318,11 @@ namespace SHADE
|
||||||
if (parentNode == nullptr)
|
if (parentNode == nullptr)
|
||||||
{
|
{
|
||||||
SHLOG_WARNING("Removing Entity {}'s parent", entityID)
|
SHLOG_WARNING("Removing Entity {}'s parent", entityID)
|
||||||
|
|
||||||
|
if (parent)
|
||||||
|
parent->RemoveChild(this);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle self assignment
|
// Handle self assignment
|
||||||
|
@ -359,10 +365,19 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
|
|
||||||
|
const SHSceneGraphChangeParentEvent EVENT_DATA
|
||||||
|
{
|
||||||
|
.node = NODE_ITER->second
|
||||||
|
, .oldParent = NODE_ITER->second->GetParent()
|
||||||
|
, .newParent = parent ? parent : root
|
||||||
|
};
|
||||||
|
|
||||||
if (parent == nullptr)
|
if (parent == nullptr)
|
||||||
parent = root;
|
parent = root;
|
||||||
|
|
||||||
NODE_ITER->second->SetParent(parent);
|
NODE_ITER->second->SetParent(parent);
|
||||||
|
|
||||||
|
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept
|
void SHSceneGraph::SetParent(EntityID entityID, EntityID parent) const noexcept
|
||||||
|
@ -396,8 +411,17 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
|
|
||||||
|
const SHSceneGraphChangeParentEvent EVENT_DATA
|
||||||
|
{
|
||||||
|
.node = NODE_ITER->second
|
||||||
|
, .oldParent = NODE_ITER->second->GetParent()
|
||||||
|
, .newParent = PARENT_ITER->second
|
||||||
|
};
|
||||||
|
|
||||||
SHSceneNode* currentNode = NODE_ITER->second;
|
SHSceneNode* currentNode = NODE_ITER->second;
|
||||||
currentNode->SetParent(PARENT_ITER->second);
|
currentNode->SetParent(PARENT_ITER->second);
|
||||||
|
|
||||||
|
SHEventManager::BroadcastEvent<SHSceneGraphChangeParentEvent>(EVENT_DATA, SH_SCENEGRAPH_CHANGE_PARENT_EVENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -558,7 +582,7 @@ namespace SHADE
|
||||||
ReleaseNode(node);
|
ReleaseNode(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHSceneGraph::Traverse (const UnaryPredicate& predicate) const
|
void SHSceneGraph::Traverse (const UnaryFunction& predicate) const
|
||||||
{
|
{
|
||||||
TraverseAndInvokePredicate(root, predicate);
|
TraverseAndInvokePredicate(root, predicate);
|
||||||
}
|
}
|
||||||
|
@ -597,7 +621,7 @@ namespace SHADE
|
||||||
delete node;
|
delete node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHSceneGraph::TraverseAndInvokePredicate(const SHSceneNode* node, const UnaryPredicate& predicate)
|
void SHSceneGraph::TraverseAndInvokePredicate(const SHSceneNode* node, const UnaryFunction& predicate)
|
||||||
{
|
{
|
||||||
for (auto* child : node->children)
|
for (auto* child : node->children)
|
||||||
{
|
{
|
||||||
|
|
|
@ -97,9 +97,8 @@ namespace SHADE
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
using EntityNodeMap = std::unordered_map<EntityID, SHSceneNode*>;
|
using EntityNodeMap = std::unordered_map<EntityID, SHSceneNode*>;
|
||||||
|
using UnaryFunction = std::function<void(SHSceneNode*)>;
|
||||||
using UnaryPredicate = std::function<void(SHSceneNode*)>;
|
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -143,8 +142,7 @@ namespace SHADE
|
||||||
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
|
bool RemoveNode (SHSceneNode* nodeToRemove) noexcept;
|
||||||
void Reset () noexcept;
|
void Reset () noexcept;
|
||||||
|
|
||||||
void Traverse (const UnaryPredicate& predicate) const;
|
void Traverse (const UnaryFunction& predicate) const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -160,8 +158,14 @@ namespace SHADE
|
||||||
|
|
||||||
SHSceneNode* AllocateNode (EntityID entityID);
|
SHSceneNode* AllocateNode (EntityID entityID);
|
||||||
void ReleaseNode (SHSceneNode* node) noexcept;
|
void ReleaseNode (SHSceneNode* node) noexcept;
|
||||||
static void TraverseAndInvokePredicate (const SHSceneNode* node, const UnaryPredicate& predicate);
|
static void TraverseAndInvokePredicate (const SHSceneNode* node, const UnaryFunction& predicate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SHSceneGraphChangeParentEvent
|
||||||
|
{
|
||||||
|
SHSceneNode* node;
|
||||||
|
SHSceneNode* oldParent;
|
||||||
|
SHSceneNode* newParent;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -29,13 +29,21 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
GetNativeComponent()->SetLocalPosition(Convert::ToNative(val));
|
GetNativeComponent()->SetLocalPosition(Convert::ToNative(val));
|
||||||
}
|
}
|
||||||
Vector3 Transform::LocalRotation::get()
|
Quaternion Transform::LocalRotation::get()
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(GetNativeComponent()->GetLocalRotation());
|
return Convert::ToCLI(GetNativeComponent()->GetLocalOrientation());
|
||||||
}
|
}
|
||||||
void Transform::LocalRotation::set(Vector3 val)
|
void Transform::LocalRotation::set(Quaternion val)
|
||||||
{
|
{
|
||||||
GetNativeComponent()->SetLocalRotation(Convert::ToNative(val));
|
GetNativeComponent()->SetLocalOrientation(Convert::ToNative(val));
|
||||||
|
}
|
||||||
|
Vector3 Transform::LocalEulerAngles::get()
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(GetNativeComponent()->GetLocalRotation());
|
||||||
|
}
|
||||||
|
void Transform::LocalEulerAngles::set(Vector3 val)
|
||||||
|
{
|
||||||
|
GetNativeComponent()->SetLocalRotation(Convert::ToNative(val));
|
||||||
}
|
}
|
||||||
Vector3 Transform::LocalScale::get()
|
Vector3 Transform::LocalScale::get()
|
||||||
{
|
{
|
||||||
|
@ -54,13 +62,21 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
GetNativeComponent()->SetWorldPosition(Convert::ToNative(val));
|
GetNativeComponent()->SetWorldPosition(Convert::ToNative(val));
|
||||||
}
|
}
|
||||||
Vector3 Transform::GlobalRotation::get()
|
Quaternion Transform::GlobalRotation::get()
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(GetNativeComponent()->GetWorldRotation());
|
return Convert::ToCLI(GetNativeComponent()->GetLocalOrientation());
|
||||||
}
|
}
|
||||||
void Transform::GlobalRotation::set(Vector3 val)
|
void Transform::GlobalRotation::set(Quaternion val)
|
||||||
{
|
{
|
||||||
GetNativeComponent()->SetWorldRotation(Convert::ToNative(val));
|
GetNativeComponent()->SetWorldOrientation(Convert::ToNative(val));
|
||||||
|
}
|
||||||
|
Vector3 Transform::GlobalEulerAngles::get()
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(GetNativeComponent()->GetWorldRotation());
|
||||||
|
}
|
||||||
|
void Transform::GlobalEulerAngles::set(Vector3 val)
|
||||||
|
{
|
||||||
|
GetNativeComponent()->SetWorldRotation(Convert::ToNative(val));
|
||||||
}
|
}
|
||||||
Vector3 Transform::GlobalScale::get()
|
Vector3 Transform::GlobalScale::get()
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,14 +17,14 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Components/Component.hxx"
|
#include "Components/Component.hxx"
|
||||||
#include "Math/Vector3.hxx"
|
#include "Math/Vector3.hxx"
|
||||||
#include "Utility/Convert.hxx"
|
#include "Math/Quaternion.hxx"
|
||||||
// External Dependencies
|
// External Dependencies
|
||||||
#include "Math/Transform/SHTransformComponent.h"
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// CLR version of the the SHADE Engine's TransformComponent.
|
/// CLR version of the SHADE Engine's TransformComponent.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ref class Transform : public Component<SHTransformComponent>
|
public ref class Transform : public Component<SHTransformComponent>
|
||||||
{
|
{
|
||||||
|
@ -52,9 +52,17 @@ namespace SHADE
|
||||||
void set(Vector3 val);
|
void set(Vector3 val);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Local Z-axis rotation angle stored by this Transform in Radians.
|
/// Local rotation quaternion stored by this Transform.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
property Vector3 LocalRotation
|
property Quaternion LocalRotation
|
||||||
|
{
|
||||||
|
Quaternion get();
|
||||||
|
void set(Quaternion val);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Local euler angle rotations stored by this Transform.
|
||||||
|
/// </summary>
|
||||||
|
property Vector3 LocalEulerAngles
|
||||||
{
|
{
|
||||||
Vector3 get();
|
Vector3 get();
|
||||||
void set(Vector3 val);
|
void set(Vector3 val);
|
||||||
|
@ -76,16 +84,23 @@ namespace SHADE
|
||||||
void set(Vector3 val);
|
void set(Vector3 val);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Global Z-axis rotation angle stored by this Transform in Radians.
|
/// Global rotation quaternion stored by this Transform.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
property Vector3 GlobalRotation
|
property Quaternion GlobalRotation
|
||||||
|
{
|
||||||
|
Quaternion get();
|
||||||
|
void set(Quaternion val);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Global euler angle rotations stored by this Transform.
|
||||||
|
/// </summary>
|
||||||
|
property Vector3 GlobalEulerAngles
|
||||||
{
|
{
|
||||||
Vector3 get();
|
Vector3 get();
|
||||||
void set(Vector3 val);
|
void set(Vector3 val);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Global scale stored by this Transform.
|
/// Global scale stored by this Transform.
|
||||||
/// Note that this operation is expensive.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
property Vector3 GlobalScale
|
property Vector3 GlobalScale
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Utility Functions */
|
/* Utility Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
double Math::Wrap(double value, double min, double max)
|
float Math::Wrap(float value, float min, float max)
|
||||||
{
|
{
|
||||||
while (value < min)
|
while (value < min)
|
||||||
{
|
{
|
||||||
|
@ -33,24 +33,24 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
double Math::DegreesToRadians(double degrees)
|
float Math::DegreesToRadians(float degrees)
|
||||||
{
|
{
|
||||||
return degrees * Deg2Rad;
|
return degrees * Deg2Rad;
|
||||||
}
|
}
|
||||||
double Math::RadiansToDegrees(double radians)
|
float Math::RadiansToDegrees(float radians)
|
||||||
{
|
{
|
||||||
return radians * Rad2Deg;
|
return radians * Rad2Deg;
|
||||||
}
|
}
|
||||||
double Math::Lerp(double a, double b, double t)
|
float Math::Lerp(float a, float b, float t)
|
||||||
{
|
{
|
||||||
return LerpUnclamped(a, b, System::Math::Clamp(t, 0.0, 1.0));
|
return LerpUnclamped(a, b, System::Math::Clamp(t, 0.0f, 1.0f));
|
||||||
}
|
}
|
||||||
double Math::LerpUnclamped(double a, double b, double t)
|
float Math::LerpUnclamped(float a, float b, float t)
|
||||||
{
|
{
|
||||||
return a + t * (b - a);
|
return a + t * (b - a);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Math::InverseLerp(double a, double b, double value)
|
float Math::InverseLerp(float a, float b, float value)
|
||||||
{
|
{
|
||||||
return (value - a) / (b - a);
|
return (value - a) / (b - a);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,11 @@ namespace SHADE
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Degrees-to-radians conversion constant
|
/// Degrees-to-radians conversion constant
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static constexpr double Deg2Rad = System::Math::PI / 180.0;
|
static constexpr float Deg2Rad = System::Math::PI / 180.0f;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Radians-to-degrees conversion constant
|
/// Radians-to-degrees conversion constant
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static constexpr double Rad2Deg = 180.0 / System::Math::PI;
|
static constexpr float Rad2Deg = 180.0f / System::Math::PI;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Small value used for single precision floating point comparisons.
|
/// Small value used for single precision floating point comparisons.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -47,28 +47,28 @@ namespace SHADE
|
||||||
/// <param name="min">Minimum value to wrap at.</param>
|
/// <param name="min">Minimum value to wrap at.</param>
|
||||||
/// <param name="max">Maximum value to wrap at.</param>
|
/// <param name="max">Maximum value to wrap at.</param>
|
||||||
/// <returns>Wrapped value.</returns>
|
/// <returns>Wrapped value.</returns>
|
||||||
static double Wrap(double value, double min, double max);
|
static float Wrap(float value, float min, float max);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts an angle from degree representation to radian representation.
|
/// Converts an angle from degree representation to radian representation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="degrees">Degree-based angle to convert.</param>
|
/// <param name="degrees">Degree-based angle to convert.</param>
|
||||||
/// <returns>The specified angle in radians.</returns>
|
/// <returns>The specified angle in radians.</returns>
|
||||||
static double DegreesToRadians(double degrees);
|
static float DegreesToRadians(float degrees);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts an angle from radian representation to degree representation.
|
/// Converts an angle from radian representation to degree representation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="radians">Radian-based angle to convert.</param>
|
/// <param name="radians">Radian-based angle to convert.</param>
|
||||||
/// <returns>The specified angle in degrees.</returns>
|
/// <returns>The specified angle in degrees.</returns>
|
||||||
static double RadiansToDegrees(double radians);
|
static float RadiansToDegrees(float radians);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Linearly interpolates between a and b by t.
|
/// Linearly interpolates between a and b by t.
|
||||||
/// The parameter t is clamped to the range [0, 1].
|
/// The parameter t is clamped to the range [0, 1].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="a">The start value.</param>
|
/// <param name="a">The start value.</param>
|
||||||
/// <param name="b">The end value.</param>
|
/// <param name="b">The end value.</param>
|
||||||
/// <param name="t">The interpolation value between the two double.</param>
|
/// <param name="t">The interpolation value between the two float.</param>
|
||||||
/// <returns>The interpolated double result between the two double values.</returns>
|
/// <returns>The interpolated float result between the two float values.</returns>
|
||||||
static double Lerp(double a, double b, double t);
|
static float Lerp(float a, float b, float t);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Linearly interpolates between a and b by t.
|
/// Linearly interpolates between a and b by t.
|
||||||
/// The parameter t is not clamped and a value based on a and b is supported.
|
/// The parameter t is not clamped and a value based on a and b is supported.
|
||||||
|
@ -77,9 +77,9 @@ namespace SHADE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="a">The start value.</param>
|
/// <param name="a">The start value.</param>
|
||||||
/// <param name="b">The end value.</param>
|
/// <param name="b">The end value.</param>
|
||||||
/// <param name="t">The interpolation value between the two double.</param>
|
/// <param name="t">The interpolation value between the two float.</param>
|
||||||
/// <returns>The interpolated double result between the two double values.</returns>
|
/// <returns>The interpolated float result between the two float values.</returns>
|
||||||
static double LerpUnclamped(double a, double b, double t);
|
static float LerpUnclamped(float a, float b, float t);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the linear parameter t that produces the interpolant value within the range [a, b].
|
/// Calculates the linear parameter t that produces the interpolant value within the range [a, b].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -87,6 +87,6 @@ namespace SHADE
|
||||||
/// <param name="b">End value.</param>
|
/// <param name="b">End value.</param>
|
||||||
/// <param name="value">Value between start and end.</param>
|
/// <param name="value">Value between start and end.</param>
|
||||||
/// <returns>Percentage of value between start and end.</returns>
|
/// <returns>Percentage of value between start and end.</returns>
|
||||||
static double InverseLerp(double a, double b, double value);
|
static float InverseLerp(float a, float b, float value);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Quaternion.cxx
|
||||||
|
\author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
\par email: diren.dbharwani\@digipen.edu
|
||||||
|
\date Oct 23, 2022
|
||||||
|
\brief Contains the definitions of functions in the Quaternion struct.
|
||||||
|
|
||||||
|
Note: This file is written in C++17/CLI.
|
||||||
|
|
||||||
|
Copyright (C) 2021 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
|
||||||
|
// Precompiled Headers
|
||||||
|
#include "SHpch.h"
|
||||||
|
// Primary Header
|
||||||
|
#include "Quaternion.hxx"
|
||||||
|
// External Dependencies
|
||||||
|
#include "Math/SHQuaternion.h"
|
||||||
|
#include "Math/Vector/SHVec4.h"
|
||||||
|
// Project Headers
|
||||||
|
#include "Utility/Convert.hxx"
|
||||||
|
#include "Math.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
Quaternion::Quaternion(float _x, float _y, float _z, float _w)
|
||||||
|
: x { _x }
|
||||||
|
, y { _y }
|
||||||
|
, z { _z }
|
||||||
|
, w { _w }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void Quaternion::SetFromToRotation(Vector3 fromDirection, Vector3 toDirection)
|
||||||
|
{
|
||||||
|
const SHQuaternion R = SHQuaternion::FromToRotation(Convert::ToNative(fromDirection), Convert::ToNative(toDirection));
|
||||||
|
*this = Convert::ToCLI(R);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Quaternion::SetLookRotation(Vector3 view, Vector3 up)
|
||||||
|
{
|
||||||
|
const SHQuaternion R = SHQuaternion::LookRotation(Convert::ToNative(view), Convert::ToNative(up));
|
||||||
|
*this = Convert::ToCLI(R);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Quaternion::ToAngleAxis(float^% angle, Vector3^% axis)
|
||||||
|
{
|
||||||
|
const SHVec4 NATIVE_AXIS_ANGLE = Convert::ToNative(*this).GetAxisAngle();
|
||||||
|
axis = Convert::ToCLI(NATIVE_AXIS_ANGLE.ToVec3());
|
||||||
|
angle = NATIVE_AXIS_ANGLE.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
System::String^ Quaternion::ToString()
|
||||||
|
{
|
||||||
|
return ValueType::ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* IEquatable */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool Quaternion::Equals(Quaternion other)
|
||||||
|
{
|
||||||
|
const float DOT = Dot(*this, other);
|
||||||
|
return fabs(1.0f - DOT) <= Math::Epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Object Overrides */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool Quaternion::Equals(Object^ o)
|
||||||
|
{
|
||||||
|
return ValueType::Equals(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Quaternion::GetHashCode()
|
||||||
|
{
|
||||||
|
return ValueType::GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Static Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
float Quaternion::Angle(Quaternion a, Quaternion b)
|
||||||
|
{
|
||||||
|
return SHQuaternion::Angle(Convert::ToNative(a), Convert::ToNative(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::AngleAxis(float angle, Vector3 axis)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(SHQuaternion::FromAxisAngle(Convert::ToNative(axis), angle));
|
||||||
|
}
|
||||||
|
|
||||||
|
float Quaternion::Dot(Quaternion a, Quaternion b)
|
||||||
|
{
|
||||||
|
return (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::Euler(float _x, float _y, float _z)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(SHQuaternion::FromPitchYawRoll(_x, _y, _z));
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::FromToRotation(Vector3 fromDirection, Vector3 toDirection)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(SHQuaternion::FromToRotation(Convert::ToNative(fromDirection), Convert::ToNative(toDirection)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::Inverse(Quaternion rotation)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(SHQuaternion::Inverse(Convert::ToNative(rotation)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::Lerp(Quaternion a, Quaternion b, float t)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(SHQuaternion::ClampedLerp(Convert::ToNative(a), Convert::ToNative(b), t));
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::LerpUnclamped(Quaternion a, Quaternion b, float t)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(SHQuaternion::Lerp(Convert::ToNative(a), Convert::ToNative(b), t));
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::LookRotation(Vector3 forward, Vector3 upwards)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(SHQuaternion::LookRotation(Convert::ToNative(forward), Convert::ToNative(upwards)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::Normalize(Quaternion q)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(SHQuaternion::Normalise(Convert::ToNative(q)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(SHQuaternion::RotateTowards(Convert::ToNative(from), Convert::ToNative(to), Math::DegreesToRadians(maxDegreesDelta)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::Slerp(Quaternion a, Quaternion b, float t)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(SHQuaternion::ClampedSlerp(Convert::ToNative(a), Convert::ToNative(b), t));
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Quaternion::SlerpUnclamped(Quaternion a, Quaternion b, float t)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(SHQuaternion::Slerp(Convert::ToNative(a), Convert::ToNative(b), t));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Quaternion Quaternion::operator*(Quaternion lhs, Quaternion rhs)
|
||||||
|
{
|
||||||
|
return Convert::ToCLI(Convert::ToNative(lhs) * Convert::ToNative(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Quaternion::operator==(Quaternion lhs, Quaternion rhs)
|
||||||
|
{
|
||||||
|
return lhs.Equals(rhs);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,237 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file Quaternion.hxx
|
||||||
|
\author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
\par email: diren.dbharwani\@digipen.edu
|
||||||
|
\date Oct 23, 2022
|
||||||
|
\brief Contains the definitions of Quaternion struct.
|
||||||
|
|
||||||
|
Note: This file is written in C++17/CLI.
|
||||||
|
|
||||||
|
Copyright (C) 2021 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Standard Libraries
|
||||||
|
#include <limits>
|
||||||
|
// Project Includes
|
||||||
|
#include "Vector3.hxx"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
///<summary>
|
||||||
|
/// CLR version of SHADE's Quaternion class that represents an orientation.
|
||||||
|
/// Designed to closely match Unity's Quaternion struct.
|
||||||
|
/// </summary>
|
||||||
|
[System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)]
|
||||||
|
public value struct Quaternion : public System::IEquatable<Quaternion>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constants */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
#pragma region Constants
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// Shorthand for writing Quaternion(0, 0, 0, 1).
|
||||||
|
///</summary>
|
||||||
|
static initonly Quaternion Identity = Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Public Members */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
///<summary>
|
||||||
|
/// X-component of the Quaternion.
|
||||||
|
/// Don't modify this directly unless you know quaternions inside out.
|
||||||
|
///</summary>
|
||||||
|
float x;
|
||||||
|
///<summary>
|
||||||
|
/// Y-component of the Quaternion.
|
||||||
|
/// Don't modify this directly unless you know quaternions inside out.
|
||||||
|
///</summary>
|
||||||
|
float y;
|
||||||
|
///<summary>
|
||||||
|
/// Z-component of the Quaternion.
|
||||||
|
/// Don't modify this directly unless you know quaternions inside out.
|
||||||
|
///</summary>
|
||||||
|
float z;
|
||||||
|
///<summary>
|
||||||
|
/// W-component of the Quaternion. Do not directly modify quaternions.
|
||||||
|
///</summary>
|
||||||
|
float w;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Constructors */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor to construct a Quaternion with the specified components.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="_x">X-coordinate to set.</param>
|
||||||
|
/// <param name="_y">Y-coordinate to set.</param>
|
||||||
|
/// <param name="_z">Z-coordinate to set.</param>
|
||||||
|
/// <param name="_z">W-coordinate to set.</param>
|
||||||
|
Quaternion(float _x, float _y, float _z, float _w);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a rotation which rotates from fromDirection to toDirection. <br/>
|
||||||
|
/// Use this to create a rotation which starts at the first Vector (fromDirection) and rotates to the second Vector (toDirection).
|
||||||
|
/// These Vectors must be set up in a script.
|
||||||
|
/// </summary>
|
||||||
|
void SetFromToRotation(Vector3 fromDirection, Vector3 toDirection);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a rotation with the specified forward and upwards directions. <br/>
|
||||||
|
/// The result is applied to this quaternion.
|
||||||
|
/// If used to orient a Transform, the Z axis will be aligned with forward and the Y axis with upwards, assuming these vectors are orthogonal.
|
||||||
|
/// Logs an error if the forward direction is zero.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="view">The direction to look in.</param>
|
||||||
|
/// <param name="up">The vector that defines in which direction up is.</param>
|
||||||
|
void SetLookRotation(Vector3 view, Vector3 up);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a rotation to angle-axis representation (angles in degrees).
|
||||||
|
/// </summary>
|
||||||
|
void ToAngleAxis(float^% angle, Vector3^% axis);
|
||||||
|
|
||||||
|
System::String^ ToString() override;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* IEquatable */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares equality with an object of the same type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">The object to compare with.</param>
|
||||||
|
/// <returns>True if both objects are the same.</returns>
|
||||||
|
virtual bool Equals(Quaternion other);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Object */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares equality with another unboxed object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="o">The unboxed object to compare with.</param>
|
||||||
|
/// <returns>True if both objects are the same.</returns>
|
||||||
|
bool Equals(Object^ o) override;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a unique hash for this object.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Unique hash for this object.</returns>
|
||||||
|
int GetHashCode() override;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Static Functions */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the angle in degrees between two rotations a and b.<br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The angle in degrees between the two vectors. </returns>
|
||||||
|
static float Angle(Quaternion a, Quaternion b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a rotation which rotates angle degrees around axis.
|
||||||
|
/// </summary>
|
||||||
|
static Quaternion AngleAxis(float angle, Vector3 axis);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The dot product between two rotations.
|
||||||
|
/// </summary>
|
||||||
|
static float Dot(Quaternion a, Quaternion b);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a rotation that rotates y degrees around the y axis, x degrees around the x axis, and z degrees around the z axis; applied in that order.
|
||||||
|
/// </summary>
|
||||||
|
static Quaternion Euler(float _x, float _y, float _z);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a rotation which rotates from fromDirection to toDirection.
|
||||||
|
/// </summary>
|
||||||
|
static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the Inverse of rotation.
|
||||||
|
/// </summary>
|
||||||
|
static Quaternion Inverse(Quaternion rotation);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interpolates between a and b by t and normalizes the result afterwards. The parameter t is clamped to the range [0, 1].
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">Start value, returned when t = 0.</param>
|
||||||
|
/// <param name="b">End value, returned when t = 1.</param>
|
||||||
|
/// <param name="t">Interpolation ratio.</param>
|
||||||
|
/// <returns> A quaternion interpolated between quaternions a and b.</returns>
|
||||||
|
static Quaternion Lerp(Quaternion a, Quaternion b, float t);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interpolates between a and b by t and normalizes the result afterwards. The parameter t is not clamped.
|
||||||
|
/// </summary>
|
||||||
|
static Quaternion LerpUnclamped(Quaternion a, Quaternion b, float t);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a rotation with the specified forward and upwards directions. <br/>
|
||||||
|
/// Z axis will be aligned with forward, X axis aligned with cross product between forward and upwards, and Y axis aligned with cross product between Z and X.
|
||||||
|
/// </summary>
|
||||||
|
static Quaternion LookRotation(Vector3 forward, Vector3 upwards);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts this quaternion to one with the same orientation but with a magnitude of 1.
|
||||||
|
/// </summary>
|
||||||
|
static Quaternion Normalize(Quaternion q);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rotates a rotation from towards to. <br/>
|
||||||
|
/// The from quaternion is rotated towards to by an angular step of maxDegreesDelta (but note that the rotation will not overshoot).
|
||||||
|
/// Negative values of maxDegreesDelta will move away from to until the rotation is exactly the opposite direction.
|
||||||
|
/// </summary>
|
||||||
|
static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Spherically interpolates between quaternions a and b by ratio t. The parameter t is clamped to the range [0, 1].
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a">Start value, returned when t = 0.</param>
|
||||||
|
/// <param name="b">End value, returned when t = 1.</param>
|
||||||
|
/// <param name="t">Interpolation ratio.</param>
|
||||||
|
/// <returns> A quaternion spherically interpolated between quaternions a and b.</returns>
|
||||||
|
static Quaternion Slerp(Quaternion a, Quaternion b, float t);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Spherically interpolates between a and b by t. The parameter t is not clamped.
|
||||||
|
/// </summary>
|
||||||
|
static Quaternion SlerpUnclamped(Quaternion a, Quaternion b, float t);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
/* Overloaded Operators */
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Combines rotations lhs and rhs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Left-hand side quaternion.</param>
|
||||||
|
/// <param name="rhs">Right-hand side quaternion.</param>
|
||||||
|
static Quaternion operator*(Quaternion lhs, Quaternion rhs);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Are two quaternions equal to each other?
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lhs">Left-hand side quaternion.</param>
|
||||||
|
/// <param name="rhs">Right-hand side quaternion.</param>
|
||||||
|
static bool operator==(Quaternion lhs, Quaternion rhs);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -26,10 +26,10 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
Vector2::Vector2(double _x)
|
Vector2::Vector2(float _x)
|
||||||
: Vector2 { _x, 0.0 }
|
: Vector2 { _x, 0.0f }
|
||||||
{}
|
{}
|
||||||
Vector2::Vector2(double _x, double _y)
|
Vector2::Vector2(float _x, float _y)
|
||||||
: x { _x }
|
: x { _x }
|
||||||
, y { _y }
|
, y { _y }
|
||||||
{}
|
{}
|
||||||
|
@ -47,22 +47,22 @@ namespace SHADE
|
||||||
return *this / GetMagnitude();
|
return *this / GetMagnitude();
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector2::GetMagnitude()
|
float Vector2::GetMagnitude()
|
||||||
{
|
{
|
||||||
return sqrt(x * x + y * y);
|
return sqrt(x * x + y * y);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector2::GetSqrMagnitude()
|
float Vector2::GetSqrMagnitude()
|
||||||
{
|
{
|
||||||
return x * x + y * y;
|
return x * x + y * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector2::AngleFromRightRadians()
|
float Vector2::AngleFromRightRadians()
|
||||||
{
|
{
|
||||||
return atan2(y, x);
|
return atan2(y, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector2::AngleFromRightDegrees()
|
float Vector2::AngleFromRightDegrees()
|
||||||
{
|
{
|
||||||
return Math::RadiansToDegrees(AngleFromRightRadians());
|
return Math::RadiansToDegrees(AngleFromRightRadians());
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ namespace SHADE
|
||||||
return IsNearPoint(point, Math::Epsilon);
|
return IsNearPoint(point, Math::Epsilon);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Vector2::IsNearPoint(Vector2 point, double tolerance)
|
bool Vector2::IsNearPoint(Vector2 point, float tolerance)
|
||||||
{
|
{
|
||||||
return (*this - point).GetSqrMagnitude() < (tolerance * tolerance);
|
return (*this - point).GetSqrMagnitude() < (tolerance * tolerance);
|
||||||
}
|
}
|
||||||
|
@ -113,13 +113,13 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
return IsNear(lhs, rhs, Math::Epsilon);
|
return IsNear(lhs, rhs, Math::Epsilon);
|
||||||
}
|
}
|
||||||
bool Vector2::IsNear(Vector2 lhs, Vector2 rhs, double tolerance)
|
bool Vector2::IsNear(Vector2 lhs, Vector2 rhs, float tolerance)
|
||||||
{
|
{
|
||||||
return (std::abs(lhs.x) - std::abs(rhs.x)) < tolerance
|
return (std::abs(lhs.x) - std::abs(rhs.x)) < tolerance
|
||||||
&&
|
&&
|
||||||
(std::abs(lhs.y) - std::abs(rhs.y)) < tolerance;
|
(std::abs(lhs.y) - std::abs(rhs.y)) < tolerance;
|
||||||
}
|
}
|
||||||
double Vector2::Dot(Vector2 lhs, Vector2 rhs)
|
float Vector2::Dot(Vector2 lhs, Vector2 rhs)
|
||||||
{
|
{
|
||||||
return lhs.x * rhs.x + lhs.y * rhs.y;
|
return lhs.x * rhs.x + lhs.y * rhs.y;
|
||||||
}
|
}
|
||||||
|
@ -153,12 +153,12 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
Vector2 Vector2::Reflect(Vector2 vec, Vector2 normal)
|
Vector2 Vector2::Reflect(Vector2 vec, Vector2 normal)
|
||||||
{
|
{
|
||||||
return vec - (Project(vec, normal.GetNormalised()) * 2.0);
|
return vec - (Project(vec, normal.GetNormalised()) * 2.0f);
|
||||||
}
|
}
|
||||||
Vector2 Vector2::RotateRadians(Vector2 vec, double radians)
|
Vector2 Vector2::RotateRadians(Vector2 vec, float radians)
|
||||||
{
|
{
|
||||||
const double SINE = sin(radians);
|
const float SINE = sin(radians);
|
||||||
const double COSINE = cos(radians);
|
const float COSINE = cos(radians);
|
||||||
|
|
||||||
return Vector2
|
return Vector2
|
||||||
(
|
(
|
||||||
|
@ -166,35 +166,35 @@ namespace SHADE
|
||||||
vec.x * SINE + vec.y * COSINE
|
vec.x * SINE + vec.y * COSINE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Vector2 Vector2::RotateDegrees(Vector2 vec, double degrees)
|
Vector2 Vector2::RotateDegrees(Vector2 vec, float degrees)
|
||||||
{
|
{
|
||||||
return RotateRadians(vec, Math::DegreesToRadians(degrees));
|
return RotateRadians(vec, Math::DegreesToRadians(degrees));
|
||||||
}
|
}
|
||||||
Vector2 Vector2::Min(Vector2 lhs, Vector2 rhs)
|
Vector2 Vector2::Min(Vector2 lhs, Vector2 rhs)
|
||||||
{
|
{
|
||||||
double lx = lhs.x, rx = rhs.x;
|
float lx = lhs.x, rx = rhs.x;
|
||||||
double ly = lhs.y, ry = rhs.y;
|
float ly = lhs.y, ry = rhs.y;
|
||||||
|
|
||||||
return Vector2(std::min(lx, rx),
|
return Vector2(std::min(lx, rx),
|
||||||
std::min(ly, ry));
|
std::min(ly, ry));
|
||||||
}
|
}
|
||||||
Vector2 Vector2::Max(Vector2 lhs, Vector2 rhs)
|
Vector2 Vector2::Max(Vector2 lhs, Vector2 rhs)
|
||||||
{
|
{
|
||||||
double lx = lhs.x, rx = rhs.x;
|
float lx = lhs.x, rx = rhs.x;
|
||||||
double ly = lhs.y, ry = rhs.y;
|
float ly = lhs.y, ry = rhs.y;
|
||||||
|
|
||||||
return Vector2(std::max(lx, rx),
|
return Vector2(std::max(lx, rx),
|
||||||
std::max(ly, ry));
|
std::max(ly, ry));
|
||||||
}
|
}
|
||||||
Vector2 Vector2::Lerp(Vector2 a, Vector2 b, double t)
|
Vector2 Vector2::Lerp(Vector2 a, Vector2 b, float t)
|
||||||
{
|
{
|
||||||
return LerpUnclamped(a, b, std::clamp(t, 0.0, 1.0));
|
return LerpUnclamped(a, b, std::clamp(t, 0.0f, 1.0f));
|
||||||
}
|
}
|
||||||
Vector2 Vector2::LerpUnclamped(Vector2 a, Vector2 b, double t)
|
Vector2 Vector2::LerpUnclamped(Vector2 a, Vector2 b, float t)
|
||||||
{
|
{
|
||||||
return a + ((b - a) * t);
|
return a + ((b - a) * t);
|
||||||
}
|
}
|
||||||
Vector2 Vector2::MoveTowards(Vector2 current, Vector2 target, double maxDistanceDelta)
|
Vector2 Vector2::MoveTowards(Vector2 current, Vector2 target, float maxDistanceDelta)
|
||||||
{
|
{
|
||||||
// Ignore if it is exactly on the same point
|
// Ignore if it is exactly on the same point
|
||||||
if (current == target)
|
if (current == target)
|
||||||
|
@ -206,7 +206,7 @@ namespace SHADE
|
||||||
|
|
||||||
// Check if check if is behind or ahead of target
|
// Check if check if is behind or ahead of target
|
||||||
Vector2 DIFF = target - newPos;
|
Vector2 DIFF = target - newPos;
|
||||||
if (Dot(DELTA, DIFF) < 0.0)
|
if (Dot(DELTA, DIFF) < 0.0f)
|
||||||
{
|
{
|
||||||
newPos = target;
|
newPos = target;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +236,7 @@ namespace SHADE
|
||||||
lhs.y * rhs.y
|
lhs.y * rhs.y
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Vector2 Vector2::operator*(Vector2 lhs, double rhs)
|
Vector2 Vector2::operator*(Vector2 lhs, float rhs)
|
||||||
{
|
{
|
||||||
return Vector2
|
return Vector2
|
||||||
(
|
(
|
||||||
|
@ -244,7 +244,7 @@ namespace SHADE
|
||||||
lhs.y * rhs
|
lhs.y * rhs
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Vector2 Vector2::operator/(Vector2 lhs, double rhs)
|
Vector2 Vector2::operator/(Vector2 lhs, float rhs)
|
||||||
{
|
{
|
||||||
return Vector2
|
return Vector2
|
||||||
(
|
(
|
||||||
|
|
|
@ -19,8 +19,8 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
///<summary>
|
///<summary>
|
||||||
/// CLR version of the the SHADE Engine's Vector2 class that represents a
|
/// CLR version of SHADE Engine's Vector2 class that represents a 2-Dimensional Vector.
|
||||||
/// 2-Dimensional Vector. Designed to closely match Unity's Vector2 struct.
|
/// Designed to closely match Unity's Vector2 struct.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)]
|
[System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)]
|
||||||
public value struct Vector2 : public System::IEquatable<Vector2>
|
public value struct Vector2 : public System::IEquatable<Vector2>
|
||||||
|
@ -33,37 +33,37 @@ namespace SHADE
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector2(0, -1).
|
/// Shorthand for writing Vector2(0, -1).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector2 Down = Vector2(0.0, -1.0);
|
static initonly Vector2 Down = Vector2(0.0f, -1.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector2(-1, 0).
|
/// Shorthand for writing Vector2(-1, 0).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector2 Left = Vector2(-1.0, 0.0);
|
static initonly Vector2 Left = Vector2(-1.0f, 0.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector2(double.NegativeInfinity,
|
/// Shorthand for writing Vector2(float.NegativeInfinity,
|
||||||
/// double.NegativeInfinity).
|
/// float.NegativeInfinity).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector2 NegativeInfinity = Vector2(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest());
|
static initonly Vector2 NegativeInfinity = Vector2(std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest());
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector2(1, 1).
|
/// Shorthand for writing Vector2(1, 1).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector2 One = Vector2(1.0, 1.0);
|
static initonly Vector2 One = Vector2(1.0f, 1.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector2(double.PositiveInfinity,
|
/// Shorthand for writing Vector2(float.PositiveInfinity,
|
||||||
/// double.PositiveInfinity).
|
/// float.PositiveInfinity).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector2 PositiveInfinity = Vector2(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
|
static initonly Vector2 PositiveInfinity = Vector2(std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector2(1, 0).
|
/// Shorthand for writing Vector2(1, 0).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector2 Right = Vector2(1.0, 0.0);
|
static initonly Vector2 Right = Vector2(1.0f, 0.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector2(0, 1).
|
/// Shorthand for writing Vector2(0, 1).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector2 Up = Vector2(0.0, 1.0);
|
static initonly Vector2 Up = Vector2(0.0f, 1.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector2(0, 0).
|
/// Shorthand for writing Vector2(0, 0).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector2 Zero = Vector2(0.0, 0.0);
|
static initonly Vector2 Zero = Vector2(0.0f, 0.0f);
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
@ -72,27 +72,27 @@ namespace SHADE
|
||||||
///<summary>
|
///<summary>
|
||||||
/// X-component of the Vector2.
|
/// X-component of the Vector2.
|
||||||
///</summary>
|
///</summary>
|
||||||
double x;
|
float x;
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Y-component of the Vector2.
|
/// Y-component of the Vector2.
|
||||||
///</summary>
|
///</summary>
|
||||||
double y;
|
float y;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor to construct a Vector2 with the specified components with the
|
/// Constructor to construct a Vector2 with the specified components with the
|
||||||
/// Y-component set to 0.0.
|
/// Y-component set to 0.0f.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="_x">X-coordinate to set.</param>
|
/// <param name="_x">X-coordinate to set.</param>
|
||||||
Vector2(double _x);
|
Vector2(float _x);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor to construct a Vector2 with the specified components..
|
/// Constructor to construct a Vector2 with the specified components..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="_x">X-coordinate to set.</param>
|
/// <param name="_x">X-coordinate to set.</param>
|
||||||
/// <param name="_y">Y-coordinate to set.</param>
|
/// <param name="_y">Y-coordinate to set.</param>
|
||||||
Vector2(double _x, double _y);
|
Vector2(float _x, float _y);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Usage Functions */
|
/* Usage Functions */
|
||||||
|
@ -117,24 +117,24 @@ namespace SHADE
|
||||||
/// need the precise magnitude, consider using GetSqrMagnitude() instead.
|
/// need the precise magnitude, consider using GetSqrMagnitude() instead.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns the length of this Vector2.</returns>
|
/// <returns>Returns the length of this Vector2.</returns>
|
||||||
double GetMagnitude();
|
float GetMagnitude();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates and returns the squared magnitude of this Vector2.
|
/// Calculates and returns the squared magnitude of this Vector2.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns the squared length of this Vector2.</returns>
|
/// <returns>Returns the squared length of this Vector2.</returns>
|
||||||
double GetSqrMagnitude();
|
float GetSqrMagnitude();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates and returns the angle of this vector from the right vector. This
|
/// Calculates and returns the angle of this vector from the right vector. This
|
||||||
/// function returns values between -Math.PI and Math.PI.
|
/// function returns values between -Math.PI and Math.PI.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns the angle of this vector from the right vector in radians.</returns>
|
/// <returns>Returns the angle of this vector from the right vector in radians.</returns>
|
||||||
double AngleFromRightRadians();
|
float AngleFromRightRadians();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates and returns the angle of this vector from the right vector. This
|
/// Calculates and returns the angle of this vector from the right vector. This
|
||||||
/// function returns values between -180.0 and 180.0.
|
/// function returns values between -180.0f and 180.0f.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns the angle of this vector from the right vector in degrees.</returns>
|
/// <returns>Returns the angle of this vector from the right vector in degrees.</returns>
|
||||||
double AngleFromRightDegrees();
|
float AngleFromRightDegrees();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if a specified point is near this Vector2 that represents a point with
|
/// Checks if a specified point is near this Vector2 that represents a point with
|
||||||
/// a tolerance value of PLS_EPSILON.
|
/// a tolerance value of PLS_EPSILON.
|
||||||
|
@ -156,7 +156,7 @@ namespace SHADE
|
||||||
/// True if this Vector2 representing a point and the specified point are within
|
/// True if this Vector2 representing a point and the specified point are within
|
||||||
/// the range of the specified tolerance. False otherwise.
|
/// the range of the specified tolerance. False otherwise.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
bool IsNearPoint(Vector2 point, double tolerance);
|
bool IsNearPoint(Vector2 point, float tolerance);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* IEquatable */
|
/* IEquatable */
|
||||||
|
@ -206,7 +206,7 @@ namespace SHADE
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// True if the two Vector2s are within the tolerance value specified
|
/// True if the two Vector2s are within the tolerance value specified
|
||||||
/// </returns>
|
/// </returns>
|
||||||
static bool IsNear(Vector2 lhs, Vector2 rhs, double tolerance);
|
static bool IsNear(Vector2 lhs, Vector2 rhs, float tolerance);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes and returns the dot product of 2 specified Vector2s.
|
/// Computes and returns the dot product of 2 specified Vector2s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -215,7 +215,7 @@ namespace SHADE
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// Scalar value representing the dot product of the two Vector2s.
|
/// Scalar value representing the dot product of the two Vector2s.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
static double Dot(Vector2 lhs, Vector2 rhs);
|
static float Dot(Vector2 lhs, Vector2 rhs);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the inward perpendicular Vector2 to the specified Vector2.
|
/// Computes the inward perpendicular Vector2 to the specified Vector2.
|
||||||
/// Equivalent to calling Perpendicular(lhs, true). This means, the
|
/// Equivalent to calling Perpendicular(lhs, true). This means, the
|
||||||
|
@ -260,7 +260,7 @@ namespace SHADE
|
||||||
/// Angle to rotate the vector by in an anti-clockwise direction in radians.
|
/// Angle to rotate the vector by in an anti-clockwise direction in radians.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>The Vector2 that represents the rotated vector.</returns>
|
/// <returns>The Vector2 that represents the rotated vector.</returns>
|
||||||
static Vector2 RotateRadians(Vector2 vec, double radians);
|
static Vector2 RotateRadians(Vector2 vec, float radians);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rotates a Vector2 on the Z-axis by a specified angle in an anti-clockwise
|
/// Rotates a Vector2 on the Z-axis by a specified angle in an anti-clockwise
|
||||||
/// direction.
|
/// direction.
|
||||||
|
@ -270,7 +270,7 @@ namespace SHADE
|
||||||
/// Angle to rotate the vector by in an anti-clockwise direction in degrees.
|
/// Angle to rotate the vector by in an anti-clockwise direction in degrees.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>The Vector2 that represents the rotated vector.</returns>
|
/// <returns>The Vector2 that represents the rotated vector.</returns>
|
||||||
static Vector2 RotateDegrees(Vector2 vec, double degrees);
|
static Vector2 RotateDegrees(Vector2 vec, float degrees);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes and returns a Vector2 that is made from the smallest components of
|
/// Computes and returns a Vector2 that is made from the smallest components of
|
||||||
/// the two specified Vector2s.
|
/// the two specified Vector2s.
|
||||||
|
@ -298,25 +298,25 @@ namespace SHADE
|
||||||
/// This is most commonly used to find a point some fraction of the way along a
|
/// This is most commonly used to find a point some fraction of the way along a
|
||||||
/// line between two endpoints.
|
/// line between two endpoints.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="a">The start Vector2, returned when t = 0.0.</param>
|
/// <param name="a">The start Vector2, returned when t = 0.0f.</param>
|
||||||
/// <param name="b">The end Vector2, returned when t = 1.0.</param>
|
/// <param name="b">The end Vector2, returned when t = 1.0f.</param>
|
||||||
/// <param name="t">
|
/// <param name="t">
|
||||||
/// Value used to interpolate between a and b which is clamped to
|
/// Value used to interpolate between a and b which is clamped to
|
||||||
/// the range[0, 1].
|
/// the range[0, 1].
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>The interpolated Vector2.</returns>
|
/// <returns>The interpolated Vector2.</returns>
|
||||||
static Vector2 Lerp(Vector2 a, Vector2 b, double t);
|
static Vector2 Lerp(Vector2 a, Vector2 b, float t);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Linearly interpolates between two specified points.
|
/// Linearly interpolates between two specified points.
|
||||||
/// This is most commonly used to find a point some fraction of the way along a
|
/// This is most commonly used to find a point some fraction of the way along a
|
||||||
/// line between two endpoints.
|
/// line between two endpoints.
|
||||||
/// Unlike Lerp(), t is not clamped to a range at all.
|
/// Unlike Lerp(), t is not clamped to a range at all.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="a">The start Vector2, returned when t = 0.0.</param>
|
/// <param name="a">The start Vector2, returned when t = 0.0f.</param>
|
||||||
/// <param name="b">The end Vector2, returned when t = 1.0.</param>
|
/// <param name="b">The end Vector2, returned when t = 1.0f.</param>
|
||||||
/// <param name="t">Value used to interpolate between a and b.</param>
|
/// <param name="t">Value used to interpolate between a and b.</param>
|
||||||
/// <returns>The interpolated Vector2.</returns>
|
/// <returns>The interpolated Vector2.</returns>
|
||||||
static Vector2 LerpUnclamped(Vector2 a, Vector2 b, double t);
|
static Vector2 LerpUnclamped(Vector2 a, Vector2 b, float t);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Moves a point current towards target.
|
/// Moves a point current towards target.
|
||||||
/// Similar to Lerp(), however, the function will ensure that the distance never
|
/// Similar to Lerp(), however, the function will ensure that the distance never
|
||||||
|
@ -327,7 +327,7 @@ namespace SHADE
|
||||||
/// <param name="target">The target position to move to.</param>
|
/// <param name="target">The target position to move to.</param>
|
||||||
/// <param name="maxDistanceDelta">Maximum distance moved per call.</param>
|
/// <param name="maxDistanceDelta">Maximum distance moved per call.</param>
|
||||||
/// <returns>Vector representing the moved point.</returns>
|
/// <returns>Vector representing the moved point.</returns>
|
||||||
static Vector2 MoveTowards(Vector2 current, Vector2 target, double maxDistanceDelta);
|
static Vector2 MoveTowards(Vector2 current, Vector2 target, float maxDistanceDelta);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Overloaded Operators */
|
/* Overloaded Operators */
|
||||||
|
@ -361,7 +361,7 @@ namespace SHADE
|
||||||
/// <param name="lhs">Vector2 to multiply with.</param>
|
/// <param name="lhs">Vector2 to multiply with.</param>
|
||||||
/// <param name="rhs">Scalar to multiply with.</param>
|
/// <param name="rhs">Scalar to multiply with.</param>
|
||||||
/// <returns>The result of the scalar multiplication.</returns>
|
/// <returns>The result of the scalar multiplication.</returns>
|
||||||
static Vector2 operator*(Vector2 lhs, double rhs);
|
static Vector2 operator*(Vector2 lhs, float rhs);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the division of a Vector2 with a scalar value and returns
|
/// Calculates the division of a Vector2 with a scalar value and returns
|
||||||
/// the result.
|
/// the result.
|
||||||
|
@ -369,7 +369,7 @@ namespace SHADE
|
||||||
/// <param name="lhs">Scalar to divide with.</param>
|
/// <param name="lhs">Scalar to divide with.</param>
|
||||||
/// <param name="rhs">Vector2 to divide with.</param>
|
/// <param name="rhs">Vector2 to divide with.</param>
|
||||||
/// <returns>The result of the scalar division.</returns>
|
/// <returns>The result of the scalar division.</returns>
|
||||||
static Vector2 operator/(Vector2 lhs, double rhs);
|
static Vector2 operator/(Vector2 lhs, float rhs);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if two Vector2s are approximately equal. This is equivalent to
|
/// Checks if two Vector2s are approximately equal. This is equivalent to
|
||||||
/// calling Vector2.IsNear() with default tolerance values.
|
/// calling Vector2.IsNear() with default tolerance values.
|
||||||
|
|
|
@ -11,6 +11,7 @@ Copyright (C) 2021 DigiPen Institute of Technology.
|
||||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
of DigiPen Institute of Technology is prohibited.
|
of DigiPen Institute of Technology is prohibited.
|
||||||
*//*************************************************************************************/
|
*//*************************************************************************************/
|
||||||
|
|
||||||
// Precompiled Headers
|
// Precompiled Headers
|
||||||
#include "SHpch.h"
|
#include "SHpch.h"
|
||||||
// Primary Header
|
// Primary Header
|
||||||
|
@ -26,13 +27,13 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
Vector3::Vector3(double _x)
|
Vector3::Vector3(float _x)
|
||||||
: Vector3 {_x, 0.0, 0.0}
|
: Vector3 {_x, 0.0f, 0.0f}
|
||||||
{}
|
{}
|
||||||
Vector3::Vector3(double _x, double _y)
|
Vector3::Vector3(float _x, float _y)
|
||||||
: Vector3 {_x, _y, 0.0}
|
: Vector3 {_x, _y, 0.0f}
|
||||||
{}
|
{}
|
||||||
Vector3::Vector3(double _x, double _y, double _z)
|
Vector3::Vector3(float _x, float _y, float _z)
|
||||||
: x { _x }
|
: x { _x }
|
||||||
, y { _y }
|
, y { _y }
|
||||||
, z { _z }
|
, z { _z }
|
||||||
|
@ -54,22 +55,22 @@ namespace SHADE
|
||||||
return *this / GetSqrMagnitude();
|
return *this / GetSqrMagnitude();
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector3::GetMagnitude()
|
float Vector3::GetMagnitude()
|
||||||
{
|
{
|
||||||
return sqrt(x * x + y * y + z * z);
|
return sqrt(x * x + y * y + z * z);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector3::GetSqrMagnitude()
|
float Vector3::GetSqrMagnitude()
|
||||||
{
|
{
|
||||||
return x * x + y * y + z * z;
|
return x * x + y * y + z * z;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector3::Angle2DFromRightRadians()
|
float Vector3::Angle2DFromRightRadians()
|
||||||
{
|
{
|
||||||
return atan2(y, x);
|
return atan2(y, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
double Vector3::Angle2DFromRightDegrees()
|
float Vector3::Angle2DFromRightDegrees()
|
||||||
{
|
{
|
||||||
return Math::RadiansToDegrees(Angle2DFromRightRadians());
|
return Math::RadiansToDegrees(Angle2DFromRightRadians());
|
||||||
}
|
}
|
||||||
|
@ -79,7 +80,7 @@ namespace SHADE
|
||||||
return IsNearPoint(point, Math::Epsilon);
|
return IsNearPoint(point, Math::Epsilon);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Vector3::IsNearPoint(Vector3 point, double tolerance)
|
bool Vector3::IsNearPoint(Vector3 point, float tolerance)
|
||||||
{
|
{
|
||||||
return (*this - point).GetSqrMagnitude() < (tolerance * tolerance);
|
return (*this - point).GetSqrMagnitude() < (tolerance * tolerance);
|
||||||
}
|
}
|
||||||
|
@ -121,7 +122,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
return IsNear(lhs, rhs, Math::Epsilon);
|
return IsNear(lhs, rhs, Math::Epsilon);
|
||||||
}
|
}
|
||||||
bool Vector3::IsNear(Vector3 lhs, Vector3 rhs, double tolerance)
|
bool Vector3::IsNear(Vector3 lhs, Vector3 rhs, float tolerance)
|
||||||
{
|
{
|
||||||
return (std::abs(lhs.x) - std::abs(rhs.x)) < tolerance
|
return (std::abs(lhs.x) - std::abs(rhs.x)) < tolerance
|
||||||
&&
|
&&
|
||||||
|
@ -129,7 +130,7 @@ namespace SHADE
|
||||||
&&
|
&&
|
||||||
(std::abs(lhs.z) - std::abs(rhs.z)) < tolerance;
|
(std::abs(lhs.z) - std::abs(rhs.z)) < tolerance;
|
||||||
}
|
}
|
||||||
double Vector3::Dot(Vector3 lhs, Vector3 rhs)
|
float Vector3::Dot(Vector3 lhs, Vector3 rhs)
|
||||||
{
|
{
|
||||||
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
|
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
|
||||||
}
|
}
|
||||||
|
@ -145,12 +146,12 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
Vector3 Vector3::Reflect(Vector3 vec, Vector3 normal)
|
Vector3 Vector3::Reflect(Vector3 vec, Vector3 normal)
|
||||||
{
|
{
|
||||||
return vec - (Project(vec, normal.GetNormalised()) * 2.0);
|
return vec - (Project(vec, normal.GetNormalised()) * 2.0f);
|
||||||
}
|
}
|
||||||
Vector3 Vector3::RotateRadians(Vector3 vec, double radians)
|
Vector3 Vector3::RotateRadians(Vector3 vec, float radians)
|
||||||
{
|
{
|
||||||
const double SINE = sin(radians);
|
const float SINE = sin(radians);
|
||||||
const double COSINE = cos(radians);
|
const float COSINE = cos(radians);
|
||||||
|
|
||||||
return Vector3
|
return Vector3
|
||||||
(
|
(
|
||||||
|
@ -159,15 +160,15 @@ namespace SHADE
|
||||||
vec.z
|
vec.z
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Vector3 Vector3::RotateDegrees(Vector3 vec, double degrees)
|
Vector3 Vector3::RotateDegrees(Vector3 vec, float degrees)
|
||||||
{
|
{
|
||||||
return RotateRadians(vec, Math::DegreesToRadians(degrees));
|
return RotateRadians(vec, Math::DegreesToRadians(degrees));
|
||||||
}
|
}
|
||||||
Vector3 Vector3::Min(Vector3 lhs, Vector3 rhs)
|
Vector3 Vector3::Min(Vector3 lhs, Vector3 rhs)
|
||||||
{
|
{
|
||||||
double lx = lhs.x, rx = rhs.x;
|
float lx = lhs.x, rx = rhs.x;
|
||||||
double ly = lhs.y, ry = rhs.y;
|
float ly = lhs.y, ry = rhs.y;
|
||||||
double lz = lhs.z, rz = rhs.z;
|
float lz = lhs.z, rz = rhs.z;
|
||||||
|
|
||||||
return Vector3(std::min(lx, rx),
|
return Vector3(std::min(lx, rx),
|
||||||
std::min(ly, ry),
|
std::min(ly, ry),
|
||||||
|
@ -175,23 +176,23 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
Vector3 Vector3::Max(Vector3 lhs, Vector3 rhs)
|
Vector3 Vector3::Max(Vector3 lhs, Vector3 rhs)
|
||||||
{
|
{
|
||||||
double lx = lhs.x, rx = rhs.x;
|
float lx = lhs.x, rx = rhs.x;
|
||||||
double ly = lhs.y, ry = rhs.y;
|
float ly = lhs.y, ry = rhs.y;
|
||||||
double lz = lhs.z, rz = rhs.z;
|
float lz = lhs.z, rz = rhs.z;
|
||||||
|
|
||||||
return Vector3(std::max(lx, rx),
|
return Vector3(std::max(lx, rx),
|
||||||
std::max(ly, ry),
|
std::max(ly, ry),
|
||||||
std::max(lz, rz));
|
std::max(lz, rz));
|
||||||
}
|
}
|
||||||
Vector3 Vector3::Lerp(Vector3 a, Vector3 b, double t)
|
Vector3 Vector3::Lerp(Vector3 a, Vector3 b, float t)
|
||||||
{
|
{
|
||||||
return LerpUnclamped(a, b, std::clamp(t, 0.0, 1.0));
|
return LerpUnclamped(a, b, std::clamp(t, 0.0f, 1.0f));
|
||||||
}
|
}
|
||||||
Vector3 Vector3::LerpUnclamped(Vector3 a, Vector3 b, double t)
|
Vector3 Vector3::LerpUnclamped(Vector3 a, Vector3 b, float t)
|
||||||
{
|
{
|
||||||
return a + ((b - a) * t);
|
return a + ((b - a) * t);
|
||||||
}
|
}
|
||||||
Vector3 Vector3::MoveTowards(Vector3 current, Vector3 target, double maxDistanceDelta)
|
Vector3 Vector3::MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta)
|
||||||
{
|
{
|
||||||
// Ignore if it is exactly on the same point
|
// Ignore if it is exactly on the same point
|
||||||
if (current == target)
|
if (current == target)
|
||||||
|
@ -203,7 +204,7 @@ namespace SHADE
|
||||||
|
|
||||||
// Check if check if is behind or ahead of target
|
// Check if check if is behind or ahead of target
|
||||||
Vector3 DIFF = target - newPos;
|
Vector3 DIFF = target - newPos;
|
||||||
if (Dot(DELTA, DIFF) < 0.0)
|
if (Dot(DELTA, DIFF) < 0.0f)
|
||||||
{
|
{
|
||||||
newPos = target;
|
newPos = target;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +237,7 @@ namespace SHADE
|
||||||
lhs.z * rhs.z
|
lhs.z * rhs.z
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Vector3 Vector3::operator*(Vector3 lhs, double rhs)
|
Vector3 Vector3::operator*(Vector3 lhs, float rhs)
|
||||||
{
|
{
|
||||||
return Vector3
|
return Vector3
|
||||||
(
|
(
|
||||||
|
@ -245,7 +246,7 @@ namespace SHADE
|
||||||
lhs.z * rhs
|
lhs.z * rhs
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Vector3 Vector3::operator/(Vector3 lhs, double rhs)
|
Vector3 Vector3::operator/(Vector3 lhs, float rhs)
|
||||||
{
|
{
|
||||||
return Vector3
|
return Vector3
|
||||||
(
|
(
|
||||||
|
|
|
@ -11,6 +11,7 @@ Copyright (C) 2021 DigiPen Institute of Technology.
|
||||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
of DigiPen Institute of Technology is prohibited.
|
of DigiPen Institute of Technology is prohibited.
|
||||||
*//*************************************************************************************/
|
*//*************************************************************************************/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Standard Libraries
|
// Standard Libraries
|
||||||
|
@ -21,8 +22,8 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
///<summary>
|
///<summary>
|
||||||
/// CLR version of the the PlushieEngine's Vector3 class that represents a
|
/// CLR version of SHADE Engine's Vector3 class that represents a 3-Dimensional Vector.
|
||||||
/// 3-Dimensional Vector. Designed to closely match Unity's Vector3 struct.
|
/// Designed to closely match Unity's Vector3 struct.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)]
|
[System::Runtime::InteropServices::StructLayout(System::Runtime::InteropServices::LayoutKind::Sequential)]
|
||||||
public value struct Vector3 : public System::IEquatable<Vector3>
|
public value struct Vector3 : public System::IEquatable<Vector3>
|
||||||
|
@ -35,49 +36,49 @@ namespace SHADE
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector3(0, 0, -1).
|
/// Shorthand for writing Vector3(0, 0, -1).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector3 Back = Vector3(0.0, 0.0, -1.0);
|
static initonly Vector3 Back = Vector3(0.0f, 0.0f, -1.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector3(0, -1, 0).
|
/// Shorthand for writing Vector3(0, -1, 0).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector3 Down = Vector3(0.0, -1.0, 0.0);
|
static initonly Vector3 Down = Vector3(0.0f, -1.0f, 0.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector3(0, 0, 1).
|
/// Shorthand for writing Vector3(0, 0, 1).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector3 Forward = Vector3(0.0, 0.0, 1.0);
|
static initonly Vector3 Forward = Vector3(0.0f, 0.0f, 1.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector3(-1, 0, 0).
|
/// Shorthand for writing Vector3(-1, 0, 0).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector3 Left = Vector3(-1.0, 0.0, 0.0);
|
static initonly Vector3 Left = Vector3(-1.0f, 0.0f, 0.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector3(double.NegativeInfinity,
|
/// Shorthand for writing Vector3(float.NegativeInfinity,
|
||||||
/// double.NegativeInfinity, double.NegativeInfinity).
|
/// float.NegativeInfinity, float.NegativeInfinity).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector3 NegativeInfinity = Vector3(std::numeric_limits<double>::lowest(),
|
static initonly Vector3 NegativeInfinity = Vector3(std::numeric_limits<float>::lowest(),
|
||||||
std::numeric_limits<double>::lowest(),
|
std::numeric_limits<float>::lowest(),
|
||||||
std::numeric_limits<double>::lowest());
|
std::numeric_limits<float>::lowest());
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector3(1, 1, 1).
|
/// Shorthand for writing Vector3(1, 1, 1).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector3 One = Vector3(1.0, 1.0, 1.0);
|
static initonly Vector3 One = Vector3(1.0f, 1.0f, 1.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector3(double.PositiveInfinity,
|
/// Shorthand for writing Vector3(float.PositiveInfinity,
|
||||||
/// double.PositiveInfinity, double.PositiveInfinity).
|
/// float.PositiveInfinity, float.PositiveInfinity).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector3 PositiveInfinity = Vector3(std::numeric_limits<double>::max(),
|
static initonly Vector3 PositiveInfinity = Vector3(std::numeric_limits<float>::max(),
|
||||||
std::numeric_limits<double>::max(),
|
std::numeric_limits<float>::max(),
|
||||||
std::numeric_limits<double>::max());
|
std::numeric_limits<float>::max());
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector3(1, 0, 0).
|
/// Shorthand for writing Vector3(1, 0, 0).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector3 Right = Vector3(1.0, 0.0, 0.0);
|
static initonly Vector3 Right = Vector3(1.0f, 0.0f, 0.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector3(0, 1, 0).
|
/// Shorthand for writing Vector3(0, 1, 0).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector3 Up = Vector3(0.0, 1.0, 0.0);
|
static initonly Vector3 Up = Vector3(0.0f, 1.0f, 0.0f);
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Shorthand for writing Vector3(0, 0, 0).
|
/// Shorthand for writing Vector3(0, 0, 0).
|
||||||
///</summary>
|
///</summary>
|
||||||
static initonly Vector3 Zero = Vector3(0.0, 0.0, 0.0);
|
static initonly Vector3 Zero = Vector3(0.0f, 0.0f, 0.0f);
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
@ -86,39 +87,39 @@ namespace SHADE
|
||||||
///<summary>
|
///<summary>
|
||||||
/// X-component of the Vector3.
|
/// X-component of the Vector3.
|
||||||
///</summary>
|
///</summary>
|
||||||
double x;
|
float x;
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Y-component of the Vector3.
|
/// Y-component of the Vector3.
|
||||||
///</summary>
|
///</summary>
|
||||||
double y;
|
float y;
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Z-component of the Vector3.
|
/// Z-component of the Vector3.
|
||||||
///</summary>
|
///</summary>
|
||||||
double z;
|
float z;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor to construct a Vector3 with the specified components with the
|
/// Constructor to construct a Vector3 with the specified components with the
|
||||||
/// Y and Z-component set to 0.0.
|
/// Y and Z-component set to 0.0f.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="_x">X-coordinate to set.</param>
|
/// <param name="_x">X-coordinate to set.</param>
|
||||||
Vector3(double _x);
|
Vector3(float _x);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor to construct a Vector3 with the specified components with the
|
/// Constructor to construct a Vector3 with the specified components with the
|
||||||
/// Z-component set to 0.0.
|
/// Z-component set to 0.0f.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="_x">X-coordinate to set.</param>
|
/// <param name="_x">X-coordinate to set.</param>
|
||||||
/// <param name="_y">Y-coordinate to set.</param>
|
/// <param name="_y">Y-coordinate to set.</param>
|
||||||
Vector3(double _x, double _y);
|
Vector3(float _x, float _y);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor to construct a Vector3 with the specified components.
|
/// Constructor to construct a Vector3 with the specified components.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="_x">X-coordinate to set.</param>
|
/// <param name="_x">X-coordinate to set.</param>
|
||||||
/// <param name="_y">Y-coordinate to set.</param>
|
/// <param name="_y">Y-coordinate to set.</param>
|
||||||
/// <param name="_z">Z-coordinate to set.</param>
|
/// <param name="_z">Z-coordinate to set.</param>
|
||||||
Vector3(double _x, double _y, double _z);
|
Vector3(float _x, float _y, float _z);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Conversion constructor to construct a Vector3 using a Vector2.
|
/// Conversion constructor to construct a Vector3 using a Vector2.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -148,24 +149,24 @@ namespace SHADE
|
||||||
/// need the precise magnitude, consider using GetSqrMagnitude() instead.
|
/// need the precise magnitude, consider using GetSqrMagnitude() instead.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns the length of this Vector3.</returns>
|
/// <returns>Returns the length of this Vector3.</returns>
|
||||||
double GetMagnitude();
|
float GetMagnitude();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates and returns the squared magnitude of this Vector3.
|
/// Calculates and returns the squared magnitude of this Vector3.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns the squared length of this Vector3.</returns>
|
/// <returns>Returns the squared length of this Vector3.</returns>
|
||||||
double GetSqrMagnitude();
|
float GetSqrMagnitude();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates and returns the angle of this vector from the right vector. This
|
/// Calculates and returns the angle of this vector from the right vector. This
|
||||||
/// function returns values between -Math.PI and Math.PI.
|
/// function returns values between -Math.PI and Math.PI.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns the angle of this vector from the right vector in radians.</returns>
|
/// <returns>Returns the angle of this vector from the right vector in radians.</returns>
|
||||||
double Angle2DFromRightRadians();
|
float Angle2DFromRightRadians();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates and returns the angle of this vector from the right vector. This
|
/// Calculates and returns the angle of this vector from the right vector. This
|
||||||
/// function returns values between -180.0 and 180.0.
|
/// function returns values between -180.0f and 180.0f.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns the angle of this vector from the right vector in degrees.</returns>
|
/// <returns>Returns the angle of this vector from the right vector in degrees.</returns>
|
||||||
double Angle2DFromRightDegrees();
|
float Angle2DFromRightDegrees();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if a specified point is near this Vector3 that represents a point with
|
/// Checks if a specified point is near this Vector3 that represents a point with
|
||||||
/// a tolerance value of PLS_EPSILON.
|
/// a tolerance value of PLS_EPSILON.
|
||||||
|
@ -187,7 +188,7 @@ namespace SHADE
|
||||||
/// True if this Vector3 representing a point and the specified point are within
|
/// True if this Vector3 representing a point and the specified point are within
|
||||||
/// the range of the specified tolerance. False otherwise.
|
/// the range of the specified tolerance. False otherwise.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
bool IsNearPoint(Vector3 point, double tolerance);
|
bool IsNearPoint(Vector3 point, float tolerance);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* IEquatable */
|
/* IEquatable */
|
||||||
|
@ -207,12 +208,12 @@ namespace SHADE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="o">The unboxed object to compare with.</param>
|
/// <param name="o">The unboxed object to compare with.</param>
|
||||||
/// <returns>True if both objects are the same.</returns>
|
/// <returns>True if both objects are the same.</returns>
|
||||||
bool Equals(Object^ o) override;
|
bool Equals(Object^ o) override;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a unique hash for this object.
|
/// Gets a unique hash for this object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Unique hash for this object.</returns>
|
/// <returns>Unique hash for this object.</returns>
|
||||||
int GetHashCode() override;
|
int GetHashCode() override;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Static Functions */
|
/* Static Functions */
|
||||||
|
@ -235,14 +236,14 @@ namespace SHADE
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// True if the two Vector3s are within the tolerance value specified
|
/// True if the two Vector3s are within the tolerance value specified
|
||||||
/// </returns>
|
/// </returns>
|
||||||
static bool IsNear(Vector3 lhs, Vector3 rhs, double tolerance);
|
static bool IsNear(Vector3 lhs, Vector3 rhs, float tolerance);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes and returns the dot product of 2 specified Vector3s.
|
/// Computes and returns the dot product of 2 specified Vector3s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lhs">Vector3 to calculate dot product with.</param>
|
/// <param name="lhs">Vector3 to calculate dot product with.</param>
|
||||||
/// <param name="rhs">Another Vector3 to calculate dot product with.</param>
|
/// <param name="rhs">Another Vector3 to calculate dot product with.</param>
|
||||||
/// <returns>Scalar value representing the dot product of the two Vector3s.</returns>
|
/// <returns>Scalar value representing the dot product of the two Vector3s.</returns>
|
||||||
static double Dot(Vector3 lhs, Vector3 rhs);
|
static float Dot(Vector3 lhs, Vector3 rhs);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes and returns the cross product of 2 specified Vector3s.
|
/// Computes and returns the cross product of 2 specified Vector3s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -273,7 +274,7 @@ namespace SHADE
|
||||||
/// Angle to rotate the vector by in an anti-clockwise direction in radians.
|
/// Angle to rotate the vector by in an anti-clockwise direction in radians.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>The Vector3 that represents the rotated vector.</returns>
|
/// <returns>The Vector3 that represents the rotated vector.</returns>
|
||||||
static Vector3 RotateRadians(Vector3 vec, double radians);
|
static Vector3 RotateRadians(Vector3 vec, float radians);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rotates a Vector3 on the Z-axis by a specified angle in an anti-clockwise
|
/// Rotates a Vector3 on the Z-axis by a specified angle in an anti-clockwise
|
||||||
/// direction.
|
/// direction.
|
||||||
|
@ -283,7 +284,7 @@ namespace SHADE
|
||||||
/// Angle to rotate the vector by in an anti-clockwise direction in degrees.
|
/// Angle to rotate the vector by in an anti-clockwise direction in degrees.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>The Vector3 that represents the rotated vector.</returns>
|
/// <returns>The Vector3 that represents the rotated vector.</returns>
|
||||||
static Vector3 RotateDegrees(Vector3 vec, double degrees);
|
static Vector3 RotateDegrees(Vector3 vec, float degrees);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes and returns a Vector3 that is made from the smallest components of
|
/// Computes and returns a Vector3 that is made from the smallest components of
|
||||||
/// the two specified Vector3s.
|
/// the two specified Vector3s.
|
||||||
|
@ -311,25 +312,25 @@ namespace SHADE
|
||||||
/// This is most commonly used to find a point some fraction of the way along a
|
/// This is most commonly used to find a point some fraction of the way along a
|
||||||
/// line between two endpoints.
|
/// line between two endpoints.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="a">The start Vector3, returned when t = 0.0.</param>
|
/// <param name="a">The start Vector3, returned when t = 0.0f.</param>
|
||||||
/// <param name="b">The end Vector3, returned when t = 1.0.</param>
|
/// <param name="b">The end Vector3, returned when t = 1.0f.</param>
|
||||||
/// <param name="t">
|
/// <param name="t">
|
||||||
/// Value used to interpolate between a and b which is clamped to
|
/// Value used to interpolate between a and b which is clamped to
|
||||||
/// the range[0, 1].
|
/// the range[0, 1].
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>The interpolated Vector3.</returns>
|
/// <returns>The interpolated Vector3.</returns>
|
||||||
static Vector3 Lerp(Vector3 a, Vector3 b, double t);
|
static Vector3 Lerp(Vector3 a, Vector3 b, float t);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Linearly interpolates between two specified points.
|
/// Linearly interpolates between two specified points.
|
||||||
/// This is most commonly used to find a point some fraction of the way along a
|
/// This is most commonly used to find a point some fraction of the way along a
|
||||||
/// line between two endpoints.
|
/// line between two endpoints.
|
||||||
/// Unlike Lerp(), t is not clamped to a range at all.
|
/// Unlike Lerp(), t is not clamped to a range at all.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="a">The start Vector3, returned when t = 0.0.</param>
|
/// <param name="a">The start Vector3, returned when t = 0.0f.</param>
|
||||||
/// <param name="b">The end Vector3, returned when t = 1.0.</param>
|
/// <param name="b">The end Vector3, returned when t = 1.0f.</param>
|
||||||
/// <param name="t">Value used to interpolate between a and b.</param>
|
/// <param name="t">Value used to interpolate between a and b.</param>
|
||||||
/// <returns>The interpolated Vector3.</returns>
|
/// <returns>The interpolated Vector3.</returns>
|
||||||
static Vector3 LerpUnclamped(Vector3 a, Vector3 b, double t);
|
static Vector3 LerpUnclamped(Vector3 a, Vector3 b, float t);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Moves a point current towards target.
|
/// Moves a point current towards target.
|
||||||
/// Similar to Lerp(), however, the function will ensure that the distance never
|
/// Similar to Lerp(), however, the function will ensure that the distance never
|
||||||
|
@ -340,7 +341,7 @@ namespace SHADE
|
||||||
/// <param name="target">The target position to move to.</param>
|
/// <param name="target">The target position to move to.</param>
|
||||||
/// <param name="maxDistanceDelta">Maximum distance moved per call.</param>
|
/// <param name="maxDistanceDelta">Maximum distance moved per call.</param>
|
||||||
/// <returns>Vector representing the moved point.</returns>
|
/// <returns>Vector representing the moved point.</returns>
|
||||||
static Vector3 MoveTowards(Vector3 current, Vector3 target, double maxDistanceDelta);
|
static Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* Overloaded Operators */
|
/* Overloaded Operators */
|
||||||
|
@ -374,7 +375,7 @@ namespace SHADE
|
||||||
/// <param name="lhs">Vector3 to multiply with.</param>
|
/// <param name="lhs">Vector3 to multiply with.</param>
|
||||||
/// <param name="rhs">Scalar to multiply with.</param>
|
/// <param name="rhs">Scalar to multiply with.</param>
|
||||||
/// <returns>The result of the scalar multiplication.</returns>
|
/// <returns>The result of the scalar multiplication.</returns>
|
||||||
static Vector3 operator*(Vector3 lhs, double rhs);
|
static Vector3 operator*(Vector3 lhs, float rhs);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the division of a Vector3 with a scalar value and returns
|
/// Calculates the division of a Vector3 with a scalar value and returns
|
||||||
/// the result.
|
/// the result.
|
||||||
|
@ -382,7 +383,7 @@ namespace SHADE
|
||||||
/// <param name="lhs">Scalar to divide with.</param>
|
/// <param name="lhs">Scalar to divide with.</param>
|
||||||
/// <param name="rhs">Vector3 to divide with.</param>
|
/// <param name="rhs">Vector3 to divide with.</param>
|
||||||
/// <returns>The result of the scalar division.</returns>
|
/// <returns>The result of the scalar division.</returns>
|
||||||
static Vector3 operator/(Vector3 lhs, double rhs);
|
static Vector3 operator/(Vector3 lhs, float rhs);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if two Vector3s are approximately equal. This is equivalent to
|
/// Checks if two Vector3s are approximately equal. This is equivalent to
|
||||||
/// calling Vector3.IsNear() with default tolerance values.
|
/// calling Vector3.IsNear() with default tolerance values.
|
||||||
|
|
|
@ -35,10 +35,7 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
SHVec3 Convert::ToNative(Vector3 vec)
|
SHVec3 Convert::ToNative(Vector3 vec)
|
||||||
{
|
{
|
||||||
const double X = vec.x;
|
return SHVec3(vec.x, vec.y, vec.z);
|
||||||
const double Y = vec.y;
|
|
||||||
const double Z = vec.z;
|
|
||||||
return SHVec3(X, Y, Z);
|
|
||||||
}
|
}
|
||||||
Vector3 Convert::ToCLI(const SHVec3& vec)
|
Vector3 Convert::ToCLI(const SHVec3& vec)
|
||||||
{
|
{
|
||||||
|
@ -46,9 +43,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
SHVec2 Convert::ToNative(Vector2 vec)
|
SHVec2 Convert::ToNative(Vector2 vec)
|
||||||
{
|
{
|
||||||
const double X = vec.x;
|
return SHVec2(vec.x, vec.y);
|
||||||
const double Y = vec.y;
|
|
||||||
return SHVec2(X, Y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 Convert::ToCLI(const SHVec2& vec)
|
Vector2 Convert::ToCLI(const SHVec2& vec)
|
||||||
|
@ -56,6 +51,16 @@ namespace SHADE
|
||||||
return Vector2(vec.x, vec.y);
|
return Vector2(vec.x, vec.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHQuaternion Convert::ToNative(Quaternion quat)
|
||||||
|
{
|
||||||
|
return SHQuaternion{ quat.x, quat.y, quat.z, quat.w };
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion Convert::ToCLI(const SHQuaternion& quat)
|
||||||
|
{
|
||||||
|
return Quaternion{ quat.x, quat.y, quat.z, quat.w };
|
||||||
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* String Conversions */
|
/* String Conversions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -18,10 +18,12 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "ECS_Base/Entity/SHEntity.h"
|
#include "ECS_Base/Entity/SHEntity.h"
|
||||||
#include "Math/Vector/SHVec2.h"
|
#include "Math/Vector/SHVec2.h"
|
||||||
#include "Math/Vector/SHVec3.h"
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/SHQuaternion.h"
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Engine/Entity.hxx"
|
#include "Engine/Entity.hxx"
|
||||||
#include "Math/Vector2.hxx"
|
#include "Math/Vector2.hxx"
|
||||||
#include "Math/Vector3.hxx"
|
#include "Math/Vector3.hxx"
|
||||||
|
#include "Math/Quaternion.hxx"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -74,6 +76,18 @@ namespace SHADE
|
||||||
/// <param name="vec">The native Vector2 to convert from.</param>
|
/// <param name="vec">The native Vector2 to convert from.</param>
|
||||||
/// <returns>Managed copy of a native Vector2.</returns>
|
/// <returns>Managed copy of a native Vector2.</returns>
|
||||||
static Vector2 ToCLI(const SHVec2& vec);
|
static Vector2 ToCLI(const SHVec2& vec);
|
||||||
|
/// <summary>
|
||||||
|
/// Converts from a managed Quaternion to a native Quaternion.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="quat">The managed Quaternion to convert from.</param>
|
||||||
|
/// <returns>Native copy of a managed Quaternion.</returns>
|
||||||
|
static SHQuaternion ToNative(Quaternion quat);
|
||||||
|
/// <summary>
|
||||||
|
/// Converts from a native Quaternion to a managed Quaternion.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="quat">The native Quaternion to convert from.</param>
|
||||||
|
/// <returns>Managed copy of a native Quaternion.</returns>
|
||||||
|
static Quaternion ToCLI(const SHQuaternion& quat);
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/* String Conversions */
|
/* String Conversions */
|
||||||
|
|
Loading…
Reference in New Issue