Major cleanup.

Moved to namespace
Cleanup includes
This commit is contained in:
Antoine Pilote
2021-07-11 18:56:44 -04:00
parent f77bef6b28
commit 0c6ed48bbd
174 changed files with 11772 additions and 11296 deletions

View File

@@ -1,5 +1,8 @@
#pragma once
#include <memory>
#include <map>
#include <string>
#include <vector>
template<typename T>
using Scope = std::unique_ptr<T>;

View File

@@ -1,7 +1,7 @@
#include "FileSystem.h"
#include <filesystem>
#include "../../Engine.h"
#include "Engine.h"
#define GLFW_EXPOSE_NATIVE_WIN32
#include <GLFW/glfw3.h>
@@ -10,150 +10,154 @@
#include <fstream>
#include <iostream>
namespace fs = std::filesystem;
std::string FileDialog::OpenFile(const char* filter)
namespace Nuake
{
namespace fs = std::filesystem;
OPENFILENAMEA ofn;
CHAR szFile[260] = { 0 };
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = glfwGetWin32Window(Engine::GetCurrentWindow()->GetHandle());
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = filter;
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (GetOpenFileNameA(&ofn) == TRUE)
std::string FileDialog::OpenFile(const char* filter)
{
return ofn.lpstrFile;
}
return std::string();
}
std::string FileDialog::SaveFile(const char* filter)
{
OPENFILENAMEA ofn;
CHAR szFile[260] = { 0 };
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = glfwGetWin32Window(Engine::GetCurrentWindow()->GetHandle());
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = filter;
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (GetSaveFileNameA(&ofn) == TRUE)
{
return ofn.lpstrFile;
}
return std::string();
}
std::string FileSystem::Root = "";
Ref<Directory> FileSystem::RootDirectory;
void FileSystem::ScanDirectory(Ref<Directory> directory)
{
for (const auto& entry : std::filesystem::directory_iterator(directory->fullPath))
{
if (entry.is_directory())
OPENFILENAMEA ofn;
CHAR szFile[260] = { 0 };
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = glfwGetWin32Window(Engine::GetCurrentWindow()->GetHandle());
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = filter;
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (GetOpenFileNameA(&ofn) == TRUE)
{
Ref<Directory> newDir = CreateRef<Directory>();
newDir->fullPath = entry.path().string();
newDir->name = entry.path().filename().string();
newDir->Parent = directory;
ScanDirectory(newDir);
directory->Directories.push_back(newDir);
return ofn.lpstrFile;
}
else if (entry.is_regular_file())
return std::string();
}
std::string FileDialog::SaveFile(const char* filter)
{
OPENFILENAMEA ofn;
CHAR szFile[260] = { 0 };
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = glfwGetWin32Window(Engine::GetCurrentWindow()->GetHandle());
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = filter;
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (GetSaveFileNameA(&ofn) == TRUE)
{
Ref<File> newFile = CreateRef<File>();
newFile->Type = entry.path().extension().string();
newFile->name = entry.path().filename().string();
newFile->Parent = directory;
newFile->fullPath = entry.path().string();
directory->Files.push_back(newFile);
return ofn.lpstrFile;
}
return std::string();
}
std::string FileSystem::Root = "";
Ref<Directory> FileSystem::RootDirectory;
void FileSystem::ScanDirectory(Ref<Directory> directory)
{
for (const auto& entry : std::filesystem::directory_iterator(directory->fullPath))
{
if (entry.is_directory())
{
Ref<Directory> newDir = CreateRef<Directory>();
newDir->fullPath = entry.path().string();
newDir->name = entry.path().filename().string();
newDir->Parent = directory;
ScanDirectory(newDir);
directory->Directories.push_back(newDir);
}
else if (entry.is_regular_file())
{
Ref<File> newFile = CreateRef<File>();
newFile->Type = entry.path().extension().string();
newFile->name = entry.path().filename().string();
newFile->Parent = directory;
newFile->fullPath = entry.path().string();
directory->Files.push_back(newFile);
}
}
}
}
bool FileSystem::DirectoryExists(const std::string path)
{
return false;
}
void FileSystem::SetRootDirectory(const std::string path)
{
Root = path;
Scan();
}
void FileSystem::Scan()
{
RootDirectory = CreateRef<Directory>();
RootDirectory->Files = std::vector<Ref<File>>();
RootDirectory->Directories = std::vector<Ref<Directory>>();
RootDirectory->name = FileSystem::AbsoluteToRelative(Root);
RootDirectory->fullPath = Root;
ScanDirectory(RootDirectory);
}
std::string FileSystem::AbsoluteToRelative(const std::string& path)
{
const fs::path rootPath(Root);
const fs::path absolutePath(path);
return fs::relative(absolutePath, rootPath).generic_string();
}
std::string FileSystem::ReadFile(const std::string& path, bool absolute)
{
std::string finalPath = path;
if (!absolute)
finalPath = Root + path;
std::ifstream MyReadFile(finalPath);
std::string fileContent = "";
std::string allFile = "";
// Use a while loop together with the getline() function to read the file line by line
while (getline(MyReadFile, fileContent))
bool FileSystem::DirectoryExists(const std::string path)
{
allFile.append(fileContent + "\n");
return false;
}
void FileSystem::SetRootDirectory(const std::string path)
{
Root = path;
Scan();
}
void FileSystem::Scan()
{
RootDirectory = CreateRef<Directory>();
RootDirectory->Files = std::vector<Ref<File>>();
RootDirectory->Directories = std::vector<Ref<Directory>>();
RootDirectory->name = FileSystem::AbsoluteToRelative(Root);
RootDirectory->fullPath = Root;
ScanDirectory(RootDirectory);
}
std::string FileSystem::AbsoluteToRelative(const std::string& path)
{
const fs::path rootPath(Root);
const fs::path absolutePath(path);
return fs::relative(absolutePath, rootPath).generic_string();
}
std::string FileSystem::ReadFile(const std::string& path, bool absolute)
{
std::string finalPath = path;
if (!absolute)
finalPath = Root + path;
std::ifstream MyReadFile(finalPath);
std::string fileContent = "";
std::string allFile = "";
// Use a while loop together with the getline() function to read the file line by line
while (getline(MyReadFile, fileContent))
{
allFile.append(fileContent + "\n");
}
// Close the file
MyReadFile.close();
return allFile;
}
std::ofstream FileSystem::fileWriter;
bool FileSystem::BeginWriteFile(const std::string path)
{
fileWriter = std::ofstream();
fileWriter.open(path);
return false;
}
bool FileSystem::WriteLine(const std::string line)
{
fileWriter << line.c_str();
return true;
}
void FileSystem::EndWriteFile()
{
fileWriter.close();
}
Ref<Directory> FileSystem::GetFileTree()
{
return RootDirectory;
}
// Close the file
MyReadFile.close();
return allFile;
}
std::ofstream FileSystem::fileWriter;
bool FileSystem::BeginWriteFile(const std::string path)
{
fileWriter = std::ofstream();
fileWriter.open(path);
return false;
}
bool FileSystem::WriteLine(const std::string line)
{
fileWriter << line.c_str();
return true;
}
void FileSystem::EndWriteFile()
{
fileWriter.close();
}
Ref<Directory> FileSystem::GetFileTree()
{
return RootDirectory;
}

View File

@@ -4,54 +4,58 @@
#include "Core.h"
#include <iostream>
#include <fstream>
class FileDialog
namespace Nuake
{
public:
static std::string OpenFile(const char* filter);
static std::string SaveFile(const char* filter);
};
class FileDialog
{
public:
static std::string OpenFile(const char* filter);
static std::string SaveFile(const char* filter);
};
struct Directory;
struct File
{
std::string Type;
std::string name;
struct Directory;
struct File
{
std::string Type;
std::string name;
std::string fullPath;
Ref<Directory> Parent;
};
std::string fullPath;
Ref<Directory> Parent;
};
struct Directory
{
std::string name;
std::string fullPath;
Ref<Directory> Parent;
std::vector<Ref<Directory>> Directories;
std::vector<Ref<File>> Files;
};
struct Directory
{
std::string name;
std::string fullPath;
Ref<Directory> Parent;
std::vector<Ref<Directory>> Directories;
std::vector<Ref<File>> Files;
};
class FileSystem
{
public:
static std::string Root;
class FileSystem
{
public:
static std::string Root;
static Ref<Directory> RootDirectory;
static Ref<Directory> RootDirectory;
static void SetRootDirectory(const std::string path);
static void SetRootDirectory(const std::string path);
static void Scan();
static std::string AbsoluteToRelative(const std::string& path);
static Ref<Directory> GetFileTree();
static void ScanDirectory(Ref<Directory> directory);
static void GetDirectories();
static void Scan();
static std::string AbsoluteToRelative(const std::string& path);
static Ref<Directory> GetFileTree();
static void ScanDirectory(Ref<Directory> directory);
static void GetDirectories();
static bool DirectoryExists(const std::string path);
static bool FileExists(const std::string path);
static bool DirectoryExists(const std::string path);
static bool FileExists(const std::string path);
static std::string ReadFile(const std::string& path, bool absolute = false);
static std::string ReadFile(const std::string& path, bool absolute = false);
static std::ofstream fileWriter;
static bool BeginWriteFile(const std::string path);
static bool WriteLine(const std::string line);
static void EndWriteFile();
};
static std::ofstream fileWriter;
static bool BeginWriteFile(const std::string path);
static bool WriteLine(const std::string line);
static void EndWriteFile();
};
}

View File

@@ -2,166 +2,170 @@
#include "../Window.h"
#include <GLFW/glfw3.h>
Input* Input::s_Instance;
std::map<int, bool> Input::m_Keys = std::map<int, bool>();
bool Input::m_MouseButtons[5] = { false, false, false, false, false };
namespace Nuake
{
Input* Input::s_Instance;
std::map<int, bool> Input::m_Keys = std::map<int, bool>();
bool Input::m_MouseButtons[5] = { false, false, false, false, false };
#pragma region Keys
// Only true if the key is currently being pressed
bool Input::IsKeyDown(int keycode)
{
auto window = Window::Get()->GetHandle();
int state = glfwGetKey(window, keycode);
bool result = state == GLFW_PRESS;
m_Keys[keycode] = state;
return result;
}
// Only true if the key is pressed for the first frame. no repeat.
bool Input::IsKeyPressed(int keycode)
{
auto window = Window::Get()->GetHandle();
int state = glfwGetKey(window, keycode);
bool result = state == GLFW_PRESS;
// First time pressed?
if (m_Keys.find(keycode) == m_Keys.end() || m_Keys[keycode] == true)
// Only true if the key is currently being pressed
bool Input::IsKeyDown(int keycode)
{
if (result)
m_Keys[keycode] = true;
auto window = Window::Get()->GetHandle();
int state = glfwGetKey(window, keycode);
bool result = state == GLFW_PRESS;
m_Keys[keycode] = state;
return result;
}
return false;
}
bool Input::IsKeyReleased(int keycode)
{
auto window = Window::Get()->GetHandle();
int state = glfwGetKey(window, keycode);
bool result = state == GLFW_RELEASE;
// First time pressed?
if (m_Keys.find(keycode) == m_Keys.end())
return result;
if (result && m_Keys[keycode] == true)
// Only true if the key is pressed for the first frame. no repeat.
bool Input::IsKeyPressed(int keycode)
{
return true;
}
auto window = Window::Get()->GetHandle();
int state = glfwGetKey(window, keycode);
bool result = state == GLFW_PRESS;
return false;
}
// First time pressed?
if (m_Keys.find(keycode) == m_Keys.end() || m_Keys[keycode] == true)
{
if (result)
m_Keys[keycode] = true;
return result;
}
return false;
}
bool Input::IsKeyReleased(int keycode)
{
auto window = Window::Get()->GetHandle();
int state = glfwGetKey(window, keycode);
bool result = state == GLFW_RELEASE;
// First time pressed?
if (m_Keys.find(keycode) == m_Keys.end())
return result;
if (result && m_Keys[keycode] == true)
{
return true;
}
return false;
}
#pragma endregion
#pragma region Mouse
// Visibility
void Input::HideMouse() {
auto window = Window::Get()->GetHandle();
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
}
bool Input::IsMouseHidden() {
auto window = Window::Get()->GetHandle();
return glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED;
}
void Input::ShowMouse() {
auto window = Window::Get()->GetHandle();
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
// Action
bool Input::IsMouseButtonDown(int button)
{
auto window = Window::Get()->GetHandle();
auto state = glfwGetMouseButton(window, button);
return state == GLFW_PRESS;
}
bool Input::IsMouseButtonPressed(int button)
{
auto window = Window::Get()->GetHandle();
auto state = glfwGetMouseButton(window, button);
if (m_MouseButtons[button] == false && state == GLFW_PRESS)
{
m_MouseButtons[button] = true;
return true;
// Visibility
void Input::HideMouse() {
auto window = Window::Get()->GetHandle();
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
}
return false;
}
bool Input::IsMouseHidden() {
auto window = Window::Get()->GetHandle();
return glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED;
}
bool Input::IsMouseButtonReleased(int button)
{
auto window = Window::Get()->GetHandle();
auto state = glfwGetMouseButton(window, button);
void Input::ShowMouse() {
auto window = Window::Get()->GetHandle();
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
return state == GLFW_RELEASE && m_MouseButtons[button] == true;
}
// Position
float Input::GetMouseX()
{
auto window = Window::Get()->GetHandle();
// Action
bool Input::IsMouseButtonDown(int button)
{
auto window = Window::Get()->GetHandle();
auto state = glfwGetMouseButton(window, button);
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
return state == GLFW_PRESS;
}
return (float)xpos;
}
bool Input::IsMouseButtonPressed(int button)
{
auto window = Window::Get()->GetHandle();
auto state = glfwGetMouseButton(window, button);
float Input::GetMouseY()
{
auto window = Window::Get()->GetHandle();
if (m_MouseButtons[button] == false && state == GLFW_PRESS)
{
m_MouseButtons[button] = true;
return true;
}
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
return false;
}
return (float)ypos;
}
bool Input::IsMouseButtonReleased(int button)
{
auto window = Window::Get()->GetHandle();
auto state = glfwGetMouseButton(window, button);
Vector2 Input::GetMousePosition()
{
auto window = Window::Get()->GetHandle();
return state == GLFW_RELEASE && m_MouseButtons[button] == true;
}
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
// Position
float Input::GetMouseX()
{
auto window = Window::Get()->GetHandle();
return Vector2(xpos, ypos);
}
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
return (float)xpos;
}
float Input::GetMouseY()
{
auto window = Window::Get()->GetHandle();
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
return (float)ypos;
}
Vector2 Input::GetMousePosition()
{
auto window = Window::Get()->GetHandle();
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
return Vector2(xpos, ypos);
}
#pragma endregion
bool Input::Init()
{
//auto window = Application::Get().GetWindow()->GetNative();
//glfwSetKeyCallback(window, Input::HandleInputCallback);
return false;
}
void Input::Update()
{
// Reset all input to false.
for (auto& k : m_Keys)
bool Input::Init()
{
if(!IsKeyDown(k.first))
k.second = false;
//auto window = Application::Get().GetWindow()->GetNative();
//glfwSetKeyCallback(window, Input::HandleInputCallback);
return false;
}
for (int i = 0; i < 5; i++)
void Input::Update()
{
if(!IsMouseButtonDown(i))
m_MouseButtons[i] = false;
// Reset all input to false.
for (auto& k : m_Keys)
{
if (!IsKeyDown(k.first))
k.second = false;
}
for (int i = 0; i < 5; i++)
{
if (!IsMouseButtonDown(i))
m_MouseButtons[i] = false;
}
}
}

View File

@@ -2,33 +2,37 @@
#include <utility>
#include "../Core/Maths.h"
#include <map>
class Input
namespace Nuake
{
private:
static bool m_MouseButtons[5];
static std::map<int, bool> m_Keys;
public:
static bool IsKeyPressed(int keycode);
static bool IsKeyDown(int keycode);
static bool IsKeyReleased(int keycode);
class Input
{
private:
static bool m_MouseButtons[5];
static std::map<int, bool> m_Keys;
public:
static bool IsKeyPressed(int keycode);
static bool IsKeyDown(int keycode);
static bool IsKeyReleased(int keycode);
static void HideMouse();
static void ShowMouse();
static bool IsMouseHidden();
static bool IsMouseButtonPressed(int button);
static bool IsMouseButtonDown(int button);
static bool IsMouseButtonReleased(int button);
static float GetMouseX();
static float GetMouseY();
static Vector2 GetMousePosition();
static void HideMouse();
static void ShowMouse();
static bool IsMouseHidden();
static bool IsMouseButtonPressed(int button);
static bool IsMouseButtonDown(int button);
static bool IsMouseButtonReleased(int button);
static bool Init();
static void Update();
static float GetMouseX();
static float GetMouseY();
static Vector2 GetMousePosition();
Input* Get() { return s_Instance; }
static bool Init();
static void Update();
private:
static Input* s_Instance;
};
Input* Get() { return s_Instance; }
private:
static Input* s_Instance;
};
}

View File

@@ -4,30 +4,33 @@
#include <string>
#include <time.h>
std::vector<LogEntry> Logger::m_Logs = std::vector<LogEntry>();
void Logger::Log(std::string log, LOG_TYPE type)
namespace Nuake
{
char buff[100];
time_t now = time(0);
strftime(buff, 100, "%Y-%m-%d %H:%M:%S.000", localtime(&now));
std::vector<LogEntry> Logger::m_Logs = std::vector<LogEntry>();
LogEntry newLog = {
type,
buff,
log
};
void Logger::Log(std::string log, LOG_TYPE type)
{
char buff[100];
time_t now = time(0);
strftime(buff, 100, "%Y-%m-%d %H:%M:%S.000", localtime(&now));
std::string msg = "[" + std::string(buff) + "]" + std::string(" - ") + log;
printf((msg + "\n").c_str());
LogEntry newLog = {
type,
buff,
log
};
if (m_Logs.size() >= MAX_LOG)
m_Logs.erase(m_Logs.begin());
std::string msg = "[" + std::string(buff) + "]" + std::string(" - ") + log;
printf((msg + "\n").c_str());
m_Logs.push_back(newLog);
if (m_Logs.size() >= MAX_LOG)
m_Logs.erase(m_Logs.begin());
m_Logs.push_back(newLog);
}
std::vector<LogEntry> Logger::GetLogs()
{
return m_Logs;
}
}
std::vector<LogEntry> Logger::GetLogs()
{
return m_Logs;
}

View File

@@ -2,25 +2,29 @@
#include <string>
#include <vector>
enum LOG_TYPE
namespace Nuake
{
VERBOSE,
WARNING,
CRITICAL
};
enum LOG_TYPE
{
VERBOSE,
WARNING,
CRITICAL
};
struct LogEntry
{
LOG_TYPE type;
std::string time;
std::string message;
};
struct LogEntry
{
LOG_TYPE type;
std::string time;
std::string message;
};
class Logger
{
static const int MAX_LOG = 64;
static std::vector<LogEntry> m_Logs; // TODO: Use log struct.
public:
static void Log(std::string log, LOG_TYPE type = VERBOSE);
static std::vector<LogEntry> GetLogs();
};
class Logger
{
public:
static void Log(std::string log, LOG_TYPE type = VERBOSE);
static std::vector<LogEntry> GetLogs();
private:
static const int MAX_LOG = 64;
static std::vector<LogEntry> m_Logs; // TODO: Use log struct.
};
}

View File

@@ -7,91 +7,100 @@
#include "json/json.hpp"
#include "../Rendering/Textures/Material.h"
using json = nlohmann::json;
Ref<MaterialManager> MaterialManager::s_Instance;
MaterialManager::MaterialManager()
namespace Nuake
{
m_Materials = std::map<std::string, Ref<Material>>();
}
using json = nlohmann::json;
Ref<Material> MaterialManager::GetMaterial(const std::string name)
{
if (!IsMaterialLoaded(name))
Ref<MaterialManager> MaterialManager::s_Instance;
MaterialManager::MaterialManager()
{
Ref<Material> newMaterial = CreateRef<Material>(name);
RegisterMaterial(newMaterial);
m_Materials = std::map<std::string, Ref<Material>>();
}
Ref<Material> MaterialManager::GetMaterial(const std::string name)
{
if (!IsMaterialLoaded(name))
{
Ref<Material> newMaterial = CreateRef<Material>(name);
RegisterMaterial(newMaterial);
return newMaterial;
}
return m_Materials[name];
}
void MaterialManager::RegisterMaterial(Ref<Material> material)
{
m_Materials[material->GetName()] = material;
}
// Gets a material from path and load file if not already loaded.
//
// NOTE: The path passed as param is relative to Res/Materials and
// shouldn't contain the '.material' extension.
Ref<Material> MaterialManager::LoadMaterial(const std::string materialPath)
{
if (IsMaterialLoaded(materialPath))
return (m_Materials)[materialPath];
std::string finalPath = "Res/Materials/" + materialPath + ".material";
std::ifstream i(finalPath);
json j;
i >> j;
std::string matName;
if (!j.contains("name"))
{
std::string msg = "Error: Cannot load material file: " + materialPath +
" - Material file must have a name. \n";
printf(msg.c_str());
return nullptr;
}
else
{
matName = j["name"];
}
std::string albedoPath;
std::string normalPath;
std::string aoPath;
std::string metalPath;
std::string roughnessPath;
std::string displacementPath;
Ref<Material> newMaterial = CreateRef<Material>(j["albedo"]);
//if (j.contains("albedo"))
// newMaterial = new Material(albedoPath);
//else
// newMaterial = new Material(glm::vec3(1, 1, 1));
newMaterial->SetName(matName);
if (j.contains("normal"))
newMaterial->SetNormal(j["normal"]);
if (j.contains("ao"))
newMaterial->SetAO(j["ao"]);
if (j.contains("metal"))
newMaterial->SetMetalness(j["metal"]);
if (j.contains("roughness"))
newMaterial->SetRoughness(j["roughness"]);
if (j.contains("displacement"))
newMaterial->SetDisplacement(j["displacement"]);
return newMaterial;
}
return m_Materials[name];
}
void MaterialManager::RegisterMaterial(Ref<Material> material)
{
m_Materials[material->GetName()] = material;
}
// Gets a material from path and load file if not already loaded.
//
// NOTE: The path passed as param is relative to Res/Materials and
// shouldn't contain the '.material' extension.
Ref<Material> MaterialManager::LoadMaterial(const std::string materialPath) {
if (IsMaterialLoaded(materialPath))
return (m_Materials)[materialPath];
std::string finalPath = "Res/Materials/" + materialPath + ".material";
std::ifstream i(finalPath);
json j;
i >> j;
std::string matName;
if (!j.contains("name")) {
std::string msg = "Error: Cannot load material file: " + materialPath +
" - Material file must have a name. \n";
printf(msg.c_str());
return nullptr;
std::map<std::string, Ref<Material>> MaterialManager::GetAllMaterials()
{
return m_Materials;
}
else {
matName = j["name"];
bool MaterialManager::IsMaterialLoaded(const std::string materialPath)
{
return m_Materials.find(materialPath) != m_Materials.end();
}
std::string albedoPath;
std::string normalPath;
std::string aoPath;
std::string metalPath;
std::string roughnessPath;
std::string displacementPath;
Ref<Material> newMaterial = CreateRef<Material>(j["albedo"]);
//if (j.contains("albedo"))
// newMaterial = new Material(albedoPath);
//else
// newMaterial = new Material(glm::vec3(1, 1, 1));
newMaterial->SetName(matName);
if (j.contains("normal"))
newMaterial->SetNormal(j["normal"]);
if (j.contains("ao"))
newMaterial->SetAO(j["ao"]);
if (j.contains("metal"))
newMaterial->SetMetalness(j["metal"]);
if (j.contains("roughness"))
newMaterial->SetRoughness(j["roughness"]);
if (j.contains("displacement"))
newMaterial->SetDisplacement(j["displacement"]);
return newMaterial;
}
std::map<std::string, Ref<Material>> MaterialManager::GetAllMaterials()
{
return m_Materials;
}
bool MaterialManager::IsMaterialLoaded(const std::string materialPath) {
return m_Materials.find(materialPath) != m_Materials.end();
}

View File

@@ -1,41 +1,46 @@
#pragma once
#include <map>
#include <string>
#include "../Core/Core.h"
#include "src/Core/Core.h"
class Material;
namespace Nuake
{
class Material;
// TODO: Should probably be static.
class MaterialManager {
private:
static Ref<MaterialManager> s_Instance;
std::map<std::string, Ref<Material>> m_Materials;
// TODO: Pile of crap
Material* ParseMaterialFile(const std::string path);
void SaveMaterialFile(const std::string path, Material* material);
bool IsMaterialLoaded(const std::string path);
public:
std::string CurrentlyBoundedMaterial = "";
MaterialManager();
void LoadMaterials();
void RegisterMaterial(Ref<Material> material);
Ref<Material> LoadMaterial(const std::string path);
Ref<Material> GetMaterial(const std::string name);
std::map<std::string, Ref<Material>> GetAllMaterials();
static Ref<MaterialManager> Get()
// TODO: Should probably be static.
class MaterialManager
{
if (!s_Instance)
s_Instance = CreateRef<MaterialManager>();
private:
static Ref<MaterialManager> s_Instance;
return s_Instance;
}
};
std::map<std::string, Ref<Material>> m_Materials;
// TODO: Pile of crap
Material* ParseMaterialFile(const std::string path);
void SaveMaterialFile(const std::string path, Material* material);
bool IsMaterialLoaded(const std::string path);
public:
std::string CurrentlyBoundedMaterial = "";
MaterialManager();
void LoadMaterials();
void RegisterMaterial(Ref<Material> material);
Ref<Material> LoadMaterial(const std::string path);
Ref<Material> GetMaterial(const std::string name);
std::map<std::string, Ref<Material>> GetAllMaterials();
static Ref<MaterialManager> Get()
{
if (!s_Instance)
s_Instance = CreateRef<MaterialManager>();
return s_Instance;
}
};
}

View File

@@ -1,15 +1,17 @@
#pragma once
#include <glm\ext\vector_float4.hpp>
#include <glm\ext\vector_float3.hpp>
#include <glm\ext\matrix_transform.hpp>
#include <src/Vendors/glm/ext/vector_float2.hpp>
#include <src/Vendors/glm/ext/matrix_float4x4.hpp>
#include <glm\ext\matrix_transform.hpp>
using Vector3 = glm::vec3;
using Vector2 = glm::vec2;
using Vector4 = glm::vec4;
using Color = glm::vec4;
using Matrix4 = glm::mat4;
namespace Nuake
{
using Vector3 = glm::vec3;
using Vector2 = glm::vec2;
using Vector4 = glm::vec4;
using Color = glm::vec4;
using Matrix4 = glm::mat4;
}

View File

@@ -1,9 +1,13 @@
#pragma once
class OS {
public:
static int GetTime() {
return std::chrono::system_clock::now().time_since_epoch().count();
}
};
namespace Nuake
{
class OS
{
public:
static int GetTime()
{
return std::chrono::system_clock::now().time_since_epoch().count();
}
};
}

View File

@@ -2,30 +2,32 @@
#include "../../Rendering/Renderer.h"
#include <GL/glew.h>
void BulletDebugDrawer::drawLine(const btVector3& from, const btVector3& to, const btVector3& color)
namespace Nuake
{
TransformComponent tc = TransformComponent();
void BulletDebugDrawer::drawLine(const btVector3& from, const btVector3& to, const btVector3& color)
{
TransformComponent tc = TransformComponent();
tc.Translation = glm::vec3(from.x(), from.y(), from.z());
tc.Scale = glm::vec3(1.0f);
tc.Rotation = glm::vec3(0.0f);
tc.Translation = glm::vec3(from.x(), from.y(), from.z());
tc.Scale = glm::vec3(1.0f);
tc.Rotation = glm::vec3(0.0f);
glBegin(GL_LINES);
glColor3f((float)(color.x()), (float)(color.y()), (float)(color.z()));
glVertex3f((float)(from.x()), (float)(from.y()), (float)(from.z()));
glVertex3f((float)(to.x()), (float)(to.y()), (float)(to.z()));
glEnd();
glBegin(GL_LINES);
glColor3f((float)(color.x()), (float)(color.y()), (float)(color.z()));
glVertex3f((float)(from.x()), (float)(from.y()), (float)(from.z()));
glVertex3f((float)(to.x()), (float)(to.y()), (float)(to.z()));
glEnd();
//Renderer::DrawCube(tc, glm::vec4(color.x(), color.y(), color.z(), 1.0f));
//Renderer::DrawCube(tc, glm::vec4(color.x(), color.y(), color.z(), 1.0f));
}
void BulletDebugDrawer::drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color)
{
if (lifeTime > 3.0f)
return;
glBegin(GL_POINTS);
glColor3f(color.x(), color.y(), color.z());
glVertex3f(PointOnB.x(), PointOnB.y(), PointOnB.z());
glEnd();
}
}
void BulletDebugDrawer::drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color)
{
if (lifeTime > 3.0f)
return;
glBegin(GL_POINTS);
glColor3f(color.x(), color.y(), color.z());
glVertex3f(PointOnB.x(), PointOnB.y(), PointOnB.z());
glEnd();
}

View File

@@ -1,16 +1,20 @@
#pragma once
#include "btBulletCollisionCommon.h"
class BulletDebugDrawer : public btIDebugDraw
namespace Nuake
{
void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) override;
class BulletDebugDrawer : public btIDebugDraw
{
void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) override;
int getDebugMode() const override { return 1; }
int getDebugMode() const override { return 1; }
void draw3dText(const btVector3& location, const char* textString) override {}
void draw3dText(const btVector3& location, const char* textString) override {}
void reportErrorWarning(const char* warningString) override { };
void reportErrorWarning(const char* warningString) override { };
void setDebugMode(int debugMode) {};
void setDebugMode(int debugMode) {};
void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) override;
};
void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) override;
};
}

View File

@@ -1,211 +1,216 @@
#include "CharacterController.h"
#include "../Core/Physics/PhysicsManager.h"
#include "../Core/Physics/RaycastResult.h"
namespace Physics
#include "src/Core/Physics/PhysicsManager.h"
#include "src/Core/Physics/RaycastResult.h"
namespace Nuake
{
CharacterController::CharacterController(float height, float radius, float mass, Vector3 position)
namespace Physics
{
m_surfaceHitNormals = std::vector<glm::vec3>();
m_bottomRoundedRegionYOffset = (height + radius) / 2.0f;
m_bottomYOffset = height / 2.0f + radius;
m_CollisionShape = new btCapsuleShape(radius, height);
btQuaternion quat = btQuaternion(0, 0, 0);
m_Transform = new btTransform();
m_Transform->setOrigin(btVector3(position.x, position.y, position.z));
m_Transform->setRotation(quat);
m_MotionState = new btDefaultMotionState(*m_Transform);
btVector3 inertia;
//m_CollisionShape->calculateLocalInertia(mass, inertia);
btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, m_MotionState, m_CollisionShape, inertia);
rigidBodyCI.m_friction = 0.0f;
//rigidBodyCI.m_additionalDamping = true;
//rigidBodyCI.m_additionalLinearDampingThresholdSqr= 1.0f;
//rigidBodyCI.m_additionalLinearDampingThresholdSqr = 0.5f;
rigidBodyCI.m_restitution = 0.0f;
rigidBodyCI.m_linearDamping = 0.0f;
m_Rigidbody = new btRigidBody(rigidBodyCI);
m_Rigidbody->setGravity(btVector3(0, 0, 0));
// Keep upright
m_Rigidbody->setAngularFactor(0.0f);
// No sleeping (or else setLinearVelocity won't work)
m_Rigidbody->setActivationState(DISABLE_DEACTIVATION);
//m_pPhysicsWorld->m_pDynamicsWorld->addRigidBody(m_pRigidBody);
// Ghost object that is synchronized with rigid body
m_GhostObject = new btPairCachingGhostObject();
m_GhostObject->setCollisionShape(m_CollisionShape);
// Specify filters manually, otherwise ghost doesn't collide with statics for some reason
//m_pPhysicsWorld->m_pDynamicsWorld->addCollisionObject(m_pGhostObject, btBroadphaseProxy::KinematicFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
}
void CharacterController::SetEntity(Entity& ent)
{
m_Rigidbody->setUserIndex(ent.GetHandle());
m_GhostObject->setUserIndex(ent.GetHandle());
}
void CharacterController::MoveAndSlide(glm::vec3 velocity)
{
m_Rigidbody->setGravity(btVector3(0, 0, 0));
m_manualVelocity = velocity;
// Sync ghost with actually object
m_GhostObject->setWorldTransform(m_Rigidbody->getWorldTransform());
IsOnGround = false;
ParseGhostContacts();
UpdatePosition();
UpdateVelocity();
m_MotionState->getWorldTransform(m_motionTransform);
}
void CharacterController::ParseGhostContacts()
{
btManifoldArray manifoldArray;
btBroadphasePairArray& pairArray = m_GhostObject->getOverlappingPairCache()->getOverlappingPairArray();
int numPairs = pairArray.size();
m_hittingWall = false;
for (int i = 0; i < numPairs; i++)
CharacterController::CharacterController(float height, float radius, float mass, Vector3 position)
{
manifoldArray.clear();
m_surfaceHitNormals = std::vector<glm::vec3>();
const btBroadphasePair& pair = pairArray[i];
btDiscreteDynamicsWorld* world = PhysicsManager::Get()->GetWorld()->GetDynamicWorld();
btBroadphasePair* collisionPair = world->getPairCache()->findPair(pair.m_pProxy0, pair.m_pProxy1);
m_bottomRoundedRegionYOffset = (height + radius) / 2.0f;
m_bottomYOffset = height / 2.0f + radius;
m_CollisionShape = new btCapsuleShape(radius, height);
if (collisionPair == NULL)
continue;
btQuaternion quat = btQuaternion(0, 0, 0);
m_Transform = new btTransform();
m_Transform->setOrigin(btVector3(position.x, position.y, position.z));
m_Transform->setRotation(quat);
m_MotionState = new btDefaultMotionState(*m_Transform);
if (collisionPair->m_algorithm != NULL)
collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
btVector3 inertia;
//m_CollisionShape->calculateLocalInertia(mass, inertia);
for (int j = 0; j < manifoldArray.size(); j++)
btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, m_MotionState, m_CollisionShape, inertia);
rigidBodyCI.m_friction = 0.0f;
//rigidBodyCI.m_additionalDamping = true;
//rigidBodyCI.m_additionalLinearDampingThresholdSqr= 1.0f;
//rigidBodyCI.m_additionalLinearDampingThresholdSqr = 0.5f;
rigidBodyCI.m_restitution = 0.0f;
rigidBodyCI.m_linearDamping = 0.0f;
m_Rigidbody = new btRigidBody(rigidBodyCI);
m_Rigidbody->setGravity(btVector3(0, 0, 0));
// Keep upright
m_Rigidbody->setAngularFactor(0.0f);
// No sleeping (or else setLinearVelocity won't work)
m_Rigidbody->setActivationState(DISABLE_DEACTIVATION);
//m_pPhysicsWorld->m_pDynamicsWorld->addRigidBody(m_pRigidBody);
// Ghost object that is synchronized with rigid body
m_GhostObject = new btPairCachingGhostObject();
m_GhostObject->setCollisionShape(m_CollisionShape);
// Specify filters manually, otherwise ghost doesn't collide with statics for some reason
//m_pPhysicsWorld->m_pDynamicsWorld->addCollisionObject(m_pGhostObject, btBroadphaseProxy::KinematicFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
}
void CharacterController::SetEntity(Entity& ent)
{
m_Rigidbody->setUserIndex(ent.GetHandle());
m_GhostObject->setUserIndex(ent.GetHandle());
}
void CharacterController::MoveAndSlide(glm::vec3 velocity)
{
m_Rigidbody->setGravity(btVector3(0, 0, 0));
m_manualVelocity = velocity;
// Sync ghost with actually object
m_GhostObject->setWorldTransform(m_Rigidbody->getWorldTransform());
IsOnGround = false;
ParseGhostContacts();
UpdatePosition();
UpdateVelocity();
m_MotionState->getWorldTransform(m_motionTransform);
}
void CharacterController::ParseGhostContacts()
{
btManifoldArray manifoldArray;
btBroadphasePairArray& pairArray = m_GhostObject->getOverlappingPairCache()->getOverlappingPairArray();
int numPairs = pairArray.size();
m_hittingWall = false;
for (int i = 0; i < numPairs; i++)
{
btPersistentManifold* pManifold = manifoldArray[j];
manifoldArray.clear();
// Skip the rigid body the ghost monitors
if (pManifold->getBody0() == m_Rigidbody)
const btBroadphasePair& pair = pairArray[i];
btDiscreteDynamicsWorld* world = PhysicsManager::Get()->GetWorld()->GetDynamicWorld();
btBroadphasePair* collisionPair = world->getPairCache()->findPair(pair.m_pProxy0, pair.m_pProxy1);
if (collisionPair == NULL)
continue;
for (int p = 0; p < pManifold->getNumContacts(); p++)
if (collisionPair->m_algorithm != NULL)
collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
for (int j = 0; j < manifoldArray.size(); j++)
{
const btManifoldPoint& point = pManifold->getContactPoint(p);
btPersistentManifold* pManifold = manifoldArray[j];
if (point.getDistance() < 0.0f)
// Skip the rigid body the ghost monitors
if (pManifold->getBody0() == m_Rigidbody)
continue;
for (int p = 0; p < pManifold->getNumContacts(); p++)
{
//const btVector3 &ptA = point.getPositionWorldOnA();
const btVector3& ptB = point.getPositionWorldOnB();
const btManifoldPoint& point = pManifold->getContactPoint(p);
//const btVector3 &normalOnB = point.m_normalWorldOnB;
// If point is in rounded bottom region of capsule shape, it is on the ground
if (ptB.getY() < m_motionTransform.getOrigin().getY() - m_bottomRoundedRegionYOffset)
IsOnGround = true;
else
if (point.getDistance() < 0.0f)
{
m_hittingWall = true;
//const btVector3 &ptA = point.getPositionWorldOnA();
const btVector3& ptB = point.getPositionWorldOnB();
m_surfaceHitNormals.push_back(glm::vec3(point.m_normalWorldOnB.x(), point.m_normalWorldOnB.y(), point.m_normalWorldOnB.z()));
//const btVector3 &normalOnB = point.m_normalWorldOnB;
// If point is in rounded bottom region of capsule shape, it is on the ground
if (ptB.getY() < m_motionTransform.getOrigin().getY() - m_bottomRoundedRegionYOffset)
IsOnGround = true;
else
{
m_hittingWall = true;
m_surfaceHitNormals.push_back(glm::vec3(point.m_normalWorldOnB.x(), point.m_normalWorldOnB.y(), point.m_normalWorldOnB.z()));
}
}
}
}
}
}
}
void CharacterController::UpdatePosition()
{
// Ray cast, ignore rigid body
IgnoreBodyAndGhostCast rayCallBack_bottom(m_Rigidbody, m_GhostObject);
btVector3 from = m_Rigidbody->getWorldTransform().getOrigin();
btVector3 toBt = m_Rigidbody->getWorldTransform().getOrigin() - btVector3(0.0f, m_bottomYOffset + m_stepHeight , 0.0f);
PhysicsManager::Get()->GetWorld()->GetDynamicWorld()->rayTest(from, toBt, rayCallBack_bottom);
// Bump up if hit
if (rayCallBack_bottom.hasHit())
void CharacterController::UpdatePosition()
{
float previousY = m_Rigidbody->getWorldTransform().getOrigin().getY();
// Ray cast, ignore rigid body
IgnoreBodyAndGhostCast rayCallBack_bottom(m_Rigidbody, m_GhostObject);
btVector3 from = m_Rigidbody->getWorldTransform().getOrigin();
btVector3 toBt = m_Rigidbody->getWorldTransform().getOrigin() - btVector3(0.0f, m_bottomYOffset + m_stepHeight, 0.0f);
PhysicsManager::Get()->GetWorld()->GetDynamicWorld()->rayTest(from, toBt, rayCallBack_bottom);
float t = rayCallBack_bottom.m_closestHitFraction ;
float clamped = (1.0 - rayCallBack_bottom.m_closestHitFraction);
btVector3 vel(m_Rigidbody->getLinearVelocity());
if(vel.getY() < 0) // -magic number is to fix bouncing down a slope.
m_Rigidbody->getWorldTransform().getOrigin().setY(previousY - 0.14f + (m_bottomYOffset + m_stepHeight) * (clamped));
vel.setY(0.0f);
m_Rigidbody->setLinearVelocity(vel);
IsOnGround = true;
}
float testOffset = 0.07f;
// Ray cast, ignore rigid body
IgnoreBodyAndGhostCast rayCallBack_top(m_Rigidbody, m_GhostObject);
PhysicsManager::Get()->GetWorld()->GetDynamicWorld()->rayTest(m_Rigidbody->getWorldTransform().getOrigin(), m_Rigidbody->getWorldTransform().getOrigin() + btVector3(0.0f, m_bottomYOffset + testOffset, 0.0f), rayCallBack_top);
// Bump up if hit
if (rayCallBack_top.hasHit())
{
m_Rigidbody->getWorldTransform().setOrigin(m_previousPosition);
btVector3 vel(m_Rigidbody->getLinearVelocity());
vel.setY(0.0f);
m_Rigidbody->setLinearVelocity(vel);
}
m_previousPosition = m_Rigidbody->getWorldTransform().getOrigin();
}
void CharacterController::UpdateVelocity()
{
//m_manualVelocity.y = m_Rigidbody->getLinearVelocity().getY();
btVector3 grav = m_Rigidbody->getGravity();
btVector3 finalVel = btVector3(m_manualVelocity.x, m_manualVelocity.y, m_manualVelocity.z);
m_Rigidbody->setLinearVelocity(finalVel);
// Decelerate
//m_manualVelocity -= m_manualVelocity * m_deceleration * m_pPhysicsWorld->GetScene()->m_frameTimer.GetTimeMultiplier();
if (m_hittingWall)
{
for (unsigned int i = 0, size = m_surfaceHitNormals.size(); i < size; i++)
// Bump up if hit
if (rayCallBack_bottom.hasHit())
{
// Cancel velocity across normal
glm::vec3 velInNormalDir(glm::reflect(m_manualVelocity, m_surfaceHitNormals[i]));
float previousY = m_Rigidbody->getWorldTransform().getOrigin().getY();
float t = rayCallBack_bottom.m_closestHitFraction;
float clamped = (1.0 - rayCallBack_bottom.m_closestHitFraction);
btVector3 vel(m_Rigidbody->getLinearVelocity());
if (vel.getY() < 0) // -magic number is to fix bouncing down a slope.
m_Rigidbody->getWorldTransform().getOrigin().setY(previousY - 0.14f + (m_bottomYOffset + m_stepHeight) * (clamped));
vel.setY(0.0f);
m_Rigidbody->setLinearVelocity(vel);
IsOnGround = true;
// Apply correction
m_manualVelocity -= velInNormalDir * 1.05f;
}
// Do not adjust rigid body velocity manually (so bodies can still be pushed by character)
return;
float testOffset = 0.07f;
// Ray cast, ignore rigid body
IgnoreBodyAndGhostCast rayCallBack_top(m_Rigidbody, m_GhostObject);
PhysicsManager::Get()->GetWorld()->GetDynamicWorld()->rayTest(m_Rigidbody->getWorldTransform().getOrigin(), m_Rigidbody->getWorldTransform().getOrigin() + btVector3(0.0f, m_bottomYOffset + testOffset, 0.0f), rayCallBack_top);
// Bump up if hit
if (rayCallBack_top.hasHit())
{
m_Rigidbody->getWorldTransform().setOrigin(m_previousPosition);
btVector3 vel(m_Rigidbody->getLinearVelocity());
vel.setY(0.0f);
m_Rigidbody->setLinearVelocity(vel);
}
m_previousPosition = m_Rigidbody->getWorldTransform().getOrigin();
}
void CharacterController::UpdateVelocity()
{
//m_manualVelocity.y = m_Rigidbody->getLinearVelocity().getY();
btVector3 grav = m_Rigidbody->getGravity();
btVector3 finalVel = btVector3(m_manualVelocity.x, m_manualVelocity.y, m_manualVelocity.z);
m_Rigidbody->setLinearVelocity(finalVel);
// Decelerate
//m_manualVelocity -= m_manualVelocity * m_deceleration * m_pPhysicsWorld->GetScene()->m_frameTimer.GetTimeMultiplier();
if (m_hittingWall)
{
for (unsigned int i = 0, size = m_surfaceHitNormals.size(); i < size; i++)
{
// Cancel velocity across normal
glm::vec3 velInNormalDir(glm::reflect(m_manualVelocity, m_surfaceHitNormals[i]));
// Apply correction
m_manualVelocity -= velInNormalDir * 1.05f;
}
// Do not adjust rigid body velocity manually (so bodies can still be pushed by character)
return;
}
}
}
}

View File

@@ -1,56 +1,57 @@
#pragma once
#include <glm/ext/vector_float3.hpp>
#include "../Core/Core.h"
#include "src/Core/Core.h"
#include "src/Core/Maths.h"
#include <btBulletDynamicsCommon.h>
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
#include <vector>
#include "../Core/Maths.h"
class Entity;
namespace Physics
namespace Nuake
{
class CharacterController
class Entity;
namespace Physics
{
public:
bool IsOnGround = false;
bool m_hittingWall;
float m_stepHeight = 0.35f;
float m_MaxSlopeAngle = 45.0f;
btTransform* m_Transform;
btCollisionShape* m_CollisionShape;
btRigidBody* m_Rigidbody;
btPairCachingGhostObject* m_GhostObject;
btMotionState* m_MotionState;
//bool m_onJumpableGround; // A bit lower contact than just onGround
float m_bottomYOffset;
float m_bottomRoundedRegionYOffset ;
btTransform m_motionTransform;
glm::vec3 m_manualVelocity;
std::vector<glm::vec3> m_surfaceHitNormals;
btVector3 m_previousPosition;
float m_jumpRechargeTimer;
CharacterController(float height, float radius, float mass, Vector3 position);
void SetEntity(Entity& ent);
void MoveAndSlide(glm::vec3 velocity);
bool IsOnFloor()
class CharacterController
{
return IsOnGround;
}
public:
bool IsOnGround = false;
bool m_hittingWall;
float m_stepHeight = 0.35f;
float m_MaxSlopeAngle = 45.0f;
private:
void ParseGhostContacts();
void UpdatePosition();
void UpdateVelocity();
};
}
btTransform* m_Transform;
btCollisionShape* m_CollisionShape;
btRigidBody* m_Rigidbody;
btPairCachingGhostObject* m_GhostObject;
btMotionState* m_MotionState;
//bool m_onJumpableGround; // A bit lower contact than just onGround
float m_bottomYOffset;
float m_bottomRoundedRegionYOffset;
btTransform m_motionTransform;
glm::vec3 m_manualVelocity;
std::vector<glm::vec3> m_surfaceHitNormals;
btVector3 m_previousPosition;
float m_jumpRechargeTimer;
CharacterController(float height, float radius, float mass, Vector3 position);
void SetEntity(Entity& ent);
void MoveAndSlide(glm::vec3 velocity);
bool IsOnFloor()
{
return IsOnGround;
}
private:
void ParseGhostContacts();
void UpdatePosition();
void UpdateVelocity();
};
}
}

View File

@@ -5,128 +5,131 @@
#include <src/Vendors/glm/ext/quaternion_common.hpp>
#include <src/Core/Logger.h>
namespace Physics
namespace Nuake
{
DynamicWorld::DynamicWorld() {
///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep.
btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
dynamicsWorld->setDebugDrawer(new BulletDebugDrawer());
m_Bodies = std::map<btRigidBody*, Ref<RigidBody>>();
SetGravity(Vector3(0, -10000, 0));
}
void DynamicWorld::DrawDebug()
namespace Physics
{
dynamicsWorld->debugDrawWorld();
}
DynamicWorld::DynamicWorld() {
///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
void DynamicWorld::SetGravity(glm::vec3 g)
{
dynamicsWorld->setGravity(btVector3(g.x, g.y, g.z));
}
///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep.
btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
void DynamicWorld::AddRigidbody(Ref<RigidBody> rb)
{
btRigidBody* bt = rb->GetBulletRigidbody();
m_Bodies.emplace(std::pair<btRigidBody*, Ref<RigidBody>>(bt, rb));
dynamicsWorld->addRigidBody(rb->GetBulletRigidbody());
}
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
dynamicsWorld->setDebugDrawer(new BulletDebugDrawer());
void DynamicWorld::AddGhostbody(Ref<GhostObject> gb)
{
dynamicsWorld->addCollisionObject(gb->GetBulletObject(), btBroadphaseProxy::SensorTrigger, btBroadphaseProxy::KinematicFilter);
}
m_Bodies = std::map<btRigidBody*, Ref<RigidBody>>();
void DynamicWorld::AddCharacterController(Ref<CharacterController> cc)
{
dynamicsWorld->addRigidBody(cc->m_Rigidbody);
// Specify filters manually, otherwise ghost doesn't collide with statics for some reason
dynamicsWorld->addCollisionObject(cc->m_GhostObject, btBroadphaseProxy::KinematicFilter, btBroadphaseProxy::SensorTrigger | btBroadphaseProxy::StaticFilter );
}
RaycastResult DynamicWorld::Raycast(glm::vec3 from, glm::vec3 to)
{
btVector3 btFrom(from.x, from.y, from.z);
btVector3 btTo(to.x, to.y, to.z);
ClosestRayResultCallback res(btFrom, btTo);
dynamicsWorld->rayTest(btFrom, btTo, res);
btVector3 localNormal;
if(res.m_collisionObject)
{
// TODO: Fix the godammn fucked up normal
localNormal = res.m_hitNormalWorld;
SetGravity(Vector3(0, -10000, 0));
}
Vector3 localNorm = glm::vec3(localNormal.x(), localNormal.y(), localNormal.z());
//Logger::Log("normal: x:" + std::to_string(localNorm.x) + " y:" + std::to_string(localNorm.y )+ "z: " + std::to_string(localNorm.z));
res.m_closestHitFraction;
// Map bullet result to dto.
RaycastResult result{
glm::vec3(res.m_hitPointWorld.x(), res.m_hitPointWorld.y(), res.m_hitPointWorld.z()),
glm::vec3(res.m_hitPointWorld.x(), res.m_hitPointWorld.y(), res.m_hitPointWorld.z()),
localNorm
};
return result;
}
void DynamicWorld::StepSimulation(Timestep ts)
{
dynamicsWorld->stepSimulation(ts, 10);
for (int j = dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; j--)
void DynamicWorld::DrawDebug()
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
btRigidBody* body = btRigidBody::upcast(obj);
btTransform trans;
if (body && body->getMotionState())
{
body->getMotionState()->getWorldTransform(trans);
if(m_Bodies.find(body) != m_Bodies.end())
m_Bodies[body]->UpdateTransform(trans);
}
else
{
trans = obj->getWorldTransform();
if (m_Bodies.find(body) != m_Bodies.end())
m_Bodies[body]->UpdateTransform(trans);
}
//printf("world pos object %d = %f,%f,%f\n", j, float(trans.getOrigin().getX()), float(trans.getOrigin().getY()), float(trans.getOrigin().getZ()));
dynamicsWorld->debugDrawWorld();
}
}
void DynamicWorld::Clear()
{
for (int j = dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; j--)
void DynamicWorld::SetGravity(glm::vec3 g)
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
dynamicsWorld->removeCollisionObject(obj);
dynamicsWorld->setGravity(btVector3(g.x, g.y, g.z));
}
m_Bodies.clear();
void DynamicWorld::AddRigidbody(Ref<RigidBody> rb)
{
btRigidBody* bt = rb->GetBulletRigidbody();
m_Bodies.emplace(std::pair<btRigidBody*, Ref<RigidBody>>(bt, rb));
dynamicsWorld->addRigidBody(rb->GetBulletRigidbody());
}
void DynamicWorld::AddGhostbody(Ref<GhostObject> gb)
{
dynamicsWorld->addCollisionObject(gb->GetBulletObject(), btBroadphaseProxy::SensorTrigger, btBroadphaseProxy::KinematicFilter);
}
void DynamicWorld::AddCharacterController(Ref<CharacterController> cc)
{
dynamicsWorld->addRigidBody(cc->m_Rigidbody);
// Specify filters manually, otherwise ghost doesn't collide with statics for some reason
dynamicsWorld->addCollisionObject(cc->m_GhostObject, btBroadphaseProxy::KinematicFilter, btBroadphaseProxy::SensorTrigger | btBroadphaseProxy::StaticFilter);
}
RaycastResult DynamicWorld::Raycast(glm::vec3 from, glm::vec3 to)
{
btVector3 btFrom(from.x, from.y, from.z);
btVector3 btTo(to.x, to.y, to.z);
ClosestRayResultCallback res(btFrom, btTo);
dynamicsWorld->rayTest(btFrom, btTo, res);
btVector3 localNormal;
if (res.m_collisionObject)
{
// TODO: Fix the godammn fucked up normal
localNormal = res.m_hitNormalWorld;
}
Vector3 localNorm = glm::vec3(localNormal.x(), localNormal.y(), localNormal.z());
//Logger::Log("normal: x:" + std::to_string(localNorm.x) + " y:" + std::to_string(localNorm.y )+ "z: " + std::to_string(localNorm.z));
res.m_closestHitFraction;
// Map bullet result to dto.
RaycastResult result{
glm::vec3(res.m_hitPointWorld.x(), res.m_hitPointWorld.y(), res.m_hitPointWorld.z()),
glm::vec3(res.m_hitPointWorld.x(), res.m_hitPointWorld.y(), res.m_hitPointWorld.z()),
localNorm
};
return result;
}
void DynamicWorld::StepSimulation(Timestep ts)
{
dynamicsWorld->stepSimulation(ts, 10);
for (int j = dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; j--)
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
btRigidBody* body = btRigidBody::upcast(obj);
btTransform trans;
if (body && body->getMotionState())
{
body->getMotionState()->getWorldTransform(trans);
if (m_Bodies.find(body) != m_Bodies.end())
m_Bodies[body]->UpdateTransform(trans);
}
else
{
trans = obj->getWorldTransform();
if (m_Bodies.find(body) != m_Bodies.end())
m_Bodies[body]->UpdateTransform(trans);
}
//printf("world pos object %d = %f,%f,%f\n", j, float(trans.getOrigin().getX()), float(trans.getOrigin().getY()), float(trans.getOrigin().getZ()));
}
}
void DynamicWorld::Clear()
{
for (int j = dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; j--)
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
dynamicsWorld->removeCollisionObject(obj);
}
m_Bodies.clear();
}
}
}

View File

@@ -2,34 +2,39 @@
#include <btBulletDynamicsCommon.h>
#include <glm/ext/vector_float3.hpp>
#include "Rigibody.h"
#include "../Timestep.h"
#include "../Core/Core.h"
#include "src/Core/Timestep.h"
#include "src/Core/Core.h"
#include <map>
#include "RaycastResult.h"
#include <src/Core/Physics/GhostObject.h>
#include "CharacterController.h"
namespace Physics {
class DynamicWorld {
private:
btDiscreteDynamicsWorld* dynamicsWorld;
std::map<btRigidBody*, Ref<RigidBody>> m_Bodies;
public:
DynamicWorld();
void DrawDebug();
namespace Nuake
{
namespace Physics {
class DynamicWorld {
private:
btDiscreteDynamicsWorld* dynamicsWorld;
std::map<btRigidBody*, Ref<RigidBody>> m_Bodies;
public:
DynamicWorld();
void SetGravity(glm::vec3 g);
void AddRigidbody(Ref<RigidBody> rb);
void DrawDebug();
void AddGhostbody(Ref<GhostObject> gb);
void SetGravity(glm::vec3 g);
void AddRigidbody(Ref<RigidBody> rb);
void AddCharacterController(Ref < CharacterController> cc);
void AddGhostbody(Ref<GhostObject> gb);
RaycastResult Raycast(glm::vec3 from, glm::vec3 to);
void StepSimulation(Timestep ts);
void Clear();
void AddCharacterController(Ref < CharacterController> cc);
btDiscreteDynamicsWorld* GetDynamicWorld() { return dynamicsWorld; }
};
RaycastResult Raycast(glm::vec3 from, glm::vec3 to);
void StepSimulation(Timestep ts);
void Clear();
btDiscreteDynamicsWorld* GetDynamicWorld() { return dynamicsWorld; }
};
}
}

View File

@@ -4,57 +4,59 @@
#include <dependencies/bullet3/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
#include <src/Core/Physics/PhysicsManager.h>
GhostObject::GhostObject(Vector3 position, Ref<Physics::PhysicShape> shape)
namespace Nuake
{
m_OverlappingEntities = std::vector<Entity>();
m_BulletObject = new btGhostObject();
btTransform transform = btTransform();
transform.setIdentity();
transform.setOrigin(btVector3(position.x, position.y, position.z));
m_BulletObject->setWorldTransform(transform);
m_BulletObject->setCollisionShape(shape->GetBulletShape());
}
int GhostObject::OverlappingCount()
{
return m_BulletObject->getNumOverlappingObjects();
}
void GhostObject::ClearOverlappingList()
{
m_OverlappingEntities.clear();
}
void GhostObject::SetEntityID(Entity ent)
{
m_BulletObject->setUserIndex(ent.GetHandle());
}
void GhostObject::ScanOverlap()
{
ClearOverlappingList();
for (int i = 0; i < OverlappingCount(); i++)
GhostObject::GhostObject(Vector3 position, Ref<Physics::PhysicShape> shape)
{
int index = m_BulletObject->getOverlappingObject(i)->getUserIndex();
if (index == -1)
continue;
m_OverlappingEntities = std::vector<Entity>();
m_BulletObject = new btGhostObject();
Entity handle = Engine::GetCurrentScene()->GetEntity(index);
m_OverlappingEntities.push_back(handle);
btTransform transform = btTransform();
transform.setIdentity();
transform.setOrigin(btVector3(position.x, position.y, position.z));
m_BulletObject->setWorldTransform(transform);
m_BulletObject->setCollisionShape(shape->GetBulletShape());
}
int GhostObject::OverlappingCount()
{
return m_BulletObject->getNumOverlappingObjects();
}
void GhostObject::ClearOverlappingList()
{
m_OverlappingEntities.clear();
}
void GhostObject::SetEntityID(Entity ent)
{
m_BulletObject->setUserIndex(ent.GetHandle());
}
void GhostObject::ScanOverlap()
{
ClearOverlappingList();
for (int i = 0; i < OverlappingCount(); i++)
{
int index = m_BulletObject->getOverlappingObject(i)->getUserIndex();
if (index == -1)
continue;
Entity handle = Engine::GetCurrentScene()->GetEntity(index);
m_OverlappingEntities.push_back(handle);
}
}
std::vector<Entity> GhostObject::GetOverlappingEntities()
{
return m_OverlappingEntities;
}
// Internal use only.
btGhostObject* GhostObject::GetBulletObject()
{
return m_BulletObject;
}
}
std::vector<Entity> GhostObject::GetOverlappingEntities()
{
return m_OverlappingEntities;
}
// Internal use only.
btGhostObject* GhostObject::GetBulletObject()
{
return m_BulletObject;
}

View File

@@ -1,27 +1,33 @@
#pragma once
#include "src/Core/Core.h"
#include "src/Core/Maths.h"
#include "PhysicsShapes.h"
#include <vector>
#include <Engine.h>
class btGhostObject;
class GhostObject {
private:
btGhostObject* m_BulletObject;
std::vector<Entity> m_OverlappingEntities;
public:
GhostObject(Vector3 position, Ref<Physics::PhysicShape> shape);
namespace Nuake
{
class GhostObject {
private:
btGhostObject* m_BulletObject;
std::vector<Entity> m_OverlappingEntities;
int OverlappingCount();
void ClearOverlappingList();
void ScanOverlap();
public:
GhostObject(Vector3 position, Ref<Physics::PhysicShape> shape);
void SetEntityID(Entity ent);
int OverlappingCount();
void ClearOverlappingList();
void ScanOverlap();
std::vector<Entity> GetOverlappingEntities();
void SetEntityID(Entity ent);
// Internal use only.
btGhostObject* GetBulletObject();
};
std::vector<Entity> GetOverlappingEntities();
// Internal use only.
btGhostObject* GetBulletObject();
};
}

View File

@@ -2,54 +2,58 @@
#include "PhysicsShapes.h"
#include "btBulletDynamicsCommon.h"
#include "../Core/Core.h"
PhysicsManager* PhysicsManager::m_Instance;
void PhysicsManager::RegisterBody(Ref<Physics::RigidBody> rb) {
m_World->AddRigidbody(rb);
}
void PhysicsManager::RegisterGhostBody(Ref<GhostObject> rb)
namespace Nuake
{
m_World->AddGhostbody(rb);
PhysicsManager* PhysicsManager::m_Instance;
void PhysicsManager::RegisterBody(Ref<Physics::RigidBody> rb) {
m_World->AddRigidbody(rb);
}
void PhysicsManager::RegisterGhostBody(Ref<GhostObject> rb)
{
m_World->AddGhostbody(rb);
}
void PhysicsManager::RegisterCharacterController(Ref<Physics::CharacterController> cc) {
m_World->AddCharacterController(cc);
}
void PhysicsManager::Step(Timestep ts)
{
m_World->StepSimulation(ts);
}
void PhysicsManager::Reset()
{
m_World->Clear();
}
RaycastResult PhysicsManager::Raycast(glm::vec3 from, glm::vec3 to)
{
btVector3 btFrom(from.x, from.y, from.z);
btVector3 btTo(to.x, to.y, to.z);
btCollisionWorld::ClosestRayResultCallback res(btFrom, btTo);
return m_World->Raycast(from, to);
}
void PhysicsManager::DrawDebug()
{
if (m_DrawDebug)
m_World->DrawDebug();
}
void PhysicsManager::Init() {
m_World = new Physics::DynamicWorld();
m_World->SetGravity(glm::vec3(0, -3, 0));
m_World->GetDynamicWorld()->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
m_IsRunning = false;
}
}
void PhysicsManager::RegisterCharacterController(Ref<Physics::CharacterController> cc) {
m_World->AddCharacterController(cc);
}
void PhysicsManager::Step(Timestep ts)
{
m_World->StepSimulation(ts);
}
void PhysicsManager::Reset()
{
m_World->Clear();
}
RaycastResult PhysicsManager::Raycast(glm::vec3 from, glm::vec3 to)
{
btVector3 btFrom(from.x, from.y, from.z);
btVector3 btTo(to.x, to.y, to.z);
btCollisionWorld::ClosestRayResultCallback res(btFrom, btTo);
return m_World->Raycast(from, to);
}
void PhysicsManager::DrawDebug()
{
if(m_DrawDebug)
m_World->DrawDebug();
}
void PhysicsManager::Init() {
m_World = new Physics::DynamicWorld();
m_World->SetGravity(glm::vec3(0, -3, 0));
m_World->GetDynamicWorld()->getBroadphase()->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
m_IsRunning = false;
}

View File

@@ -5,48 +5,52 @@
#include "Rigibody.h"
#include "RaycastResult.h"
class PhysicsManager
namespace Nuake
{
private:
Physics::DynamicWorld* m_World;
bool m_IsRunning = false;
btAlignedObjectArray<btCollisionShape*> collisionShapes;
bool m_DrawDebug = false;
static PhysicsManager* m_Instance;
public:
static PhysicsManager* Get()
class PhysicsManager
{
if (!m_Instance)
m_Instance = new PhysicsManager();
return m_Instance;
}
private:
Physics::DynamicWorld* m_World;
bool m_IsRunning = false;
btAlignedObjectArray<btCollisionShape*> collisionShapes;
Physics::DynamicWorld* GetWorld() { return m_World; }
bool m_DrawDebug = false;
static PhysicsManager* m_Instance;
public:
static PhysicsManager* Get()
{
if (!m_Instance)
m_Instance = new PhysicsManager();
return m_Instance;
}
PhysicsManager() { if (!m_Instance) m_Instance = this; }
Physics::DynamicWorld* GetWorld() { return m_World; }
void SetDrawDebug(bool value) {
m_DrawDebug = value;
}
PhysicsManager() { if (!m_Instance) m_Instance = this; }
bool GetDrawDebug() {
return m_DrawDebug;
}
void SetDrawDebug(bool value) {
m_DrawDebug = value;
}
void Init();
bool GetDrawDebug() {
return m_DrawDebug;
}
void Start() { m_IsRunning = true; }
void Stop() { m_IsRunning = false; }
void DrawDebug();
bool IsRunning() { return m_IsRunning; }
void Step(Timestep ts);
void Init();
void Reset();
void Start() { m_IsRunning = true; }
void Stop() { m_IsRunning = false; }
void DrawDebug();
bool IsRunning() { return m_IsRunning; }
void Step(Timestep ts);
RaycastResult Raycast(glm::vec3 from, glm::vec3 to);
void Reset();
void RegisterBody(Ref<Physics::RigidBody> rb);
void RegisterGhostBody(Ref<GhostObject> rb);
void RegisterCharacterController(Ref<Physics::CharacterController> c);
};
RaycastResult Raycast(glm::vec3 from, glm::vec3 to);
void RegisterBody(Ref<Physics::RigidBody> rb);
void RegisterGhostBody(Ref<GhostObject> rb);
void RegisterCharacterController(Ref<Physics::CharacterController> c);
};
}

View File

@@ -1,60 +1,67 @@
#include "PhysicsShapes.h"
#include "btBulletDynamicsCommon.h"
Physics::Box::Box()
namespace Nuake
{
Size = glm::vec3(1);
bShape = new btBoxShape(btVector3(Size.x, Size.y, Size.z));
m_Type = BOX;
}
// Sphere
Physics::Box::Box(glm::vec3 size) {
Size = size;
bShape = new btBoxShape(btVector3(size.x, size.y, size.z));
m_Type = BOX;
}
Physics::Box::Box(float x, float y, float z) {
Size = glm::vec3(x, y, z);
bShape = new btBoxShape(btVector3(x, y, z));
m_Type = BOX;
}
btCollisionShape* Physics::Box::GetBulletShape()
{
return bShape;
}
// Sphere
Physics::Sphere::Sphere(float radius) {
Radius = radius;
bShape = new btSphereShape(Radius);
m_Type = SPHERE;
}
void Physics::Sphere::SetRadius(float radius) {
((btSphereShape*)bShape)->setUnscaledRadius(radius);
Radius = radius;
}
btCollisionShape* Physics::Sphere::GetBulletShape()
{
return bShape;
}
Physics::MeshShape::MeshShape(Ref<Mesh> mesh)
{
m_Mesh = mesh;
btConvexHullShape* trimesh = new btConvexHullShape();
for (Vertex i : mesh->m_Vertices)
namespace Physics
{
trimesh->addPoint(btVector3(i.position.x, i.position.y, i.position.z));
}
bShape = trimesh;
}
Box::Box()
{
Size = glm::vec3(1);
bShape = new btBoxShape(btVector3(Size.x, Size.y, Size.z));
m_Type = BOX;
}
// Sphere
Box::Box(glm::vec3 size) {
Size = size;
bShape = new btBoxShape(btVector3(size.x, size.y, size.z));
m_Type = BOX;
}
btCollisionShape* Physics::MeshShape::GetBulletShape()
{
return bShape;
}
Box::Box(float x, float y, float z) {
Size = glm::vec3(x, y, z);
bShape = new btBoxShape(btVector3(x, y, z));
m_Type = BOX;
}
btCollisionShape* Box::GetBulletShape()
{
return bShape;
}
// Sphere
Sphere::Sphere(float radius) {
Radius = radius;
bShape = new btSphereShape(Radius);
m_Type = SPHERE;
}
void Sphere::SetRadius(float radius) {
((btSphereShape*)bShape)->setUnscaledRadius(radius);
Radius = radius;
}
btCollisionShape* Sphere::GetBulletShape()
{
return bShape;
}
MeshShape::MeshShape(Ref<Mesh> mesh)
{
m_Mesh = mesh;
btConvexHullShape* trimesh = new btConvexHullShape();
for (Vertex i : mesh->m_Vertices)
{
trimesh->addPoint(btVector3(i.position.x, i.position.y, i.position.z));
}
bShape = trimesh;
}
btCollisionShape* MeshShape::GetBulletShape()
{
return bShape;
}
}
}

View File

@@ -1,58 +1,70 @@
#pragma once
#include "src/Core/Maths.h"
#include "src/Rendering/Mesh/Mesh.h"
#include <glm/ext/vector_float3.hpp>
#include "../../Rendering/Mesh/Mesh.h"
class btCollisionShape;
namespace Physics {
enum RigidbodyShapes {
BOX, SPHERE, CAPSULE, MESH
};
class PhysicShape {
protected:
btCollisionShape* bShape;
RigidbodyShapes m_Type;
public:
virtual btCollisionShape* GetBulletShape() = 0;
RigidbodyShapes GetType() const { return m_Type; }
};
class Box : public PhysicShape {
private:
glm::vec3 Size;
btCollisionShape* bShape;
public:
Box();
Box(glm::vec3 size);
Box(float x, float y, float z);
namespace Nuake
{
namespace Physics
{
enum RigidbodyShapes
{
BOX, SPHERE, CAPSULE, MESH
};
glm::vec3 GetSize() const { return Size; }
btCollisionShape* GetBulletShape() override;
};
class PhysicShape
{
protected:
btCollisionShape* bShape;
RigidbodyShapes m_Type;
public:
virtual btCollisionShape* GetBulletShape() = 0;
RigidbodyShapes GetType() const { return m_Type; }
class Sphere : public PhysicShape {
private:
float Radius;
btCollisionShape* bShape;
public:
Sphere(float radius);
};
float GetRadius() const { return Radius; }
void SetRadius(float radius);
class Box : public PhysicShape
{
private:
glm::vec3 Size;
btCollisionShape* bShape;
public:
Box();
Box(glm::vec3 size);
Box(float x, float y, float z);
btCollisionShape* GetBulletShape() override;
};
glm::vec3 GetSize() const { return Size; }
btCollisionShape* GetBulletShape() override;
};
class MeshShape : public PhysicShape {
private:
Ref<Mesh> m_Mesh;
btCollisionShape* bShape;
public:
MeshShape(Ref<Mesh> mesh);
class Sphere : public PhysicShape
{
private:
float Radius;
btCollisionShape* bShape;
public:
Sphere(float radius);
void SetMesh(Mesh* mesh);
Mesh* GetMesh();
float GetRadius() const { return Radius; }
void SetRadius(float radius);
btCollisionShape* GetBulletShape() override;
};
class MeshShape : public PhysicShape
{
private:
Ref<Mesh> m_Mesh;
btCollisionShape* bShape;
public:
MeshShape(Ref<Mesh> mesh);
void SetMesh(Mesh* mesh);
Mesh* GetMesh();
btCollisionShape* GetBulletShape() override;
};
}
btCollisionShape* GetBulletShape() override;
};
}

View File

@@ -3,66 +3,70 @@
#include "CharacterController.h"
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
namespace Physics
namespace Nuake
{
struct ClosestRayResultCallback : public btCollisionWorld::RayResultCallback
namespace Physics
{
ClosestRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
: m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld)
struct ClosestRayResultCallback : public btCollisionWorld::RayResultCallback
{
}
ClosestRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
: m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld)
{
}
btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction
btVector3 m_rayToWorld;
btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction
btVector3 m_rayToWorld;
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
btVector3 m_hitNormalWorld;
btVector3 m_hitPointWorld;
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
{
//caller already does the filter on the m_closestHitFraction
btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
m_closestHitFraction = rayResult.m_hitFraction;
m_collisionObject = rayResult.m_collisionObject;
m_hitNormalWorld = rayResult.m_hitNormalLocal;
m_hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction);
return rayResult.m_hitFraction;
}
};
class IgnoreBodyAndGhostCast :
public Physics::ClosestRayResultCallback
{
//caller already does the filter on the m_closestHitFraction
btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
private:
btRigidBody* m_pBody;
btPairCachingGhostObject* m_pGhostObject;
m_closestHitFraction = rayResult.m_hitFraction;
m_collisionObject = rayResult.m_collisionObject;
public:
IgnoreBodyAndGhostCast(btRigidBody* pBody, btPairCachingGhostObject* pGhostObject)
: ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)),
m_pBody(pBody), m_pGhostObject(pGhostObject)
{
}
m_hitNormalWorld = rayResult.m_hitNormalLocal;
btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
{
if (rayResult.m_collisionObject == m_pBody || rayResult.m_collisionObject == m_pGhostObject)
return 1.0f;
return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
}
};
}
m_hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction);
return rayResult.m_hitFraction;
}
};
class IgnoreBodyAndGhostCast :
public Physics::ClosestRayResultCallback
{
private:
btRigidBody* m_pBody;
btPairCachingGhostObject* m_pGhostObject;
public:
IgnoreBodyAndGhostCast(btRigidBody* pBody, btPairCachingGhostObject* pGhostObject)
: ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)),
m_pBody(pBody), m_pGhostObject(pGhostObject)
{
}
btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
{
if (rayResult.m_collisionObject == m_pBody || rayResult.m_collisionObject == m_pGhostObject)
return 1.0f;
return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
}
// result object from raycast.
struct RaycastResult {
glm::vec3 WorldPoint;
glm::vec3 LocalPoint;
glm::vec3 Normal;
};
}
// result object from raycast.
struct RaycastResult {
glm::vec3 WorldPoint;
glm::vec3 LocalPoint;
glm::vec3 Normal;
};

View File

@@ -5,44 +5,48 @@
struct btTransform;
struct btRigidBody;
struct btVector3;
class Entity;
namespace Physics {
class RigidBody {
private:
bool m_IsDynamic = false;
bool m_IsKinematic = false;
glm::vec3 m_InitialVel;
btRigidBody* m_Rigidbody;
namespace Nuake
{
class Entity;
namespace Physics {
class RigidBody {
private:
bool m_IsDynamic = false;
bool m_IsKinematic = false;
glm::vec3 m_InitialVel;
Ref<PhysicShape> m_CollisionShape;
public:
btTransform* m_Transform;
float m_Mass;
btRigidBody* m_Rigidbody;
RigidBody();
RigidBody(glm::vec3 position, Entity handle);
RigidBody(float mass, glm::vec3 position, Ref<PhysicShape> shape, glm::vec3 initialVel = glm::vec3(0, 0, 0));
Ref<PhysicShape> m_CollisionShape;
public:
btTransform* m_Transform;
float m_Mass;
btRigidBody* GetBulletRigidbody() const { return m_Rigidbody; }
void UpdateTransform(btTransform t);
glm::vec3 GetPosition() const;
glm::vec3 GetRotation() const;
RigidBody();
RigidBody(glm::vec3 position, Entity handle);
RigidBody(float mass, glm::vec3 position, Ref<PhysicShape> shape, glm::vec3 initialVel = glm::vec3(0, 0, 0));
void SetEntityID(Entity ent);
btRigidBody* GetBulletRigidbody() const { return m_Rigidbody; }
void SetKinematic(bool value);
bool IsKinematic() const { return m_IsKinematic; }
void UpdateTransform(btTransform t);
glm::vec3 GetPosition() const;
glm::vec3 GetRotation() const;
bool HasShape() { return m_CollisionShape != nullptr; }
void SetShape(Ref<PhysicShape> shape);
Ref<PhysicShape> GetShape() const { return m_CollisionShape; }
void SetEntityID(Entity ent);
float GetMass() const { return m_Mass; }
void SetMass(float m);
void SetKinematic(bool value);
bool IsKinematic() const { return m_IsKinematic; }
bool HasShape() { return m_CollisionShape != nullptr; }
void SetShape(Ref<PhysicShape> shape);
Ref<PhysicShape> GetShape() const { return m_CollisionShape; }
float GetMass() const { return m_Mass; }
void SetMass(float m);
void MoveAndSlide(glm::vec3 velocity);
};
}
void MoveAndSlide(glm::vec3 velocity);
};
}

View File

@@ -4,116 +4,120 @@
#include "../Core.h"
#include <glm/trigonometric.hpp>
#include <src/Scene/Entities/Entity.h>
namespace Physics
namespace Nuake
{
RigidBody::RigidBody()
namespace Physics
{
m_Transform = new btTransform();
m_Transform->setIdentity();
//m_Transform->setOrigin(btVector3(position.x, position.y, position.z));
}
RigidBody::RigidBody(glm::vec3 position, Entity handle)
{
Ref<Box> shape = CreateRef<Box>();
m_CollisionShape = shape;
m_Transform = new btTransform();
m_Transform->setIdentity();
m_Transform->setOrigin(btVector3(position.x, position.y, position.z));
m_Mass = 0.0f;
//rigidbody is dynamic if and only if mass is non zero, otherwise static
m_IsDynamic = (m_Mass != 0.0f);
btVector3 localInertia(0, 0, 0);
if (m_IsDynamic)
m_CollisionShape->GetBulletShape()->calculateLocalInertia(m_Mass, localInertia);
m_InitialVel = glm::vec3(0, 0, 0);
//using motionstate is optional, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(*m_Transform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(m_Mass, myMotionState, m_CollisionShape->GetBulletShape(), localInertia);
m_Rigidbody = new btRigidBody(rbInfo);
m_Rigidbody->setUserIndex(handle.GetHandle());
}
RigidBody::RigidBody(float mass, glm::vec3 position, Ref<PhysicShape> shape, glm::vec3 initialVel)
{
m_CollisionShape = shape;
m_Transform = new btTransform();
m_Transform->setIdentity();
m_Transform->setOrigin(btVector3(position.x, position.y, position.z));
m_Mass = mass;
//rigidbody is dynamic if and only if mass is non zero, otherwise static
m_IsDynamic = (m_Mass != 0.0f);
btVector3 localInertia(initialVel.x, initialVel.y, initialVel.z);
m_InitialVel = initialVel;
if (m_IsDynamic)
m_CollisionShape->GetBulletShape()->calculateLocalInertia(m_Mass, localInertia);
//using motionstate is optional, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(*m_Transform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(m_Mass, myMotionState, m_CollisionShape->GetBulletShape(), localInertia);
m_Rigidbody = new btRigidBody(rbInfo);
}
void RigidBody::SetShape(Ref<PhysicShape> shape)
{
m_Rigidbody->setCollisionShape(shape->GetBulletShape());
m_CollisionShape = shape;
}
void RigidBody::UpdateTransform(btTransform t)
{
m_Transform->setOrigin(t.getOrigin());
m_Transform->setRotation(t.getRotation());
m_Rigidbody->setWorldTransform(t);
}
glm::vec3 RigidBody::GetRotation() const {
auto q = m_Transform->getRotation();
btScalar x = 0, y = 0, z = 0;
q.getEulerZYX(z, y, x);
return glm::vec3(glm::degrees(x), glm::degrees(y), glm::degrees(z));
}
void RigidBody::SetEntityID(Entity ent)
{
m_Rigidbody->setUserIndex(ent.GetHandle());
}
void RigidBody::SetKinematic(bool value)
{
if (value) // Kinematic bodies dont deactivate.
RigidBody::RigidBody()
{
m_Rigidbody->setCollisionFlags(m_Rigidbody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
m_Rigidbody->setActivationState(DISABLE_DEACTIVATION);
m_Transform = new btTransform();
m_Transform->setIdentity();
//m_Transform->setOrigin(btVector3(position.x, position.y, position.z));
}
else // Reenable deactivation.
RigidBody::RigidBody(glm::vec3 position, Entity handle)
{
m_Rigidbody->setCollisionFlags(m_Rigidbody->getCollisionFlags() ^ ~btCollisionObject::CF_KINEMATIC_OBJECT);
m_Rigidbody->setActivationState(WANTS_DEACTIVATION);
Ref<Box> shape = CreateRef<Box>();
m_CollisionShape = shape;
m_Transform = new btTransform();
m_Transform->setIdentity();
m_Transform->setOrigin(btVector3(position.x, position.y, position.z));
m_Mass = 0.0f;
//rigidbody is dynamic if and only if mass is non zero, otherwise static
m_IsDynamic = (m_Mass != 0.0f);
btVector3 localInertia(0, 0, 0);
if (m_IsDynamic)
m_CollisionShape->GetBulletShape()->calculateLocalInertia(m_Mass, localInertia);
m_InitialVel = glm::vec3(0, 0, 0);
//using motionstate is optional, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(*m_Transform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(m_Mass, myMotionState, m_CollisionShape->GetBulletShape(), localInertia);
m_Rigidbody = new btRigidBody(rbInfo);
m_Rigidbody->setUserIndex(handle.GetHandle());
}
RigidBody::RigidBody(float mass, glm::vec3 position, Ref<PhysicShape> shape, glm::vec3 initialVel)
{
m_CollisionShape = shape;
m_Transform = new btTransform();
m_Transform->setIdentity();
m_Transform->setOrigin(btVector3(position.x, position.y, position.z));
m_Mass = mass;
//rigidbody is dynamic if and only if mass is non zero, otherwise static
m_IsDynamic = (m_Mass != 0.0f);
btVector3 localInertia(initialVel.x, initialVel.y, initialVel.z);
m_InitialVel = initialVel;
if (m_IsDynamic)
m_CollisionShape->GetBulletShape()->calculateLocalInertia(m_Mass, localInertia);
//using motionstate is optional, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(*m_Transform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(m_Mass, myMotionState, m_CollisionShape->GetBulletShape(), localInertia);
m_Rigidbody = new btRigidBody(rbInfo);
}
void RigidBody::SetShape(Ref<PhysicShape> shape)
{
m_Rigidbody->setCollisionShape(shape->GetBulletShape());
m_CollisionShape = shape;
}
void RigidBody::UpdateTransform(btTransform t)
{
m_Transform->setOrigin(t.getOrigin());
m_Transform->setRotation(t.getRotation());
m_Rigidbody->setWorldTransform(t);
}
glm::vec3 RigidBody::GetRotation() const {
auto q = m_Transform->getRotation();
btScalar x = 0, y = 0, z = 0;
q.getEulerZYX(z, y, x);
return glm::vec3(glm::degrees(x), glm::degrees(y), glm::degrees(z));
}
void RigidBody::SetEntityID(Entity ent)
{
m_Rigidbody->setUserIndex(ent.GetHandle());
}
void RigidBody::SetKinematic(bool value)
{
if (value) // Kinematic bodies dont deactivate.
{
m_Rigidbody->setCollisionFlags(m_Rigidbody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
m_Rigidbody->setActivationState(DISABLE_DEACTIVATION);
}
else // Reenable deactivation.
{
m_Rigidbody->setCollisionFlags(m_Rigidbody->getCollisionFlags() ^ ~btCollisionObject::CF_KINEMATIC_OBJECT);
m_Rigidbody->setActivationState(WANTS_DEACTIVATION);
}
}
glm::vec3 RigidBody::GetPosition() const {
btVector3 btPos = m_Transform->getOrigin();
return glm::vec3(btPos.x(), btPos.y(), btPos.z());
}
void RigidBody::SetMass(float m) { m_Rigidbody->setMassProps(m, btVector3(m_InitialVel.x, m_InitialVel.y, m_InitialVel.y)); m_Mass = m; }
void RigidBody::MoveAndSlide(glm::vec3 velocity)
{
}
}
glm::vec3 RigidBody::GetPosition() const {
btVector3 btPos = m_Transform->getOrigin();
return glm::vec3(btPos.x(), btPos.y(), btPos.z());
}
void RigidBody::SetMass(float m) { m_Rigidbody->setMassProps(m, btVector3(m_InitialVel.x, m_InitialVel.y, m_InitialVel.y)); m_Mass = m; }
void RigidBody::MoveAndSlide(glm::vec3 velocity)
{
}
}
}

View File

@@ -1,26 +1,29 @@
#include "TextureManager.h"
#include "../Rendering/Textures/Texture.h"
#include "src/Rendering/Textures/Texture.h"
std::map<std::string, Ref<Texture>> TextureManager::m_Registry;
TextureManager* TextureManager::s_Instance = nullptr;
bool TextureManager::IsTextureLoaded(const std::string path)
namespace Nuake
{
return m_Registry.find(path) != m_Registry.end();
}
Ref<Texture> TextureManager::GetTexture(const std::string path)
{
if (!IsTextureLoaded(path))
m_Registry.emplace(path, new Texture(path));
return m_Registry.at(path);
}
TextureManager* TextureManager::Get() { return s_Instance; }
TextureManager::TextureManager()
{
s_Instance = this;
std::map<std::string, Ref<Texture>> TextureManager::m_Registry;
TextureManager* TextureManager::s_Instance = nullptr;
bool TextureManager::IsTextureLoaded(const std::string path)
{
return m_Registry.find(path) != m_Registry.end();
}
Ref<Texture> TextureManager::GetTexture(const std::string path)
{
if (!IsTextureLoaded(path))
m_Registry.emplace(path, new Texture(path));
return m_Registry.at(path);
}
TextureManager* TextureManager::Get() { return s_Instance; }
TextureManager::TextureManager()
{
s_Instance = this;
}
}

View File

@@ -1,22 +1,24 @@
#pragma once
#include <map>
#include <string>
#include "../Core/Core.h"
class Texture;
#include "src/Core/Core.h"
// Todo: SHOULD probably be static too.
class TextureManager
namespace Nuake
{
private:
static TextureManager* s_Instance;
class Texture;
static std::map<std::string, Ref<Texture>> m_Registry;
bool IsTextureLoaded(const std::string path);
// Todo: SHOULD probably be static too.
class TextureManager
{
private:
static TextureManager* s_Instance;
public:
static TextureManager* Get();
static std::map<std::string, Ref<Texture>> m_Registry;
bool IsTextureLoaded(const std::string path);
TextureManager();
public:
static TextureManager* Get();
Ref<Texture> GetTexture(const std::string path);
};
TextureManager();
Ref<Texture> GetTexture(const std::string path);
};
}

View File

@@ -1,21 +1,24 @@
#pragma once
class Timestep {
private:
float m_Time;
namespace Nuake
{
class Timestep {
private:
float m_Time;
public:
operator float() const { return m_Time; }
public:
operator float() const { return m_Time; }
Timestep(float time = 0.0f) : m_Time(time) { }
Timestep(float time = 0.0f) : m_Time(time) { }
float GetSeconds()
{
return m_Time;
}
float GetSeconds()
{
return m_Time;
}
float GetMilliseconds() const
{
return m_Time * 1000.0f;
}
};
float GetMilliseconds() const
{
return m_Time * 1000.0f;
}
};
}