added rendering of MOCV vertex colours
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
10
src/renderer/render_types.h
Normal file
10
src/renderer/render_types.h
Normal 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
|
||||
10
src/util.c
10
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}*/
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user