diff --git a/ToyEngine/Shaders/pbr.comp b/ToyEngine/Shaders/pbr.comp
index d8cacd6..4bd8675 100644
--- a/ToyEngine/Shaders/pbr.comp
+++ b/ToyEngine/Shaders/pbr.comp
@@ -101,6 +101,7 @@ const int pcfRadius = 3;
float getShadowFromLayer(vec3 fragPosWorldSpace, vec3 normal,int layer)
{
float normalBias = 1.2*4. /** (1+pcfRadius)*/ * shadowBiases[layer]*max((1.0 - dot(normal, mainLightDirection)), 0.1)/textureSize(gShadowMap, 0).x;
+ normalBias = max(normalBias, 0.05);
vec4 fragPosLightSpace = lightSpaceMatrices[layer] * vec4(fragPosWorldSpace+normal*normalBias, 1.0);
// perform perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
diff --git a/ToyEngine/ToyEngine.vcxproj b/ToyEngine/ToyEngine.vcxproj
index 9d085e7..02df996 100644
--- a/ToyEngine/ToyEngine.vcxproj
+++ b/ToyEngine/ToyEngine.vcxproj
@@ -24,11 +24,13 @@
+
+
@@ -39,6 +41,7 @@
+
@@ -46,6 +49,7 @@
+
@@ -163,6 +167,9 @@
stdcpp20
stdc17
true
+ MaxSpeed
+ Speed
+ Default
Console
diff --git a/ToyEngine/ToyEngine.vcxproj.filters b/ToyEngine/ToyEngine.vcxproj.filters
index 51abfa2..467f3cd 100644
--- a/ToyEngine/ToyEngine.vcxproj.filters
+++ b/ToyEngine/ToyEngine.vcxproj.filters
@@ -57,6 +57,12 @@
头文件
+
+ 头文件
+
+
+ 头文件
+
@@ -101,6 +107,12 @@
源文件
+
+ 源文件
+
+
+ 源文件
+
diff --git a/ToyEngine/src/Actor.cpp b/ToyEngine/src/Actor.cpp
index 31a3f5c..fbdf4fc 100644
--- a/ToyEngine/src/Actor.cpp
+++ b/ToyEngine/src/Actor.cpp
@@ -1,17 +1,29 @@
#include "Actor.h"
#include "MainWindow.h"
+Actor::Actor()
+ : gl(MainWindow::getGLContext())
+ , model(gl)
+ , animator(gl, animation.get())
+{
+}
+
Actor::Actor(const std::string& path)
: gl(MainWindow::getGLContext())
, model(gl, path)
- , danceAnimation(path, &model)
- , animator(gl, &danceAnimation)
+ , animation(std::make_unique(path, &model))
+ , animator(gl, animation->available() ? animation.get() : nullptr)
{
}
-void Actor::tick(float deltaTime)
+void Actor::logicalTick(float deltaTime)
{
- animator.UpdateAnimation(deltaTime);
+ animator.updateAnimation(deltaTime);
+}
+
+void Actor::rendererTick(float deltaTime)
+{
+
}
void Actor::draw(Shader& shader)
@@ -39,6 +51,21 @@ void Actor::setRotaion(const glm::quat& rotation)
updateTransform();
}
+glm::vec3 Actor::getPosition()
+{
+ return position;
+}
+
+glm::vec3 Actor::getScale()
+{
+ return scale;
+}
+
+glm::quat Actor::getRotation()
+{
+ return rotation;
+}
+
std::pair Actor::getAABB()
{
return model.getAABB();
diff --git a/ToyEngine/src/Actor.h b/ToyEngine/src/Actor.h
index e89fd04..e13a621 100644
--- a/ToyEngine/src/Actor.h
+++ b/ToyEngine/src/Actor.h
@@ -7,21 +7,32 @@
class Actor
{
public:
+ Actor();
Actor(const std::string& path);
- void tick(float deltaTime);
- void draw(Shader& shader);
+ virtual ~Actor() = default;
+ virtual void logicalTick(float deltaTime);
+ virtual void rendererTick(float deltaTime);
+ virtual void draw(Shader& shader);
void setPosition(const glm::vec3& position);
void setScale(const glm::vec3& scale);
void setRotaion(const glm::quat& rotation);
+
+ glm::vec3 getPosition();
+ glm::vec3 getScale();
+ glm::quat getRotation();
+
std::pair getAABB();
+
+protected:
+ GladGLContext* gl;
+ Model model;
+ std::unique_ptr animation;
+ Animator animator;
+
private:
void updateTransform();
- GladGLContext* gl;
- Model model;
- Animation danceAnimation;
- Animator animator;
glm::vec3 position = glm::vec3(0);
glm::vec3 scale = glm::vec3(1);
glm::quat rotation = glm::quat(1, 0, 0, 0);
diff --git a/ToyEngine/src/Animation.h b/ToyEngine/src/Animation.h
index 54c6908..9297261 100644
--- a/ToyEngine/src/Animation.h
+++ b/ToyEngine/src/Animation.h
@@ -7,6 +7,7 @@
#include "Bone.h"
#include "Model.h"
#include
+#include
struct AssimpNodeData
{
@@ -41,16 +42,16 @@ public:
{
}
+ bool available()
+ {
+ return m_TicksPerSecond;
+ }
+
Bone* FindBone(const std::string& name)
{
- auto iter = std::find_if(m_Bones.begin(), m_Bones.end(),
- [&](const Bone& Bone)
- {
- return Bone.GetBoneName() == name;
- }
- );
+ auto iter = m_Bones.find(name);
if (iter == m_Bones.end()) return nullptr;
- else return &(*iter);
+ else return &iter->second;
}
@@ -81,7 +82,8 @@ private:
boneInfoMap[boneName].id = boneCount;
boneCount++;
}
- m_Bones.push_back(Bone(channel->mNodeName.data,
+
+ m_Bones.emplace(std::piecewise_construct, std::forward_as_tuple(channel->mNodeName.data), std::forward_as_tuple(channel->mNodeName.data,
boneInfoMap[channel->mNodeName.data].id, channel));
}
@@ -103,9 +105,11 @@ private:
dest.children.push_back(newData);
}
}
- float m_Duration;
- int m_TicksPerSecond;
- std::vector m_Bones;
+ float m_Duration = 0.f;
+ int m_TicksPerSecond = 0;
+ std::unordered_map m_Bones;
+
+ //std::set m_Bones;
AssimpNodeData m_RootNode;
std::map m_BoneInfoMap;
};
diff --git a/ToyEngine/src/Animator.h b/ToyEngine/src/Animator.h
index 9fb595d..0122aab 100644
--- a/ToyEngine/src/Animator.h
+++ b/ToyEngine/src/Animator.h
@@ -11,37 +11,43 @@ class Animator
public:
static constexpr GLint kMaxBone = 100;
- Animator(GladGLContext* gl, Animation* animation) : gl(gl)
+ Animator(GladGLContext* gl, Animation* animation)
+ : gl(gl)
{
- currentTime = 0.0;
- currentAnimation = animation;
-
- finalBoneMatrices.reserve(100);
-
- for (int i = 0; i < 100; i++)
- finalBoneMatrices.push_back(glm::mat4(1.0f));
-
- gl->CreateBuffers(1, &finalBonesMatricesUBO);
- gl->NamedBufferData(finalBonesMatricesUBO, sizeof(glm::mat4) * Animator::kMaxBone, nullptr, GL_DYNAMIC_DRAW);
+ playAnimation(animation);
}
- void UpdateAnimation(float deltaTime)
+ void updateAnimation(float deltaTime)
{
if (currentAnimation)
{
currentTime += currentAnimation->GetTicksPerSecond() * deltaTime;
currentTime = fmod(currentTime, currentAnimation->GetDuration());
- CalculateBoneTransform(¤tAnimation->GetRootNode(), glm::mat4(1.0f));
+ calculateBoneTransform(¤tAnimation->GetRootNode(), glm::mat4(1.0f));
}
}
- void PlayAnimation(Animation* pAnimation)
+ void playAnimation(Animation* pAnimation)
{
currentAnimation = pAnimation;
currentTime = 0.0f;
+
+ if (currentAnimation)
+ {
+ finalBoneMatrices.clear();
+ finalBoneMatrices.reserve(kMaxBone);
+ for (int i = 0; i < kMaxBone; i++)
+ finalBoneMatrices.push_back(glm::mat4(1.0f));
+
+ if (!finalBonesMatricesUBO)
+ {
+ gl->CreateBuffers(1, &finalBonesMatricesUBO);
+ gl->NamedBufferData(finalBonesMatricesUBO, sizeof(glm::mat4) * Animator::kMaxBone, nullptr, GL_DYNAMIC_DRAW);
+ }
+ }
}
- void CalculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform)
+ void calculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform)
{
std::string nodeName = node->name;
glm::mat4 nodeTransform = node->transformation;
@@ -56,33 +62,33 @@ public:
glm::mat4 globalTransformation = parentTransform * nodeTransform;
- auto boneInfoMap = currentAnimation->GetBoneIDMap();
- if (boneInfoMap.find(nodeName) != boneInfoMap.end())
+ auto& boneInfoMap = currentAnimation->GetBoneIDMap();
+ if (auto iter = boneInfoMap.find(nodeName); iter != boneInfoMap.end())
{
- int index = boneInfoMap[nodeName].id;
- glm::mat4 offset = boneInfoMap[nodeName].offset;
+ auto& [index, offset] = iter->second;
finalBoneMatrices[index] = globalTransformation * offset;
}
for (int i = 0; i < node->childrenCount; i++)
- CalculateBoneTransform(&node->children[i], globalTransformation);
+ calculateBoneTransform(&node->children[i], globalTransformation);
}
- std::vector GetFinalBoneMatrices()
+ std::vector getFinalBoneMatrices()
{
return finalBoneMatrices;
}
GLuint getFinalBonesMatricesUBO()
{
- gl->NamedBufferSubData(finalBonesMatricesUBO, 0, finalBoneMatrices.size() * sizeof(finalBoneMatrices[0]), finalBoneMatrices.data());
+ if (finalBonesMatricesUBO)
+ gl->NamedBufferSubData(finalBonesMatricesUBO, 0, finalBoneMatrices.size() * sizeof(finalBoneMatrices[0]), finalBoneMatrices.data());
return finalBonesMatricesUBO;
}
private:
GladGLContext* gl;
std::vector finalBoneMatrices;
- GLuint finalBonesMatricesUBO;
- Animation* currentAnimation;
+ GLuint finalBonesMatricesUBO = 0;
+ Animation* currentAnimation = nullptr;
float currentTime;
};
diff --git a/ToyEngine/src/Bone.h b/ToyEngine/src/Bone.h
index 64edaf6..8dac95d 100644
--- a/ToyEngine/src/Bone.h
+++ b/ToyEngine/src/Bone.h
@@ -114,6 +114,10 @@ public:
assert(0);
}
+ bool operator<(const Bone& e) const
+ {
+ return m_ID < e.m_ID;
+ }
private:
diff --git a/ToyEngine/src/DemoWorld.cpp b/ToyEngine/src/DemoWorld.cpp
new file mode 100644
index 0000000..d473d01
--- /dev/null
+++ b/ToyEngine/src/DemoWorld.cpp
@@ -0,0 +1,33 @@
+#include "DemoWorld.h"
+#include "Particle.h"
+
+DemoWorld::DemoWorld()
+{
+ std::string modelFilePath;
+ //modelFilePath = "E:\\3D Objects\\plane\\obj\\plane.obj";
+ //modelFilePath = "E:\\3D Objects\\plane\\plane.gltf";
+ modelFilePath = "Models/vampire/vampire.gltf";
+ //modelFilePath = "E:\\3D Objects\\cup\\cup.gltf";
+ //modelFilePath = "E:\\3D Objects\\Sponza\\Sponza.gltf";
+
+ auto actor = std::make_shared(modelFilePath);
+ actor->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
+ auto actor2 = std::make_shared(modelFilePath);
+ actor2->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
+ actor2->setPosition({ 1,0,-1 });
+ auto actor3 = std::make_shared(modelFilePath);
+ actor3->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
+ actor3->setPosition({ -1,0,-1 });
+ auto sponza = std::make_shared("Models\\Sponza\\Sponza.gltf");
+ sponza->setScale(glm::vec3(2));
+
+ auto particle = std::make_shared(10);
+ particle->setPosition({ 4, 5, 0 });
+ particle->addForce(glm::vec3(0, -particle->getMass() * 9.8f, 0));
+
+ addActor(actor);
+ addActor(actor2);
+ addActor(actor3);
+ addActor(sponza);
+ addActor(particle);
+}
diff --git a/ToyEngine/src/DemoWorld.h b/ToyEngine/src/DemoWorld.h
new file mode 100644
index 0000000..896fc19
--- /dev/null
+++ b/ToyEngine/src/DemoWorld.h
@@ -0,0 +1,9 @@
+#pragma once
+#include "World.h"
+
+class DemoWorld : public World
+{
+public:
+ DemoWorld();
+};
+
diff --git a/ToyEngine/src/MainWindow.cpp b/ToyEngine/src/MainWindow.cpp
index 1723c3f..263a29f 100644
--- a/ToyEngine/src/MainWindow.cpp
+++ b/ToyEngine/src/MainWindow.cpp
@@ -2,6 +2,8 @@
#include "IblUtils.h"
#include "RenderPass.h"
#include "World.h"
+#include "Particle.h"
+#include "DemoWorld.h"
MainWindow::MainWindow()
: camera(glm::vec3(0.0f, 0.0f, 3.0f))
@@ -50,39 +52,18 @@ int MainWindow::exec()
gl->DepthFunc(GL_LEQUAL);
gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
- std::string modelFilePath;
- //modelFilePath = "E:\\3D Objects\\plane\\obj\\plane.obj";
- //modelFilePath = "E:\\3D Objects\\plane\\plane.gltf";
- modelFilePath = "Models/vampire/vampire.gltf";
- //modelFilePath = "E:\\3D Objects\\cup\\cup.gltf";
- //modelFilePath = "E:\\3D Objects\\Sponza\\Sponza.gltf";
+ std::unique_ptr world = std::make_unique();
- auto actor = std::make_shared(modelFilePath);
- actor->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
- auto actor2 = std::make_shared(modelFilePath);
- actor2->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
- actor2->setPosition({ 1,0,-1 });
- auto actor3 = std::make_shared(modelFilePath);
- actor3->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
- actor3->setPosition({ -1,0,-1 });
- auto sponza = std::make_shared("Models\\Sponza\\Sponza.gltf");
- sponza->setScale(glm::vec3(2));
- World world;
- world.addActor(actor);
- world.addActor(actor2);
- world.addActor(actor3);
- world.addActor(sponza);
-
- auto [minPos, maxPos] = world.getAABB();
+ auto [minPos, maxPos] = world->getAABB();
std::cout << std::format("{},{},{} {},{},{}\n", minPos.x, minPos.y, minPos.z, maxPos.x, maxPos.y, maxPos.z);
- light.sceneAABB = world.getAABB();
+ light.sceneAABB = world->getAABB();
glm::mat4 projection, view;
auto [skyCubemap, irradianceMap, prefilterMap, brdfLUTTexture] = IblUtils::precomputeCubemaps(gl.get());
- ShadowMapPass shadowMapPass(gl.get(), shadowFboHandle, shadowMapResolution, world, light);
- GeometryPass geometryPass(gl.get(), frameWidth, frameHeight, fbo, world, projection, view);
+ ShadowMapPass shadowMapPass(gl.get(), shadowFboHandle, shadowMapResolution, *world, light);
+ GeometryPass geometryPass(gl.get(), frameWidth, frameHeight, fbo, *world, projection, view);
LightingPass lightingPass(gl.get(), frameWidth, frameHeight, view, camera, light, mainLightRadiance,
gbuffers, shadowGbuffer, irradianceMap, prefilterMap, brdfLUTTexture);
FinalPass finalPass(gl.get(), frameWidth, frameHeight, gbuffers, exposure);
@@ -92,14 +73,35 @@ int MainWindow::exec()
glfwGetFramebufferSize(window, &w, &h);
framebufferSizeCallback(window, w, h);
+ int logicalTickCount = 0;
+ auto logicalThread = std::jthread([&](std::stop_token stop) {
+ using namespace std::chrono_literals;
+ constexpr auto targetDuration = 1666us;
+ auto sleepTime = 0ns;
+ auto lastTick = std::chrono::high_resolution_clock::now();
+ while (!stop.stop_requested())
+ {
+ auto currentTick = std::chrono::high_resolution_clock::now();
+ auto deltaTime = currentTick - lastTick;
+ double deltaTime_s = std::chrono::duration(deltaTime).count();
+ lastTick = currentTick;
+ processInput(window, deltaTime_s);
+ world->logicalTick(deltaTime_s);
+ logicalTickCount++;
+
+ sleepTime = targetDuration - (deltaTime - sleepTime);
+ std::this_thread::sleep_for(sleepTime);
+ }
+ });
+
+ float lastFrame = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
float currentFrame = glfwGetTime();
- deltaTime = currentFrame - lastFrame;
+ float deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
- processInput(window);
- world.tick(deltaTime);
+ world->rendererTick(deltaTime);
projection = camera.getProjectionMatrix();
view = camera.getViewMatrix();
@@ -112,11 +114,24 @@ int MainWindow::exec()
glfwSwapBuffers(window);
glfwPollEvents();
+
+ static float accTime = 0, frameCnt = 0;
+ accTime += deltaTime;
+ frameCnt++;
+ if (accTime > 1.)
+ {
+ std::cout << std::format("{:20}\r", "");
+ std::cout << std::format("FPS: {:.2f} TPS: {:.2f}\r", frameCnt / accTime, logicalTickCount / accTime);
+ accTime = 0;
+ frameCnt = 0;
+ logicalTickCount = 0;
+ }
}
glfwTerminate();
}
-void MainWindow::processInput(GLFWwindow* window)
+
+void MainWindow::processInput(GLFWwindow* window, float deltaTime)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
diff --git a/ToyEngine/src/MainWindow.h b/ToyEngine/src/MainWindow.h
index 7f52f9e..c21422e 100644
--- a/ToyEngine/src/MainWindow.h
+++ b/ToyEngine/src/MainWindow.h
@@ -18,7 +18,7 @@ private:
void framebufferSizeCallback(GLFWwindow* window, int width, int height);
void mouseCallback(GLFWwindow* window, double xpos, double ypos);
void scrollCallback(GLFWwindow* window, double xoffset, double yoffset);
- void processInput(GLFWwindow* window);
+ void processInput(GLFWwindow* window, float deltaTime);
static constexpr int kWindowWidth = 1200;
static constexpr int kWindowHeight = 675;
@@ -27,11 +27,8 @@ private:
Camera camera;
Light light;
- glm::vec3 mainLightRadiance = 40.f * glm::normalize(glm::vec3(0.7529, 0.7450, 0.6784));
- float exposure = 1;
-
- float deltaTime = 0.0f;
- float lastFrame = 0.0f;
+ glm::vec3 mainLightRadiance = 30.f * glm::normalize(glm::vec3(0.7529, 0.7450, 0.6784));
+ float exposure = 0.6f;
std::unique_ptr gl;
diff --git a/ToyEngine/src/Mesh.cpp b/ToyEngine/src/Mesh.cpp
index 5d4b094..8fdadf6 100644
--- a/ToyEngine/src/Mesh.cpp
+++ b/ToyEngine/src/Mesh.cpp
@@ -1,9 +1,9 @@
#include "Mesh.h"
-Vertex::Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVector3D& texCoords)
- : position(position.x, position.y, position.z)
- , normal(normal.x, normal.y, normal.z)
- , texCoords(texCoords.x, texCoords.y)
+Vertex::Vertex(const glm::vec3& position, const glm::vec3& normal, const glm::vec2& texCoords)
+ : position(position)
+ , normal(normal)
+ , texCoords(texCoords)
{
for (std::size_t i = 0; i < kMaxBoneInfluence; i++)
{
@@ -12,6 +12,11 @@ Vertex::Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVec
}
}
+Vertex::Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVector3D& texCoords)
+ : Vertex({position.x, position.y, position.z}, {normal.x, normal.y, normal.z}, {texCoords.x, texCoords.y})
+{
+}
+
void Vertex::setBoneData(int boneID, float weight)
{
if (weight == 0) return;
@@ -43,29 +48,12 @@ void Mesh::draw(Shader& shader)
shader.setUniformValue("baseColor", baseColor);
shader.setUniformValue("metallicRoughness", metallicRoughness);
gl->BindVertexArray(VAO);
- gl->DrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
+ gl->DrawElements(drawMode, indices.size(), GL_UNSIGNED_INT, 0);
gl->BindVertexArray(0);
}
void Mesh::setupMesh()
{
- //for (auto& v : vertices)
- //{
- // if (v.boneIDs[0] == 6 && v.boneIDs[1] == 14 && v.boneIDs[2] == 18 && v.boneIDs[3] == 22)
- // {
- // v.boneIDs[0] = -1;
- // v.boneIDs[1] = -1;
- // v.boneIDs[2] = -1;
- // v.boneIDs[3] = -1;
- // }
- // for (int i = 0; i < kMaxBoneInfluence; i++)
- // {
- // std::cout << v.boneIDs[i] << " ";
- // }
- // std::cout << std::endl;
- //}
-
-
gl->GenVertexArrays(1, &VAO);
gl->GenBuffers(1, &VBO);
gl->GenBuffers(1, &EBO);
@@ -76,7 +64,6 @@ void Mesh::setupMesh()
gl->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
gl->BufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
-
enum VertexAttribute : GLuint {
kPosition = 0, kNormal = 1, kTexCoords = 2, kBoneIDs = 3, kBoneWeights = 4
};
diff --git a/ToyEngine/src/Mesh.h b/ToyEngine/src/Mesh.h
index ae8f9a1..14c9950 100644
--- a/ToyEngine/src/Mesh.h
+++ b/ToyEngine/src/Mesh.h
@@ -16,6 +16,7 @@ struct Vertex {
int boneIDs[kMaxBoneInfluence];
float boneWeights[kMaxBoneInfluence];
+ Vertex(const glm::vec3& position, const glm::vec3& normal, const glm::vec2& texCoords);
Vertex(const aiVector3D& position, const aiVector3D& normal, const aiVector3D& texCoords);
void setBoneData(int boneID, float weight);
};
@@ -25,6 +26,7 @@ public:
glm::mat4 model;
std::vector vertices;
std::vector indices;
+ GLenum drawMode = GL_TRIANGLES;
GLuint textureBasecolor = 0;
GLuint textureMetallicRoughness = 0;
GLuint textureNormal = 0;
@@ -32,12 +34,10 @@ public:
glm::vec2 metallicRoughness;
unsigned int VAO;
- Mesh(GladGLContext* gl, const std::vector& vertices, const std::vector& indices, const glm::mat4& model);
+ Mesh(GladGLContext* gl, const std::vector& vertices, const std::vector& indices, const glm::mat4& model = glm::mat4(1));
void draw(Shader& shader);
void setupMesh();
private:
GladGLContext* gl;
unsigned int VBO, EBO;
-
-
};
\ No newline at end of file
diff --git a/ToyEngine/src/Model.cpp b/ToyEngine/src/Model.cpp
index d420e73..2e4b475 100644
--- a/ToyEngine/src/Model.cpp
+++ b/ToyEngine/src/Model.cpp
@@ -1,13 +1,76 @@
#include "Model.h"
#include
#include
+#include
#include
#include
#include
#include
-Model::Model(GladGLContext* gl, std::string const& path)
+Model Model::createSphere(GladGLContext* gl, const glm::vec3& baseColor, const glm::vec2& metallicRoughness)
+{
+ Model sphere(gl);
+
+ std::vector vertices;
+ std::vector indices;
+
+ constexpr unsigned int kXSegments = 64;
+ constexpr unsigned int kYSegments = 64;
+
+ for (unsigned int x = 0; x <= kXSegments; ++x)
+ {
+ for (unsigned int y = 0; y <= kYSegments; ++y)
+ {
+ float xSegment = (float)x / (float)kXSegments;
+ float ySegment = (float)y / (float)kYSegments;
+
+ constexpr auto PI = glm::pi();
+ float xPos = std::cos(xSegment * 2.0f * PI) * std::sin(ySegment * PI);
+ float yPos = std::cos(ySegment * PI);
+ float zPos = std::sin(xSegment * 2.0f * PI) * std::sin(ySegment * PI);
+
+ vertices.emplace_back(glm::vec3(xPos, yPos, zPos), glm::vec3(xPos, yPos, zPos), glm::vec2(xSegment, ySegment));
+ }
+ }
+
+ bool oddRow = false;
+ for (unsigned int y = 0; y < kYSegments; ++y)
+ {
+ if (!oddRow) // even rows: y == 0, y == 2; and so on
+ {
+ for (unsigned int x = 0; x <= kXSegments; ++x)
+ {
+ indices.push_back(y * (kXSegments + 1) + x);
+ indices.push_back((y + 1) * (kXSegments + 1) + x);
+ }
+ }
+ else
+ {
+ for (int x = kXSegments; x >= 0; --x)
+ {
+ indices.push_back((y + 1) * (kXSegments + 1) + x);
+ indices.push_back(y * (kXSegments + 1) + x);
+ }
+ }
+ oddRow = !oddRow;
+ }
+
+ auto mesh = std::make_unique(gl, vertices, indices);
+ mesh->drawMode = GL_TRIANGLE_STRIP;
+ mesh->baseColor = baseColor;
+ mesh->metallicRoughness = metallicRoughness;
+ sphere.meshes.emplace_back(std::move(mesh));
+
+ return sphere;
+}
+
+Model::Model(GladGLContext* gl)
: gl(gl)
+{
+}
+
+Model::Model(GladGLContext* gl, std::string const& path)
+ : Model(gl)
{
loadModel(path);
}
diff --git a/ToyEngine/src/Model.h b/ToyEngine/src/Model.h
index 8dc91a8..4f8c07f 100644
--- a/ToyEngine/src/Model.h
+++ b/ToyEngine/src/Model.h
@@ -26,6 +26,8 @@ public:
std::map boneInfoMap;
int boneCount = 0;
+ static Model createSphere(GladGLContext* gl, const glm::vec3& baseColor = glm::vec3(0.5, 0, 0), const glm::vec2& metallicRoughness = glm::vec2(0, 0.5));
+ Model(GladGLContext* gl);
Model(GladGLContext* gl, std::string const& path);
void draw(Shader& shader);
void setTransform(const glm::mat4& trans);
diff --git a/ToyEngine/src/Particle.cpp b/ToyEngine/src/Particle.cpp
new file mode 100644
index 0000000..4584769
--- /dev/null
+++ b/ToyEngine/src/Particle.cpp
@@ -0,0 +1,31 @@
+#include "Particle.h"
+
+Particle::Particle(float mass)
+ : Actor()
+ , mass(mass)
+{
+ model = Model::createSphere(gl);
+ setScale(glm::vec3(0.5));
+}
+
+void Particle::logicalTick(float deltaTime)
+{
+ auto pos = getPosition() + speed * deltaTime + 0.5f * resultantForce / mass * deltaTime * deltaTime;
+ speed += resultantForce / mass * deltaTime;
+ if (speed.y < 0 && pos.y < 0.5)
+ {
+ speed.y = -speed.y;
+ }
+ setPosition(pos);
+}
+
+void Particle::addForce(glm::vec3 force)
+{
+ forces.push_back(force);
+ resultantForce += force;
+}
+
+float Particle::getMass()
+{
+ return mass;
+}
diff --git a/ToyEngine/src/Particle.h b/ToyEngine/src/Particle.h
new file mode 100644
index 0000000..1dee2a3
--- /dev/null
+++ b/ToyEngine/src/Particle.h
@@ -0,0 +1,18 @@
+#pragma once
+#include "Actor.h"
+
+class Particle : public Actor
+{
+public:
+ Particle(float mass);
+ virtual ~Particle() = default;
+ virtual void logicalTick(float deltaTime);
+ void addForce(glm::vec3 force);
+ float getMass();
+private:
+ float mass;
+ glm::vec3 speed = glm::vec3(0.f);
+ std::vector forces;
+ glm::vec3 resultantForce = glm::vec3(0);
+};
+
diff --git a/ToyEngine/src/RenderPass.cpp b/ToyEngine/src/RenderPass.cpp
index 4d17a73..8d929ab 100644
--- a/ToyEngine/src/RenderPass.cpp
+++ b/ToyEngine/src/RenderPass.cpp
@@ -73,7 +73,7 @@ void GeometryPass::dispatch()
glm::mat4 trans = glm::mat4(1.0f);
trans = glm::translate(trans, glm::vec3(
(float)(col - (nrColumns / 2)) * spacing,
- (float)(row - (nrRows / 2)) * spacing,
+ (float)(row - (nrRows / 2)) * spacing + 5,
-2.0f
));
plainShader.setUniformValue("model", trans);
diff --git a/ToyEngine/src/World.cpp b/ToyEngine/src/World.cpp
index 72284f3..96b74a7 100644
--- a/ToyEngine/src/World.cpp
+++ b/ToyEngine/src/World.cpp
@@ -1,9 +1,15 @@
#include "World.h"
-void World::tick(float deltaTime)
+void World::logicalTick(float deltaTime)
{
for (auto& actor : actors)
- actor->tick(deltaTime);
+ actor->logicalTick(deltaTime);
+}
+
+void World::rendererTick(float deltaTime)
+{
+ for (auto& actor : actors)
+ actor->rendererTick(deltaTime);
}
void World::draw(Shader& shader)
@@ -28,4 +34,4 @@ std::pair World::getAABB()
maxPos = glm::max(maxPos, max);
}
return { minPos, maxPos };
-}
+}
\ No newline at end of file
diff --git a/ToyEngine/src/World.h b/ToyEngine/src/World.h
index 4dd841e..10b6e26 100644
--- a/ToyEngine/src/World.h
+++ b/ToyEngine/src/World.h
@@ -5,7 +5,8 @@ class World
{
public:
std::vector> actors;
- void tick(float deltaTime);
+ virtual void logicalTick(float deltaTime);
+ virtual void rendererTick(float deltaTime);
void draw(Shader& shader);
void addActor(std::shared_ptr actor);
std::pair getAABB();