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"); 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");*/ //WMOData test_WMOdata = load_wmo_data(hMPQ, "World\\wmo\\PvP\\Buildings\\CTF\\CTFOrc_A.wmo");*/
// "World\\wmo\\Dungeon\\MD_Caveden\\MD_VrykulDen.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\\Dungeon\\MD_Caveden\\MD_VrykulDen.wmo";
//char *wmoFileName = "World\\wmo\\Test\\test_petes_wmo_rotation_test.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); WMOData test_WMOdata = load_wmo_data(&manager, wmoFileName);
const char *log_file_name = "wmo_geometry_export.obj.log"; 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 //glFrontFace(GL_CW); // GL_CCW for counter clock-wise
glDisable(GL_CULL_FACE); 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 last_position = 0.0f;
float cam_speed = 30.0f; // 1 unit per sec float cam_speed = 30.0f; // 1 unit per sec
float cam_yaw_speed = 1.0f; // 3.5 degrees per second float cam_yaw_speed = 1.0f; // 3.5 degrees per second
@@ -597,19 +597,16 @@ void init() {
yaw_rad = TO_RAD(cam_yaw); yaw_rad = TO_RAD(cam_yaw);
pitch_rad = TO_RAD(cam_pitch); pitch_rad = TO_RAD(cam_pitch);
vec3_t cam_front;
cam_front.x = cosf(yaw_rad) * cosf(pitch_rad); cam_front.x = cosf(yaw_rad) * cosf(pitch_rad);
cam_front.y = sinf(pitch_rad); cam_front.y = sinf(pitch_rad);
cam_front.z = sinf(yaw_rad) * cosf(pitch_rad); cam_front.z = sinf(yaw_rad) * cosf(pitch_rad);
vec3_normalize(&cam_front); vec3_normalize(&cam_front);
cam_right = vec3_cross(cam_front, world_up);
vec3_t world_up = { 0.0f, 1.0f, 0.0f };
vec3_t cam_right = vec3_cross(cam_front, world_up);
vec3_normalize(&cam_right); 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); vec3_normalize(&cam_up);
float move_dist = cam_speed * elapsed_seconds; 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 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;
// 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++) { 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 wx = positions[i].x;
float wy = positions[i].y; float wy = positions[i].y;
float wz = positions[i].z; 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 < minZ) minZ = vertices[k].position.z;
if (vertices[k].position.z > maxZ) maxZ = 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) { if (group->moba_data_ptr && group->moba_size > 0) {

View File

@@ -14,6 +14,7 @@ typedef struct {
C3Vector position; C3Vector position;
C3Vector normal; C3Vector normal;
C2Vector texCoord; C2Vector texCoord;
CImVector colour;
} Vertex; } Vertex;
typedef struct { 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, log_info("Portal reference %zu: portalIndex: %u, groupIndex: %u, side: %d", i, portal_ref.portalIndex,
portal_ref.groupIndex, portal_ref.side); 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) { 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) { void parse_mogp_sub_chunks(const char *mogp_data_buffer, DWORD mogp_data_size, WMOGroupData *out_group_data) {
if (mogp_data_size < sizeof(SMOGroupHeader)) { if (mogp_data_size < sizeof(SMOGroupHeader)) {
log_error("MOGP chunk size is too small for 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 MOBN:
case MOBR: case MOBR:
case MOCV: 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 MOC2:
case MLIQ: case MLIQ:
case MORI: 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) { void extract_wmo_geometry(const WMORootData *wmo_root_data, FILE *output_file) {
if (wmo_root_data->groups == NULL || wmo_root_data->group_count == 0) { if (wmo_root_data->groups == NULL || wmo_root_data->group_count == 0) {
log_error("No WMO group data found to extract geometry from"); 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; size_t cumulative_vertex_count = 0;
for (size_t i = 0; i < wmo_root_data->group_count; i++) { for (size_t i = 0; i < wmo_root_data->group_count; i++) {
const WMOGroupData *group = &wmo_root_data->groups[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, "\n# -------------------\n");
fprintf(output_file, "g Group_%zu\n", i); 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); size_t num_vertices = group->movt_size / sizeof(C3Vector);
const C3Vector *vertices = (const C3Vector *)group->movt_data_ptr; 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); 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++) { for (size_t j = 0; j < num_vertices; j++) {
// A. Vertices (v) - Apply offset and coordinate swap // A. Vertices (v) - Apply offset and coordinate swap
float x_wmo = vertices[j].x + offset_x; 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); 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 uint16_t *all_indices = (const uint16_t *)group->movi_data_ptr;
const SMOBatch *batches = (const SMOBatch *)group->moba_data_ptr; const SMOBatch *batches = (const SMOBatch *)group->moba_data_ptr;
size_t num_batches = group->moba_size / sizeof(SMOBatch); 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"); log_info("Geometry data written to output file");
} }
*/
// isTransFace: triangles flagged as TRANSITION. They blend lighting from exterior to interior // isTransFace: triangles flagged as TRANSITION. They blend lighting from exterior to interior
char smopoly_is_trans_face(SMOPolyFlags flags) { 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_mopv_chunk(const WMORootData *wmo_root_data);
void parse_mopt_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_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); 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); 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);

View File

@@ -37,6 +37,14 @@ typedef union {
} components; } components;
} CArgb; } 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 // Axis-aligned bounding box
typedef struct { typedef struct {
float min[3]; float min[3];
@@ -242,6 +250,8 @@ typedef struct {
DWORD moqg_size; DWORD moqg_size;
const char *molr_data_ptr; const char *molr_data_ptr;
DWORD molr_size; DWORD molr_size;
const char *mocv_data_ptr; // Vertex colours
DWORD mocv_size;
// TODO: chunks dependent on flag, need to add their ptr's // TODO: chunks dependent on flag, need to add their ptr's
} WMOGroupData; } WMOGroupData;