overhauled physics engine
This commit is contained in:
@@ -20,7 +20,7 @@ SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreat
|
||||
LightCullingPass(graphics),
|
||||
BasePass(graphics)
|
||||
))
|
||||
, cameraSystem(createInfo.dimensions, Math::Vector(0, 0, 10))
|
||||
, cameraSystem(createInfo.dimensions, Vector(0, 0, 10))
|
||||
{
|
||||
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Avatar_Girl_Sword_Ayaka_Tex_Body_Diffuse.png");
|
||||
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Avatar_Girl_Sword_Ayaka_Tex_Body_Lightmap.png");
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
ViewportControl::ViewportControl(const Math::URect& viewportDimensions, Math::Vector initialPos)
|
||||
ViewportControl::ViewportControl(const URect& viewportDimensions, Vector initialPos)
|
||||
: position(initialPos)
|
||||
, fieldOfView(glm::radians(70.f))
|
||||
, aspectRatio(static_cast<float>(viewportDimensions.size.x) / viewportDimensions.size.y)
|
||||
@@ -25,9 +25,9 @@ void ViewportControl::update(Component::Camera& camera, float deltaTime)
|
||||
{
|
||||
cameraMove *= 4;
|
||||
}
|
||||
Math::Vector moveVector = Math::Vector();
|
||||
Math::Vector forward = glm::normalize(springArm);
|
||||
Math::Vector side = glm::cross(Math::Vector(0, 1, 0), forward);
|
||||
Vector moveVector = Vector();
|
||||
Vector forward = glm::normalize(springArm);
|
||||
Vector side = glm::cross(Vector(0, 1, 0), forward);
|
||||
if(keys[KeyCode::KEY_W])
|
||||
{
|
||||
moveVector += forward * cameraMove;
|
||||
@@ -64,11 +64,11 @@ void ViewportControl::update(Component::Camera& camera, float deltaTime)
|
||||
lastX = mouseX;
|
||||
lastY = mouseY;
|
||||
springArm = glm::normalize(
|
||||
Math::Vector(
|
||||
Vector(
|
||||
cos(yaw) * cos(pitch),
|
||||
sin(pitch),
|
||||
sin(yaw) * cos(pitch)));
|
||||
camera.viewMatrix = glm::lookAt(position, position + springArm, Math::Vector(0, 1, 0));
|
||||
camera.viewMatrix = glm::lookAt(position, position + springArm, Vector(0, 1, 0));
|
||||
camera.projectionMatrix = glm::perspective(fieldOfView, aspectRatio, 0.1f, 1000.0f);
|
||||
std::cout << yaw << " " << pitch << std::endl;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ void ViewportControl::mouseButtonCallback(MouseButton button, InputAction action
|
||||
}
|
||||
}
|
||||
|
||||
void ViewportControl::viewportResize(Math::URect dimensions)
|
||||
void ViewportControl::viewportResize(URect dimensions)
|
||||
{
|
||||
aspectRatio = static_cast<float>(dimensions.size.x) / dimensions.size.y;
|
||||
}
|
||||
|
||||
@@ -8,16 +8,16 @@ namespace Seele
|
||||
class ViewportControl
|
||||
{
|
||||
public:
|
||||
ViewportControl(const Math::URect& viewportDimensions, Math::Vector initialPos /*TODO: configurable initial rotations*/);
|
||||
ViewportControl(const URect& viewportDimensions, Vector initialPos /*TODO: configurable initial rotations*/);
|
||||
~ViewportControl();
|
||||
void update(Component::Camera& camera, float deltaTime);
|
||||
void keyCallback(KeyCode key, InputAction action);
|
||||
void mouseMoveCallback(double xPos, double yPos);
|
||||
void mouseButtonCallback(MouseButton button, InputAction action);
|
||||
void viewportResize(Math::URect dimensions);
|
||||
void viewportResize(URect dimensions);
|
||||
private:
|
||||
Math::Vector position;
|
||||
Math::Vector springArm;
|
||||
Vector position;
|
||||
Vector springArm;
|
||||
float fieldOfView;
|
||||
float aspectRatio;
|
||||
StaticArray<bool, static_cast<size_t>(KeyCode::KEY_LAST)> keys;
|
||||
|
||||
@@ -6,7 +6,7 @@ using namespace Seele;
|
||||
Actor::Actor(PScene scene)
|
||||
: Entity(scene)
|
||||
{
|
||||
scene->attachComponent<Component::Transform>(identifier);
|
||||
attachComponent<Component::Transform>();
|
||||
}
|
||||
|
||||
Actor::~Actor()
|
||||
@@ -32,13 +32,9 @@ void Actor::removeChild(PActor child)
|
||||
children.remove(children.find(child), false);
|
||||
child->setParent(nullptr);
|
||||
}
|
||||
const Component::Transform& Actor::getTransform() const
|
||||
|
||||
Component::Transform& Actor::getTransform()
|
||||
{
|
||||
return scene->accessComponent<Component::Transform>(identifier);
|
||||
return accessComponent<Component::Transform>();
|
||||
}
|
||||
|
||||
//Component::Transform& Actor::getTransform()
|
||||
//{
|
||||
// return scene->accessComponent<Component::Transform>(identifier);
|
||||
//}
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@ public:
|
||||
void removeChild(PActor child);
|
||||
Array<PActor> getChildren();
|
||||
|
||||
// Returns a read-only copy of the actors transform
|
||||
const Component::Transform& getTransform() const;
|
||||
Component::Transform& getTransform();
|
||||
|
||||
protected:
|
||||
//Component::Transform& getTransform();
|
||||
|
||||
@@ -6,8 +6,8 @@ using namespace Seele;
|
||||
CameraActor::CameraActor(PScene scene)
|
||||
: Actor(scene)
|
||||
{
|
||||
scene->attachComponent<Component::Camera>(identifier);
|
||||
scene->accessComponent<Component::Transform>(identifier).setRelativeLocation(Math::Vector(10, 5, 14));
|
||||
attachComponent<Component::Camera>();
|
||||
attachComponent<Component::Transform>().setRelativeLocation(Vector(10, 5, 14));
|
||||
}
|
||||
|
||||
CameraActor::~CameraActor()
|
||||
@@ -16,10 +16,10 @@ CameraActor::~CameraActor()
|
||||
|
||||
Component::Camera& CameraActor::getCameraComponent()
|
||||
{
|
||||
return scene->accessComponent<Component::Camera>(identifier);
|
||||
return accessComponent<Component::Camera>();
|
||||
}
|
||||
|
||||
const Component::Camera& CameraActor::getCameraComponent() const
|
||||
{
|
||||
return scene->accessComponent<Component::Camera>(identifier);
|
||||
return accessComponent<Component::Camera>();
|
||||
}
|
||||
@@ -11,5 +11,5 @@ Entity::Entity(PScene scene)
|
||||
|
||||
Entity::~Entity()
|
||||
{
|
||||
|
||||
scene->destroyEntity(identifier);
|
||||
}
|
||||
@@ -13,9 +13,19 @@ public:
|
||||
virtual ~Entity();
|
||||
|
||||
template<typename Component, typename... Args>
|
||||
Component& attachComponent(Args... args)
|
||||
Component& attachComponent(Args&&... args)
|
||||
{
|
||||
return scene->attachComponent<Component>(identifier, args...);
|
||||
return scene->attachComponent<Component>(identifier, std::forward<Args>(args)...);
|
||||
}
|
||||
template<typename Component>
|
||||
Component& accessComponent()
|
||||
{
|
||||
return scene->accessComponent<Component>(identifier);
|
||||
}
|
||||
template<typename Component>
|
||||
const Component& accessComponent() const
|
||||
{
|
||||
return scene->accessComponent<Component>(identifier);
|
||||
}
|
||||
protected:
|
||||
PScene scene;
|
||||
|
||||
@@ -2,18 +2,20 @@
|
||||
#include "MeshAsset.h"
|
||||
#include "FontAsset.h"
|
||||
#include "TextureAsset.h"
|
||||
#include "MaterialAsset.h"
|
||||
#include "FontLoader.h"
|
||||
#include "TextureLoader.h"
|
||||
#include "MaterialLoader.h"
|
||||
#include "MeshLoader.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "Graphics/Mesh.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include "MeshAsset.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Seele;
|
||||
using json = nlohmann::json;
|
||||
|
||||
AssetRegistry::~AssetRegistry()
|
||||
{
|
||||
@@ -25,6 +27,11 @@ void AssetRegistry::init(const std::string& rootFolder)
|
||||
}
|
||||
|
||||
void AssetRegistry::importFile(const std::string &filePath)
|
||||
{
|
||||
importFile(filePath, "");
|
||||
}
|
||||
|
||||
void AssetRegistry::importFile(const std::string &filePath, const std::string& importPath)
|
||||
{
|
||||
std::filesystem::path fsPath = std::filesystem::path(filePath);
|
||||
std::string extension = fsPath.extension().string();
|
||||
@@ -32,43 +39,78 @@ void AssetRegistry::importFile(const std::string &filePath)
|
||||
|| extension.compare(".obj") == 0
|
||||
|| extension.compare(".blend") == 0)
|
||||
{
|
||||
get().importMesh(fsPath);
|
||||
get().importMesh(fsPath, importPath);
|
||||
}
|
||||
if (extension.compare(".png") == 0
|
||||
|| extension.compare(".jpg") == 0)
|
||||
{
|
||||
get().importTexture(fsPath);
|
||||
get().importTexture(fsPath, importPath);
|
||||
}
|
||||
if(extension.compare(".ttf") == 0)
|
||||
{
|
||||
get().importFont(fsPath);
|
||||
get().importFont(fsPath, importPath);
|
||||
}
|
||||
if (extension.compare(".asset") == 0)
|
||||
{
|
||||
get().importMaterial(fsPath);
|
||||
get().importMaterial(fsPath, importPath);
|
||||
}
|
||||
}
|
||||
|
||||
PMeshAsset AssetRegistry::findMesh(const std::string &filePath)
|
||||
{
|
||||
auto it = get().meshes.find(filePath);
|
||||
assert(it != get().meshes.end());
|
||||
AssetFolder& folder = get().assetRoot;
|
||||
std::string fileName = filePath;
|
||||
size_t slashLoc = filePath.rfind("/");
|
||||
if(slashLoc != -1)
|
||||
{
|
||||
folder = get().getOrCreateFolder(filePath.substr(0, slashLoc));
|
||||
fileName = filePath.substr(slashLoc+1, filePath.size());
|
||||
}
|
||||
auto it = folder.meshes.find(fileName);
|
||||
assert(it != folder.meshes.end());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
PTextureAsset AssetRegistry::findTexture(const std::string &filePath)
|
||||
{
|
||||
return get().textures[filePath];
|
||||
std::string fileName = filePath;
|
||||
size_t slashLoc = filePath.rfind("/");
|
||||
if(slashLoc != -1)
|
||||
{
|
||||
AssetFolder& folder = get().getOrCreateFolder(filePath.substr(0, slashLoc));
|
||||
fileName = filePath.substr(slashLoc+1, filePath.size());
|
||||
return folder.textures[fileName];
|
||||
}
|
||||
else
|
||||
{
|
||||
return get().assetRoot.textures[fileName];
|
||||
}
|
||||
}
|
||||
|
||||
PFontAsset AssetRegistry::findFont(const std::string& name)
|
||||
PFontAsset AssetRegistry::findFont(const std::string& filePath)
|
||||
{
|
||||
return get().fonts[name];
|
||||
AssetFolder& folder = get().assetRoot;
|
||||
std::string fileName = filePath;
|
||||
size_t slashLoc = filePath.rfind("/");
|
||||
if(slashLoc != -1)
|
||||
{
|
||||
folder = get().getOrCreateFolder(filePath.substr(0, slashLoc));
|
||||
fileName = filePath.substr(slashLoc+1, filePath.size());
|
||||
}
|
||||
return folder.fonts[fileName];
|
||||
}
|
||||
|
||||
PMaterialAsset AssetRegistry::findMaterial(const std::string &filePath)
|
||||
{
|
||||
return get().materials[filePath];
|
||||
AssetFolder& folder = get().assetRoot;
|
||||
std::string fileName = filePath;
|
||||
size_t slashLoc = filePath.rfind("/");
|
||||
if(slashLoc != -1)
|
||||
{
|
||||
folder = get().getOrCreateFolder(filePath.substr(0, slashLoc));
|
||||
fileName = filePath.substr(slashLoc+1, filePath.size());
|
||||
}
|
||||
return folder.materials[fileName];
|
||||
}
|
||||
|
||||
std::ofstream AssetRegistry::createWriteStream(const std::string& relativePath, std::ios_base::openmode openmode)
|
||||
@@ -106,56 +148,65 @@ std::string AssetRegistry::getRootFolder()
|
||||
return get().rootFolder.generic_string();
|
||||
}
|
||||
|
||||
void AssetRegistry::importMesh(const std::filesystem::path &filePath)
|
||||
void AssetRegistry::importMesh(const std::filesystem::path &filePath, const std::string& importPath)
|
||||
{
|
||||
meshLoader->importAsset(filePath);
|
||||
meshLoader->importAsset(filePath, importPath);
|
||||
}
|
||||
|
||||
void AssetRegistry::importTexture(const std::filesystem::path &filePath)
|
||||
void AssetRegistry::importTexture(const std::filesystem::path &filePath, const std::string& importPath)
|
||||
{
|
||||
textureLoader->importAsset(filePath);
|
||||
textureLoader->importAsset(filePath, importPath);
|
||||
}
|
||||
|
||||
void AssetRegistry::importFont(const std::filesystem::path& filePath)
|
||||
void AssetRegistry::importFont(const std::filesystem::path& filePath, const std::string& importPath)
|
||||
{
|
||||
fontLoader->importAsset(filePath);
|
||||
fontLoader->importAsset(filePath, importPath);
|
||||
}
|
||||
|
||||
void AssetRegistry::importMaterial(const std::filesystem::path &filePath)
|
||||
void AssetRegistry::importMaterial(const std::filesystem::path &filePath, const std::string& importPath)
|
||||
{
|
||||
materialLoader->importAsset(filePath);
|
||||
materialLoader->importAsset(filePath, importPath);
|
||||
}
|
||||
|
||||
void AssetRegistry::registerMesh(PMeshAsset mesh)
|
||||
void AssetRegistry::registerMesh(PMeshAsset mesh, const std::string& importPath)
|
||||
{
|
||||
PMeshAsset existingMesh = meshes[mesh->getFileName()];
|
||||
if(existingMesh != nullptr)
|
||||
AssetFolder& folder = getOrCreateFolder(importPath);
|
||||
folder.meshes[mesh->getFileName()] = mesh;
|
||||
}
|
||||
|
||||
void AssetRegistry::registerTexture(PTextureAsset texture, const std::string& importPath)
|
||||
{
|
||||
AssetFolder& folder = getOrCreateFolder(importPath);
|
||||
folder.textures[texture->getFileName()] = texture;
|
||||
}
|
||||
|
||||
void AssetRegistry::registerFont(PFontAsset font, const std::string& importPath)
|
||||
{
|
||||
AssetFolder& folder = getOrCreateFolder(importPath);
|
||||
folder.fonts[font->getFileName()] = font;
|
||||
}
|
||||
|
||||
void AssetRegistry::registerMaterial(PMaterialAsset material, const std::string& importPath)
|
||||
{
|
||||
AssetFolder& folder = getOrCreateFolder(importPath);
|
||||
folder.materials[material->getFileName()] = material;
|
||||
}
|
||||
|
||||
AssetRegistry::AssetFolder& AssetRegistry::getOrCreateFolder(std::string fullPath)
|
||||
{
|
||||
AssetFolder& result = assetRoot;
|
||||
while(!fullPath.empty())
|
||||
{
|
||||
auto newMeshes = mesh->getMeshes();
|
||||
for(uint32 i = 0; i < newMeshes.size(); ++i)
|
||||
size_t slashLoc = fullPath.find("/");
|
||||
if(slashLoc == -1)
|
||||
{
|
||||
existingMesh->addMesh(newMeshes[i]);
|
||||
return result.children[fullPath];
|
||||
}
|
||||
std::string folderName = fullPath.substr(0, slashLoc);
|
||||
result = result.children[folderName];
|
||||
fullPath = fullPath.substr(slashLoc+1, fullPath.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
meshes[mesh->getFileName()] = mesh;
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRegistry::registerTexture(PTextureAsset texture)
|
||||
{
|
||||
textures[texture->getFileName()] = texture;
|
||||
}
|
||||
|
||||
void AssetRegistry::registerFont(PFontAsset font)
|
||||
{
|
||||
fonts[font->getFileName()] = font;
|
||||
}
|
||||
|
||||
void AssetRegistry::registerMaterial(PMaterialAsset material)
|
||||
{
|
||||
materials[material->getFileName()] = material;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ofstream AssetRegistry::internalCreateWriteStream(const std::string& relativePath, std::ios_base::openmode openmode)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "Asset.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
@@ -25,6 +24,7 @@ public:
|
||||
static std::string getRootFolder();
|
||||
|
||||
static void importFile(const std::string& filePath);
|
||||
static void importFile(const std::string& filePath, const std::string& importPath);
|
||||
|
||||
static PMeshAsset findMesh(const std::string& filePath);
|
||||
static PTextureAsset findTexture(const std::string& filePath);
|
||||
@@ -34,30 +34,38 @@ public:
|
||||
static std::ofstream createWriteStream(const std::string& relativePath, std::ios_base::openmode openmode = std::ios::out);
|
||||
static std::ifstream createReadStream(const std::string& relativePath, std::ios_base::openmode openmode = std::ios::in);
|
||||
private:
|
||||
struct AssetFolder
|
||||
{
|
||||
std::map<std::string, AssetFolder> children;
|
||||
//Todo: Seele::Map doesn't really work with strings for some reason, so just use std::map for now
|
||||
std::map<std::string, PTextureAsset> textures;
|
||||
std::map<std::string, PFontAsset> fonts;
|
||||
std::map<std::string, PMeshAsset> meshes;
|
||||
std::map<std::string, PMaterialAsset> materials;
|
||||
};
|
||||
|
||||
static AssetRegistry& get();
|
||||
|
||||
AssetRegistry();
|
||||
void init(const std::filesystem::path& rootFolder, Gfx::PGraphics graphics);
|
||||
|
||||
void importMesh(const std::filesystem::path& filePath);
|
||||
void importTexture(const std::filesystem::path& filePath);
|
||||
void importFont(const std::filesystem::path& filePath);
|
||||
void importMaterial(const std::filesystem::path& filePath);
|
||||
void importMesh(const std::filesystem::path& filePath, const std::string& importPath);
|
||||
void importTexture(const std::filesystem::path& filePath, const std::string& importPath);
|
||||
void importFont(const std::filesystem::path& filePath, const std::string& importPath);
|
||||
void importMaterial(const std::filesystem::path& filePath, const std::string& importPath);
|
||||
|
||||
void registerMesh(PMeshAsset mesh);
|
||||
void registerTexture(PTextureAsset texture);
|
||||
void registerFont(PFontAsset font);
|
||||
void registerMaterial(PMaterialAsset material);
|
||||
void registerMesh(PMeshAsset mesh, const std::string& importPath);
|
||||
void registerTexture(PTextureAsset texture, const std::string& importPath);
|
||||
void registerFont(PFontAsset font, const std::string& importPath);
|
||||
void registerMaterial(PMaterialAsset material, const std::string& importPath);
|
||||
|
||||
AssetFolder& getOrCreateFolder(std::string foldername);
|
||||
|
||||
std::ofstream internalCreateWriteStream(const std::string& relativePath, std::ios_base::openmode openmode = std::ios::out);
|
||||
std::ifstream internalCreateReadStream(const std::string& relaitvePath, std::ios_base::openmode openmode = std::ios::in);
|
||||
|
||||
std::filesystem::path rootFolder;
|
||||
//Todo: Seele::Map doesn't really work with strings for some reason, so just use std::map for now
|
||||
std::map<std::string, PTextureAsset> textures;
|
||||
std::map<std::string, PFontAsset> fonts;
|
||||
std::map<std::string, PMeshAsset> meshes;
|
||||
std::map<std::string, PMaterialAsset> materials;
|
||||
AssetFolder assetRoot;
|
||||
UPTextureLoader textureLoader;
|
||||
UPFontLoader fontLoader;
|
||||
UPMeshLoader meshLoader;
|
||||
|
||||
@@ -8,6 +8,10 @@ target_sources(Engine
|
||||
FontAsset.cpp
|
||||
FontLoader.h
|
||||
FontLoader.cpp
|
||||
MaterialAsset.h
|
||||
MaterialAsset.cpp
|
||||
MaterialInstanceAsset.h
|
||||
MaterialInstanceAsset.cpp
|
||||
MaterialLoader.h
|
||||
MaterialLoader.cpp
|
||||
MeshAsset.h
|
||||
@@ -26,6 +30,8 @@ target_sources(Engine
|
||||
AssetRegistry.h
|
||||
FontAsset.h
|
||||
FontLoader.h
|
||||
MaterialAsset.h
|
||||
MaterialInstanceAsset.h
|
||||
MaterialLoader.h
|
||||
MeshAsset.h
|
||||
MeshLoader.h
|
||||
|
||||
@@ -52,8 +52,8 @@ void FontAsset::load()
|
||||
continue;
|
||||
}
|
||||
Glyph& glyph = glyphs[c];
|
||||
glyph.size = Math::IVector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
|
||||
glyph.bearing = Math::IVector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
|
||||
glyph.size = IVector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
|
||||
glyph.bearing = IVector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
|
||||
glyph.advance = face->glyph->advance.x;
|
||||
TextureCreateInfo imageData;
|
||||
imageData.format = Gfx::SE_FORMAT_R8_UINT;
|
||||
|
||||
@@ -17,8 +17,8 @@ public:
|
||||
struct Glyph
|
||||
{
|
||||
Gfx::PTexture2D texture;
|
||||
Math::IVector2 size;
|
||||
Math::IVector2 bearing;
|
||||
IVector2 size;
|
||||
IVector2 bearing;
|
||||
uint32 advance;
|
||||
};
|
||||
const std::map<uint32, Glyph> getGlyphData() const { return glyphs; }
|
||||
|
||||
@@ -15,7 +15,7 @@ FontLoader::~FontLoader()
|
||||
{
|
||||
}
|
||||
|
||||
void FontLoader::importAsset(const std::filesystem::path& filePath)
|
||||
void FontLoader::importAsset(const std::filesystem::path& filePath, const std::string& importPath)
|
||||
{
|
||||
std::filesystem::path assetPath = filePath.filename();
|
||||
assetPath.replace_extension("asset");
|
||||
@@ -23,12 +23,11 @@ void FontLoader::importAsset(const std::filesystem::path& filePath)
|
||||
std::error_code code;
|
||||
std::filesystem::copy_file(filePath, asset->getFullPath(), code);
|
||||
asset->setStatus(Asset::Status::Loading);
|
||||
AssetRegistry::get().registerFont(asset);
|
||||
AssetRegistry::get().registerFont(asset, importPath);
|
||||
import(filePath, asset);
|
||||
}
|
||||
|
||||
void FontLoader::import(std::filesystem::path path, PFontAsset asset)
|
||||
{
|
||||
asset->load();
|
||||
AssetRegistry::get().registerFont(asset);
|
||||
}
|
||||
@@ -12,7 +12,7 @@ class FontLoader
|
||||
public:
|
||||
FontLoader(Gfx::PGraphics graphic);
|
||||
~FontLoader();
|
||||
void importAsset(const std::filesystem::path& filePath);
|
||||
void importAsset(const std::filesystem::path& filePath, const std::string& importPath);
|
||||
private:
|
||||
void import(std::filesystem::path path, PFontAsset asset);
|
||||
Gfx::PGraphics graphics;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "MaterialAsset.h"
|
||||
#include "Material/Material.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MaterialAsset::MaterialAsset()
|
||||
{
|
||||
}
|
||||
|
||||
MaterialAsset::MaterialAsset(const std::string& directory, const std::string& name)
|
||||
: Asset(directory, name)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialAsset::MaterialAsset(const std::filesystem::path& fullPath)
|
||||
: Asset(fullPath)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialAsset::~MaterialAsset()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void MaterialAsset::save()
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialAsset::load()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MaterialAsset::beginFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialAsset::endFrame()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "Asset.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(Material)
|
||||
class MaterialAsset : public Asset
|
||||
{
|
||||
public:
|
||||
MaterialAsset();
|
||||
MaterialAsset(const std::string &directory, const std::string &name);
|
||||
MaterialAsset(const std::filesystem::path &fullPath);
|
||||
virtual ~MaterialAsset();
|
||||
virtual void beginFrame();
|
||||
virtual void endFrame();
|
||||
virtual void save() override;
|
||||
virtual void load() override;
|
||||
PMaterial getMaterial() const { return material; }
|
||||
private:
|
||||
PMaterial material;
|
||||
friend class MaterialLoader;
|
||||
};
|
||||
DEFINE_REF(MaterialAsset)
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "MaterialInstanceAsset.h"
|
||||
#include "Material/MaterialInstance.h"
|
||||
#include "Material/Material.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MaterialInstanceAsset::MaterialInstanceAsset()
|
||||
{
|
||||
}
|
||||
|
||||
MaterialInstanceAsset::MaterialInstanceAsset(const std::string& directory, const std::string& name)
|
||||
: Asset(directory, name)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialInstanceAsset::MaterialInstanceAsset(const std::filesystem::path& fullPath)
|
||||
: Asset(fullPath)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialInstanceAsset::~MaterialInstanceAsset()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void MaterialInstanceAsset::save()
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialInstanceAsset::load()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "Asset.h"
|
||||
#include "Material/MaterialInstance.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
class MaterialInstanceAsset : public Asset
|
||||
{
|
||||
public:
|
||||
MaterialInstanceAsset();
|
||||
MaterialInstanceAsset(const std::string &directory, const std::string &name);
|
||||
MaterialInstanceAsset(const std::filesystem::path &fullPath);
|
||||
virtual ~MaterialInstanceAsset();
|
||||
virtual void beginFrame();
|
||||
virtual void endFrame();
|
||||
virtual void save() override;
|
||||
virtual void load() override;
|
||||
private:
|
||||
PMaterialInstance material;
|
||||
};
|
||||
DEFINE_REF(MaterialInstanceAsset)
|
||||
} // namespace Seele
|
||||
@@ -1,37 +1,141 @@
|
||||
#include "MaterialLoader.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "MaterialAsset.h"
|
||||
#include "AssetRegistry.h"
|
||||
#include "Material/Material.h"
|
||||
#include "Material/BRDF.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include "Material/ShaderExpression.h"
|
||||
#include "TextureAsset.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using namespace Seele;
|
||||
using json = nlohmann::json;
|
||||
|
||||
MaterialLoader::MaterialLoader(Gfx::PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
{
|
||||
placeholderMaterial = new MaterialAsset(std::filesystem::absolute("./shaders/Placeholder.asset"));
|
||||
placeholderMaterial->load();
|
||||
graphics->getShaderCompiler()->registerMaterial(placeholderMaterial);
|
||||
importAsset(std::filesystem::absolute("./shaders/Placeholder.asset"), "");
|
||||
}
|
||||
|
||||
MaterialLoader::~MaterialLoader()
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialLoader::importAsset(const std::filesystem::path& name)
|
||||
void MaterialLoader::importAsset(const std::filesystem::path& name, const std::string& importPath)
|
||||
{
|
||||
std::filesystem::path assetPath = name.filename();
|
||||
assetPath.replace_extension("asset");
|
||||
PMaterialAsset asset = new MaterialAsset(assetPath.generic_string());
|
||||
asset->setStatus(Asset::Status::Loading);
|
||||
AssetRegistry::get().registerMaterial(asset);
|
||||
AssetRegistry::get().registerMaterial(asset, importPath);
|
||||
import(name, asset);
|
||||
}
|
||||
|
||||
void MaterialLoader::import(std::filesystem::path, PMaterialAsset asset)
|
||||
void MaterialLoader::import(std::filesystem::path name, PMaterialAsset asset)
|
||||
{
|
||||
asset->load();
|
||||
graphics->getShaderCompiler()->registerMaterial(asset);
|
||||
AssetRegistry::get().registerMaterial(asset);
|
||||
auto stream = std::ifstream(name.c_str());
|
||||
json j;
|
||||
stream >> j;
|
||||
std::string materialName = j["name"].get<std::string>() + "Material";
|
||||
Gfx::PDescriptorLayout layout = WindowManager::getGraphics()->createDescriptorLayout(materialName + "Layout");
|
||||
//Shader file needs to conform to the slang standard, which prohibits _
|
||||
materialName.erase(std::remove(materialName.begin(), materialName.end(), '_'), materialName.end());
|
||||
materialName.erase(std::remove(materialName.begin(), materialName.end(), '.'), materialName.end());
|
||||
std::ofstream codeStream("./shaders/generated/"+materialName+".slang");
|
||||
std::string profile = j["profile"].get<std::string>();
|
||||
|
||||
codeStream << "import Material;" << std::endl;
|
||||
codeStream << "import BRDF;" << std::endl;
|
||||
codeStream << "import MaterialParameter;" << std::endl << std::endl;
|
||||
|
||||
codeStream << "struct " << materialName << " : IMaterial {" << std::endl;
|
||||
uint32 uniformBufferOffset = 0;
|
||||
uint32 bindingCounter = 0; // Uniform buffers are always binding 0
|
||||
uint32 uniformBinding = -1;
|
||||
Array<PShaderParameter> parameters;
|
||||
for(auto param : j["params"].items())
|
||||
{
|
||||
std::string type = param.value()["type"].get<std::string>();
|
||||
auto defaultValue = param.value().find("default");
|
||||
// TODO: ALIGNMENT RULES
|
||||
if(type.compare("float") == 0)
|
||||
{
|
||||
PFloatParameter p = new FloatParameter(param.key(), uniformBufferOffset, 0);
|
||||
codeStream << "\tlayout(offset = " << uniformBufferOffset << ")";
|
||||
if(uniformBinding == -1)
|
||||
{
|
||||
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
uniformBinding = bindingCounter++;
|
||||
}
|
||||
uniformBufferOffset += 4;
|
||||
if(defaultValue != param.value().end())
|
||||
{
|
||||
p->data = std::stof(defaultValue.value().get<std::string>());
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
// TODO: ALIGNMENT RULES
|
||||
else if(type.compare("float3") == 0)
|
||||
{
|
||||
PVectorParameter p = new VectorParameter(param.key(), uniformBufferOffset, 0);
|
||||
codeStream << "\tlayout(offset = " << uniformBufferOffset << ")";
|
||||
if(uniformBinding == -1)
|
||||
{
|
||||
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
uniformBinding = bindingCounter++;
|
||||
}
|
||||
uniformBufferOffset += 12;
|
||||
if(defaultValue != param.value().end())
|
||||
{
|
||||
p->data = parseVector(defaultValue.value().get<std::string>().c_str());
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
else if(type.compare("Texture2D") == 0)
|
||||
{
|
||||
PTextureParameter p = new TextureParameter(param.key(), 0, bindingCounter);
|
||||
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
|
||||
if(defaultValue != param.value().end())
|
||||
{
|
||||
std::string defaultString = defaultValue.value().get<std::string>();
|
||||
p->data = AssetRegistry::findTexture(defaultString);
|
||||
}
|
||||
if(p->data == nullptr)
|
||||
{
|
||||
p->data = AssetRegistry::findTexture(""); // this will return placeholder texture
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
else if(type.compare("SamplerState") == 0)
|
||||
{
|
||||
PSamplerParameter p = new SamplerParameter(param.key(), 0, bindingCounter);
|
||||
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLER);
|
||||
p->data = WindowManager::getGraphics()->createSamplerState({});
|
||||
parameters.add(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Error unsupported parameter type" << std::endl;
|
||||
}
|
||||
codeStream << "\t" << type << " " << param.key() << ";\n";
|
||||
}
|
||||
uint32 uniformDataSize = uniformBufferOffset;
|
||||
|
||||
BRDF* brdf = BRDF::getBRDFByName(profile);
|
||||
brdf->generateMaterialCode(codeStream, j["code"]);
|
||||
codeStream << "};";
|
||||
codeStream.close();
|
||||
layout->create();
|
||||
asset->material = new Material(
|
||||
std::move(parameters),
|
||||
std::move(layout),
|
||||
uniformDataSize,
|
||||
uniformBinding,
|
||||
materialName
|
||||
);
|
||||
graphics->getShaderCompiler()->registerMaterial(asset->material);
|
||||
asset->setStatus(Asset::Status::Ready);
|
||||
////co_return;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class MaterialLoader
|
||||
public:
|
||||
MaterialLoader(Gfx::PGraphics graphic);
|
||||
~MaterialLoader();
|
||||
void importAsset(const std::filesystem::path& name);
|
||||
void importAsset(const std::filesystem::path& name, const std::string& importPath);
|
||||
PMaterialAsset getPlaceHolderMaterial();
|
||||
private:
|
||||
void import(std::filesystem::path filePath, PMaterialAsset asset);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "MeshAsset.h"
|
||||
#include "Graphics/Mesh.h"
|
||||
#include "Graphics/VertexShaderInput.h"
|
||||
#include "Material/MaterialInterface.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
#include "Asset.h"
|
||||
#include "Component/Collider.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(Mesh)
|
||||
DECLARE_REF(MaterialAsset)
|
||||
DECLARE_REF(MaterialInterface)
|
||||
class MeshAsset : public Asset
|
||||
{
|
||||
public:
|
||||
@@ -17,8 +18,9 @@ public:
|
||||
void addMesh(PMesh mesh);
|
||||
const Array<PMesh> getMeshes();
|
||||
//Workaround while no editor
|
||||
Array<PMaterialAsset> referencedMaterials;
|
||||
Array<PMaterialInterface> referencedMaterials;
|
||||
Array<PMesh> meshes;
|
||||
Component::Collider physicsMesh;
|
||||
};
|
||||
DEFINE_REF(MeshAsset)
|
||||
} // namespace Seele
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Graphics/Mesh.h"
|
||||
#include "Graphics/StaticMeshVertexInput.h"
|
||||
#include "AssetRegistry.h"
|
||||
#include "MaterialAsset.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
@@ -26,17 +27,17 @@ MeshLoader::~MeshLoader()
|
||||
{
|
||||
}
|
||||
|
||||
void MeshLoader::importAsset(const std::filesystem::path &path)
|
||||
void MeshLoader::importAsset(const std::filesystem::path &path, const std::string& importPath)
|
||||
{
|
||||
std::filesystem::path assetPath = path.filename();
|
||||
assetPath.replace_extension("asset");
|
||||
PMeshAsset asset = new MeshAsset(assetPath.generic_string());
|
||||
asset->setStatus(Asset::Status::Loading);
|
||||
AssetRegistry::get().registerMesh(asset);
|
||||
AssetRegistry::get().registerMesh(asset, importPath);
|
||||
import(path, asset);
|
||||
}
|
||||
|
||||
void MeshLoader::loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials)
|
||||
void MeshLoader::loadMaterials(const aiScene* scene, Array<PMaterial>& globalMaterials)
|
||||
{
|
||||
using json = nlohmann::json;
|
||||
for(uint32 i = 0; i < scene->mNumMaterials; ++i)
|
||||
@@ -92,15 +93,13 @@ void MeshLoader::loadMaterials(const aiScene* scene, Array<PMaterialAsset>& glob
|
||||
outMatFile.close();
|
||||
|
||||
std::cout << "writing json to " << outMatFilename << std::endl;
|
||||
PMaterialAsset result = new MaterialAsset(outMatFilename);
|
||||
result->load();
|
||||
graphics->getShaderCompiler()->registerMaterial(result);
|
||||
AssetRegistry::get().registerMaterial(result);
|
||||
PMaterialAsset asset = AssetRegistry::findMaterial(result->getFileName());
|
||||
globalMaterials[i] = asset;
|
||||
AssetRegistry::importFile(AssetRegistry::getRootFolder() + "/" + outMatFilename);
|
||||
PMaterialAsset asset = AssetRegistry::findMaterial(matCode["name"].get<std::string>());
|
||||
globalMaterials[i] = asset->getMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void findMeshRoots(aiNode *node, List<aiNode *> &meshNodes)
|
||||
{
|
||||
if (node->mNumMeshes > 0)
|
||||
@@ -115,61 +114,70 @@ void findMeshRoots(aiNode *node, List<aiNode *> &meshNodes)
|
||||
}
|
||||
VertexStreamComponent createVertexStream(uint32 size, aiVector3D* sourceData, Gfx::PGraphics graphics)
|
||||
{
|
||||
Array<Math::Vector> buffer(size);
|
||||
Array<Vector> buffer(size);
|
||||
for(uint32 i = 0; i < size; ++i)
|
||||
{
|
||||
buffer[i] = Math::Vector(sourceData[i].x, sourceData[i].y, sourceData[i].z);
|
||||
}
|
||||
buffer[i] = Vector(sourceData[i].x, sourceData[i].y, sourceData[i].z);
|
||||
}
|
||||
VertexBufferCreateInfo vbInfo;
|
||||
vbInfo.numVertices = size;
|
||||
vbInfo.vertexSize = sizeof(Math::Vector);
|
||||
vbInfo.vertexSize = sizeof(Vector);
|
||||
vbInfo.resourceData.data = (uint8 *)buffer.data();
|
||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
vbInfo.resourceData.size = sizeof(Math::Vector) * buffer.size();
|
||||
vbInfo.resourceData.size = sizeof(Vector) * buffer.size();
|
||||
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
||||
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT);
|
||||
}
|
||||
VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics)
|
||||
{
|
||||
Array<Math::Vector2> buffer(size);
|
||||
Array<Vector2> buffer(size);
|
||||
for(uint32 i = 0; i < size; ++i)
|
||||
{
|
||||
buffer[i] = Math::Vector2(sourceData[i].x, sourceData[i].y);
|
||||
buffer[i] = Vector2(sourceData[i].x, sourceData[i].y);
|
||||
}
|
||||
VertexBufferCreateInfo vbInfo;
|
||||
vbInfo.numVertices = size;
|
||||
vbInfo.vertexSize = sizeof(Math::Vector2);
|
||||
vbInfo.vertexSize = sizeof(Vector2);
|
||||
vbInfo.resourceData.data = (uint8 *)buffer.data();
|
||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
vbInfo.resourceData.size = sizeof(Math::Vector2) * buffer.size();
|
||||
vbInfo.resourceData.size = sizeof(Vector2) * buffer.size();
|
||||
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
||||
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT);
|
||||
}
|
||||
VertexStreamComponent createVertexStream(uint32 size, aiColor4D* sourceData, Gfx::PGraphics graphics)
|
||||
{
|
||||
Array<Math::Vector4> buffer(size);
|
||||
Array<Vector4> buffer(size);
|
||||
for(uint32 i = 0; i < size; ++i)
|
||||
{
|
||||
buffer[i] = Math::Vector4(sourceData[i].r, sourceData[i].g, sourceData[i].b, sourceData[i].a);
|
||||
buffer[i] = Vector4(sourceData[i].r, sourceData[i].g, sourceData[i].b, sourceData[i].a);
|
||||
}
|
||||
VertexBufferCreateInfo vbInfo;
|
||||
vbInfo.numVertices = size;
|
||||
vbInfo.vertexSize = sizeof(Math::Vector4);
|
||||
vbInfo.vertexSize = sizeof(Vector4);
|
||||
vbInfo.resourceData.data = (uint8 *)buffer.data();
|
||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
vbInfo.resourceData.size = sizeof(Math::Vector4) * buffer.size();
|
||||
vbInfo.resourceData.size = sizeof(Vector4) * buffer.size();
|
||||
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
||||
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT);
|
||||
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32A32_SFLOAT);
|
||||
}
|
||||
void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials)
|
||||
void MeshLoader::loadGlobalMeshes(const aiScene* scene, const Array<PMaterial>& materials, Array<PMesh>& globalMeshes, Component::Collider& collider)
|
||||
{
|
||||
for (uint32 meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
|
||||
{
|
||||
aiMesh *mesh = scene->mMeshes[meshIndex];
|
||||
PMaterialAsset material = materials[mesh->mMaterialIndex];
|
||||
collider.boundingbox.adjust(Vector(mesh->mAABB.mMin.x, mesh->mAABB.mMin.y, mesh->mAABB.mMin.z));
|
||||
collider.boundingbox.adjust(Vector(mesh->mAABB.mMax.x, mesh->mAABB.mMax.y, mesh->mAABB.mMax.z));
|
||||
|
||||
//! \todo duplicate from createVertexStream, clean up
|
||||
Array<Vector> vertices(mesh->mNumVertices);
|
||||
for(uint32 i = 0; i < mesh->mNumVertices; ++i)
|
||||
{
|
||||
vertices[i] = Vector(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
|
||||
}
|
||||
|
||||
PStaticMeshVertexInput vertexShaderInput = new StaticMeshVertexInput(std::string(mesh->mName.C_Str()));
|
||||
StaticMeshDataType data;
|
||||
data.positionStream = createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics);
|
||||
@@ -205,6 +213,9 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMesh
|
||||
indices[faceIndex * 3 + 1] = mesh->mFaces[faceIndex].mIndices[1];
|
||||
indices[faceIndex * 3 + 2] = mesh->mFaces[faceIndex].mIndices[2];
|
||||
}
|
||||
|
||||
collider.physicsMesh.addCollider(vertices, indices, Matrix4(1.0f));
|
||||
|
||||
IndexBufferCreateInfo idxInfo;
|
||||
idxInfo.indexType = Gfx::SE_INDEX_TYPE_UINT32;
|
||||
idxInfo.resourceData.data = (uint8 *)indices.data();
|
||||
@@ -259,22 +270,23 @@ void MeshLoader::import(std::filesystem::path path, PMeshAsset meshAsset)
|
||||
std::cout << "Starting to import "<<path << std::endl;
|
||||
meshAsset->setStatus(Asset::Status::Loading);
|
||||
Assimp::Importer importer;
|
||||
importer.ReadFile(path.string().c_str(),
|
||||
importer.ReadFile(path.string().c_str(), (uint32)(
|
||||
aiProcess_FlipUVs |
|
||||
aiProcess_Triangulate |
|
||||
aiProcess_SortByPType |
|
||||
aiProcess_GenBoundingBoxes |
|
||||
aiProcess_GenSmoothNormals |
|
||||
aiProcess_GenUVCoords |
|
||||
aiProcess_FindDegenerates);
|
||||
aiProcess_FindDegenerates));
|
||||
const aiScene *scene = importer.ApplyPostProcessing(aiProcess_CalcTangentSpace);
|
||||
|
||||
Array<PMaterialAsset> globalMaterials(scene->mNumMaterials);
|
||||
Array<PMaterial> globalMaterials(scene->mNumMaterials);
|
||||
loadTextures(scene, path.parent_path());
|
||||
loadMaterials(scene, globalMaterials);
|
||||
|
||||
Array<PMesh> globalMeshes(scene->mNumMeshes);
|
||||
loadGlobalMeshes(scene, globalMeshes, globalMaterials);
|
||||
|
||||
Component::Collider collider;
|
||||
loadGlobalMeshes(scene, globalMaterials, globalMeshes, collider);
|
||||
|
||||
List<aiNode *> meshNodes;
|
||||
findMeshRoots(scene->mRootNode, meshNodes);
|
||||
@@ -286,6 +298,7 @@ void MeshLoader::import(std::filesystem::path path, PMeshAsset meshAsset)
|
||||
meshAsset->addMesh(globalMeshes[meshNode->mMeshes[i]]);
|
||||
}
|
||||
}
|
||||
meshAsset->physicsMesh = std::move(collider);
|
||||
meshAsset->setStatus(Asset::Status::Ready);
|
||||
meshAsset->save();
|
||||
std::cout << "Finished loading " << path << std::endl;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "Containers/List.h"
|
||||
#include "Component/Collider.h"
|
||||
#include <filesystem>
|
||||
|
||||
struct aiScene;
|
||||
@@ -9,18 +10,18 @@ namespace Seele
|
||||
{
|
||||
DECLARE_REF(Mesh)
|
||||
DECLARE_REF(MeshAsset)
|
||||
DECLARE_REF(MaterialAsset)
|
||||
DECLARE_REF(Material)
|
||||
DECLARE_NAME_REF(Gfx, Graphics)
|
||||
class MeshLoader
|
||||
{
|
||||
public:
|
||||
MeshLoader(Gfx::PGraphics graphic);
|
||||
~MeshLoader();
|
||||
void importAsset(const std::filesystem::path& filePath);
|
||||
void importAsset(const std::filesystem::path& filePath, const std::string& importPath);
|
||||
private:
|
||||
void loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials);
|
||||
void loadMaterials(const aiScene* scene, Array<PMaterial>& globalMaterials);
|
||||
void loadTextures(const aiScene* scene, const std::filesystem::path& meshPath);
|
||||
void loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials);
|
||||
void loadGlobalMeshes(const aiScene* scene, const Array<PMaterial>& materials, Array<PMesh>& globalMeshes, Component::Collider& collider);
|
||||
void convertAssimpARGB(unsigned char* dst, aiTexel* src, uint32 numPixels);
|
||||
|
||||
void import(std::filesystem::path path, PMeshAsset meshAsset);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
#include "Asset.h"
|
||||
|
||||
namespace Seele
|
||||
|
||||
@@ -16,21 +16,21 @@ TextureLoader::TextureLoader(Gfx::PGraphics graphics)
|
||||
{
|
||||
placeholderAsset = new TextureAsset(std::filesystem::absolute("./textures/placeholder.ktx"));
|
||||
placeholderAsset->load();
|
||||
AssetRegistry::get().textures[""] = placeholderAsset;
|
||||
AssetRegistry::get().assetRoot.textures[""] = placeholderAsset;
|
||||
}
|
||||
|
||||
TextureLoader::~TextureLoader()
|
||||
{
|
||||
}
|
||||
|
||||
void TextureLoader::importAsset(const std::filesystem::path& path)
|
||||
void TextureLoader::importAsset(const std::filesystem::path& path, const std::string& importPath)
|
||||
{
|
||||
std::filesystem::path assetPath = path.filename();
|
||||
assetPath.replace_extension("asset");
|
||||
PTextureAsset asset = new TextureAsset(assetPath.generic_string());
|
||||
asset->setStatus(Asset::Status::Loading);
|
||||
asset->setTexture(placeholderAsset->getTexture());
|
||||
AssetRegistry::get().registerTexture(asset);
|
||||
AssetRegistry::get().registerTexture(asset, importPath);
|
||||
import(path, asset);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class TextureLoader
|
||||
public:
|
||||
TextureLoader(Gfx::PGraphics graphic);
|
||||
~TextureLoader();
|
||||
void importAsset(const std::filesystem::path& filePath);
|
||||
void importAsset(const std::filesystem::path& filePath, const std::string& importPath);
|
||||
PTextureAsset getPlaceholderTexture();
|
||||
private:
|
||||
void import(std::filesystem::path path, PTextureAsset asset);
|
||||
|
||||
+70
-22
@@ -2,16 +2,64 @@
|
||||
#include "Math/Vector.h"
|
||||
#include "Math/Matrix.h"
|
||||
#include "Containers/Array.h"
|
||||
|
||||
#include "Graphics/DebugVertex.h"
|
||||
namespace Seele
|
||||
{
|
||||
struct AABB
|
||||
{
|
||||
Math::Vector min = Math::Vector(std::numeric_limits<float>::max());
|
||||
Math::Vector max = Math::Vector(std::numeric_limits<float>::min());
|
||||
Vector min = Vector(std::numeric_limits<float>::max());
|
||||
Vector max = Vector(std::numeric_limits<float>::lowest());// cause of reasons
|
||||
void visualize(Array<DebugVertex>& vertices) const
|
||||
{
|
||||
StaticArray<DebugVertex, 8> corners;
|
||||
corners[0] = DebugVertex { .position = Vector(min.x, min.y, min.z), .color = Vector(0, 1, 0) };
|
||||
corners[1] = DebugVertex { .position = Vector(min.x, min.y, max.z), .color = Vector(0, 1, 0) };
|
||||
corners[2] = DebugVertex { .position = Vector(min.x, max.y, min.z), .color = Vector(0, 1, 0) };
|
||||
corners[3] = DebugVertex { .position = Vector(min.x, max.y, max.z), .color = Vector(0, 1, 0) };
|
||||
corners[4] = DebugVertex { .position = Vector(max.x, min.y, min.z), .color = Vector(0, 1, 0) };
|
||||
corners[5] = DebugVertex { .position = Vector(max.x, min.y, max.z), .color = Vector(0, 1, 0) };
|
||||
corners[6] = DebugVertex { .position = Vector(max.x, max.y, min.z), .color = Vector(0, 1, 0) };
|
||||
corners[7] = DebugVertex { .position = Vector(max.x, max.y, max.z), .color = Vector(0, 1, 0) };
|
||||
|
||||
vertices.add(corners[0]);
|
||||
vertices.add(corners[1]);
|
||||
|
||||
vertices.add(corners[1]);
|
||||
vertices.add(corners[3]);
|
||||
|
||||
vertices.add(corners[2]);
|
||||
vertices.add(corners[3]);
|
||||
|
||||
vertices.add(corners[0]);
|
||||
vertices.add(corners[2]);
|
||||
|
||||
vertices.add(corners[0]);
|
||||
vertices.add(corners[4]);
|
||||
|
||||
vertices.add(corners[1]);
|
||||
vertices.add(corners[5]);
|
||||
|
||||
vertices.add(corners[2]);
|
||||
vertices.add(corners[6]);
|
||||
|
||||
vertices.add(corners[3]);
|
||||
vertices.add(corners[7]);
|
||||
|
||||
vertices.add(corners[4]);
|
||||
vertices.add(corners[5]);
|
||||
|
||||
vertices.add(corners[5]);
|
||||
vertices.add(corners[7]);
|
||||
|
||||
vertices.add(corners[6]);
|
||||
vertices.add(corners[7]);
|
||||
|
||||
vertices.add(corners[4]);
|
||||
vertices.add(corners[6]);
|
||||
}
|
||||
float surfaceArea() const
|
||||
{
|
||||
Math::Vector d = max - min;
|
||||
Vector d = max - min;
|
||||
return 2.0f * (d.x * d.y + d.y * d.z + d.z * d.x);
|
||||
}
|
||||
bool intersects(const AABB& other) const
|
||||
@@ -52,31 +100,31 @@ struct AABB
|
||||
}
|
||||
return true;
|
||||
}
|
||||
AABB getTransformedBox(const Math::Matrix4& matrix) const
|
||||
AABB getTransformedBox(const Matrix4& matrix) const
|
||||
{
|
||||
StaticArray<Math::Vector, 8> corners;
|
||||
corners[0] = Math::Vector(min.x, min.y, min.z);
|
||||
corners[1] = Math::Vector(min.x, min.y, max.z);
|
||||
corners[2] = Math::Vector(min.x, max.y, min.z);
|
||||
corners[3] = Math::Vector(min.x, max.y, max.z);
|
||||
corners[4] = Math::Vector(max.x, min.y, min.z);
|
||||
corners[5] = Math::Vector(max.x, min.y, max.z);
|
||||
corners[6] = Math::Vector(max.x, max.y, min.z);
|
||||
corners[7] = Math::Vector(max.x, max.y, max.z);
|
||||
Math::Vector tmin = Math::Vector(1, 1, 1) * std::numeric_limits<float>::max();
|
||||
Math::Vector tmax = Math::Vector(1, 1, 1) * std::numeric_limits<float>::min();
|
||||
StaticArray<Vector, 8> corners;
|
||||
corners[0] = Vector(min.x, min.y, min.z);
|
||||
corners[1] = Vector(min.x, min.y, max.z);
|
||||
corners[2] = Vector(min.x, max.y, min.z);
|
||||
corners[3] = Vector(min.x, max.y, max.z);
|
||||
corners[4] = Vector(max.x, min.y, min.z);
|
||||
corners[5] = Vector(max.x, min.y, max.z);
|
||||
corners[6] = Vector(max.x, max.y, min.z);
|
||||
corners[7] = Vector(max.x, max.y, max.z);
|
||||
Vector tmin = Vector(1, 1, 1) * std::numeric_limits<float>::max();
|
||||
Vector tmax = Vector(1, 1, 1) * std::numeric_limits<float>::lowest();
|
||||
for(int i = 0; i < 8; ++i)
|
||||
{
|
||||
Math::Vector transformed = matrix * Math::Vector4(corners[i], 1.0f);
|
||||
tmin = Math::Vector(std::min(tmin.x, transformed.x), std::min(tmin.y, transformed.y), std::min(tmin.z, transformed.z));
|
||||
tmax = Math::Vector(std::max(tmax.x, transformed.x), std::max(tmax.y, transformed.y), std::max(tmax.z, transformed.z));
|
||||
Vector transformed = matrix * Vector4(corners[i], 1.0f);
|
||||
tmin = Vector(std::min(tmin.x, transformed.x), std::min(tmin.y, transformed.y), std::min(tmin.z, transformed.z));
|
||||
tmax = Vector(std::max(tmax.x, transformed.x), std::max(tmax.y, transformed.y), std::max(tmax.z, transformed.z));
|
||||
}
|
||||
return AABB {
|
||||
.min = tmin,
|
||||
.max = tmax,
|
||||
};
|
||||
}
|
||||
void adjust(const Math::Vector vertex)
|
||||
void adjust(const Vector vertex)
|
||||
{
|
||||
min.x = std::min(min.x, vertex.x);
|
||||
min.y = std::min(min.y, vertex.y);
|
||||
@@ -89,12 +137,12 @@ struct AABB
|
||||
AABB combine(const AABB& other) const
|
||||
{
|
||||
return AABB {
|
||||
.min = Math::Vector(
|
||||
.min = Vector(
|
||||
std::min(min.x, other.min.x),
|
||||
std::min(min.y, other.min.y),
|
||||
std::min(min.z, other.min.z)
|
||||
),
|
||||
.max = Math::Vector (
|
||||
.max = Vector (
|
||||
std::max(max.x, other.max.x),
|
||||
std::max(max.y, other.max.y),
|
||||
std::max(max.z, other.max.z)
|
||||
|
||||
@@ -15,14 +15,14 @@ struct Camera
|
||||
Camera();
|
||||
~Camera();
|
||||
|
||||
Math::Matrix4 getViewMatrix() const
|
||||
Matrix4 getViewMatrix() const
|
||||
{
|
||||
assert (!bNeedsViewBuild);
|
||||
return viewMatrix;
|
||||
}
|
||||
Math::Vector getCameraPosition() const
|
||||
Vector getCameraPosition() const
|
||||
{
|
||||
return Math::Vector(viewMatrix[3]);
|
||||
return Vector(viewMatrix[3]);
|
||||
}
|
||||
void setViewport(Gfx::PViewport viewport);
|
||||
void mouseMove(float deltaX, float deltaY);
|
||||
@@ -30,7 +30,7 @@ struct Camera
|
||||
void moveX(float amount);
|
||||
void moveY(float amount);
|
||||
void buildViewMatrix();
|
||||
Math::Matrix4 viewMatrix;
|
||||
Matrix4 viewMatrix;
|
||||
//Transforms relative to actor
|
||||
float yaw;
|
||||
float pitch;
|
||||
|
||||
@@ -13,7 +13,7 @@ enum class ColliderType
|
||||
};
|
||||
struct Collider
|
||||
{
|
||||
ColliderType type;
|
||||
ColliderType type = ColliderType::STATIC;
|
||||
AABB boundingbox;
|
||||
ShapeBase physicsMesh;
|
||||
Collider transform(const Transform& transform) const;
|
||||
|
||||
@@ -8,10 +8,10 @@ namespace Component
|
||||
struct RigidBody
|
||||
{
|
||||
float mass = 1.0f;
|
||||
Math::Vector force;
|
||||
Math::Vector torque;
|
||||
Math::Vector linearMomentum;
|
||||
Math::Vector angularMomentum;
|
||||
Vector force;
|
||||
Vector torque;
|
||||
Vector linearMomentum;
|
||||
Vector angularMomentum;
|
||||
};
|
||||
} // namespace Component
|
||||
} // namespace Seele
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "ShapeBase.h"
|
||||
#include "AABB.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Component;
|
||||
@@ -20,13 +21,13 @@ struct ComputationState
|
||||
|
||||
/* volume integrals */
|
||||
float T0;
|
||||
Math::Vector T1, T2, TP;
|
||||
Vector T1, T2, TP;
|
||||
};
|
||||
|
||||
struct Face
|
||||
{
|
||||
StaticArray<Math::Vector, 3> vertices;
|
||||
Math::Vector normal;
|
||||
StaticArray<Vector, 3> vertices;
|
||||
Vector normal;
|
||||
float w;
|
||||
};
|
||||
|
||||
@@ -126,7 +127,7 @@ void computeFaceIntegrals(Face& f, ComputationState& state)
|
||||
+ w * (2 * (n[state.A] * state.Paa + n[state.B] * state.Pab) + w * state.Pa));
|
||||
}
|
||||
|
||||
void computeVolumeIntegrals(const Array<Math::Vector> vertices, const Array<uint32>& indices, ComputationState& state)
|
||||
void computeVolumeIntegrals(const Array<Vector> vertices, const Array<uint32>& indices, ComputationState& state)
|
||||
{
|
||||
std::memset(&state, 0, sizeof(ComputationState));
|
||||
for (size_t i = 0; i < indices.size(); i+=3)
|
||||
@@ -138,8 +139,8 @@ void computeVolumeIntegrals(const Array<Math::Vector> vertices, const Array<uint
|
||||
vertices[indices[i+2]],
|
||||
};
|
||||
|
||||
Math::Vector e1 = f.vertices[2] - f.vertices[0];
|
||||
Math::Vector e2 = f.vertices[1] - f.vertices[0];
|
||||
Vector e1 = f.vertices[2] - f.vertices[0];
|
||||
Vector e2 = f.vertices[1] - f.vertices[0];
|
||||
f.normal = glm::normalize(glm::cross(e1, e2));
|
||||
f.w = - f.normal.x * f.vertices[0].x
|
||||
- f.normal.y * f.vertices[0].y
|
||||
@@ -171,13 +172,13 @@ void computeVolumeIntegrals(const Array<Math::Vector> vertices, const Array<uint
|
||||
state.TP /= 2.0f;
|
||||
}
|
||||
|
||||
void computePhysicsParamsForMesh(Array<Math::Vector>& vertices, const Array<uint32_t>& indices, Math::Matrix3& bodyInertia, Math::Vector& centerOfMass, float& mass)
|
||||
void computePhysicsParamsForMesh(Array<Vector>& vertices, const Array<uint32_t>& indices, Matrix3& bodyInertia, Vector& centerOfMass, float& mass)
|
||||
{
|
||||
ComputationState state;
|
||||
computeVolumeIntegrals(vertices, indices, state);
|
||||
float density = 1;
|
||||
mass = density * state.T0;
|
||||
Math::Vector r = state.T1 / state.T0;
|
||||
Vector r = state.T1 / state.T0;
|
||||
centerOfMass = r;
|
||||
bodyInertia[0][0] = density * (state.T2.y + state.T2.z);
|
||||
bodyInertia[1][1] = density * (state.T2.z + state.T2.x);
|
||||
@@ -194,7 +195,12 @@ void computePhysicsParamsForMesh(Array<Math::Vector>& vertices, const Array<uint
|
||||
bodyInertia[2][1] = bodyInertia[1][2] += mass * r.z * r.x;
|
||||
}
|
||||
|
||||
ShapeBase::ShapeBase(Array<Math::Vector> vertices, Array<uint32> indices)
|
||||
ShapeBase::ShapeBase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ShapeBase::ShapeBase(Array<Vector> vertices, Array<uint32> indices)
|
||||
: vertices(vertices)
|
||||
, indices(indices)
|
||||
{
|
||||
@@ -206,17 +212,17 @@ ShapeBase ShapeBase::transform(const Component::Transform& transform) const
|
||||
ShapeBase result = *this;
|
||||
for(auto& vert : result.vertices)
|
||||
{
|
||||
vert = transform.toMatrix() * Math::Vector4(vert, 1.0f);
|
||||
vert = transform.toMatrix() * Vector4(vert, 1.0f);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ShapeBase::addCollider(Array<Math::Vector> verts, Array<uint32> inds, Math::Matrix4 matrix)
|
||||
void ShapeBase::addCollider(Array<Vector> verts, Array<uint32> inds, Matrix4 matrix)
|
||||
{
|
||||
size_t indOffset = vertices.size();
|
||||
for(auto vert : verts)
|
||||
{
|
||||
vertices.add(Math::Vector(matrix * Math::Vector4(vert, 1.0f)));
|
||||
vertices.add(Vector(matrix * Vector4(vert, 1.0f)));
|
||||
}
|
||||
for(auto ind : inds)
|
||||
{
|
||||
@@ -224,3 +230,39 @@ void ShapeBase::addCollider(Array<Math::Vector> verts, Array<uint32> inds, Math:
|
||||
}
|
||||
computePhysicsParamsForMesh(vertices, indices, bodyInertia, centerOfMass, mass);
|
||||
}
|
||||
|
||||
void ShapeBase::visualize() const
|
||||
{
|
||||
for(uint32 i = 0; i < indices.size(); i+=3)
|
||||
{
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+0]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+1]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+1]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+2]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+2]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
|
||||
gDebugVertices.add(DebugVertex{
|
||||
.position = Vector(vertices[indices[i+0]]),
|
||||
.color = Vector(1, 0, 0),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "Containers/Array.h"
|
||||
#include "Transform.h"
|
||||
#include "Graphics/DebugVertex.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
@@ -8,13 +9,15 @@ namespace Component
|
||||
{
|
||||
struct ShapeBase
|
||||
{
|
||||
ShapeBase(Array<Math::Vector> vertices, Array<uint32> indices);
|
||||
ShapeBase();
|
||||
ShapeBase(Array<Vector> vertices, Array<uint32> indices);
|
||||
ShapeBase transform(const Component::Transform& transform) const;
|
||||
void addCollider(Array<Math::Vector> vertices, Array<uint32> indices, Math::Matrix4 matrix);
|
||||
Math::Vector centerOfMass;
|
||||
void addCollider(Array<Vector> vertices, Array<uint32> indices, Matrix4 matrix);
|
||||
void visualize() const;
|
||||
Vector centerOfMass;
|
||||
float mass;
|
||||
Math::Matrix3 bodyInertia;
|
||||
Array<Math::Vector> vertices;
|
||||
Matrix3 bodyInertia;
|
||||
Array<Vector> vertices;
|
||||
Array<uint32> indices;
|
||||
};
|
||||
} // namespace Component
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace Component
|
||||
{
|
||||
struct StaticMesh
|
||||
{
|
||||
StaticMesh() {}
|
||||
StaticMesh(PMeshAsset mesh) : mesh(mesh) {}
|
||||
PMeshAsset mesh;
|
||||
};
|
||||
} // namespace Component
|
||||
|
||||
@@ -5,55 +5,55 @@ using namespace Seele::Component;
|
||||
DEFINE_COMPONENT(Transform)
|
||||
|
||||
|
||||
void Transform::setPosition(Math::Vector pos)
|
||||
void Transform::setPosition(Vector pos)
|
||||
{
|
||||
transform.setPosition(pos);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void Transform::setRotation(Math::Quaternion quat)
|
||||
void Transform::setRotation(Quaternion quat)
|
||||
{
|
||||
transform.setRotation(quat);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void Transform::setScale(Math::Vector scale)
|
||||
void Transform::setScale(Vector scale)
|
||||
{
|
||||
transform.setScale(scale);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void Transform::setRelativeLocation(Math::Vector location)
|
||||
void Transform::setRelativeLocation(Vector location)
|
||||
{
|
||||
transform = Math::Transform(location, transform.getRotation(), transform.getScale());
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::setRelativeRotation(Math::Vector rotation)
|
||||
void Transform::setRelativeRotation(Vector rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), Math::Quaternion(rotation), transform.getScale());
|
||||
transform = Math::Transform(transform.getPosition(), Quaternion(rotation), transform.getScale());
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::setRelativeRotation(Math::Quaternion rotation)
|
||||
void Transform::setRelativeRotation(Quaternion rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), rotation, transform.getScale());
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::setRelativeScale(Math::Vector scale)
|
||||
void Transform::setRelativeScale(Vector scale)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), transform.getRotation(), scale);
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::addRelativeLocation(Math::Vector translation)
|
||||
void Transform::addRelativeLocation(Vector translation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition() + translation, transform.getRotation(), transform.getScale());
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::addRelativeRotation(Math::Vector rotation)
|
||||
void Transform::addRelativeRotation(Vector rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), transform.getRotation() * Math::Quaternion(rotation), transform.getScale());
|
||||
transform = Math::Transform(transform.getPosition(), transform.getRotation() * Quaternion(rotation), transform.getScale());
|
||||
dirty = true;
|
||||
}
|
||||
void Transform::addRelativeRotation(Math::Quaternion rotation)
|
||||
void Transform::addRelativeRotation(Quaternion rotation)
|
||||
{
|
||||
transform = Math::Transform(transform.getPosition(), transform.getRotation() * rotation, transform.getScale());
|
||||
dirty = true;
|
||||
|
||||
@@ -8,31 +8,31 @@ namespace Component
|
||||
{
|
||||
struct Transform
|
||||
{
|
||||
Math::Vector getPosition() const { return transform.getPosition(); }
|
||||
Math::Quaternion getRotation() const { return transform.getRotation(); }
|
||||
Math::Vector getScale() const { return transform.getScale(); }
|
||||
Vector getPosition() const { return transform.getPosition(); }
|
||||
Quaternion getRotation() const { return transform.getRotation(); }
|
||||
Vector getScale() const { return transform.getScale(); }
|
||||
|
||||
Math::Vector getForward() const { return transform.getForward(); }
|
||||
Math::Vector getUp() const { return transform.getUp(); }
|
||||
Math::Vector getRight() const { return transform.getRight(); }
|
||||
Vector getForward() const { return transform.getForward(); }
|
||||
Vector getUp() const { return transform.getUp(); }
|
||||
Vector getRight() const { return transform.getRight(); }
|
||||
|
||||
Math::Matrix4 toMatrix() const { return transform.toMatrix(); }
|
||||
Matrix4 toMatrix() const { return transform.toMatrix(); }
|
||||
|
||||
bool isDirty() const { return dirty; }
|
||||
void clean() { dirty = false; }
|
||||
|
||||
void setPosition(Math::Vector pos);
|
||||
void setRotation(Math::Quaternion quat);
|
||||
void setScale(Math::Vector scale);
|
||||
void setPosition(Vector pos);
|
||||
void setRotation(Quaternion quat);
|
||||
void setScale(Vector scale);
|
||||
|
||||
void setRelativeLocation(Math::Vector location);
|
||||
void setRelativeRotation(Math::Quaternion rotation);
|
||||
void setRelativeRotation(Math::Vector rotation);
|
||||
void setRelativeScale(Math::Vector scale);
|
||||
void setRelativeLocation(Vector location);
|
||||
void setRelativeRotation(Quaternion rotation);
|
||||
void setRelativeRotation(Vector rotation);
|
||||
void setRelativeScale(Vector scale);
|
||||
|
||||
void addRelativeLocation(Math::Vector translation);
|
||||
void addRelativeRotation(Math::Quaternion rotation);
|
||||
void addRelativeRotation(Math::Vector rotation);
|
||||
void addRelativeLocation(Vector translation);
|
||||
void addRelativeRotation(Quaternion rotation);
|
||||
void addRelativeRotation(Vector rotation);
|
||||
private:
|
||||
bool dirty = true;
|
||||
Math::Transform transform;
|
||||
|
||||
@@ -156,7 +156,8 @@ public:
|
||||
assert(_data != nullptr);
|
||||
std::uninitialized_copy(init.begin(), init.end(), begin());
|
||||
}
|
||||
Array(const Array &other)
|
||||
|
||||
constexpr Array(const Array &other)
|
||||
: arraySize(other.arraySize)
|
||||
, allocated(other.allocated)
|
||||
, allocator(std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.allocator))
|
||||
@@ -165,7 +166,16 @@ public:
|
||||
assert(_data != nullptr);
|
||||
std::uninitialized_copy(other.begin(), other.end(), begin());
|
||||
}
|
||||
Array(Array &&other) noexcept
|
||||
constexpr Array(const Array& other, const Allocator& alloc)
|
||||
: arraySize(other.arraySize)
|
||||
, allocated(other.allocated)
|
||||
, allocator(alloc)
|
||||
{
|
||||
_data = allocateArray(other.allocated);
|
||||
assert(_data != nullptr);
|
||||
std::uninitialized_copy(other.begin(), other.end(), begin());
|
||||
}
|
||||
constexpr Array(Array &&other) noexcept
|
||||
: arraySize(std::move(other.arraySize))
|
||||
, allocated(std::move(other.allocated))
|
||||
, allocator(std::move(other.allocator))
|
||||
@@ -175,10 +185,26 @@ public:
|
||||
other.allocated = 0;
|
||||
other.arraySize = 0;
|
||||
}
|
||||
constexpr Array(Array &&other, const Allocator& alloc) noexcept
|
||||
: arraySize(std::move(other.arraySize))
|
||||
, allocated(std::move(other.allocated))
|
||||
, allocator(alloc)
|
||||
{
|
||||
_data = allocateArray(other.allocated);
|
||||
std::uninitialized_move(other.begin(), other.end(), begin());
|
||||
other.deallocateArray(other._data, other.allocated);
|
||||
other._data = nullptr;
|
||||
other.allocated = 0;
|
||||
other.arraySize = 0;
|
||||
}
|
||||
Array &operator=(const Array &other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
if (other.arraySize > allocated)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value )
|
||||
{
|
||||
if (!std::allocator_traits<allocator_type>::is_always_equal::value
|
||||
@@ -188,10 +214,6 @@ public:
|
||||
}
|
||||
allocator = other.allocator;
|
||||
}
|
||||
if (other.arraySize > allocated)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
if(_data == nullptr)
|
||||
{
|
||||
_data = allocateArray(other.allocated);
|
||||
@@ -207,14 +229,14 @@ public:
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
|
||||
{
|
||||
allocator = std::move(other.allocator);
|
||||
}
|
||||
if (_data != nullptr)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
|
||||
{
|
||||
allocator = std::move(other.allocator);
|
||||
}
|
||||
allocated = std::move(other.allocated);
|
||||
arraySize = std::move(other.arraySize);
|
||||
_data = other._data;
|
||||
@@ -395,7 +417,7 @@ public:
|
||||
}
|
||||
constexpr void resize(size_type newSize)
|
||||
{
|
||||
resizeInternal(newSize, std::move(T()));
|
||||
resizeInternal(newSize, T());
|
||||
}
|
||||
constexpr void resize(size_type newSize, const value_type& value)
|
||||
{
|
||||
@@ -532,7 +554,7 @@ private:
|
||||
return _data[arraySize - 1];
|
||||
}
|
||||
template<typename Type>
|
||||
void resizeInternal(size_type newSize, Type&& value) noexcept
|
||||
void resizeInternal(size_type newSize, const Type& value) noexcept
|
||||
{
|
||||
if (newSize <= allocated)
|
||||
{
|
||||
@@ -550,7 +572,7 @@ private:
|
||||
// Or construct the new elements by default
|
||||
for(size_type i = arraySize; i < newSize; ++i)
|
||||
{
|
||||
std::allocator_traits<allocator_type>::construct(allocator, &_data[i], std::move(value));
|
||||
std::allocator_traits<allocator_type>::construct(allocator, &_data[i], value);
|
||||
}
|
||||
}
|
||||
arraySize = newSize;
|
||||
@@ -568,7 +590,7 @@ private:
|
||||
// As well as default initialize the others
|
||||
for(size_type i = arraySize; i < newSize; ++i)
|
||||
{
|
||||
std::allocator_traits<allocator_type>::construct(allocator, &newData[i], std::move(value));
|
||||
std::allocator_traits<allocator_type>::construct(allocator, &newData[i], value);
|
||||
}
|
||||
deallocateArray(_data, allocated);
|
||||
arraySize = newSize;
|
||||
|
||||
@@ -124,10 +124,46 @@ public:
|
||||
, beginIt(Iterator(root))
|
||||
, endIt(Iterator(tail))
|
||||
, _size(0)
|
||||
, allocator(NodeAllocator())
|
||||
, allocator(Allocator())
|
||||
{
|
||||
}
|
||||
explicit List(const Allocator& alloc)
|
||||
: root(nullptr)
|
||||
, tail(nullptr)
|
||||
, beginIt(Iterator(root))
|
||||
, endIt(Iterator(tail))
|
||||
, _size(0)
|
||||
, allocator(alloc)
|
||||
{
|
||||
}
|
||||
List(size_type count, const T& value = T(), const Allocator& alloc = Allocator())
|
||||
: List(alloc)
|
||||
{
|
||||
for(size_type i = 0; i < count; ++i)
|
||||
{
|
||||
add(value);
|
||||
}
|
||||
}
|
||||
List(size_type count, const Allocator& alloc = Allocator())
|
||||
: List(alloc)
|
||||
{
|
||||
for(size_type i = 0; i < count; ++i)
|
||||
{
|
||||
add(T());
|
||||
}
|
||||
}
|
||||
List(const List& other)
|
||||
: List(std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.allocator))
|
||||
{
|
||||
//TODO: improve
|
||||
for(const auto& it : other)
|
||||
{
|
||||
add(it);
|
||||
}
|
||||
}
|
||||
|
||||
List(const List& other, const Allocator& alloc)
|
||||
: List(alloc)
|
||||
{
|
||||
//TODO: improve
|
||||
for(const auto& it : other)
|
||||
@@ -141,8 +177,19 @@ public:
|
||||
, beginIt(std::move(other.beginIt))
|
||||
, endIt(std::move(other.endIt))
|
||||
, _size(std::move(other._size))
|
||||
, allocator(std::move(other.allocator))
|
||||
{
|
||||
other._size = 0;
|
||||
other.clear();
|
||||
}
|
||||
List(List&& other, const Allocator& alloc)
|
||||
: root(std::move(other.root))
|
||||
, tail(std::move(other.tail))
|
||||
, beginIt(std::move(other.beginIt))
|
||||
, endIt(std::move(other.endIt))
|
||||
, _size(std::move(other._size))
|
||||
, allocator(allocator)
|
||||
{
|
||||
other.clear();
|
||||
}
|
||||
~List()
|
||||
{
|
||||
@@ -153,6 +200,15 @@ public:
|
||||
if(this != &other)
|
||||
{
|
||||
clear();
|
||||
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value )
|
||||
{
|
||||
if (!std::allocator_traits<allocator_type>::is_always_equal::value
|
||||
&& allocator != other.allocator)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
allocator = other.allocator;
|
||||
}
|
||||
for(const auto& it : other)
|
||||
{
|
||||
add(it);
|
||||
@@ -166,6 +222,10 @@ public:
|
||||
if(this != &other)
|
||||
{
|
||||
clear();
|
||||
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
|
||||
{
|
||||
allocator = std::move(other.allocator);
|
||||
}
|
||||
root = other.root;
|
||||
tail = other.tail;
|
||||
beginIt = other.beginIt;
|
||||
@@ -214,7 +274,7 @@ public:
|
||||
}
|
||||
// takes all elements from other and move-inserts them into
|
||||
// this, clearing other in the process
|
||||
void moveElements(List& other)
|
||||
void moveElements(List&& other)
|
||||
{
|
||||
tail->prev->next = other.root;
|
||||
other.root->prev = tail->prev;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
typedef uint64_t uint64;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint16_t uint16;
|
||||
@@ -11,4 +9,3 @@ typedef int64_t int64;
|
||||
typedef int32_t int32;
|
||||
typedef int16_t int16;
|
||||
typedef int8_t int8;
|
||||
} // namespace Seele
|
||||
@@ -1,5 +1,6 @@
|
||||
target_sources(Engine
|
||||
PRIVATE
|
||||
DebugVertex.h
|
||||
GraphicsResources.h
|
||||
GraphicsResources.cpp
|
||||
GraphicsInitializer.h
|
||||
@@ -23,6 +24,7 @@ target_sources(Engine
|
||||
target_sources(Engine
|
||||
PUBLIC FILE_SET HEADERS
|
||||
FILES
|
||||
DebugVertex.h
|
||||
GraphicsResources.h
|
||||
GraphicsInitializer.h
|
||||
GraphicsEnums.h
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "Math/Vector.h"
|
||||
#include "Containers/Array.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
struct DebugVertex
|
||||
{
|
||||
Vector position;
|
||||
Vector color;
|
||||
};
|
||||
extern Array<DebugVertex> gDebugVertices;
|
||||
} // namespace Seele
|
||||
@@ -18,10 +18,10 @@ PVertexBuffer Graphics::getNullVertexBuffer()
|
||||
{
|
||||
VertexBufferCreateInfo createInfo;
|
||||
createInfo.numVertices = 1;
|
||||
createInfo.vertexSize = sizeof(Math::Vector4);
|
||||
Math::Vector4 data = Math::Vector4(1, 1, 1, 1);
|
||||
createInfo.vertexSize = sizeof(Vector4);
|
||||
Vector4 data = Vector4(1, 1, 1, 1);
|
||||
createInfo.resourceData.data = reinterpret_cast<uint8*>(&data);
|
||||
createInfo.resourceData.size = sizeof(Math::Vector4);
|
||||
createInfo.resourceData.size = sizeof(Vector4);
|
||||
nullVertexBuffer = createVertexBuffer(createInfo);
|
||||
}
|
||||
return nullVertexBuffer;
|
||||
|
||||
@@ -42,7 +42,7 @@ struct WindowCreateInfo
|
||||
};
|
||||
struct ViewportCreateInfo
|
||||
{
|
||||
Math::URect dimensions;
|
||||
URect dimensions;
|
||||
float fieldOfView = 1.222f; // 70 deg
|
||||
};
|
||||
// doesnt own the data, only proxy it
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "Graphics.h"
|
||||
#include "RenderPass/DepthPrepass.h"
|
||||
#include "RenderPass/BasePass.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "Material/Material.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Gfx;
|
||||
@@ -54,7 +54,7 @@ const ShaderCollection* ShaderMap::findShaders(PermutationId&& id) const
|
||||
ShaderCollection& ShaderMap::createShaders(
|
||||
PGraphics graphics,
|
||||
RenderPassType renderPass,
|
||||
PMaterialAsset material,
|
||||
PMaterial material,
|
||||
VertexInputType* vertexInput,
|
||||
bool /*bPositionOnly*/)
|
||||
{
|
||||
@@ -195,10 +195,11 @@ bool UniformBuffer::updateContents(const BulkResourceData& resourceData)
|
||||
return true;
|
||||
}
|
||||
|
||||
StructuredBuffer::StructuredBuffer(QueueFamilyMapping mapping, uint32 stride, const BulkResourceData& resourceData)
|
||||
StructuredBuffer::StructuredBuffer(QueueFamilyMapping mapping, uint32 stride, uint32 numElements, const BulkResourceData& resourceData)
|
||||
: Buffer(mapping, resourceData.owner)
|
||||
, contents(resourceData.size)
|
||||
, stride(stride)
|
||||
, numElements(numElements)
|
||||
{
|
||||
if(resourceData.data != nullptr)
|
||||
{
|
||||
@@ -515,7 +516,7 @@ Viewport::~Viewport()
|
||||
{
|
||||
}
|
||||
|
||||
Math::Matrix4 Viewport::getProjectionMatrix() const
|
||||
Matrix4 Viewport::getProjectionMatrix() const
|
||||
{
|
||||
if(fieldOfView > 0.0f)
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ struct VertexInputStream;
|
||||
struct VertexStreamComponent;
|
||||
class VertexInputType;
|
||||
struct MeshBatchElement;
|
||||
DECLARE_REF(MaterialAsset)
|
||||
DECLARE_REF(Material)
|
||||
namespace Gfx
|
||||
{
|
||||
DECLARE_REF(Graphics)
|
||||
@@ -97,11 +97,11 @@ struct PermutationId
|
||||
{
|
||||
uint32 hash;
|
||||
PermutationId()
|
||||
: hash(0)
|
||||
{}
|
||||
PermutationId(ShaderPermutation permutation)
|
||||
{
|
||||
hash = CRC::Calculate(&permutation, sizeof(ShaderPermutation), CRC::CRC_32());
|
||||
}
|
||||
: hash(CRC::Calculate(&permutation, sizeof(ShaderPermutation), CRC::CRC_32()))
|
||||
{}
|
||||
friend inline bool operator==(const PermutationId& lhs, const PermutationId& rhs)
|
||||
{
|
||||
return lhs.hash == rhs.hash;
|
||||
@@ -138,7 +138,7 @@ public:
|
||||
ShaderCollection& createShaders(
|
||||
PGraphics graphics,
|
||||
RenderPassType passName,
|
||||
PMaterialAsset material,
|
||||
PMaterial material,
|
||||
VertexInputType* vertexInput,
|
||||
bool bPositionOnly);
|
||||
private:
|
||||
@@ -409,7 +409,7 @@ DEFINE_REF(IndexBuffer)
|
||||
class StructuredBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
StructuredBuffer(QueueFamilyMapping mapping, uint32 stride, const BulkResourceData& bulkResourceData);
|
||||
StructuredBuffer(QueueFamilyMapping mapping, uint32 stride, uint32 numElements, const BulkResourceData& bulkResourceData);
|
||||
virtual ~StructuredBuffer();
|
||||
virtual bool updateContents(const BulkResourceData& resourceData);
|
||||
bool isDataEquals(StructuredBuffer* other)
|
||||
@@ -428,6 +428,10 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
constexpr uint32 getNumElements() const
|
||||
{
|
||||
return numElements;
|
||||
}
|
||||
constexpr uint32 getStride() const
|
||||
{
|
||||
return stride;
|
||||
@@ -439,6 +443,7 @@ protected:
|
||||
SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0;
|
||||
|
||||
Array<uint8> contents;
|
||||
uint32 numElements;
|
||||
uint32 stride;
|
||||
};
|
||||
DEFINE_REF(StructuredBuffer)
|
||||
@@ -655,7 +660,7 @@ public:
|
||||
constexpr uint32 getSizeY() const {return sizeY;}
|
||||
constexpr uint32 getOffsetX() const {return offsetX;}
|
||||
constexpr uint32 getOffsetY() const {return offsetY;}
|
||||
Math::Matrix4 getProjectionMatrix() const;
|
||||
Matrix4 getProjectionMatrix() const;
|
||||
protected:
|
||||
uint32 sizeX;
|
||||
uint32 sizeY;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
using namespace Seele;
|
||||
|
||||
Mesh::Mesh(PVertexShaderInput vertexInput, Gfx::PIndexBuffer indexBuffer)
|
||||
: indexBuffer(indexBuffer)
|
||||
, vertexInput(vertexInput)
|
||||
: vertexInput(vertexInput)
|
||||
, indexBuffer(indexBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
#include "GraphicsResources.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "Material/MaterialInterface.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(MaterialAsset)
|
||||
DECLARE_REF(VertexShaderInput)
|
||||
DECLARE_NAME_REF(Gfx, IndexBuffer)
|
||||
class Mesh
|
||||
{
|
||||
public:
|
||||
@@ -13,7 +14,7 @@ public:
|
||||
|
||||
Gfx::PIndexBuffer indexBuffer;
|
||||
PVertexShaderInput vertexInput;
|
||||
PMaterialAsset referencedMaterial;
|
||||
PMaterialInterface referencedMaterial;
|
||||
private:
|
||||
};
|
||||
DEFINE_REF(Mesh)
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
#include "MeshBatch.h"
|
||||
#include "GraphicsResources.h"
|
||||
#include "VertexShaderInput.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "Material/MaterialInterface.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MeshBatchElement::MeshBatchElement()
|
||||
: uniformBuffer(nullptr)
|
||||
, indexBuffer(nullptr)
|
||||
: indexBuffer(nullptr)
|
||||
, firstIndex(0)
|
||||
, numPrimitives(0)
|
||||
, numInstances(1)
|
||||
|
||||
@@ -4,22 +4,16 @@
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(VertexShaderInput)
|
||||
DECLARE_REF(MaterialAsset)
|
||||
DECLARE_REF(MaterialInterface)
|
||||
DECLARE_NAME_REF(Gfx, VertexBuffer)
|
||||
DECLARE_NAME_REF(Gfx, IndexBuffer)
|
||||
DECLARE_NAME_REF(Gfx, UniformBuffer)
|
||||
struct MeshBatchElement
|
||||
{
|
||||
public:
|
||||
Gfx::PUniformBuffer uniformBuffer;
|
||||
Gfx::PIndexBuffer indexBuffer;
|
||||
|
||||
union
|
||||
{
|
||||
uint32* instanceRuns;
|
||||
};
|
||||
|
||||
|
||||
uint32 sceneDataIndex;
|
||||
uint32 firstIndex;
|
||||
uint32 numPrimitives;
|
||||
|
||||
@@ -45,27 +39,7 @@ struct MeshBatch
|
||||
|
||||
PVertexShaderInput vertexInput;
|
||||
|
||||
PMaterialAsset material;
|
||||
|
||||
inline int32 getNumPrimitives() const
|
||||
{
|
||||
int32 count = 0;
|
||||
for(uint32 index = 0; index < elements.size(); ++index)
|
||||
{
|
||||
if(elements[index].isInstanced && elements[index].instanceRuns)
|
||||
{
|
||||
for(uint32 run = 0; run < elements[index].numInstances; ++run)
|
||||
{
|
||||
count += elements[index].numPrimitives * (elements[index].instanceRuns[run * 2 + 1] - elements[index].instanceRuns[run * 2] - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
count += elements[index].numPrimitives * elements[index].numInstances;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
PMaterialInterface material;
|
||||
|
||||
MeshBatch();
|
||||
MeshBatch(const MeshBatch& other) = default;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "Actor/CameraActor.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "RenderGraph.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "Material/MaterialInstance.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
@@ -29,7 +29,7 @@ void BasePassMeshProcessor::processMeshBatch(
|
||||
Array<Gfx::PDescriptorSet> descriptorSets,
|
||||
int32 /*staticMeshId*/)
|
||||
{
|
||||
PMaterialAsset material = batch.material;
|
||||
PMaterialInterface material = batch.material;
|
||||
//const Gfx::MaterialShadingModel shadingModel = material->getShadingModel();
|
||||
|
||||
const PVertexShaderInput vertexInput = batch.vertexInput;
|
||||
@@ -47,12 +47,7 @@ void BasePassMeshProcessor::processMeshBatch(
|
||||
descriptorSets[BasePass::INDEX_MATERIAL] = materialSet;
|
||||
for(uint32 i = 0; i < batch.elements.size(); ++i)
|
||||
{
|
||||
Gfx::PDescriptorSet descriptorSet = primitiveLayout->allocateDescriptorSet();
|
||||
descriptorSet->updateBuffer(0, batch.elements[i].uniformBuffer);
|
||||
descriptorSet->writeChanges();
|
||||
descriptorSets[BasePass::INDEX_SCENE_DATA] = descriptorSet;
|
||||
buildMeshDrawCommand(batch,
|
||||
// primitiveComponent,
|
||||
renderPass,
|
||||
pipelineLayout,
|
||||
renderCommand,
|
||||
@@ -104,9 +99,14 @@ BasePass::BasePass(Gfx::PGraphics graphics)
|
||||
descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet();
|
||||
|
||||
primitiveLayout = graphics->createDescriptorLayout("PrimitiveLayout");
|
||||
primitiveLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
primitiveLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||
primitiveLayout->create();
|
||||
basePassLayout->addDescriptorLayout(INDEX_SCENE_DATA, primitiveLayout);
|
||||
basePassLayout->addPushConstants(Gfx::SePushConstantRange{
|
||||
.stageFlags = (Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT),
|
||||
.offset = 0,
|
||||
.size = sizeof(uint32),
|
||||
});
|
||||
}
|
||||
|
||||
BasePass::~BasePass()
|
||||
@@ -121,13 +121,17 @@ void BasePass::beginFrame(const Component::Camera& cam)
|
||||
|
||||
viewParams.viewMatrix = cam.getViewMatrix();
|
||||
viewParams.projectionMatrix = viewport->getProjectionMatrix();
|
||||
viewParams.cameraPosition = Math::Vector4(cam.getCameraPosition(), 0);
|
||||
viewParams.screenDimensions = Math::Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
|
||||
viewParams.cameraPosition = Vector4(cam.getCameraPosition(), 0);
|
||||
viewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
|
||||
uniformUpdate.size = sizeof(ViewParameter);
|
||||
uniformUpdate.data = (uint8*)&viewParams;
|
||||
viewParamBuffer->updateContents(uniformUpdate);
|
||||
viewLayout->reset();
|
||||
lightLayout->reset();
|
||||
|
||||
descriptorSets[INDEX_SCENE_DATA] = primitiveLayout->allocateDescriptorSet();
|
||||
descriptorSets[INDEX_SCENE_DATA]->updateBuffer(0, passData.sceneDataBuffer);
|
||||
descriptorSets[INDEX_SCENE_DATA]->writeChanges();
|
||||
descriptorSets[INDEX_LIGHT_ENV] = lightLayout->allocateDescriptorSet();
|
||||
descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet();
|
||||
descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer);
|
||||
@@ -152,6 +156,7 @@ void BasePass::render()
|
||||
descriptorSets[INDEX_LIGHT_ENV]->updateBuffer(4, oLightIndexList);
|
||||
descriptorSets[INDEX_LIGHT_ENV]->updateTexture(5, oLightGrid);
|
||||
descriptorSets[INDEX_LIGHT_ENV]->writeChanges();
|
||||
|
||||
graphics->beginRenderPass(renderPass);
|
||||
for (auto &&meshBatch : passData.staticDrawList)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@ DECLARE_REF(CameraActor)
|
||||
struct BasePassData
|
||||
{
|
||||
Array<StaticMeshBatch> staticDrawList;
|
||||
Gfx::PStructuredBuffer sceneDataBuffer;
|
||||
};
|
||||
class BasePass : public RenderPass<BasePassData>
|
||||
{
|
||||
|
||||
@@ -2,6 +2,8 @@ target_sources(Engine
|
||||
PRIVATE
|
||||
BasePass.h
|
||||
BasePass.cpp
|
||||
DebugPass.h
|
||||
DebugPass.cpp
|
||||
DepthPrepass.h
|
||||
DepthPrepass.cpp
|
||||
LightCullingPass.h
|
||||
@@ -21,6 +23,7 @@ target_sources(Engine
|
||||
PUBLIC FILE_SET HEADERS
|
||||
FILES
|
||||
BasePass.h
|
||||
DebugPass.h
|
||||
DepthPrepass.h
|
||||
LightCullingPass.h
|
||||
MeshProcessor.h
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
#include "DebugPass.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Array<DebugVertex> Seele::gDebugVertices;
|
||||
|
||||
DebugPass::DebugPass(Gfx::PGraphics graphics)
|
||||
: RenderPass(graphics)
|
||||
{
|
||||
|
||||
}
|
||||
DebugPass::~DebugPass()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DebugPass::beginFrame(const Component::Camera& cam)
|
||||
{
|
||||
BulkResourceData uniformUpdate;
|
||||
|
||||
viewParams.viewMatrix = cam.getViewMatrix();
|
||||
viewParams.projectionMatrix = viewport->getProjectionMatrix();
|
||||
viewParams.cameraPosition = Vector4(cam.getCameraPosition(), 0);
|
||||
viewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
|
||||
uniformUpdate.size = sizeof(ViewParameter);
|
||||
uniformUpdate.data = (uint8*)&viewParams;
|
||||
viewParamsBuffer->updateContents(uniformUpdate);
|
||||
descriptorLayout->reset();
|
||||
descriptorSet = descriptorLayout->allocateDescriptorSet();
|
||||
descriptorSet->updateBuffer(0, viewParamsBuffer);
|
||||
descriptorSet->writeChanges();
|
||||
|
||||
VertexBufferCreateInfo vertexBufferInfo = {
|
||||
.resourceData = {
|
||||
.size = sizeof(DebugVertex) * passData.vertices.size(),
|
||||
.data = (uint8*)passData.vertices.data(),
|
||||
},
|
||||
.vertexSize = sizeof(DebugVertex),
|
||||
.numVertices = (uint32)passData.vertices.size(),
|
||||
};
|
||||
debugVertices = graphics->createVertexBuffer(vertexBufferInfo);
|
||||
|
||||
}
|
||||
|
||||
void DebugPass::render()
|
||||
{
|
||||
graphics->beginRenderPass(renderPass);
|
||||
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand("DebugRender");
|
||||
renderCommand->setViewport(viewport);
|
||||
renderCommand->bindPipeline(pipeline);
|
||||
renderCommand->bindDescriptor(descriptorSet);
|
||||
renderCommand->bindVertexBuffer({VertexInputStream(0, 0, debugVertices)});
|
||||
renderCommand->draw((uint32)passData.vertices.size(), 1, 0, 0);
|
||||
graphics->executeCommands(Array{renderCommand});
|
||||
graphics->endRenderPass();
|
||||
}
|
||||
|
||||
void DebugPass::endFrame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DebugPass::publishOutputs()
|
||||
{
|
||||
UniformBufferCreateInfo viewCreateInfo = {
|
||||
.resourceData = BulkResourceData {
|
||||
.size = sizeof(ViewParameter),
|
||||
.data = nullptr,
|
||||
},
|
||||
.bDynamic = true
|
||||
};
|
||||
viewParamsBuffer = graphics->createUniformBuffer(viewCreateInfo);
|
||||
|
||||
descriptorLayout = graphics->createDescriptorLayout("DebugDescLayout");
|
||||
descriptorLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
descriptorLayout->create();
|
||||
|
||||
pipelineLayout = graphics->createPipelineLayout();
|
||||
pipelineLayout->addDescriptorLayout(0, descriptorLayout);
|
||||
pipelineLayout->create();
|
||||
}
|
||||
|
||||
void DebugPass::createRenderPass()
|
||||
{
|
||||
Gfx::PRenderTargetAttachment baseColorAttachment = resources->requestRenderTarget("BASEPASS_COLOR");
|
||||
baseColorAttachment->loadOp = Gfx::SE_ATTACHMENT_LOAD_OP_LOAD;
|
||||
Gfx::PRenderTargetAttachment depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH");
|
||||
depthAttachment->loadOp = Gfx::SE_ATTACHMENT_LOAD_OP_LOAD;
|
||||
Gfx::PRenderTargetLayout layout = new Gfx::RenderTargetLayout(baseColorAttachment, depthAttachment);
|
||||
renderPass = graphics->createRenderPass(layout, viewport);
|
||||
|
||||
ShaderCreateInfo createInfo;
|
||||
createInfo.name = "DebugVertex";
|
||||
createInfo.mainModule = "Debug";
|
||||
createInfo.entryPoint = "vertexMain";
|
||||
createInfo.defines["INDEX_VIEW_PARAMS"] = "0";
|
||||
Gfx::PVertexShader vertexShader = graphics->createVertexShader(createInfo);
|
||||
|
||||
createInfo.name = "DebugFragment";
|
||||
|
||||
createInfo.entryPoint = "fragmentMain";
|
||||
Gfx::PFragmentShader fragmentShader = graphics->createFragmentShader(createInfo);
|
||||
|
||||
Gfx::PVertexDeclaration vertexDecl = graphics->createVertexDeclaration({
|
||||
Gfx::VertexElement {
|
||||
.streamIndex = 0,
|
||||
.offset = offsetof(DebugVertex, position),
|
||||
.vertexFormat = Gfx::SE_FORMAT_R32G32B32_SFLOAT,
|
||||
.attributeIndex = 0,
|
||||
.stride = sizeof(DebugVertex),
|
||||
},
|
||||
Gfx::VertexElement {
|
||||
.streamIndex = 0,
|
||||
.offset = offsetof(DebugVertex, color),
|
||||
.vertexFormat = Gfx::SE_FORMAT_R32G32B32_SFLOAT,
|
||||
.attributeIndex = 1,
|
||||
.stride = sizeof(DebugVertex),
|
||||
}
|
||||
});
|
||||
|
||||
GraphicsPipelineCreateInfo gfxInfo;
|
||||
gfxInfo.vertexDeclaration = vertexDecl;
|
||||
gfxInfo.vertexShader = vertexShader;
|
||||
gfxInfo.fragmentShader = fragmentShader;
|
||||
gfxInfo.rasterizationState.polygonMode = Gfx::SE_POLYGON_MODE_LINE;
|
||||
gfxInfo.rasterizationState.lineWidth = 5.f;
|
||||
gfxInfo.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
||||
gfxInfo.pipelineLayout = pipelineLayout;
|
||||
gfxInfo.renderPass = renderPass;
|
||||
pipeline = graphics->createGraphicsPipeline(gfxInfo);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "RenderPass.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include "Scene/Scene.h"
|
||||
#include "Graphics/DebugVertex.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(CameraActor)
|
||||
DECLARE_REF(Scene)
|
||||
DECLARE_REF(Viewport)
|
||||
struct DebugPassData
|
||||
{
|
||||
Array<DebugVertex> vertices;
|
||||
};
|
||||
class DebugPass : public RenderPass<DebugPassData>
|
||||
{
|
||||
public:
|
||||
DebugPass(Gfx::PGraphics graphics);
|
||||
virtual ~DebugPass();
|
||||
virtual void beginFrame(const Component::Camera& cam) override;
|
||||
virtual void render() override;
|
||||
virtual void endFrame() override;
|
||||
virtual void publishOutputs() override;
|
||||
virtual void createRenderPass() override;
|
||||
private:
|
||||
Gfx::PVertexBuffer debugVertices;
|
||||
Gfx::PUniformBuffer viewParamsBuffer;
|
||||
Gfx::PDescriptorLayout descriptorLayout;
|
||||
Gfx::PDescriptorSet descriptorSet;
|
||||
Gfx::PPipelineLayout pipelineLayout;
|
||||
Gfx::PGraphicsPipeline pipeline;
|
||||
};
|
||||
DEFINE_REF(DebugPass)
|
||||
} // namespace Seele
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "Actor/CameraActor.h"
|
||||
#include "Math/Vector.h"
|
||||
#include "RenderGraph.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "Material/MaterialInterface.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
@@ -28,7 +28,7 @@ void DepthPrepassMeshProcessor::processMeshBatch(
|
||||
int32 /*staticMeshId*/)
|
||||
{
|
||||
//std::cout << "Depth void started" << std::endl;
|
||||
PMaterialAsset material = batch.material;
|
||||
PMaterialInterface material = batch.material;
|
||||
//const Gfx::MaterialShadingModel shadingModel = material->getShadingModel();
|
||||
|
||||
const PVertexShaderInput vertexInput = batch.vertexInput;
|
||||
@@ -44,11 +44,7 @@ void DepthPrepassMeshProcessor::processMeshBatch(
|
||||
Gfx::PDescriptorSet materialSet = material->createDescriptorSet();
|
||||
descriptorSets[DepthPrepass::INDEX_MATERIAL] = materialSet;
|
||||
for(uint32 i = 0; i < batch.elements.size(); ++i)
|
||||
{
|
||||
Gfx::PDescriptorSet descriptorSet = primitiveLayout->allocateDescriptorSet();
|
||||
descriptorSet->updateBuffer(0, batch.elements[i].uniformBuffer);
|
||||
descriptorSet->writeChanges();
|
||||
descriptorSets[DepthPrepass::INDEX_SCENE_DATA] = descriptorSet;
|
||||
{
|
||||
buildMeshDrawCommand(batch,
|
||||
// primitiveComponent,
|
||||
renderPass,
|
||||
@@ -87,9 +83,14 @@ DepthPrepass::DepthPrepass(Gfx::PGraphics graphics)
|
||||
depthPrepassLayout->addDescriptorLayout(INDEX_VIEW_PARAMS, viewLayout);
|
||||
|
||||
primitiveLayout = graphics->createDescriptorLayout("PrimitiveLayout");
|
||||
primitiveLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
primitiveLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER);
|
||||
primitiveLayout->create();
|
||||
depthPrepassLayout->addDescriptorLayout(INDEX_SCENE_DATA, primitiveLayout);
|
||||
depthPrepassLayout->addPushConstants(Gfx::SePushConstantRange{
|
||||
.stageFlags = (Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT),
|
||||
.offset = 0,
|
||||
.size = sizeof(uint32),
|
||||
});
|
||||
}
|
||||
|
||||
DepthPrepass::~DepthPrepass()
|
||||
@@ -104,12 +105,15 @@ void DepthPrepass::beginFrame(const Component::Camera& cam)
|
||||
|
||||
viewParams.viewMatrix = cam.getViewMatrix();
|
||||
viewParams.projectionMatrix = viewport->getProjectionMatrix();
|
||||
viewParams.cameraPosition = Math::Vector4(cam.getCameraPosition(), 0);
|
||||
viewParams.screenDimensions = Math::Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
|
||||
viewParams.cameraPosition = Vector4(cam.getCameraPosition(), 0);
|
||||
viewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
|
||||
uniformUpdate.size = sizeof(ViewParameter);
|
||||
uniformUpdate.data = (uint8*)&viewParams;
|
||||
viewParamBuffer->updateContents(uniformUpdate);
|
||||
viewLayout->reset();
|
||||
descriptorSets[INDEX_SCENE_DATA] = primitiveLayout->allocateDescriptorSet();
|
||||
descriptorSets[INDEX_SCENE_DATA]->updateBuffer(0, passData.sceneDataBuffer);
|
||||
descriptorSets[INDEX_SCENE_DATA]->writeChanges();
|
||||
descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet();
|
||||
descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer);
|
||||
descriptorSets[INDEX_VIEW_PARAMS]->writeChanges();
|
||||
|
||||
@@ -26,6 +26,7 @@ DEFINE_REF(DepthPrepassMeshProcessor)
|
||||
struct DepthPrepassData
|
||||
{
|
||||
Array<StaticMeshBatch> staticDrawList;
|
||||
Gfx::PStructuredBuffer sceneDataBuffer;
|
||||
};
|
||||
class DepthPrepass : public RenderPass<DepthPrepassData>
|
||||
{
|
||||
|
||||
@@ -25,8 +25,8 @@ void LightCullingPass::beginFrame(const Component::Camera& cam)
|
||||
BulkResourceData uniformUpdate;
|
||||
viewParams.viewMatrix = cam.getViewMatrix();
|
||||
viewParams.projectionMatrix = viewport->getProjectionMatrix();
|
||||
viewParams.cameraPosition = Math::Vector4(cam.getCameraPosition(), 0);
|
||||
viewParams.screenDimensions = Math::Vector2(static_cast<float>(viewportWidth), static_cast<float>(viewportHeight));
|
||||
viewParams.cameraPosition = Vector4(cam.getCameraPosition(), 0);
|
||||
viewParams.screenDimensions = Vector2(static_cast<float>(viewportWidth), static_cast<float>(viewportHeight));
|
||||
uniformUpdate.size = sizeof(ViewParameter);
|
||||
uniformUpdate.data = (uint8*)&viewParams;
|
||||
viewParamsBuffer->updateContents(uniformUpdate);
|
||||
@@ -261,9 +261,9 @@ void LightCullingPass::setupFrustums()
|
||||
glm::uvec3 numThreadGroups = glm::ceil(glm::vec3(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1));
|
||||
|
||||
viewParams = {
|
||||
.viewMatrix = Math::Matrix4(),
|
||||
.projectionMatrix = Math::Matrix4(),
|
||||
.cameraPosition = Math::Vector4(),
|
||||
.viewMatrix = Matrix4(),
|
||||
.projectionMatrix = Matrix4(),
|
||||
.cameraPosition = Vector4(),
|
||||
.screenDimensions = glm::vec2(viewportWidth, viewportHeight),
|
||||
};
|
||||
dispatchParams.numThreads = numThreads;
|
||||
|
||||
@@ -36,7 +36,7 @@ private:
|
||||
} dispatchParams;
|
||||
struct Plane
|
||||
{
|
||||
Math::Vector n;
|
||||
Vector n;
|
||||
float d;
|
||||
};
|
||||
struct Frustum
|
||||
|
||||
@@ -56,10 +56,18 @@ void MeshProcessor::buildMeshDrawCommand(
|
||||
drawCommand->bindPipeline(pipeline);
|
||||
drawCommand->bindVertexBuffer(vertexStreams);
|
||||
drawCommand->bindDescriptor(descriptors);
|
||||
for(auto element : meshBatch.elements)
|
||||
for(const auto& element : meshBatch.elements)
|
||||
{
|
||||
drawCommand->bindIndexBuffer(element.indexBuffer);
|
||||
drawCommand->draw(element);
|
||||
drawCommand->pushConstants(pipelineLayout, Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(uint32), &element.sceneDataIndex);
|
||||
if(element.indexBuffer != nullptr)
|
||||
{
|
||||
drawCommand->bindIndexBuffer(element.indexBuffer);
|
||||
drawCommand->draw(element);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawCommand->draw(vertexStreams[0].vertexBuffer->getNumVertices(), 1, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,11 @@ public:
|
||||
protected:
|
||||
struct ViewParameter
|
||||
{
|
||||
Math::Matrix4 viewMatrix;
|
||||
Math::Matrix4 projectionMatrix;
|
||||
Math::Vector4 cameraPosition;
|
||||
Math::Vector2 screenDimensions;
|
||||
Math::Vector2 pad0;
|
||||
Matrix4 viewMatrix;
|
||||
Matrix4 projectionMatrix;
|
||||
Vector4 cameraPosition;
|
||||
Vector2 screenDimensions;
|
||||
Vector2 pad0;
|
||||
} viewParams;
|
||||
PRenderGraphResources resources;
|
||||
RenderPassDataType passData;
|
||||
|
||||
@@ -27,8 +27,8 @@ void TextPass::beginFrame(const Component::Camera&)
|
||||
for(uint32 c : render.text)
|
||||
{
|
||||
const GlyphData& glyph = fd.glyphDataSet[fd.characterToGlyphIndex[c]];
|
||||
Math::Vector2 bearing = glyph.bearing;
|
||||
Math::Vector2 size = glyph.size;
|
||||
Vector2 bearing = glyph.bearing;
|
||||
Vector2 size = glyph.size;
|
||||
float xpos = x + bearing.x * render.scale;
|
||||
float ypos = y - (size.y - bearing.y) * render.scale;
|
||||
|
||||
@@ -36,8 +36,8 @@ void TextPass::beginFrame(const Component::Camera&)
|
||||
float h = size.y * render.scale;
|
||||
|
||||
instanceData.add(GlyphInstanceData{
|
||||
.position = Math::Vector2(xpos, ypos),
|
||||
.widthHeight = Math::Vector2(w, h),
|
||||
.position = Vector2(xpos, ypos),
|
||||
.widthHeight = Vector2(w, h),
|
||||
.glyphIndex = fd.characterToGlyphIndex[c],
|
||||
});
|
||||
x += (glyph.advance >> 6) * render.scale;
|
||||
@@ -61,7 +61,7 @@ void TextPass::beginFrame(const Component::Camera&)
|
||||
}
|
||||
auto proj = viewport->getProjectionMatrix();
|
||||
BulkResourceData projectionUpdate = {
|
||||
.size = sizeof(Math::Matrix4),
|
||||
.size = sizeof(Matrix4),
|
||||
.data = (uint8*)&proj,
|
||||
};
|
||||
projectionBuffer->updateContents(projectionUpdate);
|
||||
@@ -157,7 +157,7 @@ void TextPass::createRenderPass()
|
||||
|
||||
projectionBuffer = graphics->createUniformBuffer({
|
||||
.resourceData = {
|
||||
.size = sizeof(Math::Matrix4),
|
||||
.size = sizeof(Matrix4),
|
||||
.data = nullptr,
|
||||
},
|
||||
.bDynamic = true,
|
||||
|
||||
@@ -13,8 +13,8 @@ struct TextRender
|
||||
{
|
||||
std::string text;
|
||||
PFontAsset font;
|
||||
Math::Vector4 textColor;
|
||||
Math::Vector2 position;
|
||||
Vector4 textColor;
|
||||
Vector2 position;
|
||||
float scale;
|
||||
};
|
||||
struct TextPassData
|
||||
@@ -35,19 +35,19 @@ public:
|
||||
private:
|
||||
struct GlyphData
|
||||
{
|
||||
Math::Vector2 bearing;
|
||||
Math::Vector2 size;
|
||||
Vector2 bearing;
|
||||
Vector2 size;
|
||||
uint32 advance;
|
||||
};
|
||||
struct GlyphInstanceData
|
||||
{
|
||||
Math::Vector2 position;
|
||||
Math::Vector2 widthHeight;
|
||||
Vector2 position;
|
||||
Vector2 widthHeight;
|
||||
uint32 glyphIndex;
|
||||
};
|
||||
struct TextData
|
||||
{
|
||||
Math::Vector4 textColor;
|
||||
Vector4 textColor;
|
||||
float scale;
|
||||
};
|
||||
struct FontData
|
||||
|
||||
@@ -144,10 +144,10 @@ void UIPass::createRenderPass()
|
||||
descriptorLayout->addDescriptorBinding(3, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 256, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT | Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT);
|
||||
descriptorLayout->create();
|
||||
|
||||
Math::Matrix4 projectionMatrix = glm::ortho(0, 1, 1, 0);
|
||||
Matrix4 projectionMatrix = glm::ortho(0, 1, 1, 0);
|
||||
UniformBufferCreateInfo info = {
|
||||
.resourceData = {
|
||||
.size = sizeof(Math::Matrix4),
|
||||
.size = sizeof(Matrix4),
|
||||
.data = (uint8*)&projectionMatrix,
|
||||
},
|
||||
.bDynamic = false,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "ShaderCompiler.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "VertexShaderInput.h"
|
||||
#include "Graphics.h"
|
||||
|
||||
@@ -17,7 +16,7 @@ ShaderCompiler::~ShaderCompiler()
|
||||
|
||||
}
|
||||
|
||||
void ShaderCompiler::registerMaterial(PMaterialAsset material)
|
||||
void ShaderCompiler::registerMaterial(PMaterial material)
|
||||
{
|
||||
for(auto& type : VertexInputType::getTypeList())
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "Material/Material.h"
|
||||
#include "GraphicsResources.h"
|
||||
|
||||
namespace Seele
|
||||
@@ -11,9 +12,9 @@ class ShaderCompiler
|
||||
public:
|
||||
ShaderCompiler(PGraphics graphics);
|
||||
~ShaderCompiler();
|
||||
void registerMaterial(PMaterialAsset material);
|
||||
void registerMaterial(PMaterial material);
|
||||
private:
|
||||
Array<PMaterialAsset> pendingCompiles;
|
||||
Array<PMaterial> pendingCompiles;
|
||||
PGraphics graphics;
|
||||
};
|
||||
DEFINE_REF(ShaderCompiler)
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
List<VertexInputType*> VertexInputType::globalTypeList;
|
||||
|
||||
List<VertexInputType*>& VertexInputType::getTypeList()
|
||||
{
|
||||
static List<VertexInputType*> globalTypeList;
|
||||
return globalTypeList;
|
||||
}
|
||||
|
||||
VertexInputType* VertexInputType::getVertexInputByName(const std::string& name)
|
||||
{
|
||||
for(auto type : globalTypeList)
|
||||
for(auto type : getTypeList())
|
||||
{
|
||||
if(name.compare(type->getName()) == 0)
|
||||
{
|
||||
@@ -30,12 +30,12 @@ VertexInputType::VertexInputType(const char* name,
|
||||
: name(name)
|
||||
, shaderFilename(shaderFilename)
|
||||
{
|
||||
globalTypeList.add(this);
|
||||
getTypeList().add(this);
|
||||
}
|
||||
|
||||
VertexInputType::~VertexInputType()
|
||||
{
|
||||
globalTypeList.remove(globalTypeList.find(this));
|
||||
getTypeList().remove(getTypeList().find(this));
|
||||
}
|
||||
|
||||
const char* VertexInputType::getName()
|
||||
|
||||
@@ -95,8 +95,6 @@ public:
|
||||
private:
|
||||
const char* name;
|
||||
const char* shaderFilename;
|
||||
|
||||
static List<VertexInputType*> globalTypeList;
|
||||
};
|
||||
|
||||
#define DECLARE_VERTEX_INPUT_TYPE(inputClass) \
|
||||
|
||||
@@ -95,7 +95,7 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
|
||||
VkDeviceSize allocatedOffset = it.first;
|
||||
PSubAllocation freeAllocation = it.second;
|
||||
assert(allocatedOffset == freeAllocation->allocatedOffset);
|
||||
VkDeviceSize alignedOffset = Math::align(allocatedOffset, alignment);
|
||||
VkDeviceSize alignedOffset = align(allocatedOffset, alignment);
|
||||
VkDeviceSize alignmentAdjustment = alignedOffset - allocatedOffset;
|
||||
VkDeviceSize size = alignmentAdjustment + requestedSize;
|
||||
if (freeAllocation->size == size)
|
||||
@@ -113,8 +113,8 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
|
||||
freeAllocation->alignedOffset += size;
|
||||
PSubAllocation subAlloc = new SubAllocation(this, allocatedOffset, size, alignedOffset, size);
|
||||
activeAllocations[allocatedOffset] = subAlloc.getHandle();
|
||||
freeRanges[freeAllocation->allocatedOffset] = freeAllocation;
|
||||
freeRanges.erase(allocatedOffset);
|
||||
freeRanges[freeAllocation->allocatedOffset] = freeAllocation;
|
||||
bytesUsed += size;
|
||||
return subAlloc;
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ VkAccessFlags UniformBuffer::getDestAccessMask()
|
||||
}
|
||||
|
||||
StructuredBuffer::StructuredBuffer(PGraphics graphics, const StructuredBufferCreateInfo &resourceData)
|
||||
: Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.stride, resourceData.resourceData)
|
||||
: Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.stride, resourceData.resourceData.size / resourceData.stride, resourceData.resourceData)
|
||||
, Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, resourceData.bDynamic)
|
||||
{
|
||||
if (resourceData.resourceData.data != nullptr)
|
||||
@@ -380,6 +380,7 @@ StructuredBuffer::~StructuredBuffer()
|
||||
|
||||
bool StructuredBuffer::updateContents(const BulkResourceData &resourceData)
|
||||
{
|
||||
assert(resourceData.size <= getSize());
|
||||
Gfx::StructuredBuffer::updateContents(resourceData);
|
||||
//We always want to update, as the contents could be different on the GPU
|
||||
void* data = lock();
|
||||
|
||||
@@ -2,8 +2,12 @@ target_sources(Engine
|
||||
PRIVATE
|
||||
BRDF.h
|
||||
BRDF.cpp
|
||||
MaterialAsset.h
|
||||
MaterialAsset.cpp
|
||||
Material.h
|
||||
Material.cpp
|
||||
MaterialInstance.h
|
||||
MaterialInstance.cpp
|
||||
MaterialInterface.h
|
||||
MaterialInterface.cpp
|
||||
ShaderExpression.h
|
||||
ShaderExpression.cpp)
|
||||
|
||||
@@ -11,6 +15,8 @@ target_sources(Engine
|
||||
PUBLIC FILE_SET HEADERS
|
||||
FILES
|
||||
BRDF.h
|
||||
MaterialAsset.h
|
||||
Material.h
|
||||
MaterialInstance.h
|
||||
MaterialInterface.h
|
||||
ShaderExpression.h)
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "Material.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include "MaterialInstance.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Gfx::ShaderMap Material::shaderMap;
|
||||
std::mutex Material::shaderMapLock;
|
||||
|
||||
Material::Material(Array<PShaderParameter> parameter, Gfx::PDescriptorLayout layout, uint32 uniformDataSize, uint32 uniformBinding, std::string materialName)
|
||||
: MaterialInterface(parameter, uniformDataSize, uniformBinding)
|
||||
, layout(layout)
|
||||
, materialName(materialName)
|
||||
{
|
||||
}
|
||||
|
||||
Material::~Material()
|
||||
{
|
||||
}
|
||||
|
||||
Gfx::PDescriptorSet Material::createDescriptorSet()
|
||||
{
|
||||
Gfx::PDescriptorSet descriptorSet = layout->allocateDescriptorSet();
|
||||
BulkResourceData uniformUpdate = {
|
||||
.size = uniformDataSize,
|
||||
.data = (uint8*)uniformData.data(),
|
||||
};
|
||||
for(auto param : parameters)
|
||||
{
|
||||
param->updateDescriptorSet(descriptorSet, uniformData.data());
|
||||
}
|
||||
if(uniformUpdate.size != 0)
|
||||
{
|
||||
uniformBuffer->updateContents(uniformUpdate);
|
||||
descriptorSet->updateBuffer(uniformBinding, uniformBuffer);
|
||||
}
|
||||
descriptorSet->writeChanges();
|
||||
return descriptorSet;
|
||||
}
|
||||
|
||||
PMaterialInstance Material::instantiate()
|
||||
{
|
||||
return new MaterialInstance(this);
|
||||
}
|
||||
|
||||
const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const
|
||||
{
|
||||
Gfx::ShaderPermutation permutation;
|
||||
permutation.passType = renderPass;
|
||||
std::string vertexInputName = vertexInput->getName();
|
||||
std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName));
|
||||
std::memcpy(permutation.vertexInputName, vertexInputName.c_str(), sizeof(permutation.vertexInputName));
|
||||
return shaderMap.findShaders(Gfx::PermutationId(permutation));
|
||||
}
|
||||
|
||||
Gfx::ShaderCollection& Material::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
|
||||
{
|
||||
std::scoped_lock l(shaderMapLock);
|
||||
return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "MaterialInterface.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(MaterialInstance)
|
||||
class Material : public MaterialInterface
|
||||
{
|
||||
public:
|
||||
Material(Array<PShaderParameter> parameter, Gfx::PDescriptorLayout layout, uint32 uniformDataSize, uint32 uniformBinding, std::string materialName);
|
||||
virtual ~Material();
|
||||
virtual Gfx::PDescriptorSet createDescriptorSet();
|
||||
virtual Gfx::PDescriptorLayout getDescriptorLayout() const { return layout; }
|
||||
virtual const std::string& getName() { return materialName; }
|
||||
|
||||
PMaterialInstance instantiate();
|
||||
|
||||
virtual const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const;
|
||||
virtual Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput);
|
||||
private:
|
||||
static Gfx::ShaderMap shaderMap;
|
||||
static std::mutex shaderMapLock;
|
||||
|
||||
Gfx::PDescriptorLayout layout;
|
||||
std::string materialName;
|
||||
// With draw-indirect, we batch vertex data into big vertex buffers
|
||||
// Gfx::PVertexDataManager vertexData;
|
||||
|
||||
friend class MaterialInstance;
|
||||
};
|
||||
DEFINE_REF(Material)
|
||||
} // namespace Seele
|
||||
@@ -1,189 +0,0 @@
|
||||
#include "MaterialAsset.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include "Asset/AssetRegistry.h"
|
||||
#include "Asset/TextureAsset.h"
|
||||
#include "BRDF.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Seele::Gfx::ShaderMap MaterialAsset::shaderMap;
|
||||
std::mutex MaterialAsset::shaderMapLock;
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MaterialAsset::MaterialAsset()
|
||||
{
|
||||
}
|
||||
|
||||
MaterialAsset::MaterialAsset(const std::string& directory, const std::string& name)
|
||||
: Asset(directory, name)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialAsset::MaterialAsset(const std::filesystem::path& fullPath)
|
||||
: Asset(fullPath)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialAsset::~MaterialAsset()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void MaterialAsset::save()
|
||||
{
|
||||
assert(false && "TODO");
|
||||
}
|
||||
|
||||
void MaterialAsset::load()
|
||||
{
|
||||
setStatus(Status::Loading);
|
||||
auto stream = getReadStream();
|
||||
json j;
|
||||
stream >> j;
|
||||
materialName = j["name"].get<std::string>() + "Material";
|
||||
layout = WindowManager::getGraphics()->createDescriptorLayout(materialName + "Layout");
|
||||
//Shader file needs to conform to the slang standard, which prohibits _
|
||||
materialName.erase(std::remove(materialName.begin(), materialName.end(), '_'), materialName.end());
|
||||
materialName.erase(std::remove(materialName.begin(), materialName.end(), '.'), materialName.end());
|
||||
std::ofstream codeStream("./shaders/generated/"+materialName+".slang");
|
||||
std::string profile = j["profile"].get<std::string>();
|
||||
|
||||
codeStream << "import Material;" << std::endl;
|
||||
codeStream << "import BRDF;" << std::endl;
|
||||
codeStream << "import MaterialParameter;" << std::endl << std::endl;
|
||||
|
||||
codeStream << "struct " << materialName << " : IMaterial {" << std::endl;
|
||||
uint32 uniformBufferOffset = 0;
|
||||
uint32 bindingCounter = 0; // Uniform buffers are always binding 0
|
||||
uniformBinding = -1;
|
||||
for(auto param : j["params"].items())
|
||||
{
|
||||
std::string type = param.value()["type"].get<std::string>();
|
||||
auto defaultValue = param.value().find("default");
|
||||
if(type.compare("float") == 0)
|
||||
{
|
||||
PFloatParameter p = new FloatParameter(param.key(), uniformBufferOffset, 0);
|
||||
codeStream << "\tlayout(offset = " << uniformBufferOffset << ")";
|
||||
if(uniformBinding == -1)
|
||||
{
|
||||
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
uniformBinding = bindingCounter++;
|
||||
}
|
||||
uniformBufferOffset += 4;
|
||||
if(defaultValue != param.value().end())
|
||||
{
|
||||
p->data = std::stof(defaultValue.value().get<std::string>());
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
else if(type.compare("float3") == 0)
|
||||
{
|
||||
PVectorParameter p = new VectorParameter(param.key(), uniformBufferOffset, 0);
|
||||
codeStream << "\tlayout(offset = " << uniformBufferOffset << ")";
|
||||
if(uniformBinding == -1)
|
||||
{
|
||||
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
uniformBinding = bindingCounter++;
|
||||
}
|
||||
uniformBufferOffset += 12;
|
||||
if(defaultValue != param.value().end())
|
||||
{
|
||||
p->data = Math::parseVector(defaultValue.value().get<std::string>().c_str());
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
else if(type.compare("Texture2D") == 0)
|
||||
{
|
||||
PTextureParameter p = new TextureParameter(param.key(), 0, bindingCounter);
|
||||
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
|
||||
if(defaultValue != param.value().end())
|
||||
{
|
||||
std::string defaultString = defaultValue.value().get<std::string>();
|
||||
p->data = AssetRegistry::findTexture(defaultString);
|
||||
}
|
||||
if(p->data == nullptr)
|
||||
{
|
||||
p->data = AssetRegistry::findTexture(""); // this will return placeholder texture
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
else if(type.compare("SamplerState") == 0)
|
||||
{
|
||||
PSamplerParameter p = new SamplerParameter(param.key(), 0, bindingCounter);
|
||||
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLER);
|
||||
p->data = WindowManager::getGraphics()->createSamplerState({});
|
||||
parameters.add(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Error unsupported parameter type" << std::endl;
|
||||
}
|
||||
codeStream << "\t" << type << " " << param.key() << ";\n";
|
||||
}
|
||||
uniformDataSize = uniformBufferOffset;
|
||||
if(uniformDataSize != 0)
|
||||
{
|
||||
uniformData = new uint8[uniformDataSize];
|
||||
UniformBufferCreateInfo uniformInitializer;
|
||||
uniformInitializer.resourceData.data = uniformData;
|
||||
uniformInitializer.resourceData.size = uniformDataSize;
|
||||
uniformBuffer = WindowManager::getGraphics()->createUniformBuffer(uniformInitializer);
|
||||
}
|
||||
BRDF* brdf = BRDF::getBRDFByName(profile);
|
||||
brdf->generateMaterialCode(codeStream, j["code"]);
|
||||
codeStream << "};";
|
||||
codeStream.close();
|
||||
layout->create();
|
||||
setStatus(Status::Ready);
|
||||
}
|
||||
|
||||
|
||||
void MaterialAsset::beginFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void MaterialAsset::endFrame()
|
||||
{
|
||||
}
|
||||
|
||||
Gfx::PDescriptorSet MaterialAsset::createDescriptorSet()
|
||||
{
|
||||
Gfx::PDescriptorSet descriptorSet = layout->allocateDescriptorSet();
|
||||
BulkResourceData uniformUpdate;
|
||||
uniformUpdate.size = uniformDataSize;
|
||||
uniformUpdate.data = uniformData;
|
||||
for(auto param : parameters)
|
||||
{
|
||||
param->updateDescriptorSet(descriptorSet, uniformData);
|
||||
}
|
||||
if(uniformUpdate.size != 0)
|
||||
{
|
||||
uniformBuffer->updateContents(uniformUpdate);
|
||||
descriptorSet->updateBuffer(uniformBinding, uniformBuffer);
|
||||
}
|
||||
descriptorSet->writeChanges();
|
||||
return descriptorSet;
|
||||
}
|
||||
|
||||
|
||||
const Gfx::ShaderCollection* MaterialAsset::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const
|
||||
{
|
||||
Gfx::ShaderPermutation permutation;
|
||||
permutation.passType = renderPass;
|
||||
std::string vertexInputName = vertexInput->getName();
|
||||
std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName));
|
||||
std::memcpy(permutation.vertexInputName, vertexInputName.c_str(), sizeof(permutation.vertexInputName));
|
||||
return shaderMap.findShaders(Gfx::PermutationId(permutation));
|
||||
}
|
||||
|
||||
Gfx::ShaderCollection& MaterialAsset::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
|
||||
{
|
||||
std::scoped_lock l(shaderMapLock);
|
||||
return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
#include "Asset/Asset.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include "ShaderExpression.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(VertexShaderInput)
|
||||
class MaterialAsset : public Asset
|
||||
{
|
||||
public:
|
||||
MaterialAsset();
|
||||
MaterialAsset(const std::string &directory, const std::string &name);
|
||||
MaterialAsset(const std::filesystem::path &fullPath);
|
||||
~MaterialAsset();
|
||||
virtual void beginFrame();
|
||||
virtual void endFrame();
|
||||
virtual void save() override;
|
||||
virtual void load() override;
|
||||
Gfx::SeBlendOp getBlendMode() const {return Gfx::SE_BLEND_OP_END_RANGE;}
|
||||
Gfx::MaterialShadingModel getShadingModel() const {return Gfx::MaterialShadingModel::DefaultLit;}
|
||||
|
||||
Gfx::PDescriptorSet createDescriptorSet();
|
||||
|
||||
Gfx::PDescriptorLayout getDescriptorLayout() const { return layout; }
|
||||
// The name of the generated material shader, opposed to the name of the .asset file
|
||||
const std::string& getName() {return materialName;}
|
||||
|
||||
const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const;
|
||||
Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput);
|
||||
private:
|
||||
static Gfx::ShaderMap shaderMap;
|
||||
static std::mutex shaderMapLock;
|
||||
|
||||
//For now its simply the collection of parameters, since there is no point for expressions
|
||||
Array<PShaderParameter> parameters;
|
||||
Gfx::PDescriptorLayout layout;
|
||||
Gfx::PUniformBuffer uniformBuffer;
|
||||
uint32 uniformDataSize;
|
||||
uint8* uniformData;
|
||||
int32 uniformBinding;
|
||||
std::string materialName;
|
||||
// With draw-indirect, we batch vertex data into big vertex buffers
|
||||
// Gfx::PVertexDataManager vertexData;
|
||||
};
|
||||
DEFINE_REF(MaterialAsset)
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "MaterialInstance.h"
|
||||
#include "Material.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MaterialInstance::MaterialInstance(PMaterial baseMaterial)
|
||||
: MaterialInterface(baseMaterial->parameters, baseMaterial->uniformDataSize, baseMaterial->uniformBinding)
|
||||
, baseMaterial(baseMaterial)
|
||||
{
|
||||
}
|
||||
|
||||
MaterialInstance::~MaterialInstance()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Gfx::PDescriptorSet MaterialInstance::createDescriptorSet()
|
||||
{
|
||||
Gfx::PDescriptorSet descriptorSet = baseMaterial->layout->allocateDescriptorSet();
|
||||
BulkResourceData uniformUpdate;
|
||||
uniformUpdate.size = uniformDataSize;
|
||||
uniformUpdate.data = (uint8*)uniformData.data();
|
||||
for(auto param : parameters)
|
||||
{
|
||||
param->updateDescriptorSet(descriptorSet, uniformData.data());
|
||||
}
|
||||
if(uniformUpdate.size != 0)
|
||||
{
|
||||
uniformBuffer->updateContents(uniformUpdate);
|
||||
descriptorSet->updateBuffer(uniformBinding, uniformBuffer);
|
||||
}
|
||||
descriptorSet->writeChanges();
|
||||
return descriptorSet;
|
||||
}
|
||||
|
||||
Gfx::PDescriptorLayout MaterialInstance::getDescriptorLayout() const
|
||||
{
|
||||
return baseMaterial->getDescriptorLayout();
|
||||
}
|
||||
|
||||
const std::string& MaterialInstance::getName()
|
||||
{
|
||||
return baseMaterial->getName();
|
||||
}
|
||||
|
||||
const Gfx::ShaderCollection* Seele::MaterialInstance::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const
|
||||
{
|
||||
return baseMaterial->getShaders(renderPass, vertexInput);
|
||||
}
|
||||
|
||||
Gfx::ShaderCollection& Seele::MaterialInstance::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
|
||||
{
|
||||
return baseMaterial->createShaders(graphics, renderPass, vertexInput);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "MaterialInterface.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(Material)
|
||||
class MaterialInstance : public MaterialInterface
|
||||
{
|
||||
public:
|
||||
MaterialInstance(PMaterial baseMaterial);
|
||||
virtual ~MaterialInstance();
|
||||
virtual Gfx::PDescriptorSet createDescriptorSet();
|
||||
virtual Gfx::PDescriptorLayout getDescriptorLayout() const;
|
||||
|
||||
// The name of the generated material shader, opposed to the name of the .asset file
|
||||
virtual const std::string& getName();
|
||||
virtual const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const;
|
||||
virtual Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput);
|
||||
|
||||
private:
|
||||
PMaterial baseMaterial;
|
||||
};
|
||||
DEFINE_REF(MaterialInstance)
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "MaterialInterface.h"
|
||||
#include "Window/WindowManager.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MaterialInterface::MaterialInterface(Array<PShaderParameter> parameter, uint32 uniformDataSize, uint32 uniformBinding)
|
||||
: parameters(parameter)
|
||||
, uniformDataSize(uniformDataSize)
|
||||
, uniformBinding(uniformBinding)
|
||||
{
|
||||
if(uniformDataSize != 0)
|
||||
{
|
||||
uniformData.resize(uniformDataSize);
|
||||
UniformBufferCreateInfo uniformInitializer = {
|
||||
.resourceData = {
|
||||
.size = uniformDataSize,
|
||||
.data = nullptr,
|
||||
}
|
||||
};
|
||||
uniformBuffer = WindowManager::getGraphics()->createUniformBuffer(uniformInitializer);
|
||||
}
|
||||
}
|
||||
|
||||
MaterialInterface::~MaterialInterface()
|
||||
{
|
||||
}
|
||||
|
||||
PShaderParameter MaterialInterface::getParameter(const std::string& name)
|
||||
{
|
||||
for (auto param : parameters)
|
||||
{
|
||||
if(param->name.compare(name) == 0)
|
||||
{
|
||||
return param;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "ShaderExpression.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_NAME_REF(Gfx, DescriptorLayout)
|
||||
DECLARE_NAME_REF(Gfx, UniformBuffer)
|
||||
class MaterialInterface
|
||||
{
|
||||
public:
|
||||
MaterialInterface(Array<PShaderParameter> parameter, uint32 uniformDataSize, uint32 uniformBinding);
|
||||
virtual ~MaterialInterface();
|
||||
PShaderParameter getParameter(const std::string& name);
|
||||
virtual Gfx::PDescriptorSet createDescriptorSet() = 0;
|
||||
virtual Gfx::PDescriptorLayout getDescriptorLayout() const = 0;
|
||||
|
||||
// The name of the generated material shader, opposed to the name of the .asset file
|
||||
virtual const std::string& getName() = 0;
|
||||
virtual const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const = 0;
|
||||
virtual Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput) = 0;
|
||||
protected:
|
||||
//For now its simply the collection of parameters, since there is no point for expressions
|
||||
Array<PShaderParameter> parameters;
|
||||
Gfx::PUniformBuffer uniformBuffer;
|
||||
uint32 uniformDataSize;
|
||||
Array<uint8> uniformData;
|
||||
int32 uniformBinding;
|
||||
};
|
||||
DEFINE_REF(MaterialInterface)
|
||||
} // namespace Seele
|
||||
@@ -40,7 +40,7 @@ VectorParameter::~VectorParameter()
|
||||
|
||||
void VectorParameter::updateDescriptorSet(Gfx::PDescriptorSet, uint8* dst)
|
||||
{
|
||||
std::memcpy(dst + byteOffset, &data, sizeof(Math::Vector));
|
||||
std::memcpy(dst + byteOffset, &data, sizeof(Vector));
|
||||
}
|
||||
|
||||
TextureParameter::TextureParameter(std::string name, uint32 byteOffset, uint32 binding)
|
||||
|
||||
@@ -36,7 +36,7 @@ struct FloatParameter : public ShaderParameter
|
||||
DEFINE_REF(FloatParameter)
|
||||
struct VectorParameter : public ShaderParameter
|
||||
{
|
||||
Math::Vector data;
|
||||
Vector data;
|
||||
VectorParameter(std::string name, uint32 byteOffset, uint32 binding);
|
||||
virtual ~VectorParameter();
|
||||
virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override;
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Math
|
||||
{
|
||||
struct Rect
|
||||
{
|
||||
Rect()
|
||||
@@ -60,5 +58,4 @@ inline constexpr T align(const T ptr, int64_t alignment)
|
||||
{
|
||||
return (T)(((uint64_t)ptr + alignment - 1) & ~(alignment - 1));
|
||||
}
|
||||
} // namespace Math
|
||||
} // namespace Seele
|
||||
@@ -5,10 +5,7 @@
|
||||
#include <glm/mat4x4.hpp>
|
||||
namespace Seele
|
||||
{
|
||||
namespace Math
|
||||
{
|
||||
typedef glm::mat2 Matrix2;
|
||||
typedef glm::mat3 Matrix3;
|
||||
typedef glm::mat4 Matrix4;
|
||||
} // namespace Math
|
||||
} // namespace Seele
|
||||
@@ -145,17 +145,17 @@ Vector Transform::getScale() const
|
||||
return Vector(scale);
|
||||
}
|
||||
|
||||
void Transform::setPosition(Math::Vector pos)
|
||||
void Transform::setPosition(Vector pos)
|
||||
{
|
||||
position = Vector4(pos, 0);
|
||||
}
|
||||
|
||||
void Transform::setRotation(Math::Quaternion quat)
|
||||
void Transform::setRotation(Quaternion quat)
|
||||
{
|
||||
rotation = quat;
|
||||
}
|
||||
|
||||
void Transform::setScale(Math::Vector s)
|
||||
void Transform::setScale(Vector s)
|
||||
{
|
||||
scale = Vector4(s, 0);
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ public:
|
||||
Quaternion getRotation() const;
|
||||
Vector getScale() const;
|
||||
|
||||
void setPosition(Math::Vector pos);
|
||||
void setRotation(Math::Quaternion quat);
|
||||
void setScale(Math::Vector scale);
|
||||
void setPosition(Vector pos);
|
||||
void setRotation(Quaternion quat);
|
||||
void setScale(Vector scale);
|
||||
|
||||
Vector getForward() const;
|
||||
Vector getRight() const;
|
||||
|
||||
@@ -1,7 +1,30 @@
|
||||
#include "Vector.h"
|
||||
#include <regex>
|
||||
#include <format>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using namespace Seele::Math;
|
||||
using namespace Seele;
|
||||
|
||||
void to_json(nlohmann::json& j, const Vector& vec)
|
||||
{
|
||||
j = nlohmann::json{std::format("({}, {}, {})", vec.x, vec.y, vec.z)};
|
||||
}
|
||||
|
||||
void from_json(const nlohmann::json& j, Vector& vec)
|
||||
{
|
||||
std::string str;
|
||||
j.get_to(str);
|
||||
auto newEnd = std::remove(str.begin(), str.end(), ' ');
|
||||
str.erase(newEnd);
|
||||
std::stringstream stream(str);
|
||||
std::string temp;
|
||||
std::getline(stream, temp, ',');
|
||||
vec.x = std::stof(temp);
|
||||
std::getline(stream, temp, ',');
|
||||
vec.y = std::stof(temp);
|
||||
std::getline(stream, temp, ',');
|
||||
vec.z = std::stof(temp);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const Vector2& vector)
|
||||
{
|
||||
@@ -19,7 +42,7 @@ std::ostream& operator<<(std::ostream& stream, const Vector4& vector)
|
||||
return stream;
|
||||
}
|
||||
|
||||
Vector Seele::Math::parseVector(const char* str)
|
||||
Vector Seele::parseVector(const char* str)
|
||||
{
|
||||
//regex pattern consisting of 'float3(xComp, yComp, zComp)', more also matches for invalid floats, but that will throw later
|
||||
std::regex pattern("float3\\(\\s*([0-9.]+f?)\\s*,\\s*([0-9.]+f?)\\s*,\\s*([0-9.]+f?)\\s*\\)");
|
||||
|
||||
@@ -7,10 +7,9 @@
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#pragma warning(pop)
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
namespace Seele
|
||||
{
|
||||
namespace Math
|
||||
{
|
||||
typedef glm::vec2 Vector2;
|
||||
typedef glm::vec3 Vector;
|
||||
typedef glm::vec4 Vector4;
|
||||
@@ -96,10 +95,10 @@ static inline Vector toRotator(const Quaternion &other)
|
||||
}
|
||||
return rotatorFromQuat;
|
||||
}
|
||||
} // namespace Math
|
||||
void to_json(nlohmann::json& j, const Vector& vec);
|
||||
void from_json(nlohmann::json& j, Vector& vec);
|
||||
} // namespace Seele
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const Seele::Math::Vector2& vector);
|
||||
std::ostream& operator<<(std::ostream& stream, const Seele::Math::Vector& vector);
|
||||
std::ostream& operator<<(std::ostream& stream, const Seele::Math::Vector4& vector);
|
||||
std::ostream& operator<<(std::ostream& stream, const Seele::Vector2& vector);
|
||||
std::ostream& operator<<(std::ostream& stream, const Seele::Vector& vector);
|
||||
std::ostream& operator<<(std::ostream& stream, const Seele::Vector4& vector);
|
||||
+122
-32
@@ -7,6 +7,10 @@ void BVH::findOverlaps(Array<Pair<entt::entity, entt::entity>>& overlaps)
|
||||
overlaps.clear();
|
||||
for(const auto& node : dynamicNodes)
|
||||
{
|
||||
if(!node.isLeaf)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
traverseStaticTree(node.box, node.owner, staticRoot, overlaps);
|
||||
traverseDynamicTree(node.box, node.owner, dynamicRoot, overlaps);
|
||||
}
|
||||
@@ -14,39 +18,48 @@ void BVH::findOverlaps(Array<Pair<entt::entity, entt::entity>>& overlaps)
|
||||
|
||||
void BVH::updateDynamicCollider(entt::entity entity, AABB aabb)
|
||||
{
|
||||
for(auto& aabbcenter : dynamicCollider)
|
||||
|
||||
for(auto& node : dynamicNodes)
|
||||
{
|
||||
if(aabbcenter.id == entity)
|
||||
if(node.owner == entity)
|
||||
{
|
||||
if(!aabbcenter.bb.contains(aabb))
|
||||
if(!node.box.contains(aabb))
|
||||
{
|
||||
// moved out of extended bounds
|
||||
reinsertCollider(entity, aabb);
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
// new collider
|
||||
addDynamicCollider(entity, aabb);
|
||||
|
||||
}
|
||||
|
||||
void BVH::colliderCallback(entt::registry& registry, entt::entity entity)
|
||||
{
|
||||
Component::Collider& collider = registry.get<Component::Collider>(entity);
|
||||
Component::Transform& transform = registry.get<Component::Transform>(entity);
|
||||
if(collider.type == Component::ColliderType::STATIC)
|
||||
{
|
||||
addStaticCollider(entity, collider.boundingbox.getTransformedBox(transform.toMatrix()));
|
||||
}
|
||||
}
|
||||
|
||||
void BVH::visualize()
|
||||
{
|
||||
for(const auto& node : staticNodes)
|
||||
{
|
||||
node.box.visualize(gDebugVertices);
|
||||
}
|
||||
for(const auto& node : dynamicNodes)
|
||||
{
|
||||
node.box.visualize(gDebugVertices);
|
||||
}
|
||||
}
|
||||
|
||||
void BVH::traverseStaticTree(const AABB& aabb, entt::entity source, int32 nodeIndex, Array<Pair<entt::entity, entt::entity>>& overlaps)
|
||||
{
|
||||
const Node& node = staticNodes[nodeIndex];
|
||||
if(!aabb.intersects(node.box))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(node.isLeaf)
|
||||
{
|
||||
overlaps.add(Pair<entt::entity, entt::entity>(source, node.owner));
|
||||
return;
|
||||
}
|
||||
traverseStaticTree(aabb, source, node.left, overlaps);
|
||||
traverseStaticTree(aabb, source, node.right, overlaps);
|
||||
}
|
||||
|
||||
void BVH::traverseDynamicTree(const AABB& aabb, entt::entity source, int32 nodeIndex, Array<Pair<entt::entity, entt::entity>>& overlaps)
|
||||
{
|
||||
const Node& node = staticNodes[nodeIndex];
|
||||
if(!aabb.intersects(node.box))
|
||||
@@ -62,7 +75,36 @@ void BVH::traverseDynamicTree(const AABB& aabb, entt::entity source, int32 nodeI
|
||||
traverseStaticTree(aabb, source, node.right, overlaps);
|
||||
}
|
||||
|
||||
void BVH::traverseDynamicTree(const AABB& aabb, entt::entity source, int32 nodeIndex, Array<Pair<entt::entity, entt::entity>>& overlaps)
|
||||
{
|
||||
if(nodeIndex == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const Node& node = dynamicNodes[nodeIndex];
|
||||
if(!aabb.intersects(node.box))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(node.isLeaf && node.owner != source)
|
||||
{
|
||||
overlaps.add(Pair<entt::entity, entt::entity>(source, node.owner));
|
||||
return;
|
||||
}
|
||||
traverseDynamicTree(aabb, source, node.left, overlaps);
|
||||
traverseDynamicTree(aabb, source, node.right, overlaps);
|
||||
}
|
||||
|
||||
void BVH::reinsertCollider(entt::entity entity, AABB aabb)
|
||||
{
|
||||
|
||||
removeCollider(entity);
|
||||
|
||||
addDynamicCollider(entity, aabb);
|
||||
|
||||
}
|
||||
|
||||
void BVH::removeCollider(entt::entity entity)
|
||||
{
|
||||
int32 nodeIndex = -1;
|
||||
for (int32 i = 0; i < dynamicNodes.size(); i++)
|
||||
@@ -75,11 +117,21 @@ void BVH::reinsertCollider(entt::entity entity, AABB aabb)
|
||||
}
|
||||
if(nodeIndex == -1)
|
||||
{
|
||||
|
||||
return;
|
||||
}
|
||||
int32 parentIndex = dynamicNodes[nodeIndex].parentIndex;
|
||||
if(parentIndex == -1)
|
||||
{
|
||||
// its the root node
|
||||
dynamicRoot = -1;
|
||||
freeNode(nodeIndex);
|
||||
|
||||
return;
|
||||
}
|
||||
const Node& parent = dynamicNodes[parentIndex];
|
||||
int32 siblingIndex;
|
||||
|
||||
if(parent.left == nodeIndex)
|
||||
{
|
||||
siblingIndex = parent.right;
|
||||
@@ -88,21 +140,34 @@ void BVH::reinsertCollider(entt::entity entity, AABB aabb)
|
||||
{
|
||||
siblingIndex = parent.left;
|
||||
}
|
||||
|
||||
// the node to remove and their sibling share a parent
|
||||
// now that the node is removed, the parent is also useless
|
||||
// so the grandparent should point32 to the sibling directly instead of the parent
|
||||
Node& grandParent = dynamicNodes[parent.parentIndex];
|
||||
if(grandParent.left == parentIndex)
|
||||
// so the grandparent should point to the sibling directly instead of the parent
|
||||
if(parent.parentIndex != -1)
|
||||
{
|
||||
grandParent.left = siblingIndex;
|
||||
Node& grandParent = dynamicNodes[parent.parentIndex];
|
||||
if(grandParent.left == parentIndex)
|
||||
{
|
||||
grandParent.left = siblingIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
grandParent.right = siblingIndex;
|
||||
}
|
||||
dynamicNodes[siblingIndex].parentIndex = parent.parentIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
grandParent.right = siblingIndex;
|
||||
// if the shared parent was the root, we need a new root, which is the remaining sibling
|
||||
dynamicRoot = siblingIndex;
|
||||
dynamicNodes[siblingIndex].parentIndex = -1;
|
||||
}
|
||||
freeNode(parentIndex);
|
||||
|
||||
freeNode(nodeIndex);
|
||||
addDynamicCollider(entity, aabb);
|
||||
|
||||
freeNode(parentIndex);
|
||||
|
||||
}
|
||||
|
||||
void BVH::addDynamicCollider(entt::entity entity, AABB aabb)
|
||||
@@ -113,18 +178,15 @@ void BVH::addDynamicCollider(entt::entity entity, AABB aabb)
|
||||
.min = center + (aabb.min - center) * 1.1f,
|
||||
.max = center + (aabb.max - center) * 1.1f,
|
||||
};
|
||||
dynamicCollider.add(AABBCenter {
|
||||
.bb = aabb,
|
||||
.center = center,
|
||||
.id = entity
|
||||
});
|
||||
int32 leafIndex = allocateNode();
|
||||
Node newNode = Node {
|
||||
.box = aabb,
|
||||
.isLeaf = true,
|
||||
.isValid = true,
|
||||
.owner = entity,
|
||||
};
|
||||
dynamicNodes[leafIndex] = newNode;
|
||||
|
||||
|
||||
if (dynamicRoot == -1)
|
||||
{
|
||||
@@ -135,6 +197,7 @@ void BVH::addDynamicCollider(entt::entity entity, AABB aabb)
|
||||
int32 bestSibling;
|
||||
float bestCost = std::numeric_limits<float>::max();
|
||||
findSibling(newNode, dynamicRoot, bestCost, bestSibling);
|
||||
|
||||
|
||||
int32 oldParent = dynamicNodes[bestSibling].parentIndex;
|
||||
int32 newParent = allocateNode();
|
||||
@@ -142,7 +205,9 @@ void BVH::addDynamicCollider(entt::entity entity, AABB aabb)
|
||||
.box = aabb.combine(dynamicNodes[bestSibling].box),
|
||||
.parentIndex = oldParent,
|
||||
.isLeaf = false,
|
||||
.isValid = true,
|
||||
};
|
||||
|
||||
|
||||
if(oldParent != -1)
|
||||
{
|
||||
@@ -158,6 +223,7 @@ void BVH::addDynamicCollider(entt::entity entity, AABB aabb)
|
||||
dynamicNodes[newParent].right = leafIndex;
|
||||
dynamicNodes[bestSibling].parentIndex = newParent;
|
||||
dynamicNodes[leafIndex].parentIndex = newParent;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -166,6 +232,7 @@ void BVH::addDynamicCollider(entt::entity entity, AABB aabb)
|
||||
dynamicNodes[bestSibling].parentIndex = newParent;
|
||||
dynamicNodes[leafIndex].parentIndex = newParent;
|
||||
dynamicRoot = newParent;
|
||||
|
||||
}
|
||||
int32 index = dynamicNodes[leafIndex].parentIndex;
|
||||
while(index != -1)
|
||||
@@ -186,6 +253,7 @@ void BVH::addStaticCollider(entt::entity entity, AABB boundingBox)
|
||||
.id = entity,
|
||||
});
|
||||
staticNodes.clear();
|
||||
staticRoot = splitNode(staticCollider);
|
||||
}
|
||||
|
||||
void BVH::findSibling(Node newNode, int32 nodeIndex, float& bestCost, int32& result)
|
||||
@@ -218,6 +286,7 @@ float BVH::siblingCost(Node newNode, int32 siblingIndex)
|
||||
{
|
||||
AABB parentBox = dynamicNodes[parentIndex].box;
|
||||
cost += parentBox.combine(newBox).surfaceArea() - parentBox.surfaceArea();
|
||||
parentIndex = dynamicNodes[parentIndex].parentIndex;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
@@ -240,6 +309,7 @@ int32 BVH::splitNode(Array<AABBCenter> aabbs)
|
||||
{
|
||||
int32 leafIndex = static_cast<int32>(staticNodes.size());
|
||||
Node& leaf = staticNodes.add();
|
||||
leaf.isLeaf = true;
|
||||
leaf.box = aabbs[0].bb;
|
||||
leaf.left = -1;
|
||||
leaf.right = -1;
|
||||
@@ -296,5 +366,25 @@ int32 BVH::allocateNode()
|
||||
void BVH::freeNode(int32 nodeIndex)
|
||||
{
|
||||
dynamicNodes[nodeIndex].isValid = false;
|
||||
dynamicNodes[nodeIndex].parentIndex = -1;
|
||||
}
|
||||
|
||||
void BVH::validateBVH() const
|
||||
{
|
||||
if(dynamicRoot != -1)
|
||||
{
|
||||
assert(dynamicNodes[dynamicRoot].parentIndex == -1);
|
||||
}
|
||||
for(int32 i = 0; i < dynamicNodes.size(); ++i)
|
||||
{
|
||||
int32 nodeIdx = i;
|
||||
size_t counter = dynamicNodes.size();
|
||||
if(!dynamicNodes[nodeIdx].isValid)
|
||||
continue;
|
||||
while(dynamicNodes[nodeIdx].parentIndex != -1)
|
||||
{
|
||||
nodeIdx = dynamicNodes[nodeIdx].parentIndex;
|
||||
assert(counter-- > 0 && dynamicNodes[nodeIdx].isValid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,11 +12,13 @@ class BVH
|
||||
public:
|
||||
void findOverlaps(Array<Pair<entt::entity, entt::entity>>& overlaps);
|
||||
void updateDynamicCollider(entt::entity entity, AABB aabb);
|
||||
void colliderCallback(entt::registry& registry, entt::entity entity);
|
||||
void visualize();
|
||||
private:
|
||||
struct AABBCenter
|
||||
{
|
||||
AABB bb;
|
||||
Math::Vector center;
|
||||
Vector center;
|
||||
entt::entity id;
|
||||
};
|
||||
struct Node
|
||||
@@ -41,9 +43,9 @@ private:
|
||||
int32 splitNode(Array<AABBCenter> aabbs);
|
||||
int32 allocateNode();
|
||||
void freeNode(int32 nodeIndex);
|
||||
void validateBVH() const;
|
||||
Array<Node> dynamicNodes;
|
||||
Array<Node> staticNodes;
|
||||
Array<AABBCenter> dynamicCollider;
|
||||
Array<AABBCenter> staticCollider;
|
||||
int32 staticRoot = -1;
|
||||
int32 dynamicRoot = -1;
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
using namespace Seele;
|
||||
using namespace Seele::Component;
|
||||
|
||||
CollisionSystem::CollisionSystem()
|
||||
CollisionSystem::CollisionSystem(entt::registry& registry)
|
||||
: registry(registry)
|
||||
{
|
||||
|
||||
registry.on_construct<Component::Collider>().connect<&BVH::colliderCallback>(bvh);
|
||||
}
|
||||
|
||||
CollisionSystem::~CollisionSystem()
|
||||
@@ -13,22 +14,24 @@ CollisionSystem::~CollisionSystem()
|
||||
|
||||
}
|
||||
|
||||
void CollisionSystem::detectCollisions(const entt::registry& registry, Array<Collision>& collisions)
|
||||
void CollisionSystem::detectCollisions(Array<Collision>& collisions)
|
||||
{
|
||||
collisions.clear();
|
||||
auto view = registry.view<Collider, Transform>();
|
||||
for(auto && [entity, collider, transform] : view.each())
|
||||
{
|
||||
if(collider.type == ColliderType::DYNAMIC && transform.isDirty())
|
||||
if(collider.type == ColliderType::DYNAMIC)
|
||||
{
|
||||
bvh.updateDynamicCollider(entity, collider.boundingbox.getTransformedBox(transform.toMatrix()));
|
||||
}
|
||||
collider.physicsMesh.transform(transform).visualize();
|
||||
}
|
||||
bvh.visualize();
|
||||
Array<Pair<entt::entity, entt::entity>> overlaps;
|
||||
bvh.findOverlaps(overlaps);
|
||||
for(auto pair : overlaps)
|
||||
{
|
||||
if(checkCollision(registry, pair))
|
||||
if(checkCollision(pair))
|
||||
{
|
||||
collisions.add(Collision {
|
||||
.a = pair.key,
|
||||
@@ -38,7 +41,7 @@ void CollisionSystem::detectCollisions(const entt::registry& registry, Array<Col
|
||||
}
|
||||
}
|
||||
|
||||
bool CollisionSystem::checkCollision(const entt::registry& registry, Pair<entt::entity, entt::entity> pair)
|
||||
bool CollisionSystem::checkCollision(Pair<entt::entity, entt::entity> pair)
|
||||
{
|
||||
const auto&[collider1, transform1] = registry.get<Collider, Transform>(pair.key);
|
||||
const auto&[collider2, transform2] = registry.get<Collider, Transform>(pair.value);
|
||||
@@ -64,7 +67,6 @@ void CollisionSystem::updateWitness(Witness& result, const glm::vec3& point, con
|
||||
result.p = point;
|
||||
}
|
||||
|
||||
|
||||
bool CollisionSystem::createWitness(Witness& result, const ShapeBase& source, const ShapeBase& other)
|
||||
{
|
||||
for (size_t i = 0; i < source.indices.size(); i += 3)
|
||||
|
||||
@@ -15,14 +15,14 @@ struct Collision
|
||||
class CollisionSystem
|
||||
{
|
||||
public:
|
||||
CollisionSystem();
|
||||
CollisionSystem(entt::registry& registry);
|
||||
virtual ~CollisionSystem();
|
||||
void detectCollisions(const entt::registry& registry, Array<Collision>& collisions);
|
||||
void detectCollisions(Array<Collision>& collisions);
|
||||
private:
|
||||
struct Witness
|
||||
{
|
||||
Math::Vector p;
|
||||
Math::Vector n;
|
||||
Vector p;
|
||||
Vector n;
|
||||
// for finding p
|
||||
uint32_t point1Index;
|
||||
// and the face where the plane lies on
|
||||
@@ -33,11 +33,12 @@ private:
|
||||
entt::entity other;
|
||||
};
|
||||
BVH bvh;
|
||||
entt::registry& registry;
|
||||
Map<Pair<entt::entity, entt::entity>, Witness> cachedWitness;
|
||||
|
||||
bool checkCollision(const entt::registry& registry, Pair<entt::entity, entt::entity> pair);
|
||||
bool checkCollision(Pair<entt::entity, entt::entity> pair);
|
||||
|
||||
void updateWitness(Witness& witness, const Math::Vector& point, const Math::Vector& v1, const Math::Vector& v2);
|
||||
void updateWitness(Witness& witness, const Vector& point, const Vector& v1, const Vector& v2);
|
||||
|
||||
// returns true if a collision was found
|
||||
bool createWitness(Witness& witness, const Component::ShapeBase& source, const Component::ShapeBase& other);
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#include "PhysicsSystem.h"
|
||||
#include <boost/numeric/odeint.hpp>
|
||||
#include <random>
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Component;
|
||||
|
||||
PhysicsSystem::PhysicsSystem()
|
||||
PhysicsSystem::PhysicsSystem(entt::registry& registry)
|
||||
: registry(registry)
|
||||
, collisionSystem(registry)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -14,24 +17,25 @@ PhysicsSystem::~PhysicsSystem()
|
||||
|
||||
}
|
||||
|
||||
void PhysicsSystem::update(entt::registry& registry, float deltaTime)
|
||||
void PhysicsSystem::update(float deltaTime)
|
||||
{
|
||||
Array<Body> initialBodies;
|
||||
readRigidBodies(initialBodies, registry);
|
||||
readRigidBodies(initialBodies);
|
||||
|
||||
std::cout << "Updating " << initialBodies.size() << " bodies" << std::endl;
|
||||
Array<Body> bodies = integratePhysics(initialBodies, 0, deltaTime);
|
||||
writeRigidBodies(bodies, registry);
|
||||
writeRigidBodies(bodies);
|
||||
|
||||
Array<Collision> collisions;
|
||||
collisionSystem.detectCollisions(registry, collisions);
|
||||
collisionSystem.detectCollisions(collisions);
|
||||
|
||||
if(!collisions.empty())
|
||||
{
|
||||
constexpr size_t numSteps = 2;
|
||||
for (float t = 0; t < deltaTime; t += deltaTime / numSteps)
|
||||
{
|
||||
rewindCollisions(initialBodies, registry, t, t + (deltaTime / numSteps), 10);
|
||||
readRigidBodies(initialBodies, registry);
|
||||
rewindCollisions(initialBodies, t, t + (deltaTime / numSteps), 10);
|
||||
readRigidBodies(initialBodies);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,7 +103,7 @@ void PhysicsSystem::deserializeArray(Array<Body>& bodies, const Array<float>& x)
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::readRigidBodies(Array<Body>& bodies, entt::registry& registry) const
|
||||
void PhysicsSystem::readRigidBodies(Array<Body>& bodies) const
|
||||
{
|
||||
auto view = registry.view<RigidBody, Transform, Collider>();
|
||||
bodies.clear();
|
||||
@@ -118,7 +122,7 @@ void PhysicsSystem::readRigidBodies(Array<Body>& bodies, entt::registry& registr
|
||||
});
|
||||
}
|
||||
|
||||
void PhysicsSystem::writeRigidBodies(const Array<Body>& bodies, entt::registry& registry) const
|
||||
void PhysicsSystem::writeRigidBodies(const Array<Body>& bodies) const
|
||||
{
|
||||
for(auto& body : bodies)
|
||||
{
|
||||
@@ -135,7 +139,7 @@ void PhysicsSystem::writeRigidBodies(const Array<Body>& bodies, entt::registry&
|
||||
}
|
||||
}
|
||||
|
||||
PhysicsSystem::Body PhysicsSystem::readRigidBody(entt::entity entity, entt::registry& registry) const
|
||||
PhysicsSystem::Body PhysicsSystem::readRigidBody(entt::entity entity) const
|
||||
{
|
||||
Body rigidBody;
|
||||
if(registry.all_of<RigidBody, Collider, Transform>(entity))
|
||||
@@ -153,7 +157,7 @@ PhysicsSystem::Body PhysicsSystem::readRigidBody(entt::entity entity, entt::regi
|
||||
}
|
||||
|
||||
|
||||
void PhysicsSystem::writeRigidBody(const Body& body, entt::registry& registry) const
|
||||
void PhysicsSystem::writeRigidBody(const Body& body) const
|
||||
{
|
||||
if(registry.all_of<RigidBody, Transform>(body.id))
|
||||
{
|
||||
@@ -193,7 +197,7 @@ Array<PhysicsSystem::Body> PhysicsSystem::integratePhysics(const Array<Body>& bo
|
||||
*xdot++ = result[i].v.z;
|
||||
|
||||
// R(t)' = omega(t)*R(t)
|
||||
Math::Quaternion qdot = 0.5f * (Math::Quaternion(0, result[i].omega) * result[i].q);
|
||||
Quaternion qdot = 0.5f * (Quaternion(0, result[i].omega) * result[i].q);
|
||||
*xdot++ = qdot.w;
|
||||
*xdot++ = qdot.x;
|
||||
*xdot++ = qdot.y;
|
||||
@@ -218,7 +222,7 @@ Array<PhysicsSystem::Body> PhysicsSystem::integratePhysics(const Array<Body>& bo
|
||||
|
||||
|
||||
|
||||
void PhysicsSystem::rewindCollisions(const Array<Body>& t0Bodies, entt::registry& registry, const float t0, const float t1, size_t remainingRecursionDepth)
|
||||
void PhysicsSystem::rewindCollisions(const Array<Body>& t0Bodies, const float t0, const float t1, size_t remainingRecursionDepth)
|
||||
{
|
||||
if(remainingRecursionDepth == 0)
|
||||
{
|
||||
@@ -227,8 +231,8 @@ void PhysicsSystem::rewindCollisions(const Array<Body>& t0Bodies, entt::registry
|
||||
// there are collisions happening between t0 and t1
|
||||
// we integrate until tc and see if they have already occured then
|
||||
Array<Collision> collisions;
|
||||
writeRigidBodies(integratePhysics(t0Bodies, t0, t1), registry);
|
||||
collisionSystem.detectCollisions(registry, collisions);
|
||||
writeRigidBodies(integratePhysics(t0Bodies, t0, t1));
|
||||
collisionSystem.detectCollisions(collisions);
|
||||
|
||||
//std::cout << "detected " << collisions.size() << " at " << tc << std::endl;
|
||||
// now we check if there has been a contact at tc
|
||||
@@ -239,16 +243,17 @@ void PhysicsSystem::rewindCollisions(const Array<Body>& t0Bodies, entt::registry
|
||||
const auto&[collider1, transform1] = registry.get<Collider, Transform>(collision.a);
|
||||
const auto&[collider2, transform2] = registry.get<Collider, Transform>(collision.b);
|
||||
calculateContacts(collision.a, collider1.physicsMesh.transform(transform1), collision.b, collider2.physicsMesh.transform(transform2), contacts);
|
||||
calculateContacts(collision.b, collider2.physicsMesh.transform(transform2), collision.a, collider1.physicsMesh.transform(transform1), contacts);
|
||||
}
|
||||
|
||||
// we then apply forces in order to counteract interpenetration
|
||||
Array<Contact> restingContacts;
|
||||
for(const auto& contact : contacts)
|
||||
{
|
||||
Body a = readRigidBody(contact.a, registry);
|
||||
Body b = readRigidBody(contact.b, registry);
|
||||
Math::Vector paDot = a.ptVelocity(contact.p);
|
||||
Math::Vector pbDot = b.ptVelocity(contact.p);
|
||||
Body a = readRigidBody(contact.a);
|
||||
Body b = readRigidBody(contact.b);
|
||||
Vector paDot = a.ptVelocity(contact.p);
|
||||
Vector pbDot = b.ptVelocity(contact.p);
|
||||
float vrel = glm::dot(contact.n, paDot - pbDot);
|
||||
if(vrel > 0.001f)
|
||||
{
|
||||
@@ -262,10 +267,10 @@ void PhysicsSystem::rewindCollisions(const Array<Body>& t0Bodies, entt::registry
|
||||
resolvePenetratingContact(contact, a, b);
|
||||
a.updateMatrix();
|
||||
b.updateMatrix();
|
||||
writeRigidBody(a, registry);
|
||||
writeRigidBody(b, registry);
|
||||
writeRigidBody(a);
|
||||
writeRigidBody(b);
|
||||
}
|
||||
resolveRestingContacts(restingContacts, registry);
|
||||
resolveRestingContacts(restingContacts);
|
||||
}
|
||||
|
||||
void PhysicsSystem::calculateContacts(entt::entity id1, const ShapeBase& shape1, entt::entity id2, const ShapeBase& shape2, Array<Contact>& contacts) const
|
||||
@@ -273,25 +278,33 @@ void PhysicsSystem::calculateContacts(entt::entity id1, const ShapeBase& shape1,
|
||||
for(size_t i = 0; i < shape1.indices.size(); i += 3)
|
||||
{
|
||||
// face - vertex contacts
|
||||
const Math::Vector point1 = shape1.vertices[shape1.indices[i + 0]];
|
||||
const Math::Vector point2 = shape1.vertices[shape1.indices[i + 1]];
|
||||
const Math::Vector point3 = shape1.vertices[shape1.indices[i + 2]];
|
||||
const Math::Vector v1 = point2 - point1;
|
||||
const Math::Vector v2 = point3 - point1;
|
||||
const Math::Vector faceNormal = glm::normalize(glm::cross(v1, v2));
|
||||
auto area = [](Math::Vector ab, Math::Vector ac){
|
||||
const Vector point1 = shape1.vertices[shape1.indices[i + 0]];
|
||||
const Vector point2 = shape1.vertices[shape1.indices[i + 1]];
|
||||
const Vector point3 = shape1.vertices[shape1.indices[i + 2]];
|
||||
const Vector v1 = point2 - point1;
|
||||
const Vector v2 = point3 - point1;
|
||||
const Vector faceNormal = glm::normalize(glm::cross(v1, v2));
|
||||
Seele::gDebugVertices.add(DebugVertex{
|
||||
.position = (point1 + point2 + point3) / 3.f,
|
||||
.color = Vector(1, 0, 0)
|
||||
});
|
||||
Seele::gDebugVertices.add(DebugVertex{
|
||||
.position = faceNormal + (point1 + point2 + point3) / 3.f,
|
||||
.color = Vector(1, 0, 0)
|
||||
});
|
||||
auto area = [](Vector ab, Vector ac){
|
||||
return glm::length(glm::cross(ab, ac)) / 2.0f;
|
||||
};
|
||||
float faceArea = area(v1, v2);
|
||||
for(size_t j = 0; j < shape2.vertices.size(); j++)
|
||||
{
|
||||
Math::Vector worldPos = shape2.vertices[j];
|
||||
Vector worldPos = shape2.vertices[j];
|
||||
float dot = glm::dot(faceNormal, worldPos - point1);
|
||||
if(dot < 0.2f)
|
||||
if(std::abs(dot) < 0.2f)
|
||||
{
|
||||
Math::Vector pa = point1 - worldPos;
|
||||
Math::Vector pb = point2 - worldPos;
|
||||
Math::Vector pc = point3 - worldPos;
|
||||
Vector pa = point1 - worldPos;
|
||||
Vector pb = point2 - worldPos;
|
||||
Vector pc = point3 - worldPos;
|
||||
float a1 = area(pa, pb);
|
||||
float a2 = area(pb, pc);
|
||||
float a3 = area(pc, pa);
|
||||
@@ -311,16 +324,16 @@ void PhysicsSystem::calculateContacts(entt::entity id1, const ShapeBase& shape1,
|
||||
contacts.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
//std::cout << minTemp << std::endl;
|
||||
// edge - edge contacts
|
||||
auto lineLineContact = [=, &contacts](Math::Vector p1, Math::Vector p2, Math::Vector p3, Math::Vector p4)
|
||||
auto lineLineContact = [=, &contacts](Vector p1, Vector p2, Vector p3, Vector p4)
|
||||
{
|
||||
//L1 = p1 + t * p2 - p1;
|
||||
//L2 = p3 + u * p4 - p3;
|
||||
Math::Vector a = p1;
|
||||
Math::Vector c = p3;
|
||||
Math::Vector ab = p2 - p1;
|
||||
Math::Vector cd = p4 - p3;
|
||||
Vector a = p1;
|
||||
Vector c = p3;
|
||||
Vector ab = p2 - p1;
|
||||
Vector cd = p4 - p3;
|
||||
float tx_den = cd.z * ab.y - cd.y * ab.z;
|
||||
float tx = (c.y * ab.z - a.y * ab.z - c.z * ab.y + a.z * ab.y) / tx_den;
|
||||
float ty_den = cd.z * ab.x - cd.z * ab.z;
|
||||
@@ -333,10 +346,10 @@ void PhysicsSystem::calculateContacts(entt::entity id1, const ShapeBase& shape1,
|
||||
&& tx >= 0.f
|
||||
&& tx <= 1.f)
|
||||
{
|
||||
Math::Vector p = p1 + tx * (p2 - p1);
|
||||
Math::Vector ea = p2 - p1;
|
||||
Math::Vector eb = p4 - p3;
|
||||
Math::Vector n = glm::normalize(glm::cross(eb, ea));
|
||||
Vector p = p1 + tx * (p2 - p1);
|
||||
Vector ea = p2 - p1;
|
||||
Vector eb = p4 - p3;
|
||||
Vector n = glm::normalize(glm::cross(eb, ea));
|
||||
Contact contact = {
|
||||
.a = id1,
|
||||
.b = id2,
|
||||
@@ -350,9 +363,9 @@ void PhysicsSystem::calculateContacts(entt::entity id1, const ShapeBase& shape1,
|
||||
};
|
||||
for(size_t j = 0; j < shape2.indices.size(); j+=3)
|
||||
{
|
||||
const Math::Vector point4 = shape2.vertices[shape2.indices[j + 0]];
|
||||
const Math::Vector point5 = shape2.vertices[shape2.indices[j + 1]];
|
||||
const Math::Vector point6 = shape2.vertices[shape2.indices[j + 2]];
|
||||
const Vector point4 = shape2.vertices[shape2.indices[j + 0]];
|
||||
const Vector point5 = shape2.vertices[shape2.indices[j + 1]];
|
||||
const Vector point6 = shape2.vertices[shape2.indices[j + 2]];
|
||||
|
||||
lineLineContact(point1, point2, point4, point5);
|
||||
lineLineContact(point1, point2, point5, point6);
|
||||
@@ -369,54 +382,46 @@ void PhysicsSystem::calculateContacts(entt::entity id1, const ShapeBase& shape1,
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::resolveRestingContacts(const Array<Contact>& contacts, entt::registry& registry) const
|
||||
void PhysicsSystem::resolveRestingContacts(const Array<Contact>& contacts) const
|
||||
{
|
||||
Array<Array<float>> amat(contacts.size(), Array<float>(contacts.size()));
|
||||
Array<Array<float>> amat(contacts.size());
|
||||
for(size_t i = 0; i < contacts.size(); ++i)
|
||||
{
|
||||
amat[i] = Array<float>(contacts.size());
|
||||
}
|
||||
Array<float> bvec(contacts.size());
|
||||
|
||||
computeAMatrix(contacts, amat, registry);
|
||||
computeBVector(contacts, bvec, registry);
|
||||
computeAMatrix(contacts, amat);
|
||||
computeBVector(contacts, bvec);
|
||||
|
||||
Array<float> fvec(bvec);
|
||||
solveQP(amat, bvec, fvec);
|
||||
|
||||
/*CGAL::Quadratic_program<float> qp(CGAL::SMALLER, true, 0, false, 0);
|
||||
for(size_t x = 0; x < contacts.size(); ++x)
|
||||
{
|
||||
for(size_t y = 0; y < contacts.size(); ++y)
|
||||
{
|
||||
qp.set_a(x, y, amat[x][y]);
|
||||
}
|
||||
}
|
||||
for(size_t y = 0; y < contacts.size(); ++y)
|
||||
{
|
||||
qp.set_b(y, bvec[y]);
|
||||
}
|
||||
CGAL::Quadratic_program_solution<CGAL::MP_Float> s = CGAL::solve_quadratic_program(qp, CGAL::MP_Float());
|
||||
assert(s.solves_quadratic_program(qp));
|
||||
|
||||
auto solutionBegin = s.variable_values_begin();
|
||||
for(size_t y = 0; y < contacts.size(); ++y)
|
||||
{
|
||||
float f = CGAL::to_double(*solutionBegin++);
|
||||
Math::Vector n = contacts[y].n;
|
||||
RigidBody a = readRigidBody(contacts[y].a, registry);
|
||||
RigidBody b = readRigidBody(contacts[y].b, registry);
|
||||
std::cout << "resting contact force: " << fvec[y] << std::endl;
|
||||
float f = fvec[y];
|
||||
Vector n = contacts[y].n;
|
||||
Body a = readRigidBody(contacts[y].a);
|
||||
Body b = readRigidBody(contacts[y].b);
|
||||
a.force += f * n;
|
||||
a.torque += (contacts[y].p - a.x + a.centerOfMass) * (f * n);
|
||||
|
||||
b.force -= f * n;
|
||||
b.torque -= (contacts[y].p - b.x + b.centerOfMass) * (f * n);
|
||||
writeRigidBody(a, registry);
|
||||
writeRigidBody(b, registry);
|
||||
}*/
|
||||
writeRigidBody(a);
|
||||
writeRigidBody(b);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::resolvePenetratingContact(const Contact& contact, Body& a, Body& b) const
|
||||
{
|
||||
Math::Vector paDot = a.ptVelocity(contact.p);
|
||||
Math::Vector pbDot = b.ptVelocity(contact.p);
|
||||
Vector paDot = a.ptVelocity(contact.p);
|
||||
Vector pbDot = b.ptVelocity(contact.p);
|
||||
float vrel = glm::dot(contact.n, paDot - pbDot);
|
||||
Math::Vector n = contact.n;
|
||||
Math::Vector ra = contact.p - a.x + a.centerOfMass;
|
||||
Math::Vector rb = contact.p - b.x + b.centerOfMass;
|
||||
Vector n = contact.n;
|
||||
Vector ra = contact.p - a.x + a.centerOfMass;
|
||||
Vector rb = contact.p - b.x + b.centerOfMass;
|
||||
float numerator = -(1 + 0.5f) * vrel;
|
||||
|
||||
float term1 = a.inverseMass;
|
||||
@@ -425,7 +430,7 @@ void PhysicsSystem::resolvePenetratingContact(const Contact& contact, Body& a, B
|
||||
float term4 = glm::dot(n, glm::cross(b.iInv * glm::cross(rb, n), rb));
|
||||
|
||||
float j = numerator / (term1 + term2 + term3 + term4);
|
||||
Math::Vector force = j * n;
|
||||
Vector force = j * n;
|
||||
|
||||
a.P += force;
|
||||
b.P -= force;
|
||||
@@ -439,7 +444,7 @@ void PhysicsSystem::resolvePenetratingContact(const Contact& contact, Body& a, B
|
||||
b.omega = b.iInv * b.L;
|
||||
}
|
||||
|
||||
Math::Vector PhysicsSystem::computeNdot(const Contact& c, const Body& a, const Body& b) const
|
||||
Vector PhysicsSystem::computeNdot(const Contact& c, const Body& a, const Body& b) const
|
||||
{
|
||||
if(c.vf)
|
||||
{
|
||||
@@ -447,10 +452,10 @@ Math::Vector PhysicsSystem::computeNdot(const Contact& c, const Body& a, const B
|
||||
}
|
||||
else
|
||||
{
|
||||
Math::Vector eadot = glm::cross(a.omega, c.ea);
|
||||
Math::Vector ebdot = glm::cross(b.omega, c.eb);
|
||||
Math::Vector n1 = glm::cross(c.ea, c.eb);
|
||||
Math::Vector z = glm::cross(eadot, c.eb) + glm::cross(c.ea, ebdot);
|
||||
Vector eadot = glm::cross(a.omega, c.ea);
|
||||
Vector ebdot = glm::cross(b.omega, c.eb);
|
||||
Vector n1 = glm::cross(c.ea, c.eb);
|
||||
Vector z = glm::cross(eadot, c.eb) + glm::cross(c.ea, ebdot);
|
||||
float l = glm::length(n1);
|
||||
n1 = glm::normalize(n1);
|
||||
|
||||
@@ -458,23 +463,23 @@ Math::Vector PhysicsSystem::computeNdot(const Contact& c, const Body& a, const B
|
||||
}
|
||||
}
|
||||
|
||||
float PhysicsSystem::computeAij(const Contact& ci, const Contact& cj, entt::registry& registry) const
|
||||
float PhysicsSystem::computeAij(const Contact& ci, const Contact& cj) const
|
||||
{
|
||||
if((ci.a != cj.a) && (ci.b != cj.b) &&
|
||||
(ci.a != cj.b) && (ci.b != cj.a))
|
||||
return 0.0f;
|
||||
|
||||
Body a = readRigidBody(ci.a, registry);
|
||||
Body b = readRigidBody(ci.b, registry);
|
||||
Math::Vector ni = ci.n;
|
||||
Math::Vector nj = cj.n;
|
||||
Math::Vector pi = ci.p;
|
||||
Math::Vector pj = cj.p;
|
||||
Math::Vector ra = pi - a.x + a.centerOfMass;
|
||||
Math::Vector rb = pi - b.x + b.centerOfMass;
|
||||
Body a = readRigidBody(ci.a);
|
||||
Body b = readRigidBody(ci.b);
|
||||
Vector ni = ci.n;
|
||||
Vector nj = cj.n;
|
||||
Vector pi = ci.p;
|
||||
Vector pj = cj.p;
|
||||
Vector ra = pi - a.x + a.centerOfMass;
|
||||
Vector rb = pi - b.x + b.centerOfMass;
|
||||
|
||||
Math::Vector forceOnA = Math::Vector(0);
|
||||
Math::Vector torqueOnA = Math::Vector(0);
|
||||
Vector forceOnA = Vector(0);
|
||||
Vector torqueOnA = Vector(0);
|
||||
if(cj.a == ci.a)
|
||||
{
|
||||
forceOnA = nj;
|
||||
@@ -485,8 +490,8 @@ float PhysicsSystem::computeAij(const Contact& ci, const Contact& cj, entt::regi
|
||||
forceOnA = -nj;
|
||||
torqueOnA = glm::cross((pj - a.x + a.centerOfMass), nj);
|
||||
}
|
||||
Math::Vector forceOnB = Math::Vector(0);
|
||||
Math::Vector torqueOnB = Math::Vector(0);
|
||||
Vector forceOnB = Vector(0);
|
||||
Vector torqueOnB = Vector(0);
|
||||
if(cj.a == ci.b)
|
||||
{
|
||||
forceOnB = nj;
|
||||
@@ -498,52 +503,83 @@ float PhysicsSystem::computeAij(const Contact& ci, const Contact& cj, entt::regi
|
||||
torqueOnB = glm::cross((pj - b.x + b.centerOfMass), nj);
|
||||
}
|
||||
|
||||
Math::Vector aLinear = forceOnA * a.inverseMass;
|
||||
Math::Vector aAngular = glm::cross((a.iInv * torqueOnA), ra);
|
||||
Vector aLinear = forceOnA * a.inverseMass;
|
||||
Vector aAngular = glm::cross((a.iInv * torqueOnA), ra);
|
||||
|
||||
Math::Vector bLinear = forceOnB * b.inverseMass;
|
||||
Math::Vector bAngular = glm::cross((b.iInv * torqueOnB), rb);
|
||||
Vector bLinear = forceOnB * b.inverseMass;
|
||||
Vector bAngular = glm::cross((b.iInv * torqueOnB), rb);
|
||||
|
||||
return glm::dot(ni, ((aLinear + aAngular) - (bLinear + bAngular)));
|
||||
}
|
||||
|
||||
void PhysicsSystem::computeAMatrix(const Array<Contact>& contacts, Array<Array<float>>& amat, entt::registry& registry) const
|
||||
void PhysicsSystem::computeAMatrix(const Array<Contact>& contacts, Array<Array<float>>& amat) const
|
||||
{
|
||||
for(size_t x = 0; x < contacts.size(); ++x)
|
||||
{
|
||||
for(size_t y = 0; y < contacts.size(); ++y)
|
||||
{
|
||||
amat[x][y] = computeAij(contacts[x], contacts[y], registry);
|
||||
amat[x][y] = computeAij(contacts[x], contacts[y]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::computeBVector(const Array<Contact>& contacts, Array<float>& bvec, entt::registry& registry) const
|
||||
void PhysicsSystem::computeBVector(const Array<Contact>& contacts, Array<float>& bvec) const
|
||||
{
|
||||
for(size_t y = 0; y < contacts.size(); ++y)
|
||||
{
|
||||
Contact c = contacts[y];
|
||||
Body a = readRigidBody(c.a, registry);
|
||||
Body b = readRigidBody(c.b, registry);
|
||||
Math::Vector n = c.n;
|
||||
Math::Vector ra = c.p - a.x + a.centerOfMass;
|
||||
Math::Vector rb = c.p - b.x + b.centerOfMass;
|
||||
Body a = readRigidBody(c.a);
|
||||
Body b = readRigidBody(c.b);
|
||||
Vector n = c.n;
|
||||
Vector ra = c.p - a.x + a.centerOfMass;
|
||||
Vector rb = c.p - b.x + b.centerOfMass;
|
||||
|
||||
Math::Vector fExtA = a.force;
|
||||
Math::Vector fExtB = b.force;
|
||||
Math::Vector tExtA = a.torque;
|
||||
Math::Vector tExtB = b.torque;
|
||||
Vector fExtA = a.force;
|
||||
Vector fExtB = b.force;
|
||||
Vector tExtA = a.torque;
|
||||
Vector tExtB = b.torque;
|
||||
|
||||
Math::Vector aExtPart = fExtA * a.inverseMass + glm::cross(a.iInv * tExtA, ra);
|
||||
Math::Vector bExtPart = fExtB * b.inverseMass + glm::cross(b.iInv * tExtB, rb);
|
||||
Vector aExtPart = fExtA * a.inverseMass + glm::cross(a.iInv * tExtA, ra);
|
||||
Vector bExtPart = fExtB * b.inverseMass + glm::cross(b.iInv * tExtB, rb);
|
||||
|
||||
Math::Vector aVelPart = glm::cross(a.omega, glm::cross(a.omega, ra)) + glm::cross(a.iInv * glm::cross(a.L, a.omega), ra);
|
||||
Math::Vector bVelPart = glm::cross(b.omega, glm::cross(b.omega, rb)) + glm::cross(b.iInv * glm::cross(b.L, b.omega), rb);
|
||||
Vector aVelPart = glm::cross(a.omega, glm::cross(a.omega, ra)) + glm::cross(a.iInv * glm::cross(a.L, a.omega), ra);
|
||||
Vector bVelPart = glm::cross(b.omega, glm::cross(b.omega, rb)) + glm::cross(b.iInv * glm::cross(b.L, b.omega), rb);
|
||||
|
||||
float k1 = glm::dot(n, (aExtPart + aVelPart) - (bExtPart + bVelPart));
|
||||
Math::Vector ndot = computeNdot(c, a, b);
|
||||
Vector ndot = computeNdot(c, a, b);
|
||||
|
||||
float k2 = 2.0f * glm::dot(ndot, (a.ptVelocity(c.p) - b.ptVelocity(c.p)));
|
||||
bvec[y] = k1 + k2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::solveQP(const Array<Array<float>>& CI, const Array<float>& ci0, Array<float>& sol) const
|
||||
{
|
||||
static std::mt19937_64 generator;
|
||||
static std::uniform_real_distribution<float> dist(0.01f, 0.1f);
|
||||
sol.resize(CI.size());
|
||||
bool solved = false;
|
||||
while(!solved)
|
||||
{
|
||||
for(size_t i = 0; i < sol.size(); ++i)
|
||||
{
|
||||
sol[i] = dist(generator);
|
||||
}
|
||||
solved = true;
|
||||
for(size_t i = 0; i < sol.size(); ++i)
|
||||
{
|
||||
float res = 0;
|
||||
for(size_t j = 0; j < sol.size(); ++j)
|
||||
{
|
||||
res += CI[i][j] * sol[j] + ci0[i];
|
||||
}
|
||||
if(res < 0)
|
||||
{
|
||||
solved = false;
|
||||
std::cout << "failed to solve QP" << std::endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,35 +11,35 @@ namespace Seele
|
||||
class PhysicsSystem
|
||||
{
|
||||
public:
|
||||
PhysicsSystem();
|
||||
PhysicsSystem(entt::registry& registry);
|
||||
~PhysicsSystem();
|
||||
void update(entt::registry& registry, float deltaTime);
|
||||
void update(float deltaTime);
|
||||
private:
|
||||
struct Body
|
||||
{
|
||||
entt::entity id;
|
||||
float inverseMass;
|
||||
Math::Vector centerOfMass;
|
||||
Math::Matrix3 iBody, iBodyInv;
|
||||
Math::Vector scale;
|
||||
Vector centerOfMass;
|
||||
Matrix3 iBody, iBodyInv;
|
||||
Vector scale;
|
||||
|
||||
Math::Vector x;
|
||||
Math::Quaternion q;
|
||||
Math::Vector P;
|
||||
Math::Vector L;
|
||||
Vector x;
|
||||
Quaternion q;
|
||||
Vector P;
|
||||
Vector L;
|
||||
|
||||
Math::Matrix3 iInv;
|
||||
Math::Matrix3 R;
|
||||
Math::Vector v;
|
||||
Math::Vector omega;
|
||||
Math::Vector force;
|
||||
Math::Vector torque;
|
||||
Math::Matrix4 matrix;
|
||||
Math::Vector ptVelocity(Math::Vector p) const {return v + glm::cross(omega, p - x + centerOfMass);}
|
||||
Matrix3 iInv;
|
||||
Matrix3 R;
|
||||
Vector v;
|
||||
Vector omega;
|
||||
Vector force;
|
||||
Vector torque;
|
||||
Matrix4 matrix;
|
||||
Vector ptVelocity(Vector p) const {return v + glm::cross(omega, p - x + centerOfMass);}
|
||||
void updateMatrix() {
|
||||
Math::Matrix4 scaleMatrix = glm::scale(Math::Matrix4(1), scale);
|
||||
Math::Matrix4 rotationMatrix = glm::mat4_cast(q);
|
||||
Math::Matrix4 translationMatrix = glm::translate(Math::Matrix4(1), x);
|
||||
Matrix4 scaleMatrix = glm::scale(Matrix4(1), scale);
|
||||
Matrix4 rotationMatrix = glm::mat4_cast(q);
|
||||
Matrix4 translationMatrix = glm::translate(Matrix4(1), x);
|
||||
matrix = translationMatrix * rotationMatrix * scaleMatrix;
|
||||
}
|
||||
Body()
|
||||
@@ -57,8 +57,8 @@ private:
|
||||
, L(physics.angularMomentum)
|
||||
, iInv(glm::mat3())
|
||||
, R(glm::mat3())
|
||||
, v(Math::Vector())
|
||||
, omega(Math::Vector())
|
||||
, v(Vector())
|
||||
, omega(Vector())
|
||||
, force(physics.force)
|
||||
, torque(physics.torque)
|
||||
{
|
||||
@@ -76,14 +76,14 @@ private:
|
||||
, scale(transform.getScale())
|
||||
, x(transform.getPosition())
|
||||
, q(transform.getRotation())
|
||||
, P(Math::Vector(0))
|
||||
, L(Math::Vector(0))
|
||||
, P(Vector(0))
|
||||
, L(Vector(0))
|
||||
, iInv(glm::mat3())
|
||||
, R(glm::mat3())
|
||||
, v(Math::Vector())
|
||||
, omega(Math::Vector())
|
||||
, force(Math::Vector(0))
|
||||
, torque(Math::Vector(0))
|
||||
, v(Vector())
|
||||
, omega(Vector())
|
||||
, force(Vector(0))
|
||||
, torque(Vector(0))
|
||||
{
|
||||
R = glm::mat3_cast(glm::normalize(q));
|
||||
iInv = R * iBodyInv * glm::transpose(R);
|
||||
@@ -99,9 +99,10 @@ private:
|
||||
glm::vec3 eb;
|
||||
bool vf;
|
||||
};
|
||||
static constexpr size_t FLOATS_PER_RB = sizeof(Body) / sizeof(float);
|
||||
|
||||
static constexpr size_t FLOATS_PER_RB = 13;
|
||||
entt::registry& registry;
|
||||
CollisionSystem collisionSystem;
|
||||
bool pause = false;
|
||||
|
||||
void serializeRB(const Body& rb, float* y) const;
|
||||
|
||||
@@ -111,30 +112,32 @@ private:
|
||||
|
||||
void deserializeArray(Array<Body>& bodies, const Array<float>& x) const;
|
||||
|
||||
void readRigidBodies(Array<Body>& bodies, entt::registry& registry) const;
|
||||
void readRigidBodies(Array<Body>& bodies) const;
|
||||
|
||||
void writeRigidBodies(const Array<Body>& bodies, entt::registry& registry) const;
|
||||
void writeRigidBodies(const Array<Body>& bodies) const;
|
||||
|
||||
Body readRigidBody(entt::entity entity, entt::registry& regsitry) const;
|
||||
Body readRigidBody(entt::entity entity) const;
|
||||
|
||||
void writeRigidBody(const Body& body, entt::registry& registry) const;
|
||||
void writeRigidBody(const Body& body) const;
|
||||
|
||||
Array<Body> integratePhysics(const Array<Body>& bodies, const float t0, const float tdelta) const;
|
||||
|
||||
void rewindCollisions(const Array<Body>& t0Bodies, entt::registry& registry, const float t0, const float t1, size_t remainingDepth);
|
||||
void rewindCollisions(const Array<Body>& t0Bodies, const float t0, const float t1, size_t remainingDepth);
|
||||
|
||||
void calculateContacts(entt::entity id1, const Component::ShapeBase& shape1, entt::entity id2, const Component::ShapeBase& shape2, Array<Contact>& contacts) const;
|
||||
|
||||
void resolveRestingContacts(const Array<Contact>& contacts, entt::registry& registry) const;
|
||||
void resolveRestingContacts(const Array<Contact>& contacts) const;
|
||||
|
||||
void resolvePenetratingContact(const Contact& c, Body& a, Body& b) const;
|
||||
|
||||
Math::Vector computeNdot(const Contact& c, const Body& a, const Body& b) const;
|
||||
Vector computeNdot(const Contact& c, const Body& a, const Body& b) const;
|
||||
|
||||
float computeAij(const Contact& ci, const Contact& cj, entt::registry& registry) const;
|
||||
float computeAij(const Contact& ci, const Contact& cj) const;
|
||||
|
||||
void computeAMatrix(const Array<Contact>& contacts, Array<Array<float>>& amat, entt::registry& registry) const;
|
||||
void computeAMatrix(const Array<Contact>& contacts, Array<Array<float>>& amat) const;
|
||||
|
||||
void computeBVector(const Array<Contact>& contacts, Array<float>& avec, entt::registry& registry) const;
|
||||
void computeBVector(const Array<Contact>& contacts, Array<float>& avec) const;
|
||||
|
||||
void solveQP(const Array<Array<float>>& A, const Array<float>& b, Array<float>& f) const;
|
||||
};
|
||||
} // namespace Seele
|
||||
|
||||
+28
-59
@@ -1,5 +1,4 @@
|
||||
#include "Scene.h"
|
||||
#include "Material/MaterialAsset.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Graphics/Mesh.h"
|
||||
#include "Component/StaticMesh.h"
|
||||
@@ -14,6 +13,7 @@ inline float frand()
|
||||
|
||||
Scene::Scene(Gfx::PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
, physics(registry)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -21,69 +21,24 @@ Scene::~Scene()
|
||||
{
|
||||
}
|
||||
|
||||
void Scene::start()
|
||||
void Scene::update(float deltaTime)
|
||||
{
|
||||
//for(auto actor : rootActors)
|
||||
//{
|
||||
// actor->launchStart();
|
||||
//}
|
||||
}
|
||||
|
||||
static int64 lastUpdate;
|
||||
static uint64 numUpdates;
|
||||
|
||||
void Scene::beginUpdate(double)
|
||||
{
|
||||
//std::cout << "Scene::beginUpdate" << std::endl;
|
||||
auto startTime = std::chrono::high_resolution_clock::now();
|
||||
// TODO
|
||||
auto endTime = std::chrono::high_resolution_clock::now();
|
||||
int64 delta = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count();
|
||||
lastUpdate += delta;
|
||||
numUpdates++;
|
||||
if(lastUpdate > 1000000)
|
||||
{
|
||||
lastUpdate -= 1000000;
|
||||
std::cout << numUpdates << " updates per second" << std::endl;
|
||||
numUpdates = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::commitUpdate()
|
||||
{
|
||||
//std::cout << "Scene::commitUpdate" << std::endl;
|
||||
//for(auto actor : rootActors)
|
||||
//{
|
||||
// actor->launchUpdate();
|
||||
//}
|
||||
//std::cout << "Scene::commitUpdate finished waiting" << std::endl;
|
||||
physics.update(deltaTime);
|
||||
}
|
||||
|
||||
Array<StaticMeshBatch> Scene::getStaticMeshes()
|
||||
{
|
||||
Array<StaticMeshBatch> result;
|
||||
auto view = registry.view<Component::StaticMesh, Component::Transform>();
|
||||
struct PrimitiveSceneData
|
||||
{
|
||||
Math::Matrix4 localToWorld;
|
||||
Math::Matrix4 worldToLocal;
|
||||
Math::Vector4 actorLocation;
|
||||
};
|
||||
uint32 sceneDataIndex = 0;
|
||||
sceneData.clear();
|
||||
for(auto&& [entity, mesh, transform] : view.each())
|
||||
{
|
||||
PrimitiveSceneData sceneData = {
|
||||
sceneData.add(PrimitiveSceneData {
|
||||
.localToWorld = transform.toMatrix(),
|
||||
.worldToLocal = glm::inverse(transform.toMatrix()),
|
||||
.actorLocation = Math::Vector4(transform.getPosition(), 1.0f)
|
||||
};
|
||||
UniformBufferCreateInfo info = {
|
||||
.resourceData = {
|
||||
.size = sizeof(PrimitiveSceneData),
|
||||
.data = (uint8_t*)&sceneData,
|
||||
}
|
||||
};
|
||||
Gfx::PUniformBuffer transformBuf = graphics->createUniformBuffer(info);
|
||||
// TODO
|
||||
.actorLocation = Vector4(transform.getPosition(), 1.0f)
|
||||
});
|
||||
for(auto& m : mesh.mesh->meshes)
|
||||
{
|
||||
auto& batch = result.add();
|
||||
@@ -99,23 +54,37 @@ Array<StaticMeshBatch> Scene::getStaticMeshes()
|
||||
batchElement.firstIndex = 0;
|
||||
batchElement.indexBuffer = m->indexBuffer;
|
||||
batchElement.indirectArgsBuffer = nullptr;
|
||||
batchElement.instanceRuns = nullptr;
|
||||
batchElement.isInstanced = false;
|
||||
batchElement.numInstances = 1;
|
||||
batchElement.uniformBuffer = transformBuf;
|
||||
batchElement.numPrimitives = static_cast<uint32>(m->indexBuffer->getNumIndices() / 3); //TODO: hardcoded
|
||||
batchElement.sceneDataIndex = sceneDataIndex;
|
||||
batch.elements.add(batchElement);
|
||||
}
|
||||
sceneDataIndex++;
|
||||
}
|
||||
if(sceneDataBuffer == nullptr || sceneDataBuffer->getNumElements() != sceneData.size())
|
||||
{
|
||||
StructuredBufferCreateInfo createInfo = StructuredBufferCreateInfo {
|
||||
.resourceData = {
|
||||
.size = sceneData.size() * sizeof(PrimitiveSceneData),
|
||||
.data = nullptr,
|
||||
},
|
||||
.stride = (uint32)sceneData.size(),
|
||||
};
|
||||
sceneDataBuffer = graphics->createStructuredBuffer(createInfo);
|
||||
}
|
||||
sceneDataBuffer->updateContents(BulkResourceData {
|
||||
.size = sceneData.size() * sizeof(PrimitiveSceneData),
|
||||
.data = (uint8*)sceneData.data(),
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
LightEnv Scene::getLightBuffer() const
|
||||
{
|
||||
LightEnv result;
|
||||
result.directionalLights[0].color = Math::Vector4(0.4, 0.3, 0.5, 1.0);
|
||||
result.directionalLights[0].direction = Math::Vector4(0.5, 0.5, 0, 0);
|
||||
result.directionalLights[0].intensity = Math::Vector4(1.0, 0.9, 0.7, 0.5);\
|
||||
result.directionalLights[0].color = Vector4(0.4, 0.3, 0.5, 1.0);
|
||||
result.directionalLights[0].direction = Vector4(0.5, 0.5, 0, 0);
|
||||
result.directionalLights[0].intensity = Vector4(1.0, 0.9, 0.7, 0.5);\
|
||||
result.numDirectionalLights = 1;
|
||||
result.numPointLights = 0;
|
||||
return result;
|
||||
|
||||
+24
-11
@@ -3,6 +3,7 @@
|
||||
#include "MinimalEngine.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include "Graphics/MeshBatch.h"
|
||||
#include "Physics/PhysicsSystem.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
@@ -11,16 +12,16 @@ DECLARE_REF(Entity)
|
||||
|
||||
struct DirectionalLight
|
||||
{
|
||||
Math::Vector4 color;
|
||||
Math::Vector4 direction;
|
||||
Math::Vector4 intensity;
|
||||
Vector4 color;
|
||||
Vector4 direction;
|
||||
Vector4 intensity;
|
||||
};
|
||||
|
||||
struct PointLight
|
||||
{
|
||||
Math::Vector4 positionWS;
|
||||
Vector4 positionWS;
|
||||
//Vector4 positionVS;
|
||||
Math::Vector4 colorRange;
|
||||
Vector4 colorRange;
|
||||
};
|
||||
|
||||
#define MAX_DIRECTIONAL_LIGHTS 4
|
||||
@@ -38,17 +39,19 @@ class Scene
|
||||
public:
|
||||
Scene(Gfx::PGraphics graphics);
|
||||
~Scene();
|
||||
void start();
|
||||
void beginUpdate(double deltaTime);
|
||||
void commitUpdate();
|
||||
void update(float deltaTime);
|
||||
entt::entity createEntity()
|
||||
{
|
||||
return registry.create();
|
||||
}
|
||||
template<typename Component, typename... Args>
|
||||
Component& attachComponent(entt::entity entity, Args... args)
|
||||
void destroyEntity(entt::entity identifier)
|
||||
{
|
||||
return registry.emplace<Component>(entity, args...);
|
||||
registry.destroy(identifier);
|
||||
}
|
||||
template<typename Component, typename... Args>
|
||||
Component& attachComponent(entt::entity entity, Args&&... args)
|
||||
{
|
||||
return registry.emplace<Component>(entity, std::forward<Args>(args)...);
|
||||
}
|
||||
template<typename Component>
|
||||
Component& accessComponent(entt::entity entity)
|
||||
@@ -62,9 +65,19 @@ public:
|
||||
}
|
||||
Array<StaticMeshBatch> getStaticMeshes();
|
||||
LightEnv getLightBuffer() const;
|
||||
Gfx::PStructuredBuffer getSceneDataBuffer() const { return sceneDataBuffer; }
|
||||
|
||||
entt::registry registry;
|
||||
private:
|
||||
struct PrimitiveSceneData
|
||||
{
|
||||
Matrix4 localToWorld;
|
||||
Matrix4 worldToLocal;
|
||||
Vector4 actorLocation;
|
||||
};
|
||||
Array<PrimitiveSceneData> sceneData;
|
||||
Gfx::PStructuredBuffer sceneDataBuffer;
|
||||
PhysicsSystem physics;
|
||||
Gfx::PGraphics graphics;
|
||||
};
|
||||
DEFINE_REF(Scene)
|
||||
|
||||
@@ -59,12 +59,12 @@ bool Element::isEnabled() const
|
||||
return enabled;
|
||||
}
|
||||
|
||||
Math::Rect& Element::getBoundingBox()
|
||||
Rect& Element::getBoundingBox()
|
||||
{
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
const Math::Rect Element::getBoundingBox() const
|
||||
const Rect Element::getBoundingBox() const
|
||||
{
|
||||
return boundingBox;
|
||||
}
|
||||
@@ -23,13 +23,13 @@ public:
|
||||
bool isEnabled() const;
|
||||
// maybe not the healthiest inteface
|
||||
// non-const version
|
||||
Math::Rect& getBoundingBox();
|
||||
Rect& getBoundingBox();
|
||||
// The bounding box describes the relative size of any Element
|
||||
// relative to the total view, meaning a bounding box of (0,0), (1,1)
|
||||
// would take up the entire view
|
||||
const Math::Rect getBoundingBox() const;
|
||||
const Rect getBoundingBox() const;
|
||||
protected:
|
||||
Math::Rect boundingBox;
|
||||
Rect boundingBox;
|
||||
bool dirty;
|
||||
|
||||
bool enabled;
|
||||
|
||||
@@ -18,14 +18,14 @@ HorizontalLayout::~HorizontalLayout()
|
||||
void HorizontalLayout::apply()
|
||||
{
|
||||
Array<PElement> children = element->getChildren();
|
||||
const Math::Rect parent = element->getBoundingBox();
|
||||
const Rect parent = element->getBoundingBox();
|
||||
float xOffset = parent.offset.x;
|
||||
float yOffset = parent.offset.y;
|
||||
float xSize = parent.size.x / children.size();
|
||||
float ySize = parent.size.y;
|
||||
for(uint32 index = 0; index < children.size(); ++index)
|
||||
{
|
||||
Math::Rect& child = children[index]->getBoundingBox();
|
||||
Rect& child = children[index]->getBoundingBox();
|
||||
child.offset.x = xOffset + (index * xSize);
|
||||
child.offset.y = yOffset;
|
||||
child.size.x = xSize;
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace UI
|
||||
{
|
||||
struct RenderElementStyle
|
||||
{
|
||||
Math::Vector position = Math::Vector(0, 0, 0);
|
||||
Vector position = Vector(0, 0, 0);
|
||||
uint32 backgroundImageIndex = UINT32_MAX;
|
||||
Math::Vector backgroundColor = Math::Vector(1, 1, 1);
|
||||
Vector backgroundColor = Vector(1, 1, 1);
|
||||
float opacity = 1.0f;
|
||||
//Vector4 borderBottomColor = Vector4(1, 1, 1, 1);
|
||||
//Vector4 borderLeftColor = Vector4(1, 1, 1, 1);
|
||||
@@ -21,7 +21,7 @@ struct RenderElementStyle
|
||||
//float borderBottomRightRadius = 0;
|
||||
//float borderTopLeftRadius = 0;
|
||||
//float borderTopRightRadius = 0;
|
||||
Math::Vector2 dimensions = Math::Vector2(1, 1);
|
||||
Vector2 dimensions = Vector2(1, 1);
|
||||
};
|
||||
class RenderElement
|
||||
{
|
||||
|
||||
@@ -31,9 +31,9 @@ UIPassData System::getUIPassData()
|
||||
{
|
||||
UIPassData uiPassData;
|
||||
RenderElementStyle& style = uiPassData.renderElements.add();
|
||||
style.position = Math::Vector(0, 0, -0.1);
|
||||
style.dimensions = Math::Vector2(0.4, 0.4);
|
||||
style.backgroundColor = Math::Vector(0.2, 0.3, 0.1);
|
||||
style.position = Vector(0, 0, -0.1);
|
||||
style.dimensions = Vector2(0.4, 0.4);
|
||||
style.backgroundColor = Vector(0.2, 0.3, 0.1);
|
||||
style.backgroundImageIndex = 0;
|
||||
uiPassData.usedTextures.add(AssetRegistry::findTexture("")->getTexture());
|
||||
return uiPassData;
|
||||
@@ -46,9 +46,9 @@ TextPassData System::getTextPassData()
|
||||
render.font = AssetRegistry::findFont("Calibri");
|
||||
render.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus quis magna ex. Morbi ullamcorper fringilla risus eget vehicula. Praesent vel quam vel ante molestie gravida vitae ac enim. Donec vitae eleifend orci. Phasellus at sodales lorem, ac eleifend turpis. Vivamus vitae condimentum lacus, a bibendum neque. Ut et est ut felis varius vehicula. Etiam lorem magna, dapibus vitae felis in, vulputate suscipit neque. Aenean facilisis ac risus et scelerisque. Ut tincidunt eros quis posuere iaculis. Curabitur justo lacus, molestie id varius vel, sodales efficitur diam. Integer orci velit, condimentum sit amet turpis sit amet, congue blandit nisl. Donec pretium ligula id mauris pretium commodo. Mauris quis lectus mi. In blandit, dolor non accumsan venenatis, ipsum erat congue neque, quis elementum orci nunc vel justo. ";
|
||||
//render.text = "Seele Engine";
|
||||
render.position = Math::Vector2(0.f, 300.f);
|
||||
render.position = Vector2(0.f, 300.f);
|
||||
render.scale = 0.1f;
|
||||
render.textColor = Math::Vector4(1, 0, 0, 1);
|
||||
render.textColor = Vector4(1, 0, 0, 1);
|
||||
return textPassData;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user