feat: assignment 2
This commit is contained in:
56
.clang-format
Normal file
56
.clang-format
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
|
||||||
|
AccessModifierOffset: -8
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: Consecutive
|
||||||
|
AlignConsecutiveDeclarations: Consecutive
|
||||||
|
AlignConsecutiveMacros: Consecutive
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
|
AlignOperands: DontAlign
|
||||||
|
AlignTrailingComments: Always
|
||||||
|
AllowShortBlocksOnASingleLine: Never
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AllowShortLambdasOnASingleLine: None
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: false
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
BeforeLambdaBody: false
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
BreakBeforeBinaryOperators: NonAssignment
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BreakInheritanceList: AfterColon
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakStringLiterals: false
|
||||||
|
ColumnLimit: 80
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
EmptyLineBeforeAccessModifier: Always
|
||||||
|
IndentAccessModifiers: false
|
||||||
|
IndentCaseBlocks: false
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentGotoLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 8
|
||||||
|
InsertNewlineAtEOF: true
|
||||||
|
InsertTrailingCommas: None
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
PackConstructorInitializers: NextLineOnly
|
||||||
|
PointerAlignment: Left
|
||||||
|
SortIncludes: Never
|
||||||
|
SpaceBeforeCaseColon: false
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Always
|
||||||
64
.clang-tidy
Normal file
64
.clang-tidy
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
# Linux-style naming conventions for C++ projects
|
||||||
|
Checks: >
|
||||||
|
readability-identifier-naming,
|
||||||
|
readability-braces-around-statements,
|
||||||
|
readability-function-size,
|
||||||
|
modernize-use-nullptr,
|
||||||
|
modernize-use-override,
|
||||||
|
performance-*,
|
||||||
|
-modernize-use-trailing-return-type
|
||||||
|
|
||||||
|
CheckOptions:
|
||||||
|
# Classes and structs use CamelCase (C++ convention)
|
||||||
|
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
|
||||||
|
- { key: readability-identifier-naming.StructCase, value: CamelCase }
|
||||||
|
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
|
||||||
|
- { key: readability-identifier-naming.UnionCase, value: CamelCase }
|
||||||
|
|
||||||
|
# Functions and methods use snake_case (Linux style)
|
||||||
|
- { key: readability-identifier-naming.FunctionCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.MethodCase, value: lower_case }
|
||||||
|
|
||||||
|
# Member variables: snake_case with trailing underscore
|
||||||
|
- { key: readability-identifier-naming.PrivateMemberCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.PrivateMemberSuffix, value: '_' }
|
||||||
|
- { key: readability-identifier-naming.ProtectedMemberCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.ProtectedMemberSuffix, value: '_' }
|
||||||
|
- { key: readability-identifier-naming.PublicMemberCase, value: lower_case }
|
||||||
|
|
||||||
|
# Parameters and local variables: snake_case
|
||||||
|
- { key: readability-identifier-naming.ParameterCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.VariableCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.LocalVariableCase, value: lower_case }
|
||||||
|
|
||||||
|
# Constants and macros: UPPER_CASE
|
||||||
|
- { key: readability-identifier-naming.ConstantCase, value: UPPER_CASE }
|
||||||
|
- { key: readability-identifier-naming.ConstexprVariableCase, value: UPPER_CASE }
|
||||||
|
- { key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE }
|
||||||
|
- { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE }
|
||||||
|
|
||||||
|
# Global variables: snake_case with g_ prefix (optional, can remove prefix)
|
||||||
|
- { key: readability-identifier-naming.GlobalVariableCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.GlobalVariablePrefix, value: 'g_' }
|
||||||
|
|
||||||
|
# Namespaces: snake_case
|
||||||
|
- { key: readability-identifier-naming.NamespaceCase, value: lower_case }
|
||||||
|
|
||||||
|
# Template parameters: CamelCase
|
||||||
|
- { key: readability-identifier-naming.TypeTemplateParameterCase, value: CamelCase }
|
||||||
|
- { key: readability-identifier-naming.ValueTemplateParameterCase, value: lower_case }
|
||||||
|
|
||||||
|
# Typedef and type aliases: snake_case_t suffix (Linux style)
|
||||||
|
- { key: readability-identifier-naming.TypedefCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.TypedefSuffix, value: '_t' }
|
||||||
|
- { key: readability-identifier-naming.TypeAliasCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.TypeAliasSuffix, value: '_t' }
|
||||||
|
|
||||||
|
# Function size limits
|
||||||
|
- { key: readability-function-size.LineThreshold, value: 100 }
|
||||||
|
- { key: readability-function-size.StatementThreshold, value: 50 }
|
||||||
|
|
||||||
|
WarningsAsErrors: ''
|
||||||
|
HeaderFilterRegex: 'src/.*\.h$'
|
||||||
|
FormatStyle: file
|
||||||
41
src/camera.cpp
Normal file
41
src/camera.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "camera.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "../lib/glew/GL/glew.h"
|
||||||
|
#include "../lib/glm/gtc/matrix_transform.hpp"
|
||||||
|
|
||||||
|
Camera::Camera()
|
||||||
|
: projection_(glm::mat4(1.0f))
|
||||||
|
, viewport_(0, 0, 800, 600)
|
||||||
|
, clearColor_(0.0f, 0.0f, 0.0f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Camera::prepare()
|
||||||
|
{
|
||||||
|
// Set projection matrix
|
||||||
|
State::projectionMatrix = projection_;
|
||||||
|
|
||||||
|
// Calculate view matrix
|
||||||
|
// For a camera, we need the inverse transformation:
|
||||||
|
// View = inverse(Translation * Rotation)
|
||||||
|
// Which is: Rotation^-1 * Translation^-1
|
||||||
|
glm::mat4 view = glm::mat4(1.0f);
|
||||||
|
|
||||||
|
// Inverse rotation (rotate in opposite direction)
|
||||||
|
view = glm::rotate(view, -rotation_.z, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
view = glm::rotate(view, -rotation_.y, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
view = glm::rotate(view, -rotation_.x, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
|
||||||
|
// Inverse translation (translate in opposite direction)
|
||||||
|
view = glm::translate(view, -position_);
|
||||||
|
|
||||||
|
State::viewMatrix = view;
|
||||||
|
|
||||||
|
// Set viewport
|
||||||
|
glViewport(viewport_.x, viewport_.y, viewport_.z, viewport_.w);
|
||||||
|
glScissor(viewport_.x, viewport_.y, viewport_.z, viewport_.w);
|
||||||
|
|
||||||
|
// Set clear color and clear buffers
|
||||||
|
glClearColor(clearColor_.r, clearColor_.g, clearColor_.b, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
46
src/camera.h
Normal file
46
src/camera.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef CAMERA_H_
|
||||||
|
#define CAMERA_H_
|
||||||
|
|
||||||
|
#include "entity.h"
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
|
||||||
|
class Camera : public Entity {
|
||||||
|
public:
|
||||||
|
Camera();
|
||||||
|
|
||||||
|
const glm::mat4& getProjection() const
|
||||||
|
{
|
||||||
|
return projection_;
|
||||||
|
}
|
||||||
|
void setProjection(const glm::mat4& proj)
|
||||||
|
{
|
||||||
|
projection_ = proj;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::ivec4& getViewport() const
|
||||||
|
{
|
||||||
|
return viewport_;
|
||||||
|
}
|
||||||
|
void setViewport(const glm::ivec4& vp)
|
||||||
|
{
|
||||||
|
viewport_ = vp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3& getClearColor() const
|
||||||
|
{
|
||||||
|
return clearColor_;
|
||||||
|
}
|
||||||
|
void setClearColor(const glm::vec3& color)
|
||||||
|
{
|
||||||
|
clearColor_ = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepare();
|
||||||
|
|
||||||
|
private:
|
||||||
|
glm::mat4 projection_;
|
||||||
|
glm::ivec4 viewport_;
|
||||||
|
glm::vec3 clearColor_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CAMERA_H_
|
||||||
13
src/entity.cpp
Normal file
13
src/entity.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include "entity.h"
|
||||||
|
|
||||||
|
Entity::Entity()
|
||||||
|
: position_(0.0f, 0.0f, 0.0f)
|
||||||
|
, rotation_(0.0f, 0.0f, 0.0f)
|
||||||
|
, scale_(1.0f, 1.0f, 1.0f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entity::move(const glm::vec3& vec)
|
||||||
|
{
|
||||||
|
position_ += vec;
|
||||||
|
}
|
||||||
55
src/entity.h
Normal file
55
src/entity.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#ifndef ENTITY_H_
|
||||||
|
#define ENTITY_H_
|
||||||
|
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
|
||||||
|
class Entity {
|
||||||
|
public:
|
||||||
|
Entity();
|
||||||
|
virtual ~Entity()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3& getPosition() const
|
||||||
|
{
|
||||||
|
return position_;
|
||||||
|
}
|
||||||
|
void setPosition(const glm::vec3& pos)
|
||||||
|
{
|
||||||
|
position_ = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3& getRotation() const
|
||||||
|
{
|
||||||
|
return rotation_;
|
||||||
|
}
|
||||||
|
void setRotation(const glm::vec3& rot)
|
||||||
|
{
|
||||||
|
rotation_ = rot;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3& getScale() const
|
||||||
|
{
|
||||||
|
return scale_;
|
||||||
|
}
|
||||||
|
void setScale(const glm::vec3& scale)
|
||||||
|
{
|
||||||
|
scale_ = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void move(const glm::vec3& vec);
|
||||||
|
|
||||||
|
virtual void update(float deltaTime)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual void draw()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
glm::vec3 position_;
|
||||||
|
glm::vec3 rotation_;
|
||||||
|
glm::vec3 scale_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ENTITY_H_
|
||||||
127
src/main.cpp
127
src/main.cpp
@@ -2,9 +2,9 @@
|
|||||||
#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
|
#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
|
||||||
#endif*/
|
#endif*/
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "../lib/glew/GL/glew.h"
|
#include "../lib/glew/GL/glew.h"
|
||||||
#include "../lib/glfw/glfw3.h"
|
#include "../lib/glfw/glfw3.h"
|
||||||
@@ -14,11 +14,18 @@
|
|||||||
#include "vertex.h"
|
#include "vertex.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "entity.h"
|
||||||
|
#include "model.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
#define SCREEN_WIDTH 800
|
#define SCREEN_WIDTH 800
|
||||||
#define SCREEN_HEIGHT 600
|
#define SCREEN_HEIGHT 600
|
||||||
|
|
||||||
int main() {
|
int main()
|
||||||
|
{
|
||||||
// Initialize OpenGL
|
// Initialize OpenGL
|
||||||
if (!glfwInit()) {
|
if (!glfwInit()) {
|
||||||
std::cerr << "Failed to initialize glfw\n";
|
std::cerr << "Failed to initialize glfw\n";
|
||||||
@@ -28,11 +35,12 @@ int main() {
|
|||||||
glfwWindowHint(GLFW_RESIZABLE, false);
|
glfwWindowHint(GLFW_RESIZABLE, false);
|
||||||
glfwWindowHint(GLFW_SAMPLES, 8);
|
glfwWindowHint(GLFW_SAMPLES, 8);
|
||||||
|
|
||||||
//glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
// glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
//glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
// glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||||
//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
// glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
GLFWwindow* win = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Daniel Poveda", nullptr, nullptr);
|
GLFWwindow* win = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT,
|
||||||
|
"Daniel Poveda", nullptr, nullptr);
|
||||||
if (win == nullptr) {
|
if (win == nullptr) {
|
||||||
std::cerr << "Failed to create opengl window\n";
|
std::cerr << "Failed to create opengl window\n";
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
@@ -43,69 +51,88 @@ int main() {
|
|||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
std::cout << "OpenGL initialized, version: " << glGetString(GL_VERSION) << "\n";
|
std::cout << "OpenGL initialized, version: " << glGetString(GL_VERSION)
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
// Initialize GLEW
|
// Initialize GLEW
|
||||||
glewExperimental = GL_TRUE;
|
glewExperimental = GL_TRUE;
|
||||||
GLenum err = glewInit();
|
GLenum err = glewInit();
|
||||||
if (err != GLEW_OK) {
|
if (err != GLEW_OK) {
|
||||||
std::cerr << "Failed to initialize GLEW: " << glewGetErrorString(err) << "\n";
|
std::cerr << "Failed to initialize GLEW: "
|
||||||
|
<< glewGetErrorString(err) << "\n";
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logic
|
// Initialize default shader
|
||||||
|
State::defaultShader =
|
||||||
|
std::make_shared<Shader>("data/vertex.glsl", "data/fragment.glsl");
|
||||||
|
if (std::strlen(State::defaultShader->getError()) > 0) {
|
||||||
|
std::cerr << "Failed to initialize shaders: "
|
||||||
|
<< State::defaultShader->getError() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create world
|
||||||
|
World world;
|
||||||
|
|
||||||
|
// Create camera
|
||||||
|
auto camera = std::make_shared<Camera>();
|
||||||
|
camera->setPosition(glm::vec3(0.0f, 0.0f, 6.0f));
|
||||||
|
camera->setProjection(glm::perspective(
|
||||||
|
glm::radians(45.0f),
|
||||||
|
static_cast<float>(SCREEN_WIDTH) / SCREEN_HEIGHT, 0.1f, 100.0f));
|
||||||
|
camera->setViewport(glm::ivec4(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
|
||||||
|
camera->setClearColor(glm::vec3(0.1f, 0.1f, 0.1f));
|
||||||
|
world.addEntity(camera);
|
||||||
|
|
||||||
|
// Create triangle mesh
|
||||||
std::vector<Vertex> vertices = {
|
std::vector<Vertex> vertices = {
|
||||||
{{0.0f, 0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}},
|
{{0.0f, 0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}},
|
||||||
{{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}},
|
{{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}},
|
||||||
{{0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}}
|
{{0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}}};
|
||||||
};
|
std::vector<uint16_t> indices = {0, 1, 2};
|
||||||
std::vector<uint16_t> indices = { 0, 1, 2 };
|
|
||||||
|
|
||||||
Buffer buffer(vertices, indices);
|
auto buffer = std::make_shared<Buffer>(vertices, indices);
|
||||||
Shader shader("data/vertex.glsl", "data/fragment.glsl");
|
auto mesh = std::make_shared<Mesh>();
|
||||||
if (std::strlen(shader.getError()) > 0) {
|
mesh->addBuffer(buffer);
|
||||||
std::cerr << "Failed to initialize shaders: " << shader.getError() << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 projection = glm::perspective(glm::radians(45.0f), static_cast<float>(SCREEN_WIDTH) / SCREEN_HEIGHT, 0.1f, 100.0f);
|
|
||||||
//glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 6));
|
|
||||||
glm::mat4 view = glm::lookAt(glm::vec3(0, 0, 6), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
|
|
||||||
|
|
||||||
// main loop
|
|
||||||
double angle = 0.0;
|
|
||||||
double lastTime = glfwGetTime();
|
|
||||||
while (!glfwWindowShouldClose(win) && !glfwGetKey(win, GLFW_KEY_ESCAPE)) {
|
|
||||||
// Delta
|
|
||||||
double delta_time = glfwGetTime() - lastTime;
|
|
||||||
lastTime = glfwGetTime();
|
|
||||||
|
|
||||||
// Reset window
|
|
||||||
int screenWidth, screenHeight;
|
|
||||||
glfwGetWindowSize(win, &screenWidth, &screenHeight);
|
|
||||||
glViewport(0, 0, screenWidth, screenHeight);
|
|
||||||
|
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
shader.Use();
|
|
||||||
|
|
||||||
// Logic
|
|
||||||
angle += 32.0 * delta_time;
|
|
||||||
|
|
||||||
|
// Create 9 models in a 3x3 grid
|
||||||
|
std::vector<std::shared_ptr<Model>> models;
|
||||||
for (int row = 0; row < 3; ++row) {
|
for (int row = 0; row < 3; ++row) {
|
||||||
for (int col = 0; col < 3; ++col) {
|
for (int col = 0; col < 3; ++col) {
|
||||||
glm::mat4 model = glm::translate(glm::mat4(1.0), glm::vec3(-3.0f + static_cast<float>(col) * 3.0f, 0.0f, static_cast<float>(-row) * 3.0f));
|
auto model = std::make_shared<Model>(mesh);
|
||||||
model = glm::rotate(model, glm::radians(static_cast<float>(angle)), glm::vec3(0, 1, 0));
|
model->setPosition(
|
||||||
|
glm::vec3(-3.0f + static_cast<float>(col) * 3.0f,
|
||||||
glm::mat4 mvp = projection * view * model;
|
0.0f, static_cast<float>(-row) * 3.0f));
|
||||||
|
models.push_back(model);
|
||||||
Shader::setMat4(shader.getLocation("mvp"), mvp);
|
world.addEntity(model);
|
||||||
|
|
||||||
buffer.Draw(shader);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Main loop
|
||||||
|
double angle = 0.0;
|
||||||
|
double lastTime = glfwGetTime();
|
||||||
|
while (!glfwWindowShouldClose(win)
|
||||||
|
&& !glfwGetKey(win, GLFW_KEY_ESCAPE)) {
|
||||||
|
// Delta time
|
||||||
|
double currentTime = glfwGetTime();
|
||||||
|
double deltaTime = currentTime - lastTime;
|
||||||
|
lastTime = currentTime;
|
||||||
|
|
||||||
|
// Update angle
|
||||||
|
angle += 32.0 * deltaTime;
|
||||||
|
|
||||||
|
// Update rotation for all models
|
||||||
|
for (auto& model : models) {
|
||||||
|
model->setRotation(glm::vec3(
|
||||||
|
0.0f, glm::radians(static_cast<float>(angle)),
|
||||||
|
0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update and draw world
|
||||||
|
world.update(static_cast<float>(deltaTime));
|
||||||
|
world.draw();
|
||||||
|
|
||||||
// Refresh screen
|
// Refresh screen
|
||||||
glfwSwapBuffers(win);
|
glfwSwapBuffers(win);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|||||||
33
src/mesh.cpp
Normal file
33
src/mesh.cpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#include "mesh.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "shader.h"
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
void Mesh::addBuffer(const std::shared_ptr<Buffer>& buffer,
|
||||||
|
const std::shared_ptr<Shader>& shader)
|
||||||
|
{
|
||||||
|
buffers_.push_back(buffer);
|
||||||
|
shaders_.push_back(shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::draw()
|
||||||
|
{
|
||||||
|
// Calculate MVP matrix
|
||||||
|
glm::mat4 mvp =
|
||||||
|
State::projectionMatrix * State::viewMatrix * State::modelMatrix;
|
||||||
|
|
||||||
|
// Draw each buffer with its shader
|
||||||
|
for (size_t i = 0; i < buffers_.size(); ++i) {
|
||||||
|
// Use buffer's shader if available, otherwise use default
|
||||||
|
// shader
|
||||||
|
std::shared_ptr<Shader> shader =
|
||||||
|
shaders_[i] ? shaders_[i] : State::defaultShader;
|
||||||
|
|
||||||
|
if (shader) {
|
||||||
|
shader->Use();
|
||||||
|
int mvpLoc = shader->getLocation("mvp");
|
||||||
|
Shader::setMat4(mvpLoc, mvp);
|
||||||
|
buffers_[i]->Draw(*shader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/mesh.h
Normal file
37
src/mesh.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef MESH_H_
|
||||||
|
#define MESH_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Buffer;
|
||||||
|
class Shader;
|
||||||
|
|
||||||
|
class Mesh {
|
||||||
|
public:
|
||||||
|
Mesh() = default;
|
||||||
|
|
||||||
|
void addBuffer(const std::shared_ptr<Buffer>& buffer,
|
||||||
|
const std::shared_ptr<Shader>& shader = nullptr);
|
||||||
|
|
||||||
|
size_t getNumBuffers() const
|
||||||
|
{
|
||||||
|
return buffers_.size();
|
||||||
|
}
|
||||||
|
const std::shared_ptr<Buffer>& getBuffer(size_t index) const
|
||||||
|
{
|
||||||
|
return buffers_[index];
|
||||||
|
}
|
||||||
|
std::shared_ptr<Buffer>& getBuffer(size_t index)
|
||||||
|
{
|
||||||
|
return buffers_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::shared_ptr<Buffer>> buffers_;
|
||||||
|
std::vector<std::shared_ptr<Shader>> shaders_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MESH_H_
|
||||||
35
src/model.cpp
Normal file
35
src/model.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#include "model.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "state.h"
|
||||||
|
#include "../lib/glm/gtc/matrix_transform.hpp"
|
||||||
|
|
||||||
|
Model::Model(const std::shared_ptr<Mesh>& mesh)
|
||||||
|
: mesh_(mesh)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::draw()
|
||||||
|
{
|
||||||
|
if (!mesh_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Build model matrix: Translation * Rotation * Scale
|
||||||
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
|
|
||||||
|
// Translation
|
||||||
|
model = glm::translate(model, position_);
|
||||||
|
|
||||||
|
// Rotation (applying X, Y, Z rotations)
|
||||||
|
model = glm::rotate(model, rotation_.x, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
|
model = glm::rotate(model, rotation_.y, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
|
model = glm::rotate(model, rotation_.z, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
|
||||||
|
// Scale
|
||||||
|
model = glm::scale(model, scale_);
|
||||||
|
|
||||||
|
// Set the model matrix in State
|
||||||
|
State::modelMatrix = model;
|
||||||
|
|
||||||
|
// Draw the mesh
|
||||||
|
mesh_->draw();
|
||||||
|
}
|
||||||
19
src/model.h
Normal file
19
src/model.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef MODEL_H_
|
||||||
|
#define MODEL_H_
|
||||||
|
|
||||||
|
#include "entity.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class Mesh;
|
||||||
|
|
||||||
|
class Model : public Entity {
|
||||||
|
public:
|
||||||
|
Model(const std::shared_ptr<Mesh>& mesh);
|
||||||
|
|
||||||
|
virtual void draw() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Mesh> mesh_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MODEL_H_
|
||||||
6
src/state.cpp
Normal file
6
src/state.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
std::shared_ptr<Shader> State::defaultShader = nullptr;
|
||||||
|
glm::mat4 State::projectionMatrix = glm::mat4(1.0f);
|
||||||
|
glm::mat4 State::viewMatrix = glm::mat4(1.0f);
|
||||||
|
glm::mat4 State::modelMatrix = glm::mat4(1.0f);
|
||||||
17
src/state.h
Normal file
17
src/state.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef STATE_H_
|
||||||
|
#define STATE_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "../lib/glm/glm.hpp"
|
||||||
|
|
||||||
|
class Shader;
|
||||||
|
|
||||||
|
class State {
|
||||||
|
public:
|
||||||
|
static std::shared_ptr<Shader> defaultShader;
|
||||||
|
static glm::mat4 projectionMatrix;
|
||||||
|
static glm::mat4 viewMatrix;
|
||||||
|
static glm::mat4 modelMatrix;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // STATE_H_
|
||||||
58
src/world.cpp
Normal file
58
src/world.cpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#include "world.h"
|
||||||
|
#include "entity.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
void World::addEntity(const std::shared_ptr<Entity>& entity)
|
||||||
|
{
|
||||||
|
entities_.push_back(entity);
|
||||||
|
|
||||||
|
// Check if entity is a camera
|
||||||
|
std::shared_ptr<Camera> camera =
|
||||||
|
std::dynamic_pointer_cast<Camera>(entity);
|
||||||
|
if (camera) {
|
||||||
|
cameras_.push_back(camera);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::removeEntity(const std::shared_ptr<Entity>& entity)
|
||||||
|
{
|
||||||
|
// Remove from entities list
|
||||||
|
auto it = std::find(entities_.begin(), entities_.end(), entity);
|
||||||
|
if (it != entities_.end()) {
|
||||||
|
entities_.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if entity is a camera and remove from cameras list
|
||||||
|
std::shared_ptr<Camera> camera =
|
||||||
|
std::dynamic_pointer_cast<Camera>(entity);
|
||||||
|
if (camera) {
|
||||||
|
auto camIt =
|
||||||
|
std::find(cameras_.begin(), cameras_.end(), camera);
|
||||||
|
if (camIt != cameras_.end()) {
|
||||||
|
cameras_.erase(camIt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::update(float deltaTime)
|
||||||
|
{
|
||||||
|
for (auto& entity : entities_) {
|
||||||
|
entity->update(deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::draw()
|
||||||
|
{
|
||||||
|
// Draw for each camera
|
||||||
|
for (auto& camera : cameras_) {
|
||||||
|
// Prepare the camera (sets viewport, projection, view, clears
|
||||||
|
// screen)
|
||||||
|
camera->prepare();
|
||||||
|
|
||||||
|
// Draw all entities
|
||||||
|
for (auto& entity : entities_) {
|
||||||
|
entity->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/world.h
Normal file
38
src/world.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef WORLD_H_
|
||||||
|
#define WORLD_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Entity;
|
||||||
|
class Camera;
|
||||||
|
|
||||||
|
class World {
|
||||||
|
public:
|
||||||
|
World() = default;
|
||||||
|
|
||||||
|
void addEntity(const std::shared_ptr<Entity>& entity);
|
||||||
|
void removeEntity(const std::shared_ptr<Entity>& entity);
|
||||||
|
|
||||||
|
size_t getNumEntities() const
|
||||||
|
{
|
||||||
|
return entities_.size();
|
||||||
|
}
|
||||||
|
const std::shared_ptr<Entity>& getEntity(size_t index) const
|
||||||
|
{
|
||||||
|
return entities_[index];
|
||||||
|
}
|
||||||
|
std::shared_ptr<Entity>& getEntity(size_t index)
|
||||||
|
{
|
||||||
|
return entities_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(float deltaTime);
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::shared_ptr<Entity>> entities_;
|
||||||
|
std::vector<std::shared_ptr<Camera>> cameras_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WORLD_H_
|
||||||
@@ -160,15 +160,27 @@
|
|||||||
<ClInclude Include="lib\glfw\glfw3.h" />
|
<ClInclude Include="lib\glfw\glfw3.h" />
|
||||||
<ClInclude Include="lib\glfw\glfw3native.h" />
|
<ClInclude Include="lib\glfw\glfw3native.h" />
|
||||||
<ClInclude Include="src\buffer.h" />
|
<ClInclude Include="src\buffer.h" />
|
||||||
|
<ClInclude Include="src\camera.h" />
|
||||||
|
<ClInclude Include="src\entity.h" />
|
||||||
|
<ClInclude Include="src\mesh.h" />
|
||||||
|
<ClInclude Include="src\model.h" />
|
||||||
<ClInclude Include="src\shader.h" />
|
<ClInclude Include="src\shader.h" />
|
||||||
|
<ClInclude Include="src\state.h" />
|
||||||
<ClInclude Include="src\vertex.h" />
|
<ClInclude Include="src\vertex.h" />
|
||||||
|
<ClInclude Include="src\world.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="lib\glew\glew.c" />
|
<ClCompile Include="lib\glew\glew.c" />
|
||||||
<ClCompile Include="src\buffer.cpp" />
|
<ClCompile Include="src\buffer.cpp" />
|
||||||
|
<ClCompile Include="src\camera.cpp" />
|
||||||
|
<ClCompile Include="src\entity.cpp" />
|
||||||
<ClCompile Include="src\main.cpp" />
|
<ClCompile Include="src\main.cpp" />
|
||||||
|
<ClCompile Include="src\mesh.cpp" />
|
||||||
|
<ClCompile Include="src\model.cpp" />
|
||||||
<ClCompile Include="src\shader.cpp" />
|
<ClCompile Include="src\shader.cpp" />
|
||||||
|
<ClCompile Include="src\state.cpp" />
|
||||||
<ClCompile Include="src\vertex.cpp" />
|
<ClCompile Include="src\vertex.cpp" />
|
||||||
|
<ClCompile Include="src\world.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="data\fragment.glsl" />
|
<None Include="data\fragment.glsl" />
|
||||||
|
|||||||
@@ -42,6 +42,24 @@
|
|||||||
<ClInclude Include="src\buffer.h">
|
<ClInclude Include="src\buffer.h">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\state.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\mesh.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\entity.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\model.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\camera.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\world.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\main.cpp">
|
<ClCompile Include="src\main.cpp">
|
||||||
@@ -59,6 +77,24 @@
|
|||||||
<ClCompile Include="src\buffer.cpp">
|
<ClCompile Include="src\buffer.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\state.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\mesh.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\entity.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\model.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\camera.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\world.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="data\fragment.glsl">
|
<None Include="data\fragment.glsl">
|
||||||
|
|||||||
Reference in New Issue
Block a user