From 9afc5fdef84fd3939b7e68d103b52172a7835223 Mon Sep 17 00:00:00 2001 From: Jeff Harris Date: Sat, 13 Jun 2020 00:13:49 -0700 Subject: [PATCH] Feature/brmodelupdate (#27) * Adds bbox and raduis generation for models --- src/BRSRC13/CORE/MATH/plane.c | 30 ++++- src/BRSRC13/CORE/STD/brmath.c | 5 - src/BRSRC13/CORE/V1DB/prepmesh.c | 194 +++++++++++++++++++++++++++++-- src/BRSRC13/br_types.h | 22 +++- 4 files changed, 234 insertions(+), 17 deletions(-) diff --git a/src/BRSRC13/CORE/MATH/plane.c b/src/BRSRC13/CORE/MATH/plane.c index 8450e914..5c41305b 100644 --- a/src/BRSRC13/CORE/MATH/plane.c +++ b/src/BRSRC13/CORE/MATH/plane.c @@ -1,5 +1,7 @@ #include "plane.h" +#include "brmath.h" #include "debug.h" +#include char rscid[49]; @@ -19,5 +21,31 @@ br_int_32 BrPlaneEquation(br_vector4* eqn, br_vector3* v0, br_vector3* v1, br_ve float nz; float d; float l; - NOT_IMPLEMENTED(); + + ay = v1->v[1] - v0->v[1]; + bz = v2->v[2] - v0->v[2]; + az = v1->v[2] - v0->v[2]; + bx = v2->v[0] - v0->v[0]; + ax = v1->v[0] - v0->v[0]; + by = v2->v[1] - v0->v[1]; + nx = ay * bz - az * by; + ny = az * bx - ax * bz; + nz = ax * by - ay * bx; + l = nx * nx + ny * ny + nz * nz; + l = BrFloatSqrt(l); + if (isnan(l)) { + nx = 0.0; + ny = 0.0; + nz = 1.0; + } else { + nx = nx * (1.0f / l); + ny = ny * (1.0f / l); + nz = nz * (1.0f / l); + } + d = nx * v0->v[0] + ny * v0->v[1] + nz * v0->v[2]; + eqn->v[0] = nx; + eqn->v[1] = ny; + eqn->v[2] = nz; + eqn->v[3] = d; + return !isnan(l); } diff --git a/src/BRSRC13/CORE/STD/brmath.c b/src/BRSRC13/CORE/STD/brmath.c index 997659f8..1795323f 100644 --- a/src/BRSRC13/CORE/STD/brmath.c +++ b/src/BRSRC13/CORE/STD/brmath.c @@ -8,33 +8,28 @@ char rscid[46]; // Size: 61 float BrFloatFloor(float f) { return floorf(f); - NOT_IMPLEMENTED(); } // Offset: 86 // Size: 61 float BrFloatCeil(float f) { return ceilf(f); - NOT_IMPLEMENTED(); } // Offset: 159 // Size: 61 float BrFloatSqrt(float f) { return sqrtf(f); - NOT_IMPLEMENTED(); } // Offset: 231 // Size: 70 float BrFloatPow(float a, float b) { return powf(a, b); - NOT_IMPLEMENTED(); } // Offset: 314 // Size: 70 float BrFloatAtan2(float x, float y) { return atan2f(x, y); - NOT_IMPLEMENTED(); } diff --git a/src/BRSRC13/CORE/V1DB/prepmesh.c b/src/BRSRC13/CORE/V1DB/prepmesh.c index e44d4c62..ab019801 100644 --- a/src/BRSRC13/CORE/V1DB/prepmesh.c +++ b/src/BRSRC13/CORE/V1DB/prepmesh.c @@ -1,4 +1,7 @@ #include "prepmesh.h" +#include "CORE/FW/diag.h" +#include "CORE/MATH/plane.h" +#include "CORE/STD/brmath.h" #include "debug.h" br_model* compareModel; @@ -80,7 +83,13 @@ int TVCompare_MVN(void* p1, void* p2) { // Offset: 2304 // Size: 88 br_fraction BrScalarToFractionClamp(br_scalar s) { - NOT_IMPLEMENTED(); + if (s >= 1.0f) { + return 1.0f; + } + if (s < -1.0f) { + return -0.99999988f; + } + return s; } // Offset: 2411 @@ -91,7 +100,15 @@ void PrepareFaceNormals(br_model* model) { br_vector4 v4; br_face* fp; int f; - NOT_IMPLEMENTED(); + + for (f = 0; f < model->nfaces; f++) { + fp = &model->faces[f]; + BrPlaneEquation(&v4, &model->vertices[fp->vertices[0]].p, &model->vertices[fp->vertices[1]].p, &model->vertices[fp->vertices[2]].p); + fp->n.v[0] = BrScalarToFractionClamp(v4.v[0]); + fp->n.v[1] = BrScalarToFractionClamp(v4.v[1]); + fp->n.v[2] = BrScalarToFractionClamp(v4.v[2]); + fp->d = v4.v[3]; + } } // Offset: 2705 @@ -169,7 +186,10 @@ void PrepareGroups(br_model* model) { br_uint_16* v11vuser; br_face** sorted_faces; char* cp; - NOT_IMPLEMENTED(); + + LOG_WARN("Ignoring this one for now"); + + return; } // Offset: 6862 @@ -177,10 +197,18 @@ void PrepareGroups(br_model* model) { // EAX: model void PrepareBoundingRadius(br_model* model) { float d; - float max; + float max = 0.0f; int v; br_vertex* vp; - NOT_IMPLEMENTED(); + + for (v = 0; v < model->nvertices; v++) { + vp = &model->vertices[v]; + d = vp->p.v[1] * vp->p.v[1] + vp->p.v[0] * vp->p.v[0] + vp->p.v[2] * vp->p.v[2]; + if (d > max) { + max = d; + } + } + model->radius = BrFloatSqrt(max); } // Offset: 7051 @@ -191,7 +219,25 @@ void PrepareBoundingBox(br_model* model) { int v; br_vertex* vp; br_scalar x; - NOT_IMPLEMENTED(); + + vp = &model->vertices[0]; + for (axis = 0; axis < 3; axis++) { + model->bounds.min.v[axis] = vp->p.v[axis]; + model->bounds.max.v[axis] = vp->p.v[axis]; + } + + for (v = 1; v < model->nvertices; v++) { + vp = &model->vertices[v]; + for (axis = 0; axis < 3; axis++) { + x = vp->p.v[axis]; + if (x > model->bounds.max.v[axis]) { + model->bounds.max.v[axis] = x; + } + if (x < model->bounds.min.v[axis]) { + model->bounds.min.v[axis] = x; + } + } + } } // Offset: 7345 @@ -228,7 +274,141 @@ void BrModelUpdate(br_model* model, br_uint_16 flags) { v11face* ffp; br_vertex* vp; br_face* fp; - NOT_IMPLEMENTED(); + LOG_TRACE("(%p, %d)", model, flags); + + if (!(model->flags & BR_MODF_PREPREPARED)) { + if (!model->faces || !model->vertices) { + BrFailure("BrModelUpdate: model has no faces or vertices (%s)", model->identifier ? model->identifier : ""); + } + if (flags & BR_MODU_UNKNOWN) { + flags |= BR_MODU_NORMALS; + } + if (model->flags & (BR_MODF_KEEP_ORIGINAL | BR_MODF_GENERATE_TAGS)) { + model->flags |= BR_MODF_UPDATEABLE; + } + if (!(model->flags & 0x400) && (flags & (BR_MODU_MATERIALS | BR_MODU_GROUPS | BR_MODU_NORMALS))) { + PrepareBoundingRadius(model); + PrepareBoundingBox(model); + } + if (!model->prepared || flags & 0xFFD0) { + if (!model->faces || !model->vertices) { + return; + } + PrepareFaceNormals(model); + f = 0; + fp = model->faces; + model->flags &= 0x7f; + for (f = 0; f < model->nfaces; f++) { + fp = &model->faces[f]; + if (!fp->material) { + model->flags |= BR_MODF_UPDATEABLE; + } + + for (v = 0; v < 3; v++) { + if (fp->vertices[v] >= model->nvertices) { + BrFailure("face references invalid vertex f=%d v=%d", f, v); + } + } + } + + PrepareGroups(model); + v11m = (v11model*)model->prepared; + if (v11m) { + for (g = 0; g < v11m->ngroups; g++) { + prepareEdges(&v11m->groups[g], model); + } + } + } else { + LOG_WARN("Do we ever get here??"); + // v11m = (v11model*)model->prepared; + // if (model->vertices && flags & 0xF) { + // for (g = 0; g < v11m->ngroups; g++) { + // // v5 = 0; + // // v39 = 0; + // // v30 = 0; + // // v40 = 0; + // // v29 = 36 * i; + + // for (v = 0; v < v11m->groups[g].nvertices; v++) { + // fvp = &v11m->groups[g].vertices[v]; + // vp = &model->vertices[v11m->groups[g].vertex_user[v]]; // v8->vertex_user[v5]]; + // if (flags & BR_MODU_NORMALS) { + // fvp->p.v[0] = vp->p.v[0] - model->pivot.v[0]; + // fvp->p.v[1] = vp->p.v[1] - model->pivot.v[1]; + // fvp->p.v[2] = vp->p.v[2] - model->pivot.v[2]; + // } + // if (flags & BR_MODU_EDGES) { + // v31 = _byteswap_ulong(*(_DWORD*)&vp->index); + // v11m->groups[g].vertex_colours[v] = v31; + // } + // if (flags & BR_MODU_RADIUS) { + // fvp->map.v[0] = vp->map.v[0]; + // fvp->map.v[1] = vp->map.v[1]; + // } + // if (flags & BR_MODU_GROUPS && model->flags & 0x200) { + // fvp->n.v[0] = vp->n.v[0]; + // fvp->n.v[1] = vp->n.v[1]; + // fvp->n.v[2] = vp->n.v[2]; + // } + // ++v5; + // v39 += 32; + // v30 += 4; + + // ++v; + // } + // } + // } + // if (model->faces && flags & BR_MODU_MATERIALS) { + // v35 = 0; + // v27 = 0; + // while (v11m->ngroups > v27) { + // v9 = 0; + // v10 = 0; + // v28 = v35; + // for (j = 0;; j += 4) { + // v12 = (v11group*)((char*)v11m->groups + v28); // not sure about this one + // if (v9 >= v12->nfaces) { + // break; + // } + // v31 = 40 * v12->face_user[v10]; + // fp = (br_face*)((char*)model->faces + v31); + // if (flags & 0x20) { + // v32 = fp->index << 24; + // v31 = (fp->red << 16) | v32; + // v32 = fp->grn << 8; + // v12->face_colours[j / 4] = fp->blu | v32 | v31; + // } + // ++v9; + // ++v10; + // } + // ++v27; + // v35 += 36; + // } + // } + // if (flags & 1) { + // if (!(model->flags & 0x200)) { + // RegenerateVertexNormals(v11m); + // } + // RegenerateFaceNormals(v11m); + // } + } + + // We arent generating optimized model or storing at this point, so + // we do not want to free the faces/verts + + // if (model->flags >= 0) { + // if (model->faces) { + // BrResFree(model->faces); + // } + // if (model->vertices) { + // BrResFree(model->vertices); + // } + // model->vertices = 0; + // model->nfaces = 0; + // model->nvertices = 0; + // model->faces = 0; + // } + } } // Offset: 10011 diff --git a/src/BRSRC13/br_types.h b/src/BRSRC13/br_types.h index 20f9f4c9..8e43d865 100644 --- a/src/BRSRC13/br_types.h +++ b/src/BRSRC13/br_types.h @@ -2800,10 +2800,10 @@ typedef struct v11face { typedef struct v11group { void* stored; - DR_FACE* faces; + v11face* faces; br_colour* face_colours; br_uint_16* face_user; - DR_VERTEX* vertices; + fmt_vertex* vertices; br_colour* vertex_colours; br_uint_16* vertex_user; br_uint_16 nfaces; @@ -2930,6 +2930,20 @@ enum { BR_PMT_INDEXA_88 }; +/* + * Flags to BrModelUpdate() + */ +enum { + BR_MODU_NORMALS = 0x0001, + BR_MODU_EDGES = 0x0002, + BR_MODU_RADIUS = 0x0004, + BR_MODU_GROUPS = 0x0008, + BR_MODU_BOUNDING_BOX = 0x0010, + BR_MODU_MATERIALS = 0x0020, + BR_MODU_UNKNOWN = 0x0100, /* Added by JeffH. Referred to in code */ + BR_MODU_ALL = 0x7fff +}; + /* * Bits for br_model->flags */ @@ -2938,10 +2952,10 @@ enum { BR_MODF_KEEP_ORIGINAL = 0x0002, /* Don't release model->faces/vertices during ModelUpdate() */ BR_MODF_GENERATE_TAGS = 0x0004, /* Allocate and fill in the face and vertex tag structures */ BR_MODF_QUICK_UPDATE = 0x0010, /* ModelUpdate is fast - but may produce slower models */ - BR_MODF_CUSTOM = 0x0020, /* Invoke custom callback for this model */ + BR_MODF_PREPREPARED = 0x0040, /* Model structure is pre-prepared - update performs no work */ - BR_MODF_PREPREPARED = 0x0040 /* Model structure is pre-prepared - update performs no work */ + BR_MODF_UPDATEABLE = 0x0080 /* Added by JeffH from Errols code */ }; #define BR_COLOUR_RGB(r, g, b) \