mirror of
https://github.com/JoeyDeVries/LearnOpenGL.git
synced 2026-01-02 04:37:54 +08:00
Add source files for scene (graph + frustum culling) guest article.
This commit is contained in:
479
includes/learnopengl/entity.h
Normal file
479
includes/learnopengl/entity.h
Normal file
@@ -0,0 +1,479 @@
|
|||||||
|
#ifndef ENTITY_H
|
||||||
|
#define ENTITY_H
|
||||||
|
|
||||||
|
#include <glm/glm.hpp> //glm::mat4
|
||||||
|
#include <list> //std::list
|
||||||
|
#include <array> //std::array
|
||||||
|
#include <memory> //std::unique_ptr
|
||||||
|
|
||||||
|
class Transform
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
//Local space information
|
||||||
|
glm::vec3 m_pos = { 0.0f, 0.0f, 0.0f };
|
||||||
|
glm::vec3 m_eulerRot = { 0.0f, 0.0f, 0.0f }; //In degrees
|
||||||
|
glm::vec3 m_scale = { 1.0f, 1.0f, 1.0f };
|
||||||
|
|
||||||
|
//Global space informaiton concatenate in matrix
|
||||||
|
glm::mat4 m_modelMatrix = glm::mat4(1.0f);
|
||||||
|
|
||||||
|
//Dirty flag
|
||||||
|
bool m_isDirty = true;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
glm::mat4 getLocalModelMatrix()
|
||||||
|
{
|
||||||
|
const glm::mat4 transformX = glm::rotate(glm::mat4(1.0f), glm::radians(m_eulerRot.x), glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
const glm::mat4 transformY = glm::rotate(glm::mat4(1.0f), glm::radians(m_eulerRot.y), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
const glm::mat4 transformZ = glm::rotate(glm::mat4(1.0f), glm::radians(m_eulerRot.z), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
|
||||||
|
// Y * X * Z
|
||||||
|
const glm::mat4 roationMatrix = transformY * transformX * transformZ;
|
||||||
|
|
||||||
|
// translation * rotation * scale (also know as TRS matrix)
|
||||||
|
return glm::translate(glm::mat4(1.0f), m_pos) * roationMatrix * glm::scale(glm::mat4(1.0f), m_scale);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
|
||||||
|
void computeModelMatrix()
|
||||||
|
{
|
||||||
|
m_modelMatrix = getLocalModelMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void computeModelMatrix(const glm::mat4& parentGlobalModelMatrix)
|
||||||
|
{
|
||||||
|
m_modelMatrix = parentGlobalModelMatrix * getLocalModelMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLocalPosition(const glm::vec3& newPosition)
|
||||||
|
{
|
||||||
|
m_pos = newPosition;
|
||||||
|
m_isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLocalRotation(const glm::vec3& newRotation)
|
||||||
|
{
|
||||||
|
m_eulerRot = newRotation;
|
||||||
|
m_isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLocalScale(const glm::vec3& newScale)
|
||||||
|
{
|
||||||
|
m_scale = newScale;
|
||||||
|
m_isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3& getGlobalPosition() const
|
||||||
|
{
|
||||||
|
return m_modelMatrix[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3& getLocalPosition() const
|
||||||
|
{
|
||||||
|
return m_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3& getLocalRotation() const
|
||||||
|
{
|
||||||
|
return m_eulerRot;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3& getLocalScale() const
|
||||||
|
{
|
||||||
|
return m_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::mat4& getModelMatrix() const
|
||||||
|
{
|
||||||
|
return m_modelMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 getRight() const
|
||||||
|
{
|
||||||
|
return m_modelMatrix[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
glm::vec3 getUp() const
|
||||||
|
{
|
||||||
|
return m_modelMatrix[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 getBackward() const
|
||||||
|
{
|
||||||
|
return m_modelMatrix[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 getForward() const
|
||||||
|
{
|
||||||
|
return -m_modelMatrix[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 getGlobalScale() const
|
||||||
|
{
|
||||||
|
return { glm::length(getRight()), glm::length(getUp()), glm::length(getBackward()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDirty() const
|
||||||
|
{
|
||||||
|
return m_isDirty;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Plan
|
||||||
|
{
|
||||||
|
glm::vec3 normal = { 0.f, 1.f, 0.f }; // unit vector
|
||||||
|
float distance = 0.f; // Distance with origin
|
||||||
|
|
||||||
|
Plan() = default;
|
||||||
|
|
||||||
|
Plan(const glm::vec3& p1, const glm::vec3& norm)
|
||||||
|
: normal(glm::normalize(norm)),
|
||||||
|
distance(glm::dot(normal, p1))
|
||||||
|
{}
|
||||||
|
|
||||||
|
float getSignedDistanceToPlan(const glm::vec3& point) const
|
||||||
|
{
|
||||||
|
return glm::dot(normal, point) - distance;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Frustum
|
||||||
|
{
|
||||||
|
Plan topFace;
|
||||||
|
Plan bottomFace;
|
||||||
|
|
||||||
|
Plan rightFace;
|
||||||
|
Plan leftFace;
|
||||||
|
|
||||||
|
Plan farFace;
|
||||||
|
Plan nearFace;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BoundingVolume
|
||||||
|
{
|
||||||
|
virtual bool isOnFrustum(const Frustum& camFrustum, const Transform& transform) const = 0;
|
||||||
|
|
||||||
|
virtual bool isOnOrForwardPlan(const Plan& plan) const = 0;
|
||||||
|
|
||||||
|
bool isOnFrustum(const Frustum& camFrustum) const
|
||||||
|
{
|
||||||
|
return (isOnOrForwardPlan(camFrustum.leftFace) &&
|
||||||
|
isOnOrForwardPlan(camFrustum.rightFace) &&
|
||||||
|
isOnOrForwardPlan(camFrustum.topFace) &&
|
||||||
|
isOnOrForwardPlan(camFrustum.bottomFace) &&
|
||||||
|
isOnOrForwardPlan(camFrustum.nearFace) &&
|
||||||
|
isOnOrForwardPlan(camFrustum.farFace));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sphere : public BoundingVolume
|
||||||
|
{
|
||||||
|
glm::vec3 center{ 0.f, 0.f, 0.f };
|
||||||
|
float radius{ 0.f };
|
||||||
|
|
||||||
|
Sphere(const glm::vec3& inCenter, float inRadius)
|
||||||
|
: BoundingVolume{}, center{ inCenter }, radius{ inRadius }
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool isOnOrForwardPlan(const Plan& plan) const final
|
||||||
|
{
|
||||||
|
return plan.getSignedDistanceToPlan(center) > -radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOnFrustum(const Frustum& camFrustum, const Transform& transform) const final
|
||||||
|
{
|
||||||
|
//Get global scale thanks to our transform
|
||||||
|
const glm::vec3 globalScale = transform.getGlobalScale();
|
||||||
|
|
||||||
|
//Get our global center with process it with the global model matrix of our transform
|
||||||
|
const glm::vec3 globalCenter{ transform.getModelMatrix() * glm::vec4(center, 1.f) };
|
||||||
|
|
||||||
|
//To wrap correctly our shape, we need the maximum scale scalar.
|
||||||
|
const float maxScale = std::max(std::max(globalScale.x, globalScale.y), globalScale.z);
|
||||||
|
|
||||||
|
//Max scale is assuming for the diameter. So, we need the half to apply it to our radius
|
||||||
|
Sphere globalSphere(globalCenter, radius * (maxScale * 0.5f));
|
||||||
|
|
||||||
|
//Check Firstly the result that have the most chance to faillure to avoid to call all functions.
|
||||||
|
return (globalSphere.isOnOrForwardPlan(camFrustum.leftFace) &&
|
||||||
|
globalSphere.isOnOrForwardPlan(camFrustum.rightFace) &&
|
||||||
|
globalSphere.isOnOrForwardPlan(camFrustum.farFace) &&
|
||||||
|
globalSphere.isOnOrForwardPlan(camFrustum.nearFace) &&
|
||||||
|
globalSphere.isOnOrForwardPlan(camFrustum.topFace) &&
|
||||||
|
globalSphere.isOnOrForwardPlan(camFrustum.bottomFace));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SquareAABB : public BoundingVolume
|
||||||
|
{
|
||||||
|
glm::vec3 center{ 0.f, 0.f, 0.f };
|
||||||
|
float extent{ 0.f };
|
||||||
|
|
||||||
|
SquareAABB(const glm::vec3& inCenter, float inExtent)
|
||||||
|
: BoundingVolume{}, center{ inCenter }, extent{ inExtent }
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool isOnOrForwardPlan(const Plan& plan) const final
|
||||||
|
{
|
||||||
|
// Compute the projection interval radius of b onto L(t) = b.c + t * p.n
|
||||||
|
const float r = extent * (std::abs(plan.normal.x) + std::abs(plan.normal.y) + std::abs(plan.normal.z));
|
||||||
|
return -r <= plan.getSignedDistanceToPlan(center);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOnFrustum(const Frustum& camFrustum, const Transform& transform) const final
|
||||||
|
{
|
||||||
|
//Get global scale thanks to our transform
|
||||||
|
const glm::vec3 globalCenter{ transform.getModelMatrix() * glm::vec4(center, 1.f) };
|
||||||
|
|
||||||
|
// Scaled orientation
|
||||||
|
const glm::vec3 right = transform.getRight() * extent;
|
||||||
|
const glm::vec3 up = transform.getUp() * extent;
|
||||||
|
const glm::vec3 forward = transform.getForward() * extent;
|
||||||
|
|
||||||
|
const float newIi = std::abs(glm::dot(glm::vec3{ 1.f, 0.f, 0.f }, right)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 1.f, 0.f, 0.f }, up)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 1.f, 0.f, 0.f }, forward));
|
||||||
|
|
||||||
|
const float newIj = std::abs(glm::dot(glm::vec3{ 0.f, 1.f, 0.f }, right)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 1.f, 0.f }, up)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 1.f, 0.f }, forward));
|
||||||
|
|
||||||
|
const float newIk = std::abs(glm::dot(glm::vec3{ 0.f, 0.f, 1.f }, right)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 0.f, 1.f }, up)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 0.f, 1.f }, forward));
|
||||||
|
|
||||||
|
const SquareAABB globalAABB(globalCenter, std::max(std::max(newIi, newIj), newIk));
|
||||||
|
|
||||||
|
return (globalAABB.isOnOrForwardPlan(camFrustum.leftFace) &&
|
||||||
|
globalAABB.isOnOrForwardPlan(camFrustum.rightFace) &&
|
||||||
|
globalAABB.isOnOrForwardPlan(camFrustum.topFace) &&
|
||||||
|
globalAABB.isOnOrForwardPlan(camFrustum.bottomFace) &&
|
||||||
|
globalAABB.isOnOrForwardPlan(camFrustum.nearFace) &&
|
||||||
|
globalAABB.isOnOrForwardPlan(camFrustum.farFace));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AABB : public BoundingVolume
|
||||||
|
{
|
||||||
|
glm::vec3 center{ 0.f, 0.f, 0.f };
|
||||||
|
glm::vec3 extents{ 0.f, 0.f, 0.f };
|
||||||
|
|
||||||
|
AABB(const glm::vec3& min, const glm::vec3& max)
|
||||||
|
: BoundingVolume{}, center{ (max + min) * 0.5f }, extents{ max.x - center.x, max.y - center.y, max.z - center.z }
|
||||||
|
{}
|
||||||
|
|
||||||
|
AABB(const glm::vec3& inCenter, float iI, float iJ, float iK)
|
||||||
|
: BoundingVolume{}, center{ inCenter }, extents{ iI, iJ, iK }
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::array<glm::vec3, 8> getVertice() const
|
||||||
|
{
|
||||||
|
std::array<glm::vec3, 8> vertice;
|
||||||
|
vertice[0] = { center.x - extents.x, center.y - extents.y, center.z - extents.z };
|
||||||
|
vertice[1] = { center.x + extents.x, center.y - extents.y, center.z - extents.z };
|
||||||
|
vertice[2] = { center.x - extents.x, center.y + extents.y, center.z - extents.z };
|
||||||
|
vertice[3] = { center.x + extents.x, center.y + extents.y, center.z - extents.z };
|
||||||
|
vertice[4] = { center.x - extents.x, center.y - extents.y, center.z + extents.z };
|
||||||
|
vertice[5] = { center.x + extents.x, center.y - extents.y, center.z + extents.z };
|
||||||
|
vertice[6] = { center.x - extents.x, center.y + extents.y, center.z + extents.z };
|
||||||
|
vertice[7] = { center.x + extents.x, center.y + extents.y, center.z + extents.z };
|
||||||
|
return vertice;
|
||||||
|
}
|
||||||
|
|
||||||
|
//see https://gdbooks.gitbooks.io/3dcollisions/content/Chapter2/static_aabb_plan.html
|
||||||
|
bool isOnOrForwardPlan(const Plan& plan) const final
|
||||||
|
{
|
||||||
|
// Compute the projection interval radius of b onto L(t) = b.c + t * p.n
|
||||||
|
const float r = extents.x * std::abs(plan.normal.x) + extents.y * std::abs(plan.normal.y) +
|
||||||
|
extents.z * std::abs(plan.normal.z);
|
||||||
|
|
||||||
|
return -r <= plan.getSignedDistanceToPlan(center);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOnFrustum(const Frustum& camFrustum, const Transform& transform) const final
|
||||||
|
{
|
||||||
|
//Get global scale thanks to our transform
|
||||||
|
const glm::vec3 globalCenter{ transform.getModelMatrix() * glm::vec4(center, 1.f) };
|
||||||
|
|
||||||
|
// Scaled orientation
|
||||||
|
const glm::vec3 right = transform.getRight() * extents.x;
|
||||||
|
const glm::vec3 up = transform.getUp() * extents.y;
|
||||||
|
const glm::vec3 forward = transform.getForward() * extents.z;
|
||||||
|
|
||||||
|
const float newIi = std::abs(glm::dot(glm::vec3{ 1.f, 0.f, 0.f }, right)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 1.f, 0.f, 0.f }, up)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 1.f, 0.f, 0.f }, forward));
|
||||||
|
|
||||||
|
const float newIj = std::abs(glm::dot(glm::vec3{ 0.f, 1.f, 0.f }, right)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 1.f, 0.f }, up)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 1.f, 0.f }, forward));
|
||||||
|
|
||||||
|
const float newIk = std::abs(glm::dot(glm::vec3{ 0.f, 0.f, 1.f }, right)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 0.f, 1.f }, up)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 0.f, 1.f }, forward));
|
||||||
|
|
||||||
|
const AABB globalAABB(globalCenter, newIi, newIj, newIk);
|
||||||
|
|
||||||
|
return (globalAABB.isOnOrForwardPlan(camFrustum.leftFace) &&
|
||||||
|
globalAABB.isOnOrForwardPlan(camFrustum.rightFace) &&
|
||||||
|
globalAABB.isOnOrForwardPlan(camFrustum.topFace) &&
|
||||||
|
globalAABB.isOnOrForwardPlan(camFrustum.bottomFace) &&
|
||||||
|
globalAABB.isOnOrForwardPlan(camFrustum.nearFace) &&
|
||||||
|
globalAABB.isOnOrForwardPlan(camFrustum.farFace));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Frustum createFrustumFromCamera(const Camera& cam, float aspect, float fovY, float zNear, float zFar)
|
||||||
|
{
|
||||||
|
Frustum frustum;
|
||||||
|
const float halfVSide = zFar * tanf(fovY * .5f);
|
||||||
|
const float halfHSide = halfVSide * aspect;
|
||||||
|
const glm::vec3 frontMultFar = zFar * cam.Front;
|
||||||
|
|
||||||
|
frustum.nearFace = { cam.Position + zNear * cam.Front, cam.Front };
|
||||||
|
frustum.farFace = { cam.Position + frontMultFar, -cam.Front };
|
||||||
|
frustum.rightFace = { cam.Position, glm::cross(cam.Up, frontMultFar + cam.Right * halfHSide) };
|
||||||
|
frustum.leftFace = { cam.Position, glm::cross(frontMultFar - cam.Right * halfHSide, cam.Up) };
|
||||||
|
frustum.topFace = { cam.Position, glm::cross(cam.Right, frontMultFar - cam.Up * halfVSide) };
|
||||||
|
frustum.bottomFace = { cam.Position, glm::cross(frontMultFar + cam.Up * halfVSide, cam.Right) };
|
||||||
|
|
||||||
|
return frustum;
|
||||||
|
}
|
||||||
|
|
||||||
|
AABB generateAABB(const Model& model)
|
||||||
|
{
|
||||||
|
glm::vec3 minAABB = glm::vec3(std::numeric_limits<float>::max());
|
||||||
|
glm::vec3 maxAABB = glm::vec3(std::numeric_limits<float>::min());
|
||||||
|
for (auto&& mesh : model.meshes)
|
||||||
|
{
|
||||||
|
for (auto&& vertex : mesh.vertices)
|
||||||
|
{
|
||||||
|
minAABB.x = std::min(minAABB.x, vertex.Position.x);
|
||||||
|
minAABB.y = std::min(minAABB.y, vertex.Position.y);
|
||||||
|
minAABB.z = std::min(minAABB.z, vertex.Position.z);
|
||||||
|
|
||||||
|
maxAABB.x = std::max(maxAABB.x, vertex.Position.x);
|
||||||
|
maxAABB.y = std::max(maxAABB.y, vertex.Position.y);
|
||||||
|
maxAABB.z = std::max(maxAABB.z, vertex.Position.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AABB(minAABB, maxAABB);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sphere generateSphereBV(const Model& model)
|
||||||
|
{
|
||||||
|
glm::vec3 minAABB = glm::vec3(std::numeric_limits<float>::max());
|
||||||
|
glm::vec3 maxAABB = glm::vec3(std::numeric_limits<float>::min());
|
||||||
|
for (auto&& mesh : model.meshes)
|
||||||
|
{
|
||||||
|
for (auto&& vertex : mesh.vertices)
|
||||||
|
{
|
||||||
|
minAABB.x = std::min(minAABB.x, vertex.Position.x);
|
||||||
|
minAABB.y = std::min(minAABB.y, vertex.Position.y);
|
||||||
|
minAABB.z = std::min(minAABB.z, vertex.Position.z);
|
||||||
|
|
||||||
|
maxAABB.x = std::max(maxAABB.x, vertex.Position.x);
|
||||||
|
maxAABB.y = std::max(maxAABB.y, vertex.Position.y);
|
||||||
|
maxAABB.z = std::max(maxAABB.z, vertex.Position.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Sphere((maxAABB + minAABB) * 0.5f, glm::length(minAABB - maxAABB));
|
||||||
|
}
|
||||||
|
|
||||||
|
class Entity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Scene graph
|
||||||
|
std::list<std::unique_ptr<Entity>> children;
|
||||||
|
Entity* parent = nullptr;
|
||||||
|
|
||||||
|
//Space information
|
||||||
|
Transform transform;
|
||||||
|
|
||||||
|
Model* pModel = nullptr;
|
||||||
|
std::unique_ptr<AABB> boundingVolume;
|
||||||
|
|
||||||
|
|
||||||
|
// constructor, expects a filepath to a 3D model.
|
||||||
|
Entity(Model& model) : pModel{ &model }
|
||||||
|
{
|
||||||
|
boundingVolume = std::make_unique<AABB>(generateAABB(model));
|
||||||
|
//boundingVolume = std::make_unique<Sphere>(generateSphereBV(model));
|
||||||
|
}
|
||||||
|
|
||||||
|
AABB getGlobalAABB()
|
||||||
|
{
|
||||||
|
//Get global scale thanks to our transform
|
||||||
|
const glm::vec3 globalCenter{ transform.getModelMatrix() * glm::vec4(boundingVolume->center, 1.f) };
|
||||||
|
|
||||||
|
// Scaled orientation
|
||||||
|
const glm::vec3 right = transform.getRight() * boundingVolume->extents.x;
|
||||||
|
const glm::vec3 up = transform.getUp() * boundingVolume->extents.y;
|
||||||
|
const glm::vec3 forward = transform.getForward() * boundingVolume->extents.z;
|
||||||
|
|
||||||
|
const float newIi = std::abs(glm::dot(glm::vec3{ 1.f, 0.f, 0.f }, right)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 1.f, 0.f, 0.f }, up)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 1.f, 0.f, 0.f }, forward));
|
||||||
|
|
||||||
|
const float newIj = std::abs(glm::dot(glm::vec3{ 0.f, 1.f, 0.f }, right)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 1.f, 0.f }, up)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 1.f, 0.f }, forward));
|
||||||
|
|
||||||
|
const float newIk = std::abs(glm::dot(glm::vec3{ 0.f, 0.f, 1.f }, right)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 0.f, 1.f }, up)) +
|
||||||
|
std::abs(glm::dot(glm::vec3{ 0.f, 0.f, 1.f }, forward));
|
||||||
|
|
||||||
|
return AABB(globalCenter, newIi, newIj, newIk);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add child. Argument input is argument of any constructor that you create. By default you can use the default constructor and don't put argument input.
|
||||||
|
template<typename... TArgs>
|
||||||
|
void addChild(TArgs&... args)
|
||||||
|
{
|
||||||
|
children.emplace_back(std::make_unique<Entity>(args...));
|
||||||
|
children.back()->parent = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Update transform if it was changed
|
||||||
|
void updateSelfAndChild()
|
||||||
|
{
|
||||||
|
if (!transform.isDirty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
forceUpdateSelfAndChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Force update of transform even if local space don't change
|
||||||
|
void forceUpdateSelfAndChild()
|
||||||
|
{
|
||||||
|
if (parent)
|
||||||
|
transform.computeModelMatrix(parent->transform.getModelMatrix());
|
||||||
|
else
|
||||||
|
transform.computeModelMatrix();
|
||||||
|
|
||||||
|
for (auto&& child : children)
|
||||||
|
{
|
||||||
|
child->forceUpdateSelfAndChild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void drawSelfAndChild(const Frustum& frustum, Shader& ourShader, unsigned int& display, unsigned int& total)
|
||||||
|
{
|
||||||
|
if (boundingVolume->isOnFrustum(frustum, transform))
|
||||||
|
{
|
||||||
|
ourShader.setMat4("model", transform.getModelMatrix());
|
||||||
|
pModel->Draw(ourShader);
|
||||||
|
display++;
|
||||||
|
}
|
||||||
|
total++;
|
||||||
|
|
||||||
|
for (auto&& child : children)
|
||||||
|
{
|
||||||
|
child->drawSelfAndChild(frustum, ourShader, display, total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
11
src/8.guest/2021/1.scene/1.scene_graph/1.model_loading.fs
Normal file
11
src/8.guest/2021/1.scene/1.scene_graph/1.model_loading.fs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#version 330 core
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec2 TexCoords;
|
||||||
|
|
||||||
|
uniform sampler2D texture_diffuse1;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = texture(texture_diffuse1, TexCoords);
|
||||||
|
}
|
||||||
16
src/8.guest/2021/1.scene/1.scene_graph/1.model_loading.vs
Normal file
16
src/8.guest/2021/1.scene/1.scene_graph/1.model_loading.vs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec3 aNormal;
|
||||||
|
layout (location = 2) in vec2 aTexCoords;
|
||||||
|
|
||||||
|
out vec2 TexCoords;
|
||||||
|
|
||||||
|
uniform mat4 model;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
TexCoords = aTexCoords;
|
||||||
|
gl_Position = projection * view * model * vec4(aPos, 1.0);
|
||||||
|
}
|
||||||
227
src/8.guest/2021/1.scene/1.scene_graph/scene_graph.cpp
Normal file
227
src/8.guest/2021/1.scene/1.scene_graph/scene_graph.cpp
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
#include <glad/glad.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
#include <learnopengl/filesystem.h>
|
||||||
|
#include <learnopengl/shader_m.h>
|
||||||
|
#include <learnopengl/camera.h>
|
||||||
|
#include <learnopengl/model.h>
|
||||||
|
#include <learnopengl/entity.h>
|
||||||
|
|
||||||
|
#ifndef ENTITY_H
|
||||||
|
#define ENTITY_H
|
||||||
|
|
||||||
|
#include <list> //std::list
|
||||||
|
#include <memory> //std::unique_ptr
|
||||||
|
|
||||||
|
class Entity : public Model
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
list<unique_ptr<Entity>> children;
|
||||||
|
Entity* parent;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||||
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||||
|
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||||
|
void processInput(GLFWwindow* window);
|
||||||
|
|
||||||
|
// settings
|
||||||
|
const unsigned int SCR_WIDTH = 800;
|
||||||
|
const unsigned int SCR_HEIGHT = 600;
|
||||||
|
|
||||||
|
// camera
|
||||||
|
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
|
||||||
|
float lastX = SCR_WIDTH / 2.0f;
|
||||||
|
float lastY = SCR_HEIGHT / 2.0f;
|
||||||
|
bool firstMouse = true;
|
||||||
|
|
||||||
|
// timing
|
||||||
|
float deltaTime = 0.0f;
|
||||||
|
float lastFrame = 0.0f;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// glfw: initialize and configure
|
||||||
|
// ------------------------------
|
||||||
|
glfwInit();
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// glfw window creation
|
||||||
|
// --------------------
|
||||||
|
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
|
||||||
|
if (window == NULL)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to create GLFW window" << std::endl;
|
||||||
|
glfwTerminate();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||||
|
glfwSetCursorPosCallback(window, mouse_callback);
|
||||||
|
glfwSetScrollCallback(window, scroll_callback);
|
||||||
|
|
||||||
|
// tell GLFW to capture our mouse
|
||||||
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
|
||||||
|
// glad: load all OpenGL function pointers
|
||||||
|
// ---------------------------------------
|
||||||
|
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||||
|
{
|
||||||
|
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tell stb_image.h to flip loaded texture's on the y-axis (before loading model).
|
||||||
|
stbi_set_flip_vertically_on_load(true);
|
||||||
|
|
||||||
|
// configure global opengl state
|
||||||
|
// -----------------------------
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
// build and compile shaders
|
||||||
|
// -------------------------
|
||||||
|
Shader ourShader("1.model_loading.vs", "1.model_loading.fs");
|
||||||
|
|
||||||
|
// load entities
|
||||||
|
// -----------
|
||||||
|
Entity ourEntity(FileSystem::getPath("resources/objects/planet/planet.obj"));
|
||||||
|
ourEntity.transform.setLocalPosition({ 10, 0, 0 });
|
||||||
|
const float scale = 0.75;
|
||||||
|
ourEntity.transform.setLocalScale({ scale, scale, scale });
|
||||||
|
|
||||||
|
{
|
||||||
|
Entity* lastEntity = &ourEntity;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < 10; ++i)
|
||||||
|
{
|
||||||
|
lastEntity->addChild(FileSystem::getPath("resources/objects/planet/planet.obj"));
|
||||||
|
lastEntity = lastEntity->children.back().get();
|
||||||
|
|
||||||
|
//Set tranform values
|
||||||
|
lastEntity->transform.setLocalPosition({ 10, 0, 0 });
|
||||||
|
lastEntity->transform.setLocalScale({ scale, scale, scale });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ourEntity.updateSelfAndChild();
|
||||||
|
|
||||||
|
// draw in wireframe
|
||||||
|
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
|
||||||
|
// render loop
|
||||||
|
// -----------
|
||||||
|
while (!glfwWindowShouldClose(window))
|
||||||
|
{
|
||||||
|
// per-frame time logic
|
||||||
|
// --------------------
|
||||||
|
float currentFrame = glfwGetTime();
|
||||||
|
deltaTime = currentFrame - lastFrame;
|
||||||
|
lastFrame = currentFrame;
|
||||||
|
|
||||||
|
// input
|
||||||
|
// -----
|
||||||
|
processInput(window);
|
||||||
|
|
||||||
|
// render
|
||||||
|
// ------
|
||||||
|
glClearColor(0.05f, 0.05f, 0.05f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// don't forget to enable shader before setting uniforms
|
||||||
|
ourShader.use();
|
||||||
|
|
||||||
|
// view/projection transformations
|
||||||
|
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
|
||||||
|
glm::mat4 view = camera.GetViewMatrix();
|
||||||
|
ourShader.setMat4("projection", projection);
|
||||||
|
ourShader.setMat4("view", view);
|
||||||
|
|
||||||
|
// draw our scene graph
|
||||||
|
Entity* lastEntity = &ourEntity;
|
||||||
|
while (lastEntity->children.size())
|
||||||
|
{
|
||||||
|
ourShader.setMat4("model", lastEntity->transform.getModelMatrix());
|
||||||
|
lastEntity->Draw(ourShader);
|
||||||
|
lastEntity = lastEntity->children.back().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
ourEntity.transform.setLocalRotation({ 0.f, ourEntity.transform.getLocalRotation().y + 20 * deltaTime, 0.f });
|
||||||
|
ourEntity.updateSelfAndChild();
|
||||||
|
|
||||||
|
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
|
||||||
|
// -------------------------------------------------------------------------------
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
// glfw: terminate, clearing all previously allocated GLFW resources.
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
glfwTerminate();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
|
||||||
|
// ---------------------------------------------------------------------------------------------------------
|
||||||
|
void processInput(GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||||
|
glfwSetWindowShouldClose(window, true);
|
||||||
|
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||||
|
camera.ProcessKeyboard(FORWARD, deltaTime);
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||||
|
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
||||||
|
camera.ProcessKeyboard(LEFT, deltaTime);
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
|
||||||
|
camera.ProcessKeyboard(RIGHT, deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||||
|
{
|
||||||
|
// make sure the viewport matches the new window dimensions; note that width and
|
||||||
|
// height will be significantly larger than specified on retina displays.
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// glfw: whenever the mouse moves, this callback is called
|
||||||
|
// -------------------------------------------------------
|
||||||
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||||
|
{
|
||||||
|
if (firstMouse)
|
||||||
|
{
|
||||||
|
lastX = xpos;
|
||||||
|
lastY = ypos;
|
||||||
|
firstMouse = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float xoffset = xpos - lastX;
|
||||||
|
float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
|
||||||
|
|
||||||
|
lastX = xpos;
|
||||||
|
lastY = ypos;
|
||||||
|
|
||||||
|
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||||
|
{
|
||||||
|
camera.ProcessMouseScroll(yoffset);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#version 330 core
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec2 TexCoords;
|
||||||
|
|
||||||
|
uniform sampler2D texture_diffuse1;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = texture(texture_diffuse1, TexCoords);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec3 aNormal;
|
||||||
|
layout (location = 2) in vec2 aTexCoords;
|
||||||
|
|
||||||
|
out vec2 TexCoords;
|
||||||
|
|
||||||
|
uniform mat4 model;
|
||||||
|
uniform mat4 view;
|
||||||
|
uniform mat4 projection;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
TexCoords = aTexCoords;
|
||||||
|
gl_Position = projection * view * model * vec4(aPos, 1.0);
|
||||||
|
}
|
||||||
236
src/8.guest/2021/1.scene/2.frustum_culling/frustum_culling.cpp
Normal file
236
src/8.guest/2021/1.scene/2.frustum_culling/frustum_culling.cpp
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
#include <glad/glad.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
#include <learnopengl/filesystem.h>
|
||||||
|
#include <learnopengl/shader_m.h>
|
||||||
|
#include <learnopengl/camera.h>
|
||||||
|
#include <learnopengl/model.h>
|
||||||
|
#include <learnopengl/entity.h>
|
||||||
|
|
||||||
|
#ifndef ENTITY_H
|
||||||
|
#define ENTITY_H
|
||||||
|
|
||||||
|
#include <list> //std::list
|
||||||
|
#include <memory> //std::unique_ptr
|
||||||
|
|
||||||
|
class Entity : public Model
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
list<unique_ptr<Entity>> children;
|
||||||
|
Entity* parent;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||||
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||||
|
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
|
||||||
|
void processInput(GLFWwindow* window);
|
||||||
|
|
||||||
|
// settings
|
||||||
|
const unsigned int SCR_WIDTH = 800;
|
||||||
|
const unsigned int SCR_HEIGHT = 600;
|
||||||
|
|
||||||
|
// camera
|
||||||
|
Camera camera(glm::vec3(0.0f, 10.0f, 0.0f));
|
||||||
|
Camera cameraSpy(glm::vec3(0.0f, 10.0f, 0.f));
|
||||||
|
float lastX = SCR_WIDTH / 2.0f;
|
||||||
|
float lastY = SCR_HEIGHT / 2.0f;
|
||||||
|
bool firstMouse = true;
|
||||||
|
|
||||||
|
// timing
|
||||||
|
float deltaTime = 0.0f;
|
||||||
|
float lastFrame = 0.0f;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// glfw: initialize and configure
|
||||||
|
// ------------------------------
|
||||||
|
glfwInit();
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// glfw window creation
|
||||||
|
// --------------------
|
||||||
|
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
|
||||||
|
if (window == NULL)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to create GLFW window" << std::endl;
|
||||||
|
glfwTerminate();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||||
|
glfwSetCursorPosCallback(window, mouse_callback);
|
||||||
|
glfwSetScrollCallback(window, scroll_callback);
|
||||||
|
|
||||||
|
// tell GLFW to capture our mouse
|
||||||
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||||
|
|
||||||
|
// glad: load all OpenGL function pointers
|
||||||
|
// ---------------------------------------
|
||||||
|
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||||
|
{
|
||||||
|
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tell stb_image.h to flip loaded texture's on the y-axis (before loading model).
|
||||||
|
stbi_set_flip_vertically_on_load(true);
|
||||||
|
|
||||||
|
// configure global opengl state
|
||||||
|
// -----------------------------
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
camera.MovementSpeed = 20.f;
|
||||||
|
|
||||||
|
// build and compile shaders
|
||||||
|
// -------------------------
|
||||||
|
Shader ourShader("1.model_loading.vs", "1.model_loading.fs");
|
||||||
|
|
||||||
|
// load entities
|
||||||
|
// -----------
|
||||||
|
Model model(FileSystem::getPath("resources/objects/planet/planet.obj"));
|
||||||
|
Entity ourEntity(model);
|
||||||
|
ourEntity.transform.setLocalPosition({ 0, 0, 0 });
|
||||||
|
const float scale = 1.0;
|
||||||
|
ourEntity.transform.setLocalScale({ scale, scale, scale });
|
||||||
|
|
||||||
|
{
|
||||||
|
Entity* lastEntity = &ourEntity;
|
||||||
|
|
||||||
|
for (unsigned int x = 0; x < 20; ++x)
|
||||||
|
{
|
||||||
|
for (unsigned int z = 0; z < 20; ++z)
|
||||||
|
{
|
||||||
|
ourEntity.addChild(model);
|
||||||
|
lastEntity = ourEntity.children.back().get();
|
||||||
|
|
||||||
|
//Set tranform values
|
||||||
|
lastEntity->transform.setLocalPosition({ x * 10.f - 100.f, 0.f, z * 10.f - 100.f });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ourEntity.updateSelfAndChild();
|
||||||
|
|
||||||
|
// draw in wireframe
|
||||||
|
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
|
||||||
|
// render loop
|
||||||
|
// -----------
|
||||||
|
while (!glfwWindowShouldClose(window))
|
||||||
|
{
|
||||||
|
// per-frame time logic
|
||||||
|
// --------------------
|
||||||
|
float currentFrame = glfwGetTime();
|
||||||
|
deltaTime = currentFrame - lastFrame;
|
||||||
|
lastFrame = currentFrame;
|
||||||
|
|
||||||
|
// input
|
||||||
|
// -----
|
||||||
|
processInput(window);
|
||||||
|
|
||||||
|
// render
|
||||||
|
// ------
|
||||||
|
glClearColor(0.05f, 0.05f, 0.05f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// don't forget to enable shader before setting uniforms
|
||||||
|
ourShader.use();
|
||||||
|
|
||||||
|
// view/projection transformations
|
||||||
|
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
|
||||||
|
const Frustum camFrustum = createFrustumFromCamera(camera, (float)SCR_WIDTH / (float)SCR_HEIGHT, glm::radians(camera.Zoom), 0.1f, 100.0f);
|
||||||
|
|
||||||
|
cameraSpy.ProcessMouseMovement(2, 0);
|
||||||
|
//static float acc = 0;
|
||||||
|
//acc += deltaTime * 0.0001;
|
||||||
|
//cameraSpy.Position = { cos(acc) * 10, 0.f, sin(acc) * 10 };
|
||||||
|
glm::mat4 view = camera.GetViewMatrix();
|
||||||
|
|
||||||
|
ourShader.setMat4("projection", projection);
|
||||||
|
ourShader.setMat4("view", view);
|
||||||
|
|
||||||
|
// draw our scene graph
|
||||||
|
unsigned int total = 0, display = 0;
|
||||||
|
ourEntity.drawSelfAndChild(camFrustum, ourShader, display, total);
|
||||||
|
std::cout << "Total process in CPU : " << total << " / Total send to GPU : " << display << std::endl;
|
||||||
|
|
||||||
|
//ourEntity.transform.setLocalRotation({ 0.f, ourEntity.transform.getLocalRotation().y + 20 * deltaTime, 0.f });
|
||||||
|
ourEntity.updateSelfAndChild();
|
||||||
|
|
||||||
|
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
|
||||||
|
// -------------------------------------------------------------------------------
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
// glfw: terminate, clearing all previously allocated GLFW resources.
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
glfwTerminate();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
|
||||||
|
// ---------------------------------------------------------------------------------------------------------
|
||||||
|
void processInput(GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||||
|
glfwSetWindowShouldClose(window, true);
|
||||||
|
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
||||||
|
camera.ProcessKeyboard(FORWARD, deltaTime);
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
||||||
|
camera.ProcessKeyboard(BACKWARD, deltaTime);
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
||||||
|
camera.ProcessKeyboard(LEFT, deltaTime);
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
|
||||||
|
camera.ProcessKeyboard(RIGHT, deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||||
|
{
|
||||||
|
// make sure the viewport matches the new window dimensions; note that width and
|
||||||
|
// height will be significantly larger than specified on retina displays.
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// glfw: whenever the mouse moves, this callback is called
|
||||||
|
// -------------------------------------------------------
|
||||||
|
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
|
||||||
|
{
|
||||||
|
if (firstMouse)
|
||||||
|
{
|
||||||
|
lastX = xpos;
|
||||||
|
lastY = ypos;
|
||||||
|
firstMouse = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float xoffset = xpos - lastX;
|
||||||
|
float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
|
||||||
|
|
||||||
|
lastX = xpos;
|
||||||
|
lastY = ypos;
|
||||||
|
|
||||||
|
camera.ProcessMouseMovement(xoffset, yoffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||||
|
{
|
||||||
|
camera.ProcessMouseScroll(yoffset);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user