Refactor engine code
This commit is contained in:
6
.vscode/c_cpp_properties.json
vendored
6
.vscode/c_cpp_properties.json
vendored
@@ -3,9 +3,9 @@
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/Ps1Engine/renderer",
|
||||
"${workspaceFolder}/Ps1Engine/loader",
|
||||
"${workspaceFolder}/Ps1Engine",
|
||||
"${workspaceFolder}/Engine/renderer",
|
||||
"${workspaceFolder}/Engine/loader",
|
||||
"${workspaceFolder}/Engine",
|
||||
"${workspaceFolder}/external/**",
|
||||
"/usr/include",
|
||||
"/usr/local/include"
|
||||
|
||||
16
.vscode/settings.json
vendored
16
.vscode/settings.json
vendored
@@ -63,6 +63,20 @@
|
||||
"streambuf": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"variant": "cpp"
|
||||
"variant": "cpp",
|
||||
"csignal": "cpp",
|
||||
"strstream": "cpp",
|
||||
"bitset": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"expected": "cpp",
|
||||
"mutex": "cpp",
|
||||
"ranges": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"thread": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"valarray": "cpp"
|
||||
}
|
||||
}
|
||||
@@ -8,23 +8,25 @@ set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
# Include directories
|
||||
include_directories(${CMAKE_SOURCE_DIR}/renderer)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/loader)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Engine)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Engine/renderer)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Engine/loader)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/examples)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/external/stb)
|
||||
|
||||
# Source files
|
||||
set(SOURCES
|
||||
${CMAKE_SOURCE_DIR}/renderer/renderer.cpp
|
||||
${CMAKE_SOURCE_DIR}/loader/mesh.cpp
|
||||
${CMAKE_SOURCE_DIR}/../cube.cpp
|
||||
${CMAKE_SOURCE_DIR}/Engine/renderer/renderer.cpp
|
||||
${CMAKE_SOURCE_DIR}/Engine/loader/mesh.cpp
|
||||
${CMAKE_SOURCE_DIR}/examples/cube.cpp
|
||||
)
|
||||
|
||||
# Executable
|
||||
add_executable(Ps1Engine ${SOURCES})
|
||||
add_executable(Engine ${SOURCES})
|
||||
|
||||
# Link libraries
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(GLEW REQUIRED)
|
||||
find_package(glfw3 REQUIRED)
|
||||
|
||||
target_link_libraries(Ps1Engine OpenGL::GL GLEW::GLEW glfw)
|
||||
target_link_libraries(Engine OpenGL::GL GLEW::GLEW glfw)
|
||||
@@ -7,13 +7,13 @@
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::map<std::string, Color> load_mtl_colors(const std::string& mtl_path)
|
||||
std::map<std::string, Material> load_mtl_materials(const std::string& mtl_path)
|
||||
{
|
||||
std::map<std::string, Color> material_colors;
|
||||
std::map<std::string, Material> materials;
|
||||
std::ifstream file(mtl_path);
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "Warning: could not open MTL file: " << mtl_path << std::endl;
|
||||
return material_colors;
|
||||
return materials;
|
||||
}
|
||||
|
||||
std::string line, current_mtl;
|
||||
@@ -24,21 +24,30 @@ std::map<std::string, Color> load_mtl_colors(const std::string& mtl_path)
|
||||
|
||||
if (keyword == "newmtl") {
|
||||
ss >> current_mtl;
|
||||
materials[current_mtl] = Material{Color(255, 255, 255), ""}; // Default white, no texture
|
||||
} else if (keyword == "Kd") {
|
||||
float r, g, b;
|
||||
ss >> r >> g >> b;
|
||||
material_colors[current_mtl] = Color(
|
||||
static_cast<uint8_t>(r * 255),
|
||||
static_cast<uint8_t>(g * 255),
|
||||
static_cast<uint8_t>(b * 255)
|
||||
);
|
||||
if (materials.count(current_mtl)) {
|
||||
materials[current_mtl].color = Color(
|
||||
static_cast<uint8_t>(r * 255),
|
||||
static_cast<uint8_t>(g * 255),
|
||||
static_cast<uint8_t>(b * 255)
|
||||
);
|
||||
}
|
||||
} else if (keyword == "map_Kd") {
|
||||
std::string texture_path;
|
||||
ss >> texture_path;
|
||||
if (materials.count(current_mtl)) {
|
||||
materials[current_mtl].texture_path = texture_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return material_colors;
|
||||
return materials;
|
||||
}
|
||||
|
||||
std::vector<Triangle> load_obj(const std::string& obj_path)
|
||||
std::vector<Triangle> load_obj(const std::string& obj_path, Renderer* renderer)
|
||||
{
|
||||
std::ifstream file(obj_path);
|
||||
if (!file.is_open()) {
|
||||
@@ -47,7 +56,8 @@ std::vector<Triangle> load_obj(const std::string& obj_path)
|
||||
|
||||
std::vector<Vec3> positions;
|
||||
std::vector<Vec2> texcoords;
|
||||
std::map<std::string, Color> materials;
|
||||
std::map<std::string, Material> materials;
|
||||
std::map<std::string, GLuint> texture_map;
|
||||
std::vector<Triangle> triangles;
|
||||
|
||||
std::string current_material = "";
|
||||
@@ -100,9 +110,11 @@ std::vector<Triangle> load_obj(const std::string& obj_path)
|
||||
tri.uv2 = (t_idx[i + 1] >= 0 && t_idx[i + 1] < (int)texcoords.size()) ? texcoords[t_idx[i + 1]] : Vec2(0, 0);
|
||||
|
||||
if (materials.count(current_material)) {
|
||||
tri.color = materials[current_material];
|
||||
tri.color = materials[current_material].color;
|
||||
tri.texture = texture_map[current_material];
|
||||
} else {
|
||||
tri.color = Color(255, 255, 255); // fallback white
|
||||
tri.color = Color(255, 255, 255); // Fallback white
|
||||
tri.texture = 0; // No texture
|
||||
}
|
||||
|
||||
triangles.push_back(tri);
|
||||
@@ -111,7 +123,19 @@ std::vector<Triangle> load_obj(const std::string& obj_path)
|
||||
std::string mtl_file;
|
||||
ss >> mtl_file;
|
||||
fs::path mtl_path = base_path / mtl_file;
|
||||
materials = load_mtl_colors(mtl_path.string());
|
||||
materials = load_mtl_materials(mtl_path.string());
|
||||
|
||||
// Load textures for all materials
|
||||
for (const auto& mat_pair : materials) {
|
||||
const std::string& mat_name = mat_pair.first;
|
||||
const Material& mat = mat_pair.second;
|
||||
if (!mat.texture_path.empty()) {
|
||||
fs::path texture_full_path = base_path / mat.texture_path;
|
||||
texture_map[mat_name] = renderer->load_texture(texture_full_path.string());
|
||||
} else {
|
||||
texture_map[mat_name] = 0; // No texture
|
||||
}
|
||||
}
|
||||
} else if (keyword == "usemtl") {
|
||||
ss >> current_material;
|
||||
}
|
||||
15
Engine/loader/mesh.h
Normal file
15
Engine/loader/mesh.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "renderer.h" // includes Vec3, Vec2, Triangle, Color
|
||||
|
||||
struct Material
|
||||
{
|
||||
Color color;
|
||||
std::string texture_path;
|
||||
};
|
||||
|
||||
std::map<std::string, Material> load_mtl_materials(const std::string& mtl_path);
|
||||
std::vector<Triangle> load_obj(const std::string& obj_path, Renderer* renderer);
|
||||
2
Engine/ps1engine.h
Normal file
2
Engine/ps1engine.h
Normal file
@@ -0,0 +1,2 @@
|
||||
#include <renderer.h>
|
||||
#include <mesh.h>
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "renderer.h"
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
@@ -50,7 +51,6 @@ Matrix4 matrix_multiply(const Matrix4 &a, const Matrix4 &b)
|
||||
|
||||
Color convert_color(const Color &color)
|
||||
{
|
||||
|
||||
uint8_t r = (color.r >> 3) << 3;
|
||||
uint8_t g = (color.g >> 3) << 3;
|
||||
uint8_t b = (color.b >> 3) << 3;
|
||||
@@ -61,7 +61,6 @@ Renderer::Renderer(int width_, int height_, const std::string &title_)
|
||||
: width(width_), height(height_), title(title_),
|
||||
internal_width(320), internal_height(240)
|
||||
{
|
||||
|
||||
if (!glfwInit())
|
||||
{
|
||||
throw std::runtime_error("Failed to initialize GLFW");
|
||||
@@ -105,12 +104,11 @@ void Renderer::set_view_matrix(const Matrix4 &view)
|
||||
|
||||
void Renderer::begin_frame()
|
||||
{
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void Renderer::render(const std::vector<Triangle> &triangles, GLuint texture)
|
||||
void Renderer::render(const std::vector<Triangle> &triangles)
|
||||
{
|
||||
std::vector<Triangle> transformed_triangles;
|
||||
|
||||
@@ -124,6 +122,7 @@ void Renderer::render(const std::vector<Triangle> &triangles, GLuint texture)
|
||||
t.uv1 = tri.uv1;
|
||||
t.uv2 = tri.uv2;
|
||||
t.color = tri.color;
|
||||
t.texture = tri.texture;
|
||||
|
||||
Vec3 edge1(t.v1.x - t.v0.x, t.v1.y - t.v0.y, t.v1.z - t.v0.z);
|
||||
Vec3 edge2(t.v2.x - t.v0.x, t.v2.y - t.v0.y, t.v2.z - t.v0.z);
|
||||
@@ -185,53 +184,81 @@ void Renderer::render(const std::vector<Triangle> &triangles, GLuint texture)
|
||||
screen_tri.uv1 = tri.uv1;
|
||||
screen_tri.uv2 = tri.uv2;
|
||||
screen_tri.color = convert_color(tri.color);
|
||||
screen_tri.texture = tri.texture;
|
||||
|
||||
screen_triangles.push_back(screen_tri);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
// Group triangles by texture
|
||||
std::map<GLuint, std::vector<Triangle>> texture_groups;
|
||||
for (const auto& tri : screen_triangles)
|
||||
{
|
||||
texture_groups[tri.texture].push_back(tri);
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
for (const auto &tri : screen_triangles)
|
||||
// Render each texture group
|
||||
for (const auto& group : texture_groups)
|
||||
{
|
||||
GLuint tex = group.first;
|
||||
const std::vector<Triangle>& tris = group.second;
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
|
||||
Color c = tri.color;
|
||||
glColor3ub(c.r, c.g, c.b);
|
||||
|
||||
glTexCoord2f(tri.uv0.x, tri.uv0.y);
|
||||
glVertex3f(static_cast<float>(tri.v0.x), static_cast<float>(tri.v0.y), static_cast<float>(tri.v0.z) / 32767.0f);
|
||||
|
||||
glTexCoord2f(tri.uv1.x, tri.uv1.y);
|
||||
glVertex3f(static_cast<float>(tri.v1.x), static_cast<float>(tri.v1.y), static_cast<float>(tri.v1.z) / 32767.0f);
|
||||
|
||||
glTexCoord2f(tri.uv2.x, tri.uv2.y);
|
||||
glVertex3f(static_cast<float>(tri.v2.x), static_cast<float>(tri.v2.y), static_cast<float>(tri.v2.z) / 32767.0f);
|
||||
|
||||
glEnd();
|
||||
|
||||
if (rand() % 5 == 0)
|
||||
if (tex != 0)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
}
|
||||
|
||||
for (const auto& tri : tris)
|
||||
{
|
||||
glBegin(GL_TRIANGLES);
|
||||
Color c = tri.color;
|
||||
glColor3ub(c.r, c.g, c.b);
|
||||
|
||||
if (tex != 0)
|
||||
{
|
||||
glTexCoord2f(tri.uv0.x, tri.uv0.y);
|
||||
}
|
||||
glVertex3f(static_cast<float>(tri.v0.x), static_cast<float>(tri.v0.y), static_cast<float>(tri.v0.z) / 32767.0f);
|
||||
|
||||
if (tex != 0)
|
||||
{
|
||||
glTexCoord2f(tri.uv1.x, tri.uv1.y);
|
||||
}
|
||||
glVertex3f(static_cast<float>(tri.v1.x), static_cast<float>(tri.v1.y), static_cast<float>(tri.v1.z) / 32767.0f);
|
||||
|
||||
if (tex != 0)
|
||||
{
|
||||
glTexCoord2f(tri.uv2.x, tri.uv2.y);
|
||||
}
|
||||
glVertex3f(static_cast<float>(tri.v2.x), static_cast<float>(tri.v2.y), static_cast<float>(tri.v2.z) / 32767.0f);
|
||||
|
||||
glEnd();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
if (rand() % 5 == 0)
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3f(static_cast<float>(tri.v0.x), static_cast<float>(tri.v0.y), static_cast<float>(tri.v0.z) / 32767.0f);
|
||||
glVertex3f(static_cast<float>(tri.v1.x), static_cast<float>(tri.v1.y), static_cast<float>(tri.v1.z) / 32767.0f);
|
||||
glVertex3f(static_cast<float>(tri.v2.x), static_cast<float>(tri.v2.y), static_cast<float>(tri.v2.z) / 32767.0f);
|
||||
glEnd();
|
||||
if (tex != 0) glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::end_frame()
|
||||
{
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
@@ -36,6 +36,7 @@ struct Triangle
|
||||
Vec3 v0, v1, v2;
|
||||
Vec2 uv0, uv1, uv2;
|
||||
Color color;
|
||||
GLuint texture;
|
||||
};
|
||||
|
||||
Vec3 matrix_multiply(const Matrix4 &mat, const Vec3 &v);
|
||||
@@ -60,10 +61,11 @@ public:
|
||||
~Renderer();
|
||||
void set_view_matrix(const Matrix4 &view);
|
||||
void begin_frame();
|
||||
void render(const std::vector<Triangle> &triangles, GLuint texture);
|
||||
void render(const std::vector<Triangle> &triangles);
|
||||
void end_frame();
|
||||
bool should_close();
|
||||
GLuint load_texture(const std::string &filepath);
|
||||
GLFWwindow *get_window() { return window; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "renderer.h" // includes Vec3, Vec2, Triangle, Color
|
||||
|
||||
std::vector<Triangle> load_obj(const std::string& obj_path);
|
||||
std::map<std::string, Color> load_mtl_colors(const std::string& mtl_path);
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "renderer.h"
|
||||
#include <ps1engine.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
@@ -283,10 +283,11 @@ int main()
|
||||
t.uv1 = tri.uv1;
|
||||
t.uv2 = tri.uv2;
|
||||
t.color = tri.color;
|
||||
t.texture = texture;
|
||||
transformed_cube.push_back(t);
|
||||
}
|
||||
|
||||
renderer.render(transformed_cube, texture);
|
||||
renderer.render(transformed_cube);
|
||||
|
||||
renderer.end_frame();
|
||||
}
|
||||
Reference in New Issue
Block a user