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();