Major cleanup.
Moved to namespace Cleanup includes
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
template<typename T>
|
||||
using Scope = std::unique_ptr<T>;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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.
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user