Skip to content
This repository was archived by the owner on Jun 11, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ cppcheck:
$(shell cppcheck --version | grep -qP '2\.(1[1-8]|1\d{2,}|[2-9]\d+)|[3-9]+\.'; echo $$?))
cppcheck \
--enable=all \
--inline-suppr \
--suppress=missingIncludeSystem --suppress=unusedFunction --suppress=unmatchedSuppression \
--library=opengl --library=posix --library=tinyxml2 \
$$([ $(CPPCHECK_EXHAUSTIVE_SUPPORT) -eq 0 ] && echo "--check-level=exhaustive") \
Expand Down
39 changes: 28 additions & 11 deletions include/engine/camera/Camera.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@

#pragma once

#include <array>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>

#include "engine/render/BoundingSphere.hpp"

namespace engine::camera {

enum class MovementDirection {
Expand All @@ -39,22 +42,36 @@ class Camera {
glm::vec3 lookAt;
glm::vec3 up;
float fov;
float nearPlane;
float farPlane;
float near;
float far;
float aspectRatio;

glm::mat4 cameraMatrix;
std::array<glm::vec4, 6> viewFrustum;

public:
Camera(const glm::vec3 &position,
const glm::vec3 &lookAt,
const glm::vec3 &up,
float fov,
float nearPlane,
float farPlane);
Camera(const glm::vec3 &_position,
const glm::vec3 &_lookAt,
const glm::vec3 &_up,
float _fov,
float _near,
float _far);

virtual void move(MovementDirection direction, float deltaTime) = 0;
virtual void setPosition(const glm::vec3 &pos);
void setWindowSize(int width, int height);
virtual void move(MovementDirection direction, float deltaTime) = 0;

const glm::vec3 &getPosition() const;
const glm::mat4 &getCameraMatrix() const;

bool isInFrustum(const render::BoundingSphere &sphere) const;

protected:
void updateCameraMatrix();
void updateViewFrustum();

glm::vec3 getPosition() const;
glm::mat4 getCameraMatrix(float aspectRatio) const;
private:
static glm::vec4 planeEquation(const glm::vec3 &p1, const glm::vec3 &p2, const glm::vec3 &p3);
};

}
48 changes: 48 additions & 0 deletions include/engine/render/BoundingSphere.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/// Copyright 2025 Ana Oliveira, Humberto Gomes, Mariana Rocha, Sara Lopes
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.

#pragma once

#include <glm/vec4.hpp>
#include <vector>

#include "engine/render/BoundingSphere.hpp"
#include "engine/render/RenderPipeline.hpp"
#include "utils/Vertex.hpp"

namespace engine::render {

class Model; // Importing model would lead to a recursive inclusion

class BoundingSphere {
private:
glm::vec4 center;
float radius;

static Model *sphereModel;
static bool initializingSphereModel;

public:
BoundingSphere();
BoundingSphere(const glm::vec4 &_center, float _radius);
explicit BoundingSphere(const std::vector<utils::Vertex> &vertices);
BoundingSphere(const BoundingSphere &sphere, const glm::mat4 &transform);

glm::vec4 getCenter() const;
float getRadius() const;

void draw(const RenderPipeline &pipeline, const glm::mat4 &cameraMatrix) const;
};

}
5 changes: 5 additions & 0 deletions include/engine/render/Model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <glad/glad.h>
#include <vector>

#include "engine/render/BoundingSphere.hpp"
#include "utils/Vertex.hpp"
#include "utils/WavefrontOBJ.hpp"

Expand All @@ -26,6 +27,7 @@ class Model {
private:
GLuint vao, vbo, ibo;
unsigned int vertexCount;
BoundingSphere boundingSphere;

public:
Model(const std::vector<utils::Vertex> &vertices, const std::vector<uint32_t> &indices);
Expand All @@ -34,10 +36,13 @@ class Model {
Model(Model &&) = delete;
~Model();

const BoundingSphere &getBoundingSphere() const;

void draw() const;

private:
explicit Model(const std::pair<std::vector<utils::Vertex>, std::vector<uint32_t>> &vertices);
void calculateBoundingSphere();
};

}
4 changes: 4 additions & 0 deletions include/engine/scene/Entity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace engine::scene {
class Entity {
private:
std::shared_ptr<render::Model> model;
render::BoundingSphere boundingSphere;

public:
Entity(const tinyxml2::XMLElement *modelElement,
Expand All @@ -37,6 +38,9 @@ class Entity {
Entity(const Entity &entity) = delete;
Entity(Entity &&entity) = delete;

void updateBoundingSphere(const glm::mat4 &worldTransform);
const render::BoundingSphere &getBoundingSphere() const;

void draw(const render::RenderPipeline &pipeline, const glm::mat4 &transform) const;
};

Expand Down
11 changes: 10 additions & 1 deletion include/engine/scene/Group.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <unordered_map>
#include <vector>

#include "engine/camera/Camera.hpp"
#include "engine/render/BoundingSphere.hpp"
#include "engine/render/RenderPipeline.hpp"
#include "engine/scene/Entity.hpp"
#include "engine/scene/TRSTransform.hpp"
Expand All @@ -32,6 +34,7 @@ class Group {
private:
std::vector<std::unique_ptr<Entity>> entities;
std::vector<std::unique_ptr<Group>> groups;
render::BoundingSphere boundingSphere;
TRSTransform transform;

public:
Expand All @@ -41,7 +44,13 @@ class Group {
Group(const Group &entity) = delete;
Group(Group &&entity) = delete;

void draw(const render::RenderPipeline &pipeline, const glm::mat4 &_transform) const;
int getEntityCount() const;
void updateBoundingSphere(const glm::mat4 &worldTransform);

int draw(const render::RenderPipeline &pipeline,
const camera::Camera &camera,
const glm::mat4 &_transform,
bool drawBoundingSpheres) const;
};

}
3 changes: 2 additions & 1 deletion include/engine/scene/Scene.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ class Scene {

int getWindowWidth() const;
int getWindowHeight() const;
int getEntityCount() const;
void setWindowSize(int width, int height);
camera::Camera &getCamera();

void draw(const render::RenderPipeline &pipeline) const;
int draw(const render::RenderPipeline &pipeline, bool drawBoundingSpheres) const;
};

}
2 changes: 1 addition & 1 deletion include/engine/window/SceneWindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class SceneWindow : public Window {
render::RenderPipeline pipeline;
scene::Scene scene;
render::Axis xAxis, yAxis, zAxis;
UI _UI;
UI ui;

public:
explicit SceneWindow(const std::string &sceneFile);
Expand Down
9 changes: 5 additions & 4 deletions include/engine/window/UI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ namespace engine::window {
class UI {
private:
camera::Camera &camera;
bool showAxes = true;
bool showAxes, showBoundingSpheres;
int entityCount;

public:
UI(Window &window, camera::Camera &_camera);
void render();
UI(Window &window, camera::Camera &_camera, int _entityCount);
~UI();

void setShowAxes(bool value);
void render(int renderedEntities);

bool isShowAxesEnabled() const;
bool isShowBoundingSpheresEnabled() const;
};

}
101 changes: 88 additions & 13 deletions src/engine/camera/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,106 @@
/// See the License for the specific language governing permissions and
/// limitations under the License.

#include <algorithm>

#include "engine/camera/Camera.hpp"

namespace engine::camera {

Camera::Camera(const glm::vec3 &pos,
const glm::vec3 &target,
const glm::vec3 &upDir,
float fovAngle,
float near,
float far) :
position(pos), lookAt(target), up(upDir), fov(fovAngle), nearPlane(near), farPlane(far) {}
Camera::Camera(const glm::vec3 &_position,
const glm::vec3 &_lookAt,
const glm::vec3 &_up,
float _fov,
float _near,
float _far) :
position(_position),
lookAt(_lookAt),
up(_up),
fov(glm::radians(_fov)),
near(_near),
far(_far),
aspectRatio(1.0f) {

this->updateCameraMatrix();
this->updateViewFrustum();
}

void Camera::setPosition(const glm::vec3 &pos) {
this->position = pos;

this->updateCameraMatrix();
this->updateViewFrustum();
}

glm::mat4 Camera::getCameraMatrix(float aspectRatio) const {
glm::mat4 view = glm::lookAt(this->position, this->lookAt, this->up);
glm::mat4 projection =
glm::perspective(glm::radians(this->fov), aspectRatio, this->nearPlane, this->farPlane);
return projection * view;
void Camera::setWindowSize(int width, int height) {
this->aspectRatio = static_cast<float>(width) / height;

this->updateCameraMatrix();
this->updateViewFrustum();
}

glm::vec3 Camera::getPosition() const {
const glm::vec3 &Camera::getPosition() const {
return this->position;
}

const glm::mat4 &Camera::getCameraMatrix() const {
return this->cameraMatrix;
}

void Camera::updateCameraMatrix() {
const glm::mat4 view = glm::lookAt(this->position, this->lookAt, this->up);
const glm::mat4 projection =
glm::perspective(this->fov, this->aspectRatio, this->near, this->far);

this->cameraMatrix = projection * view;
}

bool Camera::isInFrustum(const render::BoundingSphere &sphere) const {
return std::none_of(this->viewFrustum.cbegin(),
this->viewFrustum.cend(),
[sphere](const glm::vec4 &plane) {
const float distance =
glm::dot(glm::vec3(plane), glm::vec3(sphere.getCenter())) + plane.w;
return distance < -sphere.getRadius();
});
}

void Camera::updateViewFrustum() {
const float halfNearHeight = tanf(this->fov / 2) * this->near;
const float halfNearWidth = halfNearHeight * this->aspectRatio;

const float halfFarHeight = tanf(this->fov / 2) * this->far;
const float halfFarWidth = halfFarHeight * this->aspectRatio;

const glm::vec3 d = glm::normalize(this->lookAt - this->position);
const glm::vec3 right = glm::normalize(glm::cross(d, this->up));
const glm::vec3 realUp = glm::normalize(glm::cross(right, d));

const glm::vec3 farCenter = this->position + d * this->far;
const glm::vec3 nearCenter = this->position + d * this->near;

const glm::vec3 nearTopLeft = nearCenter + realUp * halfNearHeight - right * halfNearWidth;
const glm::vec3 nearTopRight = nearCenter + realUp * halfNearHeight + right * halfNearWidth;
const glm::vec3 nearBottomLeft = nearCenter - realUp * halfNearHeight - right * halfNearWidth;
const glm::vec3 nearBottomRight = nearCenter - realUp * halfNearHeight + right * halfNearWidth;

const glm::vec3 farTopLeft = farCenter + realUp * halfFarHeight - right * halfFarWidth;
const glm::vec3 farTopRight = farCenter + realUp * halfFarHeight + right * halfFarWidth;
const glm::vec3 farBottomLeft = farCenter - realUp * halfFarHeight - right * halfFarWidth;
const glm::vec3 farBottomRight = farCenter - realUp * halfFarHeight + right * halfFarWidth;

this->viewFrustum[0] = Camera::planeEquation(nearTopLeft, nearTopRight, nearBottomLeft);
this->viewFrustum[1] = Camera::planeEquation(farTopLeft, farBottomLeft, farTopRight);
this->viewFrustum[2] = Camera::planeEquation(nearTopLeft, nearBottomLeft, farTopLeft);
this->viewFrustum[3] = Camera::planeEquation(nearTopRight, farTopRight, nearBottomRight);
this->viewFrustum[4] = Camera::planeEquation(nearTopLeft, farTopLeft, nearTopRight);
this->viewFrustum[5] = Camera::planeEquation(farBottomRight, farBottomLeft, nearBottomLeft);
}

glm::vec4 Camera::planeEquation(const glm::vec3 &p1, const glm::vec3 &p2, const glm::vec3 &p3) {
const glm::vec3 normal = glm::normalize(glm::cross(p2 - p1, p3 - p1));
const float constantFactor = glm::dot(-normal, p1);
return glm::vec4(normal, constantFactor);
}

}
10 changes: 6 additions & 4 deletions src/engine/camera/FreeCamera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,28 +72,30 @@ void FreeCamera::move(MovementDirection direction, float deltaTime) {
case MovementDirection::LookLeft:
yaw -= rotationSpeed;
updateCameraVectors();
return;
break;
case MovementDirection::LookRight:
yaw += rotationSpeed;
updateCameraVectors();
return;
break;
case MovementDirection::LookUp:
pitch += rotationSpeed;
if (pitch > glm::radians(89.0f))
pitch = glm::radians(89.0f);
updateCameraVectors();
return;
break;
case MovementDirection::LookDown:
pitch -= rotationSpeed;
if (pitch < glm::radians(-89.0f))
pitch = glm::radians(-89.0f);
updateCameraVectors();
return;
break;
default:
break;
}

lookAt = position + front;
this->updateCameraMatrix();
this->updateViewFrustum();
}

void FreeCamera::setPosition(const glm::vec3 &newPosition) {
Expand Down
Loading