优化calculateBoneTransform性能

逻辑与渲染分离
main
wuyize 2023-04-18 14:06:28 +08:00
parent c5f8ce41c7
commit c5b8729ed6
21 changed files with 347 additions and 113 deletions

View File

@ -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;

View File

@ -24,11 +24,13 @@
<ClInclude Include="src\Animator.h" />
<ClInclude Include="src\Bone.h" />
<ClInclude Include="src\Camera.h" />
<ClInclude Include="src\DemoWorld.h" />
<ClInclude Include="src\IblUtils.h" />
<ClInclude Include="src\Light.h" />
<ClInclude Include="src\MainWindow.h" />
<ClInclude Include="src\Mesh.h" />
<ClInclude Include="src\Model.h" />
<ClInclude Include="src\Particle.h" />
<ClInclude Include="src\RenderPass.h" />
<ClInclude Include="src\Shader.h" />
<ClInclude Include="src\World.h" />
@ -39,6 +41,7 @@
<ClCompile Include="src\Animator.cpp" />
<ClCompile Include="src\Bone.cpp" />
<ClCompile Include="src\Camera.cpp" />
<ClCompile Include="src\DemoWorld.cpp" />
<ClCompile Include="src\gl.c" />
<ClCompile Include="src\IblUtils.cpp" />
<ClCompile Include="src\Light.cpp" />
@ -46,6 +49,7 @@
<ClCompile Include="src\MainWindow.cpp" />
<ClCompile Include="src\Mesh.cpp" />
<ClCompile Include="src\Model.cpp" />
<ClCompile Include="src\Particle.cpp" />
<ClCompile Include="src\RenderPass.cpp" />
<ClCompile Include="src\World.cpp" />
</ItemGroup>
@ -163,6 +167,9 @@
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<Optimization>MaxSpeed</Optimization>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

View File

@ -57,6 +57,12 @@
<ClInclude Include="src\World.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\Particle.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\DemoWorld.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\gl.c">
@ -101,6 +107,12 @@
<ClCompile Include="src\World.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\Particle.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\DemoWorld.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="Shaders\brdf_lut.comp">

View File

@ -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<Animation>(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<glm::vec3, glm::vec3> Actor::getAABB()
{
return model.getAABB();

View File

@ -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<glm::vec3, glm::vec3> getAABB();
protected:
GladGLContext* gl;
Model model;
std::unique_ptr<Animation> 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);

View File

@ -7,6 +7,7 @@
#include "Bone.h"
#include "Model.h"
#include <functional>
#include <set>
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<Bone> m_Bones;
float m_Duration = 0.f;
int m_TicksPerSecond = 0;
std::unordered_map<std::string, Bone> m_Bones;
//std::set<Bone> m_Bones;
AssimpNodeData m_RootNode;
std::map<std::string, BoneInfo> m_BoneInfoMap;
};

View File

@ -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(&currentAnimation->GetRootNode(), glm::mat4(1.0f));
calculateBoneTransform(&currentAnimation->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,25 +62,25 @@ 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<glm::mat4> GetFinalBoneMatrices()
std::vector<glm::mat4> getFinalBoneMatrices()
{
return finalBoneMatrices;
}
GLuint getFinalBonesMatricesUBO()
{
if (finalBonesMatricesUBO)
gl->NamedBufferSubData(finalBonesMatricesUBO, 0, finalBoneMatrices.size() * sizeof(finalBoneMatrices[0]), finalBoneMatrices.data());
return finalBonesMatricesUBO;
}
@ -82,7 +88,7 @@ public:
private:
GladGLContext* gl;
std::vector<glm::mat4> finalBoneMatrices;
GLuint finalBonesMatricesUBO;
Animation* currentAnimation;
GLuint finalBonesMatricesUBO = 0;
Animation* currentAnimation = nullptr;
float currentTime;
};

View File

@ -114,6 +114,10 @@ public:
assert(0);
}
bool operator<(const Bone& e) const
{
return m_ID < e.m_ID;
}
private:

View File

@ -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<Actor>(modelFilePath);
actor->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
auto actor2 = std::make_shared<Actor>(modelFilePath);
actor2->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
actor2->setPosition({ 1,0,-1 });
auto actor3 = std::make_shared<Actor>(modelFilePath);
actor3->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
actor3->setPosition({ -1,0,-1 });
auto sponza = std::make_shared<Actor>("Models\\Sponza\\Sponza.gltf");
sponza->setScale(glm::vec3(2));
auto particle = std::make_shared<Particle>(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);
}

View File

@ -0,0 +1,9 @@
#pragma once
#include "World.h"
class DemoWorld : public World
{
public:
DemoWorld();
};

View File

@ -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> world = std::make_unique<DemoWorld>();
auto actor = std::make_shared<Actor>(modelFilePath);
actor->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
auto actor2 = std::make_shared<Actor>(modelFilePath);
actor2->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
actor2->setPosition({ 1,0,-1 });
auto actor3 = std::make_shared<Actor>(modelFilePath);
actor3->setRotaion(glm::angleAxis(glm::radians(-90.f), glm::vec3(1, 0, 0)));
actor3->setPosition({ -1,0,-1 });
auto sponza = std::make_shared<Actor>("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<double>(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);

View File

@ -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<GladGLContext> gl;

View File

@ -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
};

View File

@ -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<Vertex> vertices;
std::vector<unsigned int> 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<Vertex>& vertices, const std::vector<unsigned int>& indices, const glm::mat4& model);
Mesh(GladGLContext* gl, const std::vector<Vertex>& vertices, const std::vector<unsigned int>& indices, const glm::mat4& model = glm::mat4(1));
void draw(Shader& shader);
void setupMesh();
private:
GladGLContext* gl;
unsigned int VBO, EBO;
};

View File

@ -1,13 +1,76 @@
#include "Model.h"
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/ext/scalar_constants.hpp>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stb_image.h>
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<Vertex> vertices;
std::vector<unsigned int> 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>();
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<Mesh>(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);
}

View File

@ -26,6 +26,8 @@ public:
std::map<std::string, BoneInfo> 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);

View File

@ -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;
}

18
ToyEngine/src/Particle.h Normal file
View File

@ -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<glm::vec3> forces;
glm::vec3 resultantForce = glm::vec3(0);
};

View File

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

View File

@ -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)

View File

@ -5,7 +5,8 @@ class World
{
public:
std::vector<std::shared_ptr<Actor>> 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> actor);
std::pair<glm::vec3, glm::vec3> getAABB();