This commit is contained in:
2026-02-27 19:02:52 +03:00
parent e92104e41b
commit 5434239b47
6 changed files with 368 additions and 335 deletions

View File

@@ -271,8 +271,6 @@ void Engine::RenderFrame()
g_render->RenderStats();
ImGui::ShowDemoWindow();
// ImGui scope end ***
g_ImGuiManager.EndFrame();

View File

@@ -4,6 +4,7 @@
#include "engine/ientity.h"
#include "engine/camera.h"
#include "render/model.h"
#include "render/modelsystem.h"
enum EMovmentDir

316
src/render/model.cpp Normal file
View File

@@ -0,0 +1,316 @@
#include <assert.h>
#include <vector>
#include <string>
#include "ifilesystem.h"
#include "log.h"
#include "render.h"
#include "gpu_buffer.h"
#include "shader.h"
#include "shadersystem.h"
#include "renderdevice.h"
#include "model.h"
#include "modelsystem.h"
#include "texturesmanager.h"
extern Shader* g_litShader;
static std::string getFileNameWithoutExtension(const std::string& filename)
{
size_t lastindex = filename.find_last_of(".");
if (lastindex != std::string::npos) {
return filename.substr(0, lastindex);
}
return filename;
}
Model::Model()
{
m_data.vb = nullptr;
m_data.ib = nullptr;
m_AlbedoTexture = nullptr;
//m_boundingBox.min = glm::vec3(0.0f);
//m_boundingBox.max = glm::vec3(0.0f);
}
Model::~Model()
{
m_AlbedoTexture = nullptr;
if (m_data.vb)
{
delete m_data.vb;
m_data.vb = nullptr;
}
}
void Model::LoadObj(const char* filename)
{
Msg("Loading OBJ file %s...", filename);
std::vector<unsigned int> vertexIndices, uvIndices, normalIndices;
std::vector<glm::vec3> temp_vertices;
std::vector<glm::vec2> temp_uvs;
std::vector<glm::vec3> temp_normals;
std::vector<glm::vec3> out_vertices;
std::vector<glm::vec2> out_uvs;
std::vector<glm::vec3> out_normals;
FILE* file = fopen(filename, "r");
if (file == NULL) {
Msg("Model::LoadObj: Impossible to open the file !");
return;
}
while (1) {
char lineHeader[128];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF)
break; // EOF = End Of File. Quit the loop.
// else : parse lineHeader
if (strcmp(lineHeader, "v") == 0) {
glm::vec3 vertex;
fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
temp_vertices.push_back(vertex);
}
else if (strcmp(lineHeader, "vt") == 0) {
glm::vec2 uv;
fscanf(file, "%f %f\n", &uv.x, &uv.y);
uv.y = -uv.y; // Invert V coordinate since we will only use DDS texture, which are inverted. Remove if you want to use TGA or BMP loaders.
temp_uvs.push_back(uv);
}
else if (strcmp(lineHeader, "vn") == 0) {
glm::vec3 normal;
fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
temp_normals.push_back(normal);
}
else if (strcmp(lineHeader, "f") == 0) {
std::string vertex1, vertex2, vertex3;
unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2]);
if (matches != 9) {
Msg("Model::LoadObj: File can't be read by our simple parser :-( Try exporting with other options");
fclose(file);
return;
}
vertexIndices.push_back(vertexIndex[0]);
vertexIndices.push_back(vertexIndex[1]);
vertexIndices.push_back(vertexIndex[2]);
uvIndices.push_back(uvIndex[0]);
uvIndices.push_back(uvIndex[1]);
uvIndices.push_back(uvIndex[2]);
normalIndices.push_back(normalIndex[0]);
normalIndices.push_back(normalIndex[1]);
normalIndices.push_back(normalIndex[2]);
}
else {
// Probably a comment, eat up the rest of the line
char stupidBuffer[1000];
fgets(stupidBuffer, 1000, file);
}
}
// For each vertex of each triangle
for (unsigned int i = 0; i < vertexIndices.size(); i++) {
// Get the indices of its attributes
unsigned int vertexIndex = vertexIndices[i];
unsigned int uvIndex = uvIndices[i];
unsigned int normalIndex = normalIndices[i];
// Get the attributes thanks to the index
glm::vec3 vertex = temp_vertices[vertexIndex - 1];
glm::vec2 uv = temp_uvs[uvIndex - 1];
glm::vec3 normal = temp_normals[normalIndex - 1];
// Put the attributes in buffers
out_vertices.push_back(vertex);
out_uvs.push_back(uv);
out_normals.push_back(normal);
}
fclose(file);
m_boundingBox.m_min = glm::vec3(FLT_MAX);
m_boundingBox.m_max = glm::vec3(FLT_MIN);
// Combine in to the one array
std::vector<StaticMeshVertex> vertices;
for (unsigned int i = 0; i < vertexIndices.size(); i++)
{
// Get the indices of its attributes
unsigned int vertexIndex = vertexIndices[i];
unsigned int uvIndex = uvIndices[i];
unsigned int normalIndex = normalIndices[i];
// Get the attributes thanks to the index
glm::vec3 vertex = temp_vertices[vertexIndex - 1];
glm::vec2 uv = temp_uvs[uvIndex - 1];
glm::vec3 normal = temp_normals[normalIndex - 1];
StaticMeshVertex vtx = {};
vtx.position = vertex;
vtx.normal = normal;
vtx.texcoord = uv;
vertices.push_back(vtx);
m_boundingBox.m_min = glm::min(m_boundingBox.m_min, vertex);
m_boundingBox.m_max = glm::max(m_boundingBox.m_max, vertex);
}
m_Vertices = vertices;
m_data.vb = g_renderDevice->CreateVertexBuffer(vertices.data(), (int)sizeof(StaticMeshVertex) * (int)vertices.size());
m_data.vbcount = vertices.size();
std::string mtlfilename = getFileNameWithoutExtension(filename);
mtlfilename += ".mtl";
LoadMtl(mtlfilename.c_str());
}
void Model::LoadMtl(const char* filename)
{
Msg("Loading MTL file %s...", filename);
FILE* file = fopen(filename, "r");
if (file == NULL) {
Msg("Model::LoadObj: Impossible to open the file !");
return;
}
while (1) {
char lineHeader[128];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF)
break; // EOF = End Of File. Quit the loop.
if (strcmp(lineHeader, "map_Kd") == 0) {
char stupidBuffer[1000];
fgets(stupidBuffer, 1000, file);
const char* textureFilename = stupidBuffer + 1;
m_AlbedoTexture = g_texturesManager->LoadTexture2D(textureFilename, true);
}
//if (strcmp(lineHeader, "v") == 0) {
// glm::vec3 vertex;
// fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
// temp_vertices.push_back(vertex);
//}
//else {
// // Probably a comment, eat up the rest of the line
// char stupidBuffer[1000];
// fgets(stupidBuffer, 1000, file);
//}
}
fclose(file);
}
void Model::Draw(const glm::mat4& model, bool isTransparent /*= false*/)
{
SDL_assert(g_litShader);
glFrontFace(GL_CCW);
glDepthFunc(GL_LESS);
g_renderDevice->SetCullFace(true);
g_renderDevice->SetDepthTest(true);
g_renderDevice->SetDepthWrite(true);
if (isTransparent)
{
// Enable blending
g_renderDevice->SetBlending(true);
g_renderDevice->SetBlendingFunction(BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA);
glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, .5f);
g_shaderSystem->SetUniformFloat4(g_litShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr(color));
}
else
{
g_renderDevice->SetBlending(false);
//glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, 1.f);
//g_shaderSystem->SetUniformFloat4(g_litShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr(color));
}
g_renderDevice->SetVerticesBuffer(m_data.vb);
g_shaderSystem->SetShader(g_litShader);
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MODEL_MATRIX, &model[0]);
//static float test = 0.0f;
//test += g_systemTimer->GetDelta() * 6.0f;
//glm::mat4 model = glm::mat4(1.0f);
//int32_t x = 0, y = 0;
//g_inputSystem->GetMousePosition(&x, &y);
//
//glm::mat4 model = glm::mat4(1.0f);
//model = glm::rotate(model, test, glm::vec3(0.0f, 1.0f, 0.0f));
//
//float realY = (float)g_renderView.height - (float)y - 1;
//
//glm::vec4 viewport = glm::vec4(0.0f, 0.0f, (float)g_renderView.width, (float)g_renderView.height);
//glm::vec3 pos = glm::unProject(
// glm::vec3((float)x, realY, 0.0f),
// model,
// g_renderView.proj,
// viewport);
//
//pos *= 50.0f;
//
//model = glm::translate(model, pos);
glm::mat4 mvp = glm::identity<glm::mat4>();
mvp = g_render->GetProjectionMatrix() * g_render->GetViewMatrix() * model;
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MVP_MATRIX, &mvp[0]);
g_texturesManager->SetTexture(0, m_AlbedoTexture);
g_shaderSystem->SetUniformSampler(g_litShader, SAMPLER_ALBEDO, 0);
g_renderDevice->DrawArrays(PT_TRIANGLES, 0, m_data.vbcount);
#if 0
glm::mat4 mvp = glm::identity<glm::mat4>();
mvp = g_renderView.proj * g_renderView.view * model;
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MVP_MATRIX, &mvp[0]);
g_texturesManager->SetTexture(0, m_AlbedoTexture);
g_shaderSystem->SetUniformSampler(g_litShader, SAMPLER_ALBEDO, 0);
g_renderDevice->DrawArrays(PT_TRIANGLES, 0, m_data.vbcount);
BoundingBox bbox = m_boundingBox;
TransformBoundingBox(bbox, model);
g_debugRender->DrawBoundingBox(bbox, glm::vec3(1.0f));
#endif
}
void ReleaseModelData(ModelData_t& data)
{
if (data.ib)
{
delete data.ib;
data.ib = nullptr;
}
if (data.vb)
{
delete data.vb;
data.vb = nullptr;
}
}

48
src/render/model.h Normal file
View File

@@ -0,0 +1,48 @@
#ifndef MODEL_H
#define MODEL_H
#include <vector>
#include "boundingbox.h"
#include "render_shared.h"
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
class GPUBuffer;
class Texture2D;
struct ModelData_t
{
GPUBuffer* vb;
GPUBuffer* ib;
uint32_t vbcount;
uint32_t ibcount;
};
void ReleaseModelData(ModelData_t& data);
class Render;
class Model
{
friend class Render;
public:
Model();
~Model();
void LoadObj(const char* filename);
void LoadMtl(const char* filename);
void Draw(const glm::mat4& model, bool isTransparent = false);
const BoundingBox& GetBoundingBox() { return m_boundingBox; }
private:
std::vector<StaticMeshVertex> m_Vertices;
ModelData_t m_data;
BoundingBox m_boundingBox;
Texture2D* m_AlbedoTexture;
};
#endif // !MODEL_H

View File

@@ -8,6 +8,7 @@
#include "shader.h"
#include "shadersystem.h"
#include "renderdevice.h"
#include "model.h"
#include "modelsystem.h"
#include "texturesmanager.h"
@@ -27,7 +28,7 @@ static InputLayoutDesc_t g_skinnedVertexLayout[] = {
Shader* g_litShader = nullptr;
std::string getFileNameWithoutExtension(const std::string& filename)
static std::string getFileNameWithoutExtension(const std::string& filename)
{
size_t lastindex = filename.find_last_of(".");
if (lastindex != std::string::npos) {
@@ -117,294 +118,3 @@ Model* ModelSystem::LoadModel(const char* filename)
return model;
}
Model::Model()
{
m_data.vb = nullptr;
m_data.ib = nullptr;
m_AlbedoTexture = nullptr;
//m_boundingBox.min = glm::vec3(0.0f);
//m_boundingBox.max = glm::vec3(0.0f);
}
Model::~Model()
{
m_AlbedoTexture = nullptr;
if (m_data.vb)
{
delete m_data.vb;
m_data.vb = nullptr;
}
}
void Model::LoadObj(const char* filename)
{
Msg("Loading OBJ file %s...", filename);
std::vector<unsigned int> vertexIndices, uvIndices, normalIndices;
std::vector<glm::vec3> temp_vertices;
std::vector<glm::vec2> temp_uvs;
std::vector<glm::vec3> temp_normals;
std::vector<glm::vec3> out_vertices;
std::vector<glm::vec2> out_uvs;
std::vector<glm::vec3> out_normals;
FILE* file = fopen(filename, "r");
if (file == NULL) {
Msg("Model::LoadObj: Impossible to open the file !");
return;
}
while (1) {
char lineHeader[128];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF)
break; // EOF = End Of File. Quit the loop.
// else : parse lineHeader
if (strcmp(lineHeader, "v") == 0) {
glm::vec3 vertex;
fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
temp_vertices.push_back(vertex);
}
else if (strcmp(lineHeader, "vt") == 0) {
glm::vec2 uv;
fscanf(file, "%f %f\n", &uv.x, &uv.y);
uv.y = -uv.y; // Invert V coordinate since we will only use DDS texture, which are inverted. Remove if you want to use TGA or BMP loaders.
temp_uvs.push_back(uv);
}
else if (strcmp(lineHeader, "vn") == 0) {
glm::vec3 normal;
fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
temp_normals.push_back(normal);
}
else if (strcmp(lineHeader, "f") == 0) {
std::string vertex1, vertex2, vertex3;
unsigned int vertexIndex[3], uvIndex[3], normalIndex[3];
int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2]);
if (matches != 9) {
Msg("Model::LoadObj: File can't be read by our simple parser :-( Try exporting with other options");
fclose(file);
return;
}
vertexIndices.push_back(vertexIndex[0]);
vertexIndices.push_back(vertexIndex[1]);
vertexIndices.push_back(vertexIndex[2]);
uvIndices.push_back(uvIndex[0]);
uvIndices.push_back(uvIndex[1]);
uvIndices.push_back(uvIndex[2]);
normalIndices.push_back(normalIndex[0]);
normalIndices.push_back(normalIndex[1]);
normalIndices.push_back(normalIndex[2]);
}
else {
// Probably a comment, eat up the rest of the line
char stupidBuffer[1000];
fgets(stupidBuffer, 1000, file);
}
}
// For each vertex of each triangle
for (unsigned int i = 0; i < vertexIndices.size(); i++) {
// Get the indices of its attributes
unsigned int vertexIndex = vertexIndices[i];
unsigned int uvIndex = uvIndices[i];
unsigned int normalIndex = normalIndices[i];
// Get the attributes thanks to the index
glm::vec3 vertex = temp_vertices[vertexIndex - 1];
glm::vec2 uv = temp_uvs[uvIndex - 1];
glm::vec3 normal = temp_normals[normalIndex - 1];
// Put the attributes in buffers
out_vertices.push_back(vertex);
out_uvs.push_back(uv);
out_normals.push_back(normal);
}
fclose(file);
m_boundingBox.m_min = glm::vec3(FLT_MAX);
m_boundingBox.m_max = glm::vec3(FLT_MIN);
// Combine in to the one array
std::vector<StaticMeshVertex> vertices;
for (unsigned int i = 0; i < vertexIndices.size(); i++)
{
// Get the indices of its attributes
unsigned int vertexIndex = vertexIndices[i];
unsigned int uvIndex = uvIndices[i];
unsigned int normalIndex = normalIndices[i];
// Get the attributes thanks to the index
glm::vec3 vertex = temp_vertices[vertexIndex - 1];
glm::vec2 uv = temp_uvs[uvIndex - 1];
glm::vec3 normal = temp_normals[normalIndex - 1];
StaticMeshVertex vtx = {};
vtx.position = vertex;
vtx.normal = normal;
vtx.texcoord = uv;
vertices.push_back(vtx);
m_boundingBox.m_min = glm::min(m_boundingBox.m_min, vertex);
m_boundingBox.m_max = glm::max(m_boundingBox.m_max, vertex);
}
m_Vertices = vertices;
m_data.vb = g_renderDevice->CreateVertexBuffer(vertices.data(), (int)sizeof(StaticMeshVertex) * (int)vertices.size());
m_data.vbcount = vertices.size();
std::string mtlfilename = getFileNameWithoutExtension(filename);
mtlfilename += ".mtl";
LoadMtl(mtlfilename.c_str());
}
void Model::LoadMtl(const char* filename)
{
Msg("Loading MTL file %s...", filename);
FILE* file = fopen(filename, "r");
if (file == NULL) {
Msg("Model::LoadObj: Impossible to open the file !");
return;
}
while (1) {
char lineHeader[128];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF)
break; // EOF = End Of File. Quit the loop.
if (strcmp(lineHeader, "map_Kd") == 0) {
char stupidBuffer[1000];
fgets(stupidBuffer, 1000, file);
const char* textureFilename = stupidBuffer + 1;
m_AlbedoTexture = g_texturesManager->LoadTexture2D(textureFilename, true);
}
//if (strcmp(lineHeader, "v") == 0) {
// glm::vec3 vertex;
// fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
// temp_vertices.push_back(vertex);
//}
//else {
// // Probably a comment, eat up the rest of the line
// char stupidBuffer[1000];
// fgets(stupidBuffer, 1000, file);
//}
}
fclose(file);
}
void Model::Draw(const glm::mat4& model, bool isTransparent /*= false*/)
{
SDL_assert(g_litShader);
glFrontFace(GL_CCW);
glDepthFunc(GL_LESS);
g_renderDevice->SetCullFace(true);
g_renderDevice->SetDepthTest(true);
g_renderDevice->SetDepthWrite(true);
if (isTransparent)
{
// Enable blending
g_renderDevice->SetBlending(true);
g_renderDevice->SetBlendingFunction(BF_SRC_ALPHA, BF_ONE_MINUS_SRC_ALPHA);
glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, .5f);
g_shaderSystem->SetUniformFloat4(g_litShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr(color));
}
else
{
g_renderDevice->SetBlending(false);
//glm::vec4 color = glm::vec4(1.f, 1.f, 1.f, 1.f);
//g_shaderSystem->SetUniformFloat4(g_litShader, UNIFORM_CUSTOM_COLOR, glm::value_ptr(color));
}
g_renderDevice->SetVerticesBuffer(m_data.vb);
g_shaderSystem->SetShader(g_litShader);
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MODEL_MATRIX, &model[0]);
//static float test = 0.0f;
//test += g_systemTimer->GetDelta() * 6.0f;
//glm::mat4 model = glm::mat4(1.0f);
//int32_t x = 0, y = 0;
//g_inputSystem->GetMousePosition(&x, &y);
//
//glm::mat4 model = glm::mat4(1.0f);
//model = glm::rotate(model, test, glm::vec3(0.0f, 1.0f, 0.0f));
//
//float realY = (float)g_renderView.height - (float)y - 1;
//
//glm::vec4 viewport = glm::vec4(0.0f, 0.0f, (float)g_renderView.width, (float)g_renderView.height);
//glm::vec3 pos = glm::unProject(
// glm::vec3((float)x, realY, 0.0f),
// model,
// g_renderView.proj,
// viewport);
//
//pos *= 50.0f;
//
//model = glm::translate(model, pos);
glm::mat4 mvp = glm::identity<glm::mat4>();
mvp = g_render->GetProjectionMatrix() * g_render->GetViewMatrix() * model;
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MVP_MATRIX, &mvp[0]);
g_texturesManager->SetTexture(0, m_AlbedoTexture);
g_shaderSystem->SetUniformSampler(g_litShader, SAMPLER_ALBEDO, 0);
g_renderDevice->DrawArrays(PT_TRIANGLES, 0, m_data.vbcount);
#if 0
glm::mat4 mvp = glm::identity<glm::mat4>();
mvp = g_renderView.proj * g_renderView.view * model;
g_shaderSystem->SetUniformMatrix(g_litShader, UNIFORM_MVP_MATRIX, &mvp[0]);
g_texturesManager->SetTexture(0, m_AlbedoTexture);
g_shaderSystem->SetUniformSampler(g_litShader, SAMPLER_ALBEDO, 0);
g_renderDevice->DrawArrays(PT_TRIANGLES, 0, m_data.vbcount);
BoundingBox bbox = m_boundingBox;
TransformBoundingBox(bbox, model);
g_debugRender->DrawBoundingBox(bbox, glm::vec3(1.0f));
#endif
}
void ReleaseModelData(ModelData_t& data)
{
if (data.ib)
{
delete data.ib;
data.ib = nullptr;
}
if (data.vb)
{
delete data.vb;
data.vb = nullptr;
}
}

View File

@@ -3,47 +3,7 @@
#include <vector>
#include "boundingbox.h"
#include "render_shared.h"
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
class GPUBuffer;
class Texture2D;
struct ModelData_t
{
GPUBuffer* vb;
GPUBuffer* ib;
uint32_t vbcount;
uint32_t ibcount;
};
void ReleaseModelData(ModelData_t& data);
class Render;
class Model
{
friend class Render;
public:
Model();
~Model();
void LoadObj(const char* filename);
void LoadMtl(const char* filename);
void Draw(const glm::mat4& model, bool isTransparent = false);
const BoundingBox& GetBoundingBox() { return m_boundingBox; }
private:
std::vector<StaticMeshVertex> m_Vertices;
ModelData_t m_data;
BoundingBox m_boundingBox;
Texture2D* m_AlbedoTexture;
};
class Model;
class ModelSystem
{