aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Image.cpp (renamed from src/RenderBackend/OpenGL/Image.cpp)2
-rw-r--r--src/RenderBackend/OpenGL/DeviceMemory.cpp28
-rw-r--r--src/RenderBackend/OpenGL/Shader.cpp1
-rw-r--r--src/RenderBackend/OpenGL/ShaderProgram.cpp4
-rw-r--r--src/RenderBackend/OpenGL/Texture2D.cpp52
-rw-r--r--src/RenderBackend/OpenGL/Uniform.cpp10
-rw-r--r--src/main.cpp111
-rw-r--r--src/model_loader/ObjModelLoader.cpp176
8 files changed, 295 insertions, 89 deletions
diff --git a/src/RenderBackend/OpenGL/Image.cpp b/src/Image.cpp
index 128a580..c312f88 100644
--- a/src/RenderBackend/OpenGL/Image.cpp
+++ b/src/Image.cpp
@@ -1,4 +1,4 @@
-#include "../../../include/RenderBackend/OpenGL/Image.hpp"
+#include "../../../include/Image.hpp"
#include <SOIL/SOIL.h>
using namespace std;
diff --git a/src/RenderBackend/OpenGL/DeviceMemory.cpp b/src/RenderBackend/OpenGL/DeviceMemory.cpp
index f071cd8..a82cdaa 100644
--- a/src/RenderBackend/OpenGL/DeviceMemory.cpp
+++ b/src/RenderBackend/OpenGL/DeviceMemory.cpp
@@ -15,24 +15,6 @@ namespace amalgine
}
}
- u32 getOpenglPrimitiveType(DeviceMemory::PrimitiveType primitiveType)
- {
- switch(primitiveType)
- {
- case DeviceMemory::PrimitiveType::TRIANGLE: return GL_TRIANGLES;
- default: assert(false); return -1;
- }
- }
-
- u32 getPrimitiveTypePointsPerVertices(DeviceMemory::PrimitiveType primitiveType)
- {
- switch(primitiveType)
- {
- case DeviceMemory::PrimitiveType::TRIANGLE: return 3;
- default: assert(false); return -1;
- }
- }
-
DeviceMemory::DeviceMemory() : primitiveType(0), numVertices(0), type(DeviceMemoryType::NONE)
{
glGenBuffers(1, &vertexBufferObjectId);
@@ -57,12 +39,20 @@ namespace amalgine
numVertices = getPrimitiveTypePointsPerVertices(primitiveType);
}
*/
+ void DeviceMemory::copy(const DataView<vec2f> &texture_coords, StorageType storageType) {
+ glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectId);
+ glBufferData(GL_ARRAY_BUFFER, texture_coords.getByteSize(), texture_coords.data, getOpenglStorageType(storageType));
+ primitiveType = GL_TRIANGLES;
+ numVertices = texture_coords.size * 2;
+ type = DeviceMemoryType::VEC2;
+ }
+
void DeviceMemory::copy(const DataView<Triangle2D> &triangles, StorageType storageType)
{
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectId);
glBufferData(GL_ARRAY_BUFFER, triangles.getByteSize(), triangles.data, getOpenglStorageType(storageType));
primitiveType = GL_TRIANGLES;
- numVertices = triangles.size * 3;
+ numVertices = triangles.size * 2;
type = DeviceMemoryType::VEC2;
}
diff --git a/src/RenderBackend/OpenGL/Shader.cpp b/src/RenderBackend/OpenGL/Shader.cpp
index 3b6563f..32e2fe6 100644
--- a/src/RenderBackend/OpenGL/Shader.cpp
+++ b/src/RenderBackend/OpenGL/Shader.cpp
@@ -10,6 +10,7 @@ namespace amalgine {
return GL_FRAGMENT_SHADER;
}
assert(false);
+ return 0;
}
static std::string get_shader_compile_log(GLuint shaderId)
diff --git a/src/RenderBackend/OpenGL/ShaderProgram.cpp b/src/RenderBackend/OpenGL/ShaderProgram.cpp
index 389a929..14b15aa 100644
--- a/src/RenderBackend/OpenGL/ShaderProgram.cpp
+++ b/src/RenderBackend/OpenGL/ShaderProgram.cpp
@@ -73,7 +73,7 @@ namespace amalgine {
return Result<Uniform>::Ok(std::move(uniform));
}
- int ShaderProgram::set_vertex_input(const char *name, const DeviceMemory &data) {
+ int ShaderProgram::set_input_data(const char *name, const DeviceMemory &data) {
GLint attrib_location = glGetAttribLocation(program_id, name);
if(attrib_location == -1) {
fprintf(stderr, "No such attribute in shader: %s\n", name);
@@ -81,6 +81,7 @@ namespace amalgine {
}
data.use();
+ glEnableVertexAttribArray(attrib_location);
switch(data.get_type()) {
case DeviceMemoryType::NONE:
return -1;
@@ -93,7 +94,6 @@ namespace amalgine {
break;
}
}
- glEnableVertexAttribArray(attrib_location);
return 0;
}
diff --git a/src/RenderBackend/OpenGL/Texture2D.cpp b/src/RenderBackend/OpenGL/Texture2D.cpp
index 07d807a..a561f6e 100644
--- a/src/RenderBackend/OpenGL/Texture2D.cpp
+++ b/src/RenderBackend/OpenGL/Texture2D.cpp
@@ -1,15 +1,54 @@
#include "../../../include/RenderBackend/OpenGL/Texture2D.hpp"
-#include "../../../include/RenderBackend/OpenGL/Image.hpp"
#include "../../../include/RenderBackend/OpenGL/opengl.hpp"
+#include "../../../include/Image.hpp"
+#include <stack>
#include <cassert>
-namespace amalgine
-{
+namespace amalgine {
+ struct TextureIdAllocator {
+ TextureIdAllocator(){
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_units);
+ if(max_texture_units < 1)
+ max_texture_units = 1;
+ printf("max texture units: %d\n", max_texture_units);
+ }
+
+ u32 get_free_texture_id() {
+ if(!free_spots.empty()) {
+ u32 texture_id = free_spots.top();
+ free_spots.pop();
+ return texture_id;
+ }
+
+ if(texture_id_counter + 1 == max_texture_units) {
+ fprintf(stderr, "Error: No free spot left for textures, resetting counter\n");
+ texture_id_counter = 0;
+ }
+
+ return texture_id_counter++;
+ }
+
+ void free_texture_id(i32 texture_id) {
+ free_spots.push(texture_id);
+ }
+
+ std::stack<u32> free_spots;
+ i32 texture_id_counter = 0;
+ i32 max_texture_units = 0;
+ };
+
+ static TextureIdAllocator *texture_id_allocator = nullptr;
+
Texture2D::Texture2D(Image *image)
{
assert(image);
- glGenTextures(1, &textureId);
- glBindTexture(GL_TEXTURE_2D, textureId);
+ if(!texture_id_allocator)
+ texture_id_allocator = new TextureIdAllocator();
+
+ texture_id = texture_id_allocator->get_free_texture_id();
+ glGenTextures(1, &texture_ref);
+ glActiveTexture(GL_TEXTURE0 + texture_id);
+ glBindTexture(GL_TEXTURE_2D, texture_ref);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image->getWidth(), image->getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, image->getData());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -21,6 +60,7 @@ namespace amalgine
Texture2D::~Texture2D()
{
- glDeleteTextures(1, &textureId);
+ texture_id_allocator->free_texture_id(texture_id);
+ glDeleteTextures(1, &texture_ref);
}
}
diff --git a/src/RenderBackend/OpenGL/Uniform.cpp b/src/RenderBackend/OpenGL/Uniform.cpp
index 67cf3c6..5f68bc6 100644
--- a/src/RenderBackend/OpenGL/Uniform.cpp
+++ b/src/RenderBackend/OpenGL/Uniform.cpp
@@ -4,6 +4,11 @@
namespace amalgine {
Uniform::~Uniform() {}
+ void Uniform::set(float value) {
+ use();
+ glUniform1f(uniform_id, value);
+ }
+
void Uniform::set(const vec3f &value) {
use();
glUniform3f(uniform_id, value.x, value.y, value.z);
@@ -14,6 +19,11 @@ namespace amalgine {
glUniformMatrix4fv(uniform_id, 1, GL_FALSE, glm::value_ptr(value));
}
+ void Uniform::set(const Texture2D &texture) {
+ use();
+ glUniform1i(uniform_id, texture.get_texture_id());
+ }
+
Uniform::Uniform(i32 uniform_id, u32 shader_program_id) : uniform_id(uniform_id), program_id(shader_program_id) {
}
diff --git a/src/main.cpp b/src/main.cpp
index 6f825b1..5845332 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -3,6 +3,8 @@
#include "../include/RenderBackend/OpenGL/ShaderProgram.hpp"
#include "../include/RenderBackend/OpenGL/DeviceMemory.hpp"
#include "../include/RenderBackend/OpenGL/DeviceFrame.hpp"
+#include "../include/RenderBackend/OpenGL/Texture2D.hpp"
+#include "../include/Image.hpp"
#include "../include/Triangle.hpp"
#include "../include/model_loader/ObjModelLoader.hpp"
@@ -27,6 +29,29 @@ struct Userdata {
float cam_dist;
};
+static std::vector<Triangle3D> generate_sand() {
+ const int rows = 50;
+ const int columns = 50;
+ std::vector<Triangle3D> vertices(rows * columns * 2);
+ int i = 0;
+ float div = 0.3f;
+ for(int y = 0; y < rows; ++y) {
+ for(int x = 0; x < columns; ++x) {
+ vertices[i++] = {
+ Vertex3D{x * div + 0.0f, y * div + 0.0f, 0.0f},
+ Vertex3D{x * div + 1.0f * div, y * div + 0.0f, 0.0f},
+ Vertex3D{x * div + 0.0f, y * div + 1.0f * div, 0.0f}
+ };
+ vertices[i++] = {
+ Vertex3D{x * div + 1.0f * div, y * div + 0.0f, 0.0f},
+ Vertex3D{x * div + 1.0f * div, y * div + 1.0f * div, 0.0f},
+ Vertex3D{x * div + 0.0f, y * div + 1.0f * div, 0.0f}
+ };
+ }
+ }
+ return vertices;
+}
+
int main()
{
initGlfw();
@@ -38,40 +63,50 @@ int main()
DeviceFrame frame;
- std::array<Triangle3D, 2> cpuTriangle = {
- Triangle3D(
- Vertex3D(0.0f, 0.0f, 0.0f),
- Vertex3D(1.0f, 0.0f, 0.0f),
- Vertex3D(0.0f, 1.0f, 0.0f)
- ),
- Triangle3D(
- Vertex3D(1.0f, 0.0f, 0.0f),
- Vertex3D(1.0f, 1.0f, 0.0f),
- Vertex3D(0.0f, 1.0f, 0.0f)
- ),
- };
- //DataView<Triangle3D> cpuTriangles(cpuTriangle.data(), cpuTriangle.size());
+ std::vector<Triangle3D> cpu_sand = generate_sand();
+ DeviceMemory *gpuSand = frame.alloc();
+ gpuSand->copy({cpu_sand.data(), cpu_sand.size()}, DeviceMemory::StorageType::STATIC);
+
+ std::unique_ptr<Shader> sand_vertex_shader = load_shader_from_file("shaders/sand_vertex.vert", Shader::Type::VERTEX);
+ std::unique_ptr<Shader> sand_pixel_shader = load_shader_from_file("shaders/sand_fragment.frag", Shader::Type::PIXEL);
+ std::unique_ptr<ShaderProgram> sand_shader_program = build_shader_program_from_shaders({ sand_vertex_shader.get(), sand_pixel_shader.get() });
+
std::vector<Triangle3D> triangles;
- ObjModelLoader::load_from_file("/home/dec05eba/Downloads/FinalBaseMesh.obj", triangles);
- DataView<Triangle3D> cpuTriangles(triangles.data(), triangles.size());
- DeviceMemory *gpuTriangle = frame.alloc();
- gpuTriangle->copy(cpuTriangles, DeviceMemory::StorageType::STATIC);
+ std::vector<vec2f> texture_coords;
+ Image *image;
+ ObjModelLoader::load_from_file("/home/dec05eba/Downloads/ELI4OS.obj", triangles, texture_coords, &image);
+ DeviceMemory *gpuModel = frame.alloc();
+ gpuModel->copy({triangles.data(), triangles.size()}, DeviceMemory::StorageType::STATIC);
+
+ Texture2D model_texture(image);
+ DeviceMemory *model_gpu_texture = frame.alloc();
+ model_gpu_texture->copy({texture_coords.data(), texture_coords.size()}, DeviceMemory::StorageType::STATIC);
std::unique_ptr<Shader> vertex_shader = load_shader_from_file("shaders/vertex.vert", Shader::Type::VERTEX);
std::unique_ptr<Shader> pixel_shader = load_shader_from_file("shaders/fragment.frag", Shader::Type::PIXEL);
std::unique_ptr<ShaderProgram> shader_program = build_shader_program_from_shaders({ vertex_shader.get(), pixel_shader.get() });
- shader_program->set_vertex_input("position", *gpuTriangle);
-
- Result<Uniform> proj_uniform = shader_program->get_uniform_by_name("proj");
glm::mat4 proj = glm::perspective(glm::radians(75.0f), (float)window_width / (float)window_height, 0.2f, 1000.0f);
- proj_uniform->set(proj);
+ vec3f triangle_color = { 1.0f, 0.0f, 0.0f };
- Result<Uniform> triangle_color_uniform = shader_program->get_uniform_by_name("triangle_color");
- triangle_color_uniform->set(vec3f{ 1.0f, 0.0f, 0.0f });
+ Result<Uniform> sand_proj_uniform = sand_shader_program->get_uniform_by_name("proj");
+ Result<Uniform> sand_view_uniform = sand_shader_program->get_uniform_by_name("view");
+ Result<Uniform> sand_model_uniform = sand_shader_program->get_uniform_by_name("model");
+ Result<Uniform> sand_time = sand_shader_program->get_uniform_by_name("time");
+ Result<Uniform> sand_triangle_color_uniform = sand_shader_program->get_uniform_by_name("triangle_color");
+ Result<Uniform> proj_uniform = shader_program->get_uniform_by_name("proj");
Result<Uniform> view_uniform = shader_program->get_uniform_by_name("view");
Result<Uniform> model_uniform = shader_program->get_uniform_by_name("model");
+ Result<Uniform> tex_uniform = shader_program->get_uniform_by_name("tex");
+
+ sand_proj_uniform->set(proj);
+ sand_triangle_color_uniform->set(triangle_color);
+
+ proj_uniform->set(proj);
+
+ shader_program->set_input_data("texcoord_vert", *model_gpu_texture);
+ tex_uniform->set(model_texture);
Userdata userdata;
userdata.cam_dist = 3.0f;
@@ -85,7 +120,8 @@ int main()
userdata->cam_dist += yoffset;
});
- //glEnable(GL_CULL_FACE);
+ glEnable(GL_CULL_FACE);
+ float time = 0.0f;
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
@@ -94,6 +130,7 @@ int main()
auto t_now = std::chrono::high_resolution_clock::now();
float time_delta = std::chrono::duration_cast<std::chrono::duration<float>>(t_now - t_start).count();
t_start = t_now;
+ time += time_delta;
float move_speed = time_delta * 3.0f;
if(glfwGetKey(window, GLFW_KEY_W))
@@ -112,6 +149,7 @@ int main()
character_pos - glm::vec3(0.0f, 3.0f, 3.0f),
glm::vec3(0.0f, 0.0f, 1.0f)
);
+ sand_view_uniform->set(view);
view_uniform->set(view);
glm::mat4 model = glm::mat4(1.0f);
@@ -120,18 +158,32 @@ int main()
0.0f,
glm::vec3(0.0f, 0.0f, 1.0f)
);
+ sand_model_uniform->set(model);
model_uniform->set(model);
+ //printf("now: %f\n", time);
+ sand_time->set(time);
+
// Set color for clearing
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Do the actual screen clearing, using the color set using glClearColor
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ shader_program->set_input_data("position", *gpuModel);
frame.draw(shader_program.get());
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ sand_shader_program->set_input_data("position", *gpuSand);
+ frame.draw(sand_shader_program.get());
+
+ //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glfwSwapBuffers(window);
}
+ delete model_gpu_texture;
+ delete image;
+ delete gpuModel;
+ delete gpuSand;
glfwTerminate();
return 0;
}
@@ -166,13 +218,8 @@ void initGlew() {
}
}
-static void error_callback(int error, const char *description) {
- fprintf(stderr, "Opengl error: %s (%d)\n", description, error);
-}
-
GLFWwindow* createWindow() {
- glfwSetErrorCallback(error_callback);
- GLFWwindow *window = glfwCreateWindow(1280, 720, "Amalgine", nullptr, nullptr);
+ GLFWwindow *window = glfwCreateWindow(1920, 1080, "Amalgine", nullptr, nullptr);
if(!window)
{
fprintf(stderr, "Failed to open GLFW window\n");
diff --git a/src/model_loader/ObjModelLoader.cpp b/src/model_loader/ObjModelLoader.cpp
index 1bae458..51d8a74 100644
--- a/src/model_loader/ObjModelLoader.cpp
+++ b/src/model_loader/ObjModelLoader.cpp
@@ -1,25 +1,20 @@
#include "../../include/model_loader/ObjModelLoader.hpp"
#include "../../include/File.hpp"
#include "../../include/DataView.hpp"
+#include "../../include/Image.hpp"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
+#include <libgen.h>
+#include <string>
namespace amalgine {
static StringView get_line(char *str, size_t size) {
- #if 0
char *found_ptr = (char*)memchr(str, '\n', size);
if(!found_ptr)
found_ptr = str + size;
return { str, static_cast<size_t>(found_ptr - str) };
- #endif
- for(size_t i = 0; i < size; ++i) {
- char c = str[i];
- if(c == '\n')
- return { str, i };
- }
- return { str, size };
}
static bool is_whitespace(char c) {
@@ -44,13 +39,13 @@ namespace amalgine {
}
// Return the number of columns, limited by @output_size
- static int split_columns(const StringView &str, StringView *output, int output_size) {
+ static int split_columns(const StringView &str, char split_char, StringView *output, int output_size) {
char *data = str.data;
ssize_t size = str.size;
int column = 0;
while(size > 0) {
- char *found_ptr = (char*)memchr(data, ' ', size);
+ char *found_ptr = (char*)memchr(data, split_char, size);
if(!found_ptr)
found_ptr = data + size;
@@ -75,17 +70,32 @@ namespace amalgine {
return static_cast<size_t>(found_ptr - str.data);
}
- void ObjModelLoader::load_from_file(const char *filepath, std::vector<Triangle3D> &triangles) {
+ struct Material {
+ Image *image;
+ };
+
+ static Result<Material> load_material_from_file(const char *filepath);
+
+ void ObjModelLoader::load_from_file(const char *filepath, std::vector<Triangle3D> &triangles, std::vector<vec2f> &texture_coords, Image **image) {
+ triangles.clear();
+ texture_coords.clear();
+ *image = nullptr;
+
size_t file_size;
char *file_data = file_get_content(filepath, &file_size);
- triangles.clear();
if(!file_data)
return;
- const int max_columns = 12;
+ std::string dir_path = filepath;
+ dirname(&dir_path[0]);
+ const int dir_path_size = strlen(dir_path.c_str());
+ dir_path.resize(dir_path_size);
+
+ const int max_columns = 8;
StringView columns[max_columns];
std::vector<Vertex3D> vertices;
+ std::vector<vec2f> temp_texture_coords;
char *data = file_data;
ssize_t size = file_size;
@@ -94,9 +104,9 @@ namespace amalgine {
if(line_data.size > 2 && memcmp(line_data.data, "v ", 2) == 0) {
//printf("line: |%.*s|\n", line_data.size, line_data.data);
- StringView column_data = { line_data.data + 1, line_data.size - 1 };
+ StringView column_data = { line_data.data + 2, line_data.size - 2 };
- int num_columns = split_columns(column_data, columns, max_columns);
+ int num_columns = split_columns(column_data, ' ', columns, max_columns);
if(num_columns >= 3) {
columns[0].data[columns[0].size] = '\0';
columns[1].data[columns[1].size] = '\0';
@@ -105,33 +115,140 @@ namespace amalgine {
}
} else if(line_data.size > 2 && memcmp(line_data.data, "f ", 2) == 0) {
//printf("line: |%.*s|\n", line_data.size, line_data.data);
- StringView column_data = { line_data.data + 1, line_data.size - 1 };
+ StringView column_data = { line_data.data + 2, line_data.size - 2 };
- int num_columns = split_columns(column_data, columns, max_columns);
+ int num_columns = split_columns(column_data, ' ', columns, max_columns);
if(num_columns == 3 || num_columns == 4) {
bool valid = true;
- int indices[4];
+ int vertex_indices[4];
+ int texture_coord_indices[4];
+
for(int i = 0; i < num_columns; ++i) {
- columns[i].size = find_or_end(columns[i], '/');
- columns[i].data[columns[i].size] = '\0';
- indices[i] = atoi(columns[i].data);
- //printf("column[%d] = %.*s = %d\n", i, columns[i].size, columns[i].data, vertices.size());
- if(indices[i] < 1 || indices[i] > vertices.size()) {
+ const int max_attributes = 3;
+ StringView attributes[max_attributes];
+ int num_attributes = split_columns(columns[i], '/', attributes, max_attributes);
+ assert(num_attributes == 3);
+
+ attributes[0].data[attributes[0].size] = '\0';
+ attributes[1].data[attributes[1].size] = '\0';
+ attributes[2].data[attributes[2].size] = '\0';
+
+ vertex_indices[i] = atoi(attributes[0].data);
+ texture_coord_indices[i] = atoi(attributes[1].data);
+
+ if(vertex_indices[i] < 1 || vertex_indices[i] > vertices.size()) {
valid = false;
+ abort();
break;
}
- --indices[i];
+
+ if(texture_coord_indices[i] < 1 || texture_coord_indices[i] > temp_texture_coords.size()) {
+ valid = false;
+ abort();
+ break;
+ }
+
+ --vertex_indices[i];
+ --texture_coord_indices[i];
}
if(valid) {
- if(num_columns == 3) {
- triangles.push_back({ vertices[indices[0]], vertices[indices[1]], vertices[indices[2]] });
- } else if(num_columns == 4) {
- triangles.push_back({ vertices[indices[0]], vertices[indices[1]], vertices[indices[3]] });
- triangles.push_back({ vertices[indices[3]], vertices[indices[2]], vertices[indices[1]] });
+ if(num_columns == 3) { // Triangle
+ triangles.push_back({ vertices[vertex_indices[0]], vertices[vertex_indices[1]], vertices[vertex_indices[2]] });
+
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[0]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[1]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[2]]);
+ } else if(num_columns == 4) { // Quad, convert to triangle. TODO: Support rendering quads instead of converting to triangles
+ triangles.push_back({ vertices[vertex_indices[0]], vertices[vertex_indices[1]], vertices[vertex_indices[3]] });
+ triangles.push_back({ vertices[vertex_indices[3]], vertices[vertex_indices[2]], vertices[vertex_indices[1]] });
+
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[0]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[1]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[3]]);
+
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[3]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[2]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[1]]);
}
}
}
+ } else if(line_data.size > 3 && memcmp(line_data.data, "vt ", 3) == 0) {
+ StringView column_data = { line_data.data + 3, line_data.size - 3 };
+ int num_columns = split_columns(column_data, ' ', columns, max_columns);
+ if(num_columns == 2) {
+ columns[0].data[columns[0].size] = '\0';
+ columns[1].data[columns[1].size] = '\0';
+ temp_texture_coords.push_back({ atof(columns[0].data), atof(columns[1].data) });
+ }
+ } else if(line_data.size > 7 && memcmp(line_data.data, "mtllib ", 7) == 0) {
+ StringView column_data = { line_data.data + 7, line_data.size - 7 };
+ int num_columns = split_columns(column_data, ' ', columns, max_columns);
+ if(num_columns == 1) {
+ std::string material_path;
+ material_path.resize(dir_path_size + 1 + columns[0].size);
+ memcpy(&material_path[0], dir_path.data(), dir_path_size);
+ material_path[dir_path_size] = '/';
+ memcpy(&material_path[dir_path_size + 1], columns[0].data, columns[0].size);
+ printf("mtl file: %.*s\n", material_path.size(), material_path.data());
+
+ assert(!*image);
+ Result<Material> material = load_material_from_file(material_path.c_str());
+ if(!material) {
+ fprintf(stderr, "Error: %s\n", material.getErrorMsg().c_str());
+ abort();
+ goto cleanup;
+ }
+
+ *image = material->image;
+ }
+ }
+
+ data += (line_data.size + 1);
+ size -= (line_data.size + 1);
+ }
+
+ printf("num tex coords: %d\n", texture_coords.size());
+
+ cleanup:
+ free(file_data);
+ }
+
+ Result<Material> load_material_from_file(const char *filepath) {
+ size_t file_size;
+ char *file_data = file_get_content(filepath, &file_size);
+ if(!file_data)
+ return Result<Material>::Err("Failed to load material: " + std::string(filepath));
+
+ std::string dir_path = filepath;
+ dirname(&dir_path[0]);
+ const int dir_path_size = strlen(dir_path.c_str());
+ dir_path.resize(dir_path_size);
+
+ Image *image = nullptr;
+
+ char *data = file_data;
+ ssize_t size = file_size;
+ while(size > 0) {
+ StringView line_data = get_line(data, size);
+
+ if(line_data.size > 7 && memcmp(line_data.data, "map_Kd ", 7) == 0) {
+ StringView texture_file = { line_data.data + 7, line_data.size - 7 };
+ line_data.data[line_data.size] = '\0';
+
+ std::string texture_path;
+ texture_path.resize(dir_path_size + 1 + texture_file.size);
+ memcpy(&texture_path[0], dir_path.data(), dir_path_size);
+ texture_path[dir_path_size] = '/';
+ memcpy(&texture_path[dir_path_size + 1], texture_file.data, texture_file.size);
+ printf("texture file: |%.*s|\n", texture_path.size(), texture_path.data());
+
+ Result<Image*> image_result = Image::loadFromFile(texture_path.c_str());
+ if(!image_result)
+ return Result<Material>::Err("Failed to load texture: " + texture_path);
+
+ image = image_result.unwrap();
+ break;
}
data += (line_data.size + 1);
@@ -139,5 +256,6 @@ namespace amalgine {
}
free(file_data);
+ return Result<Material>::Ok({ image });
}
} \ No newline at end of file