added MOCV chunk parsing for vertex colours

This commit is contained in:
Natsirt867
2026-01-06 00:49:59 -06:00
parent da45ad2815
commit 85171a5d21
6 changed files with 73 additions and 34 deletions

View File

@@ -265,10 +265,10 @@ void init() {
log_info("Getting (CTFNightelf_A.wmo) for WMO data test");
//WMOData test_WMOdata = load_wmo_data(hMPQ, "World\\wmo\\PvP\\Buildings\\CTF\\CTFOrc_A.wmo");*/
// "World\\wmo\\Dungeon\\MD_Caveden\\MD_VrykulDen.wmo"
//char *wmoFileName = "World\\wmo\\PvP\\Buildings\\CTF\\CTFNightelf_A.wmo";
char *wmoFileName = "World\\wmo\\PvP\\Buildings\\CTF\\CTFNightelf_A.wmo";
//char *wmoFileName = "World\\wmo\\Dungeon\\MD_Caveden\\MD_VrykulDen.wmo";
//char *wmoFileName = "World\\wmo\\Test\\test_petes_wmo_rotation_test.wmo";
char *wmoFileName = "World\\wmo\\Dungeon\\Ulduar\\Ulduar_Raid.wmo";
//char *wmoFileName = "World\\wmo\\Dungeon\\Ulduar\\Ulduar_Raid.wmo";
WMOData test_WMOdata = load_wmo_data(&manager, wmoFileName);
const char *log_file_name = "wmo_geometry_export.obj.log";
@@ -472,7 +472,7 @@ void init() {
//glFrontFace(GL_CW); // GL_CCW for counter clock-wise
glDisable(GL_CULL_FACE);
float speed = 10.0f; // 1 unit per second
float speed = 30.0f; // 1 unit per second
float last_position = 0.0f;
float cam_speed = 30.0f; // 1 unit per sec
float cam_yaw_speed = 1.0f; // 3.5 degrees per second
@@ -597,19 +597,16 @@ void init() {
yaw_rad = TO_RAD(cam_yaw);
pitch_rad = TO_RAD(cam_pitch);
vec3_t cam_front;
cam_front.x = cosf(yaw_rad) * cosf(pitch_rad);
cam_front.y = sinf(pitch_rad);
cam_front.z = sinf(yaw_rad) * cosf(pitch_rad);
vec3_normalize(&cam_front);
vec3_t world_up = { 0.0f, 1.0f, 0.0f };
vec3_t cam_right = vec3_cross(cam_front, world_up);
cam_right = vec3_cross(cam_front, world_up);
vec3_normalize(&cam_right);
vec3_t cam_up = vec3_cross(cam_right, cam_front);
cam_up = vec3_cross(cam_right, cam_front);
vec3_normalize(&cam_up);
float move_dist = cam_speed * elapsed_seconds;

View File

@@ -27,16 +27,7 @@ GroupMesh create_mesh_from_group(const WMOGroupData* group, const WMORootData* r
const C3Vector* normals = (const C3Vector*)group->monr_data_ptr;
const C2Vector* texCoords = (const C2Vector*)group->motv_data_ptr;
// TODO: double check if we need the offset here, I believe its
GLfloat offset_x = group->header.boundingBox.min[0];
GLfloat offset_y = group->header.boundingBox.min[1];
GLfloat offset_z = group->header.boundingBox.min[2];
for (size_t i = 0; i < num_vertices; i++) {
//float wx = positions[i].x + offset_x;
//float wy = positions[i].y + offset_y;
//float wz = positions[i].z + offset_z;
float wx = positions[i].x;
float wy = positions[i].y;
float wz = positions[i].z;
@@ -75,11 +66,6 @@ GroupMesh create_mesh_from_group(const WMOGroupData* group, const WMORootData* r
if (vertices[k].position.z < minZ) minZ = vertices[k].position.z;
if (vertices[k].position.z > maxZ) maxZ = vertices[k].position.z;
}
log_info("MESH DEBUG: Group has %zu vertices", num_vertices);
// This is the critical line. It tells us where the mesh actually IS.
log_info("BOUNDS: X[%.1f to %.1f] Y[%.1f to %.1f] Z[%.1f to %.1f]",
minX, maxX, minY, maxY, minZ, maxZ);
}
if (group->moba_data_ptr && group->moba_size > 0) {

View File

@@ -14,6 +14,7 @@ typedef struct {
C3Vector position;
C3Vector normal;
C2Vector texCoord;
CImVector colour;
} Vertex;
typedef struct {

View File

@@ -200,8 +200,6 @@ void parse_mopr_chunk(const WMORootData *wmo_root_data) {
log_info("Portal reference %zu: portalIndex: %u, groupIndex: %u, side: %d", i, portal_ref.portalIndex,
portal_ref.groupIndex, portal_ref.side);
}
// TODO - DOES THE CALLER OR THE FUNCTION FREE MALLOC()?
}
WMOGroupData parse_wmo_group_file(ArchiveManager *archives, const char *group_file_path) {
@@ -385,6 +383,44 @@ void parse_movi_chunk(const WMOGroupData *wmo_group_data) {
}
void parse_mocv_chunk(const WMOGroupData *wmo_group_data) {
if (wmo_group_data->mocv_data_ptr == NULL || wmo_group_data->mocv_size == 0) {
log_error("Could not find valid MOCV chunk inside WMO Group File");
return;
}
//uint32_t expected_count = wmo_group_data->movt_size / sizeof(C3Vector);
uint32_t actual_colour_count = wmo_group_data->mocv_size / sizeof(uint32_t);
/*
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");
}*/
const CImVector* colourVertexList = (const CImVector*)wmo_group_data->mocv_data_ptr;
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++) {
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");
}
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);
}
}
void parse_mogp_sub_chunks(const char *mogp_data_buffer, DWORD mogp_data_size, WMOGroupData *out_group_data) {
if (mogp_data_size < sizeof(SMOGroupHeader)) {
log_error("MOGP chunk size is too small for SMOGroupHeader");
@@ -470,6 +506,11 @@ void parse_mogp_sub_chunks(const char *mogp_data_buffer, DWORD mogp_data_size, W
case MOBN:
case MOBR:
case MOCV:
out_group_data->mocv_data_ptr = data_start;
out_group_data->mocv_size = header->chunk_size;
log_info(" -> MOCV Chunk found at offset %td", out_group_data->mocv_data_ptr - mogp_data_buffer);
parse_mocv_chunk(out_group_data);
break;
case MOC2:
case MLIQ:
case MORI:
@@ -486,6 +527,7 @@ void parse_mogp_sub_chunks(const char *mogp_data_buffer, DWORD mogp_data_size, W
}
}
/*
void extract_wmo_geometry(const WMORootData *wmo_root_data, FILE *output_file) {
if (wmo_root_data->groups == NULL || wmo_root_data->group_count == 0) {
log_error("No WMO group data found to extract geometry from");
@@ -517,6 +559,7 @@ void extract_wmo_geometry(const WMORootData *wmo_root_data, FILE *output_file) {
size_t cumulative_vertex_count = 0;
for (size_t i = 0; i < wmo_root_data->group_count; i++) {
const WMOGroupData *group = &wmo_root_data->groups[i];
@@ -529,9 +572,9 @@ void extract_wmo_geometry(const WMORootData *wmo_root_data, FILE *output_file) {
fprintf(output_file, "\n# -------------------\n");
fprintf(output_file, "g Group_%zu\n", i);
/* -----------------------------------------------------------------
1. SETUP ALL CHUNKS AND OFFSETS
----------------------------------------------------------------- */
// -----------------------------------------------------------------
// 1. SETUP ALL CHUNKS AND OFFSETS
// -----------------------------------------------------------------
size_t num_vertices = group->movt_size / sizeof(C3Vector);
const C3Vector *vertices = (const C3Vector *)group->movt_data_ptr;
@@ -546,9 +589,9 @@ void extract_wmo_geometry(const WMORootData *wmo_root_data, FILE *output_file) {
fprintf(output_file, "# Found %zu vertices (MOVT), normals (MONR), and texcoords (MOTV)\n", num_vertices);
/* -----------------------------------------------------------------
2. VERTICES, NORMALS, AND TEXCOORDS (MOVT, MONR, MOTV) - ONE LOOP
----------------------------------------------------------------- */
// -----------------------------------------------------------------
// 2. VERTICES, NORMALS, AND TEXCOORDS (MOVT, MONR, MOTV) - ONE LOOP
// -----------------------------------------------------------------
for (size_t j = 0; j < num_vertices; j++) {
// A. Vertices (v) - Apply offset and coordinate swap
float x_wmo = vertices[j].x + offset_x;
@@ -586,9 +629,9 @@ void extract_wmo_geometry(const WMORootData *wmo_root_data, FILE *output_file) {
fprintf(output_file, "vn %.6f %.6f %.6f\n", nx_obj, ny_obj, nz_obj);
}
/* -----------------------------------------------------------------
3. FACES (MOVI & MOBA) - Second Loop
----------------------------------------------------------------- */
// -----------------------------------------------------------------
// 3. FACES (MOVI & MOBA) - Second Loop
// -----------------------------------------------------------------
const uint16_t *all_indices = (const uint16_t *)group->movi_data_ptr;
const SMOBatch *batches = (const SMOBatch *)group->moba_data_ptr;
size_t num_batches = group->moba_size / sizeof(SMOBatch);
@@ -636,6 +679,7 @@ void extract_wmo_geometry(const WMORootData *wmo_root_data, FILE *output_file) {
log_info("Geometry data written to output file");
}
*/
// isTransFace: triangles flagged as TRANSITION. They blend lighting from exterior to interior
char smopoly_is_trans_face(SMOPolyFlags flags) {

View File

@@ -13,6 +13,7 @@ void parse_mohd_chunk(const WMORootData *wmo_root_data);
void parse_mopv_chunk(const WMORootData *wmo_root_data);
void parse_mopt_chunk(const WMORootData *wmo_root_data);
void parse_mopr_chunk(const WMORootData *wmo_root_data);
void parse_mocv_chunk(const WMOGroupData *wmo_group_data);
void parse_mogp_sub_chunks(const char *mogp_data_buffer, DWORD mogp_data_size, WMOGroupData *out_group_data);
WMOGroupData parse_wmo_group_file(ArchiveManager *archives, const char *group_file_path);
void extract_wmo_geometry(const WMORootData *wmo_root_data, FILE *output_file);

View File

@@ -37,6 +37,14 @@ typedef union {
} components;
} CArgb;
// a color given in values of blue, green, red and alpha
typedef union {
uint32_t raw_value;
struct {
uint8_t r, g, b, a;
};
} CImVector;
// Axis-aligned bounding box
typedef struct {
float min[3];
@@ -242,6 +250,8 @@ typedef struct {
DWORD moqg_size;
const char *molr_data_ptr;
DWORD molr_size;
const char *mocv_data_ptr; // Vertex colours
DWORD mocv_size;
// TODO: chunks dependent on flag, need to add their ptr's
} WMOGroupData;