diff --git a/CMakeLists.txt b/CMakeLists.txt index 776d6e8..3425397 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ add_executable(BLPExtractor src/renderer/vector.h src/renderer/texture.c src/renderer/texture.h + src/renderer/render_types.h ) # static C runtime /MTd (debug mode StormLibDUS.lib) diff --git a/shaders/wmo.frag b/shaders/wmo.frag index dfc2a9c..ebf4378 100644 --- a/shaders/wmo.frag +++ b/shaders/wmo.frag @@ -2,6 +2,7 @@ out vec4 FragColor; in vec2 TexCoord; +in vec4 VertexColour; uniform sampler2D texSampler; void main() { @@ -11,5 +12,5 @@ void main() { if (texColor.a < 0.1) discard; //FragColor = vec4(0.6, 0.0, 1.0, 1.0); - FragColor = texColor; + FragColor = texColor * VertexColour; } \ No newline at end of file diff --git a/shaders/wmo.vert b/shaders/wmo.vert index d4c6885..b74365b 100644 --- a/shaders/wmo.vert +++ b/shaders/wmo.vert @@ -2,8 +2,10 @@ layout(location = 0) in vec3 vertex_position; // position layout(location = 1) in vec3 vertex_normal; // colour of each vertex point layout(location = 2) in vec2 vertex_tex; +layout(location = 3) in vec4 vertex_colour; out vec2 TexCoord; +out vec4 VertexColour; uniform mat4 matrix; // must match "matrix" in C code uniform mat4 view; // must match "view" in C code @@ -12,4 +14,5 @@ uniform mat4 proj; // must match "proj" in C code void main() { gl_Position = proj * view * matrix * vec4(vertex_position, 1.0); TexCoord = vertex_tex; + VertexColour = vertex_colour; } \ No newline at end of file diff --git a/src/renderer/mesh.c b/src/renderer/mesh.c index 39757ee..c54720c 100644 --- a/src/renderer/mesh.c +++ b/src/renderer/mesh.c @@ -26,6 +26,11 @@ GroupMesh create_mesh_from_group(const WMOGroupData* group, const WMORootData* r const C3Vector* positions = (const C3Vector*)group->movt_data_ptr; const C3Vector* normals = (const C3Vector*)group->monr_data_ptr; const C2Vector* texCoords = (const C2Vector*)group->motv_data_ptr; + const CImVector* colours = (const CImVector*)group->mocv_data_ptr; + // size_t num_colours = (group->mocv_data_ptr) ? group->mocv_size / 4 : 0; + + int is_outdoor = !group->header.flags.isIndoor; + int has_mocv = group->header.flags.vertexColors; for (size_t i = 0; i < num_vertices; i++) { float wx = positions[i].x; @@ -51,6 +56,17 @@ GroupMesh create_mesh_from_group(const WMOGroupData* group, const WMORootData* r } else { vertices[i].texCoord = (C2Vector){0.0f, 0.0f}; } + + // TODO: confirm this check is proper and we don't need to compare colours to vertices + if (has_mocv && !is_outdoor) { + // swap order (BGRA) for openGL rendering (RGBA) + vertices[i].colour.b = colours[i].r; + vertices[i].colour.g = colours[i].g; + vertices[i].colour.r = colours[i].b; + vertices[i].colour.a = colours[i].a; + } else { + vertices[i].colour = (CImVector){ .b = 255, .g = 255, .r = 255, .a = 255 }; + } } if (num_vertices > 0) { @@ -122,7 +138,9 @@ GroupMesh create_mesh_from_group(const WMOGroupData* group, const WMORootData* r // 2: TexCoord glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(2 * sizeof(C3Vector))); glEnableVertexAttribArray(2); - + // 3: Colour + glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)(32)); + glEnableVertexAttribArray(3); glBindVertexArray(0); free(vertices); diff --git a/src/renderer/mesh.h b/src/renderer/mesh.h index 23dee6f..11f1290 100644 --- a/src/renderer/mesh.h +++ b/src/renderer/mesh.h @@ -10,13 +10,6 @@ #include "../wmo/wmo_structs.h" -typedef struct { - C3Vector position; - C3Vector normal; - C2Vector texCoord; - CImVector colour; -} Vertex; - typedef struct { uint32_t indexOffset; // where in the EBO this batch starts uint32_t indexCount; // how many indices to draw diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h new file mode 100644 index 0000000..0cf025b --- /dev/null +++ b/src/renderer/render_types.h @@ -0,0 +1,10 @@ +// +// Created by Tristan on 1/6/2026. +// + +#ifndef RENDER_TYPES_H +#define RENDER_TYPES_H + +// TODO: move common types out of mesh.h/wmo_structures.h into here for header simplicity when linking :) + +#endif //RENDER_TYPES_H diff --git a/src/util.c b/src/util.c index 5f3b8f6..4d69946 100644 --- a/src/util.c +++ b/src/util.c @@ -49,7 +49,7 @@ int load_wmo_file(const char *filename, FILE **file_ptr_out) { int create_dir_recursive(const char *full_path) { char temp_path[FILENAME_MAX]; - log_info("Full Path in craete_dir_recursive == '%s", full_path); + //log_info("Full Path in create_dir_recursive == '%s", full_path); strncpy(temp_path, full_path, FILENAME_MAX - 1); temp_path[FILENAME_MAX - 1] = '\0'; @@ -412,23 +412,23 @@ void parse_momt_and_extract_textures(ArchiveManager *archives, const WMORootData // Skip materials that dont reference a texture if (offset == 0) { - log_info("Material [%zu]: No texture referenced (Offset 0)\n", i); + log_info("Material [%zu]: No texture referenced (Offset 0)", i); continue; } if (offset >= wmo_data->motx_size) { - log_error("Material [%zu]: Invalid texture offset %lu (outside MOTX boundaries).\n", i, offset); + log_error("Material [%zu]: Invalid texture offset %lu (outside MOTX boundaries).", i, offset); continue; } const char *mpq_blp_path = wmo_data->motx_data_ptr + offset; // offset was throwing us off by 4 bytes it looked like - log_info("Material [%zu] references texture at offset %lu: %s\n", i, offset, mpq_blp_path); + log_info("Material [%zu] references texture at offset %lu: %s", i, offset, mpq_blp_path); size_t file_len = strlen(mpq_blp_path); char *local_path_buffer = (char *)malloc(file_len + 1); if (local_path_buffer == NULL) { - log_error("Memory allocation failed for output path.\n"); + log_error("Memory allocation failed for output path."); continue; } diff --git a/src/wmo/wmo.c b/src/wmo/wmo.c index af7770e..018a7fe 100644 --- a/src/wmo/wmo.c +++ b/src/wmo/wmo.c @@ -403,22 +403,22 @@ void parse_mocv_chunk(const WMOGroupData *wmo_group_data) { log_info("Total MOCV Bytes (%lu) / 4 = %lu", wmo_group_data->mocv_size, (wmo_group_data->mocv_size) / sizeof(uint32_t)); // TODO: store data in a new packed vertex array - for (size_t i = 0; i < actual_colour_count; i++) { + /*for (size_t i = 0; i < actual_colour_count; i++) { uint32_t expected_count = wmo_group_data->movt_size / sizeof(C3Vector); - if (expected_count != actual_colour_count) { - log_warn("We have %d vertices but %d colours", expected_count, actual_colour_count); - } else { - log_info("1:1 vertex to colour mapping confirmed"); - } + //if (expected_count != actual_colour_count) { + // log_warn("We have %d vertices but %d colours", expected_count, actual_colour_count); + //} else { + // log_info("1:1 vertex to colour mapping confirmed"); + //} uint8_t b = colourVertexList[i].b; uint8_t g = colourVertexList[i].g; uint8_t r = colourVertexList[i].r; uint8_t a = colourVertexList[i].a; - log_info("Vertex %zu has colours: (B: %u, G: %u, R: %u, A: %u)", i, b, g, r, a); - } + //log_info("Vertex %zu has colours: (B: %u, G: %u, R: %u, A: %u)", i, b, g, r, a); + }*/ } void parse_mogp_sub_chunks(const char *mogp_data_buffer, DWORD mogp_data_size, WMOGroupData *out_group_data) { @@ -698,11 +698,11 @@ char smopoly_is_collidable(SMOPolyFlags flags) { return flags.f_collision || smopoly_is_render_face(flags); } - void wmo_load_textures_to_gpu(ArchiveManager* manager, WMORootData* root) { - if (!root->momt_data_ptr || !root->motx_data_ptr) - // TODO: error logging + if (!root->momt_data_ptr || !root->motx_data_ptr) { + log_error("In 'wmo_load_textures_to_gpu()' MOMT and MOTX invalid"); return; + } SMOMaterial *materials = (SMOMaterial *)root->momt_data_ptr; int num_materials = root->momt_size / sizeof(SMOMaterial); @@ -744,4 +744,60 @@ void wmo_load_textures_to_gpu(ArchiveManager* manager, WMORootData* root) { root->material_textures[i] = 0; } } -} \ No newline at end of file +} + +// TODO: SEE MESH.C - CREATE_GROUP_FROM_MESH +/* +Vertex* build_render_batch(WMOGroupData* group, size_t* out_vertex_count) { + Vertex* vertices = { 0 }; + + if (!group->movt_data_ptr) { + log_error("In 'build_render_batch()' MOVT invalid"); + return vertices; + } + + size_t num_vertexs = group->movt_size / sizeof(C3Vector); + size_t num_colours = (group->mocv_data_ptr) ? group->mocv_size / 4 : 0; + + vertices = (Vertex*)malloc(num_vertexs * sizeof(Vertex)); + + if (!vertices) return NULL; + + const C3Vector* pos_ptr = (const C3Vector*)group->movt_data_ptr; + const CImVector* colour_ptr = (const CImVector*)group->mocv_data_ptr; + const C2Vector* uv_ptr = (const C2Vector*)group->motv_data_ptr; + const C3Vector* norm_ptr = (const C3Vector*)group->monr_data_ptr; + + + + for (int i = 0; i < num_vertexs; i++) { + // position + vertices[i].position = pos_ptr[i]; + + // colour + if (i < num_colours && colour_ptr) { + vertices[i].colour = colour_ptr[i]; + } else { + // fallback to white? + vertices[i].colour = (CImVector){ .b = 255, .g = 255, .r = 255, .a = 255 }; + } + + // uv's + if (uv_ptr) { + vertices[i].texCoord = uv_ptr[i]; + } else { + vertices[i].texCoord = (C2Vector){ 0, 0 }; + } + + // normals + if (norm_ptr) { + vertices[i].normal = norm_ptr[i]; + } else { + // default to up or out vector if missing + vertices[i].normal = (C3Vector){ 0, 1, 0 }; + } + } + + *out_vertex_count = num_vertexs; + return vertices; +}*/ \ No newline at end of file diff --git a/src/wmo/wmo.h b/src/wmo/wmo.h index 69c715b..996d5ce 100644 --- a/src/wmo/wmo.h +++ b/src/wmo/wmo.h @@ -7,6 +7,7 @@ #include "wmo_structs.h" + void get_wmo_group_names(HANDLE hMPQ, WMORootData *wmo_root_data, const char *wmo_file_path); void get_mosb_skybox(const WMORootData *wmo_root_data); void parse_mohd_chunk(const WMORootData *wmo_root_data); @@ -18,7 +19,7 @@ void parse_mogp_sub_chunks(const char *mogp_data_buffer, DWORD mogp_data_size, W WMOGroupData parse_wmo_group_file(ArchiveManager *archives, const char *group_file_path); void extract_wmo_geometry(const WMORootData *wmo_root_data, FILE *output_file); void wmo_load_textures_to_gpu(ArchiveManager* manager, WMORootData* root); - +Vertex* build_render_batch(WMOGroupData* group, size_t* out_vertex_count); bool smopoly_is_trans_face(SMOPolyFlags flags); bool smopoly_is_color(SMOPolyFlags flags); bool smopoly_is_render_face(SMOPolyFlags flags); diff --git a/src/wmo/wmo_structs.h b/src/wmo/wmo_structs.h index 4fbaef2..8fb6e47 100644 --- a/src/wmo/wmo_structs.h +++ b/src/wmo/wmo_structs.h @@ -30,6 +30,7 @@ typedef struct { } CAaBspNode; // unions allow access to a single uint32 or component value +// a color given in values of alpha, red, green, blue typedef union { uint32_t raw_value; struct { @@ -303,5 +304,12 @@ typedef struct { extern WMORootData out_wmo_data; +// TODO: move this to render_types.h for testing only in here +typedef struct { + C3Vector position; + C3Vector normal; + C2Vector texCoord; + CImVector colour; +} Vertex; #endif //WMO_STRUCTS_H