added rendering of MOCV vertex colours

This commit is contained in:
Natsirt867
2026-01-06 18:04:07 -06:00
parent 85171a5d21
commit 84f2f7470f
10 changed files with 118 additions and 27 deletions

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
@@ -745,3 +745,59 @@ void wmo_load_textures_to_gpu(ArchiveManager* manager, WMORootData* root) {
}
}
}
// 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;
}*/

View File

@@ -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);

View File

@@ -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