added rendering of MOCV vertex colours
This commit is contained in:
@@ -35,6 +35,7 @@ add_executable(BLPExtractor
|
|||||||
src/renderer/vector.h
|
src/renderer/vector.h
|
||||||
src/renderer/texture.c
|
src/renderer/texture.c
|
||||||
src/renderer/texture.h
|
src/renderer/texture.h
|
||||||
|
src/renderer/render_types.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# static C runtime /MTd (debug mode StormLibDUS.lib)
|
# static C runtime /MTd (debug mode StormLibDUS.lib)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
|
|
||||||
in vec2 TexCoord;
|
in vec2 TexCoord;
|
||||||
|
in vec4 VertexColour;
|
||||||
uniform sampler2D texSampler;
|
uniform sampler2D texSampler;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@@ -11,5 +12,5 @@ void main() {
|
|||||||
if (texColor.a < 0.1) discard;
|
if (texColor.a < 0.1) discard;
|
||||||
|
|
||||||
//FragColor = vec4(0.6, 0.0, 1.0, 1.0);
|
//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 = 0) in vec3 vertex_position; // position
|
||||||
layout(location = 1) in vec3 vertex_normal; // colour of each vertex point
|
layout(location = 1) in vec3 vertex_normal; // colour of each vertex point
|
||||||
layout(location = 2) in vec2 vertex_tex;
|
layout(location = 2) in vec2 vertex_tex;
|
||||||
|
layout(location = 3) in vec4 vertex_colour;
|
||||||
|
|
||||||
out vec2 TexCoord;
|
out vec2 TexCoord;
|
||||||
|
out vec4 VertexColour;
|
||||||
|
|
||||||
uniform mat4 matrix; // must match "matrix" in C code
|
uniform mat4 matrix; // must match "matrix" in C code
|
||||||
uniform mat4 view; // must match "view" 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() {
|
void main() {
|
||||||
gl_Position = proj * view * matrix * vec4(vertex_position, 1.0);
|
gl_Position = proj * view * matrix * vec4(vertex_position, 1.0);
|
||||||
TexCoord = vertex_tex;
|
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* positions = (const C3Vector*)group->movt_data_ptr;
|
||||||
const C3Vector* normals = (const C3Vector*)group->monr_data_ptr;
|
const C3Vector* normals = (const C3Vector*)group->monr_data_ptr;
|
||||||
const C2Vector* texCoords = (const C2Vector*)group->motv_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++) {
|
for (size_t i = 0; i < num_vertices; i++) {
|
||||||
float wx = positions[i].x;
|
float wx = positions[i].x;
|
||||||
@@ -51,6 +56,17 @@ GroupMesh create_mesh_from_group(const WMOGroupData* group, const WMORootData* r
|
|||||||
} else {
|
} else {
|
||||||
vertices[i].texCoord = (C2Vector){0.0f, 0.0f};
|
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) {
|
if (num_vertices > 0) {
|
||||||
@@ -122,7 +138,9 @@ GroupMesh create_mesh_from_group(const WMOGroupData* group, const WMORootData* r
|
|||||||
// 2: TexCoord
|
// 2: TexCoord
|
||||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(2 * sizeof(C3Vector)));
|
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(2 * sizeof(C3Vector)));
|
||||||
glEnableVertexAttribArray(2);
|
glEnableVertexAttribArray(2);
|
||||||
|
// 3: Colour
|
||||||
|
glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)(32));
|
||||||
|
glEnableVertexAttribArray(3);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
free(vertices);
|
free(vertices);
|
||||||
|
|||||||
@@ -10,13 +10,6 @@
|
|||||||
#include "../wmo/wmo_structs.h"
|
#include "../wmo/wmo_structs.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
C3Vector position;
|
|
||||||
C3Vector normal;
|
|
||||||
C2Vector texCoord;
|
|
||||||
CImVector colour;
|
|
||||||
} Vertex;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t indexOffset; // where in the EBO this batch starts
|
uint32_t indexOffset; // where in the EBO this batch starts
|
||||||
uint32_t indexCount; // how many indices to draw
|
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) {
|
int create_dir_recursive(const char *full_path) {
|
||||||
char temp_path[FILENAME_MAX];
|
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);
|
strncpy(temp_path, full_path, FILENAME_MAX - 1);
|
||||||
temp_path[FILENAME_MAX - 1] = '\0';
|
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
|
// Skip materials that dont reference a texture
|
||||||
if (offset == 0) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset >= wmo_data->motx_size) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *mpq_blp_path = wmo_data->motx_data_ptr + offset; // offset was throwing us off by 4 bytes it looked like
|
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);
|
size_t file_len = strlen(mpq_blp_path);
|
||||||
char *local_path_buffer = (char *)malloc(file_len + 1);
|
char *local_path_buffer = (char *)malloc(file_len + 1);
|
||||||
if (local_path_buffer == NULL) {
|
if (local_path_buffer == NULL) {
|
||||||
log_error("Memory allocation failed for output path.\n");
|
log_error("Memory allocation failed for output path.");
|
||||||
continue;
|
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));
|
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
|
// 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);
|
uint32_t expected_count = wmo_group_data->movt_size / sizeof(C3Vector);
|
||||||
|
|
||||||
if (expected_count != actual_colour_count) {
|
//if (expected_count != actual_colour_count) {
|
||||||
log_warn("We have %d vertices but %d colours", expected_count, actual_colour_count);
|
// log_warn("We have %d vertices but %d colours", expected_count, actual_colour_count);
|
||||||
} else {
|
//} else {
|
||||||
log_info("1:1 vertex to colour mapping confirmed");
|
// log_info("1:1 vertex to colour mapping confirmed");
|
||||||
}
|
//}
|
||||||
|
|
||||||
uint8_t b = colourVertexList[i].b;
|
uint8_t b = colourVertexList[i].b;
|
||||||
uint8_t g = colourVertexList[i].g;
|
uint8_t g = colourVertexList[i].g;
|
||||||
uint8_t r = colourVertexList[i].r;
|
uint8_t r = colourVertexList[i].r;
|
||||||
uint8_t a = colourVertexList[i].a;
|
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) {
|
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);
|
return flags.f_collision || smopoly_is_render_face(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void wmo_load_textures_to_gpu(ArchiveManager* manager, WMORootData* root) {
|
void wmo_load_textures_to_gpu(ArchiveManager* manager, WMORootData* root) {
|
||||||
if (!root->momt_data_ptr || !root->motx_data_ptr)
|
if (!root->momt_data_ptr || !root->motx_data_ptr) {
|
||||||
// TODO: error logging
|
log_error("In 'wmo_load_textures_to_gpu()' MOMT and MOTX invalid");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SMOMaterial *materials = (SMOMaterial *)root->momt_data_ptr;
|
SMOMaterial *materials = (SMOMaterial *)root->momt_data_ptr;
|
||||||
int num_materials = root->momt_size / sizeof(SMOMaterial);
|
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;
|
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"
|
#include "wmo_structs.h"
|
||||||
|
|
||||||
|
|
||||||
void get_wmo_group_names(HANDLE hMPQ, WMORootData *wmo_root_data, const char *wmo_file_path);
|
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 get_mosb_skybox(const WMORootData *wmo_root_data);
|
||||||
void parse_mohd_chunk(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);
|
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 extract_wmo_geometry(const WMORootData *wmo_root_data, FILE *output_file);
|
||||||
void wmo_load_textures_to_gpu(ArchiveManager* manager, WMORootData* root);
|
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_trans_face(SMOPolyFlags flags);
|
||||||
bool smopoly_is_color(SMOPolyFlags flags);
|
bool smopoly_is_color(SMOPolyFlags flags);
|
||||||
bool smopoly_is_render_face(SMOPolyFlags flags);
|
bool smopoly_is_render_face(SMOPolyFlags flags);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ typedef struct {
|
|||||||
} CAaBspNode;
|
} CAaBspNode;
|
||||||
|
|
||||||
// unions allow access to a single uint32 or component value
|
// unions allow access to a single uint32 or component value
|
||||||
|
// a color given in values of alpha, red, green, blue
|
||||||
typedef union {
|
typedef union {
|
||||||
uint32_t raw_value;
|
uint32_t raw_value;
|
||||||
struct {
|
struct {
|
||||||
@@ -303,5 +304,12 @@ typedef struct {
|
|||||||
|
|
||||||
extern WMORootData out_wmo_data;
|
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
|
#endif //WMO_STRUCTS_H
|
||||||
|
|||||||
Reference in New Issue
Block a user