Subversion Repositories Games.Carmageddon

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include "prepmesh.h"
  2. #include "CORE/FW/brqsort.h"
  3. #include "CORE/FW/diag.h"
  4. #include "CORE/FW/resource.h"
  5. #include "CORE/FW/scratch.h"
  6. #include "CORE/MATH/angles.h"
  7. #include "CORE/MATH/plane.h"
  8. #include "CORE/MATH/vector.h"
  9. #include "CORE/STD/brmath.h"
  10. #include "CORE/STD/brstdlib.h"
  11. #include "harness/hooks.h"
  12. #include "harness/trace.h"
  13. #include <assert.h>
  14.  
  15. br_model* compareModel;
  16. char* pm_edge_scratch;
  17. pm_temp_edge** pm_edge_hash;
  18. int num_edges;
  19. pm_temp_edge* pm_edge_table;
  20.  
  21. #define PREP_ALIGN(f) (f)
  22.  
  23. #define MODF_USES_DEFAULT 0x8000
  24.  
  25. // IDA: int __usercall addEdge@<EAX>(br_uint_16 first@<EAX>, br_uint_16 last@<EDX>)
  26. int addEdge(br_uint_16 first, br_uint_16 last) {
  27.     //pm_temp_edge* tep; // Pierre-Marie Baty -- unused variable
  28.     LOG_TRACE("(%d, %d)", first, last);
  29.     NOT_IMPLEMENTED();
  30. }
  31.  
  32. // IDA: void __usercall prepareEdges(v11group *group@<EAX>, br_model *model@<EDX>)
  33. void prepareEdges(v11group* group, br_model* model) {
  34.     //br_size_t scratch_size; // Pierre-Marie Baty -- unused variable
  35.     //br_face* mfp; // Pierre-Marie Baty -- unused variable
  36.     //v11face* fp; // Pierre-Marie Baty -- unused variable
  37.     //int f; // Pierre-Marie Baty -- unused variable
  38.     LOG_TRACE("(%p, %p)", group, model);
  39.     NOT_IMPLEMENTED();
  40. }
  41.  
  42. // IDA: void __usercall BrPrepareEdges(br_model *model@<EAX>)
  43. void BrPrepareEdges(br_model* model) {
  44.     //int g; // Pierre-Marie Baty -- unused variable
  45.     //v11model* v11m; // Pierre-Marie Baty -- unused variable
  46.     LOG_TRACE("(%p)", model);
  47.     NOT_IMPLEMENTED();
  48. }
  49.  
  50. // IDA: int __cdecl FacesCompare(void *p1, void *p2)
  51. int FacesCompare(const void* p1, const void* p2) {
  52.     br_face* f1;
  53.     br_face* f2;
  54.     // LOG_TRACE9("(%p, %p)", p1, p2);
  55.  
  56.     f1 = *(br_face**)p1;
  57.     f2 = *(br_face**)p2;
  58.  
  59.     if (f1->material > f2->material) {
  60.         return 1;
  61.     }
  62.     if (f1->material < f2->material) {
  63.         return -1;
  64.     }
  65.     return 0;
  66. }
  67.  
  68. // IDA: int __cdecl TVCompare_XYZ(void *p1, void *p2)
  69. int TVCompare_XYZ(const void* p1, const void* p2) {
  70.     prep_vertex* tv1;
  71.     prep_vertex* tv2;
  72.     br_vertex* v1;
  73.     br_vertex* v2;
  74.     int i;
  75.     // LOG_TRACE9("(%p, %p)", p1, p2);
  76.  
  77.     tv1 = *(prep_vertex**)p1;
  78.     tv2 = *(prep_vertex**)p2;
  79.  
  80.     assert(compareModel != NULL);
  81.  
  82.     if (tv1->v == tv2->v)
  83.         return 0;
  84.  
  85.     v1 = compareModel->vertices + tv1->v;
  86.     v2 = compareModel->vertices + tv2->v;
  87.  
  88.     for (i = 0; i < 3; i++) {
  89.         if (v1->p.v[i] > v2->p.v[i])
  90.             return 1;
  91.         if (v1->p.v[i] < v2->p.v[i])
  92.             return -1;
  93.     }
  94.  
  95.     return 0;
  96. }
  97.  
  98. // IDA: int __cdecl TVCompare_MXYZUVN(void *p1, void *p2)
  99. int TVCompare_MXYZUVN(const void* p1, const void* p2) {
  100.     prep_vertex* tv1;
  101.     prep_vertex* tv2;
  102.     br_vertex* v1;
  103.     br_vertex* v2;
  104.     int i;
  105.     // LOG_TRACE("(%p, %p)", p1, p2);
  106.  
  107.     tv1 = *(struct prep_vertex**)p1;
  108.     tv2 = *(struct prep_vertex**)p2;
  109.  
  110.     assert(compareModel != NULL);
  111.  
  112.     if (compareModel->faces[tv1->f].material > compareModel->faces[tv2->f].material)
  113.         return 1;
  114.     if (compareModel->faces[tv1->f].material < compareModel->faces[tv2->f].material)
  115.         return -1;
  116.  
  117.     if (tv1->v != tv2->v) {
  118.         v1 = compareModel->vertices + tv1->v;
  119.         v2 = compareModel->vertices + tv2->v;
  120.  
  121.         for (i = 0; i < 3; i++) {
  122.             if (v1->p.v[i] > v2->p.v[i])
  123.                 return 1;
  124.             if (v1->p.v[i] < v2->p.v[i])
  125.                 return -1;
  126.         }
  127.  
  128.         for (i = 0; i < 2; i++) {
  129.             if (v1->map.v[i] > v2->map.v[i])
  130.                 return 1;
  131.             if (v1->map.v[i] < v2->map.v[i])
  132.                 return -1;
  133.         }
  134.     }
  135.  
  136.     for (i = 0; i < 3; i++) {
  137.         if (tv1->n.v[i] > tv2->n.v[i])
  138.             return 1;
  139.         if (tv1->n.v[i] < tv2->n.v[i])
  140.             return -1;
  141.     }
  142.  
  143.     return 0;
  144. }
  145.  
  146. // IDA: int __cdecl TVCompare_MVN(void *p1, void *p2)
  147. int TVCompare_MVN(const void* p1, const void* p2) {
  148.     prep_vertex* tv1;
  149.     prep_vertex* tv2;
  150.     int i;
  151.     // LOG_TRACE9("(%p, %p)", p1, p2);
  152.  
  153.     tv1 = *(prep_vertex**)p1;
  154.     tv2 = *(prep_vertex**)p2;
  155.  
  156.     // if (compareModel->faces[tv1->f].material != NULL) {
  157.     //     LOG_DEBUG("%s, %s", compareModel->faces[tv1->f].material->identifier, compareModel->faces[tv2->f].material->identifier);
  158.     // }
  159.     if (compareModel->faces[tv1->f].material > compareModel->faces[tv2->f].material)
  160.         return 1;
  161.     if (compareModel->faces[tv1->f].material < compareModel->faces[tv2->f].material)
  162.         return -1;
  163.  
  164.     if (tv1->v > tv2->v)
  165.         return 1;
  166.     if (tv1->v < tv2->v)
  167.         return -1;
  168.  
  169.     for (i = 0; i < 3; i++) {
  170.         if (tv1->n.v[i] > tv2->n.v[i])
  171.             return 1;
  172.         if (tv1->n.v[i] < tv2->n.v[i])
  173.             return -1;
  174.     }
  175.     return 0;
  176. }
  177.  
  178. // IDA: br_fraction __cdecl BrScalarToFractionClamp(br_scalar s)
  179. br_fraction BrScalarToFractionClamp(br_scalar s) {
  180.     if (s >= 1.0f) {
  181.         return 1.0f;
  182.     }
  183.     if (s < -1.0f) {
  184.         return -0.99999988f;
  185.     }
  186.     return s;
  187. }
  188.  
  189. // IDA: void __usercall PrepareFaceNormals(br_model *model@<EAX>)
  190. void PrepareFaceNormals(br_model* model) {
  191.     //br_vertex* vertices; // Pierre-Marie Baty -- unused variable
  192.     br_vector4 v4;
  193.     br_face* fp;
  194.     int f;
  195.  
  196.     for (f = 0; f < model->nfaces; f++) {
  197.         fp = &model->faces[f];
  198.         BrPlaneEquation(&v4, &model->vertices[fp->vertices[0]].p, &model->vertices[fp->vertices[1]].p, &model->vertices[fp->vertices[2]].p);
  199.         fp->n.v[0] = BrScalarToFractionClamp(v4.v[0]);
  200.         fp->n.v[1] = BrScalarToFractionClamp(v4.v[1]);
  201.         fp->n.v[2] = BrScalarToFractionClamp(v4.v[2]);
  202.         fp->d = v4.v[3];
  203.     }
  204. }
  205.  
  206. // IDA: void __usercall Smoothing(br_model *model@<EAX>, br_scalar crease_limit, prep_vertex **start, prep_vertex **end)
  207. void Smoothing(br_model* model, br_scalar crease_limit, prep_vertex** start, prep_vertex** end) {
  208.     prep_vertex** outer;
  209.     prep_vertex** inner;
  210.     LOG_TRACE9("(%p, %f, %p, %p)", model, crease_limit, start, end);
  211.  
  212.     for (outer = start; outer < end; outer++) {
  213.         for (inner = start; inner < end; inner++) {
  214.             if ((inner == outer) || (model->faces[(*outer)->f].smoothing & model->faces[(*inner)->f].smoothing)) {
  215.                 BrVector3Accumulate(&(*outer)->n, (br_vector3*)&model->faces[(*inner)->f].n);
  216.             }
  217.         }
  218.     }
  219. }
  220.  
  221. // IDA: void __usercall SmoothingCreased(br_model *model@<EAX>, br_scalar crease_limit, prep_vertex **start, prep_vertex **end)
  222. void SmoothingCreased(br_model* model, br_scalar crease_limit, prep_vertex** start, prep_vertex** end) {
  223.     br_vector3 o_n;
  224.     prep_vertex** outer;
  225.     prep_vertex** inner;
  226.     LOG_TRACE9("(%p, %f, %p, %p)", model, crease_limit, start, end);
  227.  
  228.     for (outer = start; outer < end; outer++) {
  229.         o_n.v[0] = model->faces[(*outer)->f].n.v[0];
  230.         o_n.v[1] = model->faces[(*outer)->f].n.v[1];
  231.         o_n.v[2] = model->faces[(*outer)->f].n.v[2];
  232.         for (inner = start; inner < end; inner++) {
  233.             if ((inner == outer) || ((model->faces[(*outer)->f].smoothing & model->faces[(*inner)->f].smoothing) && (BrVector3Dot((br_vector3*)&model->faces[(*inner)->f].n, &o_n) > crease_limit))) {
  234.                 BrVector3Accumulate(&(*outer)->n, (br_vector3*)&model->faces[(*inner)->f].n);
  235.             }
  236.         }
  237.     }
  238. }
  239.  
  240. // IDA: void __usercall CopyVertex(v11group *group@<EAX>, int v@<EDX>, prep_vertex *src@<EBX>, br_model *model@<ECX>)
  241. void CopyVertex(v11group* group, int v, prep_vertex* src, br_model* model) {
  242.     br_vertex* srcv;
  243.     //br_vector3 n; // Pierre-Marie Baty -- unused variable
  244.     LOG_TRACE9("(%p, %d, %p, %p)", group, v, src, model);
  245.  
  246.     srcv = model->vertices + src->v;
  247.  
  248.     BrVector3Sub(&group->vertices[v].p, &srcv->p, &model->pivot);
  249.  
  250.     group->vertices[v].map = srcv->map;
  251.  
  252.     BrVector3Normalise(&group->vertices[v].n, &src->n);
  253.  
  254.     group->vertex_colours[v] = BR_COLOUR_RGBA(srcv->red, srcv->grn, srcv->blu, srcv->index);
  255.     group->vertex_user[v] = src->v;
  256. }
  257.  
  258. // IDA: void __usercall CopyFace(v11group *group@<EAX>, int f@<EDX>, br_face *src@<EBX>, br_model *model@<ECX>)
  259. void CopyFace(v11group* group, int f, br_face* src, br_model* model) {
  260.     LOG_TRACE9("(%p, %d, %p, %p)", group, f, src, model);
  261.  
  262.     group->faces[f].vertices[0] = src->vertices[0];
  263.     group->faces[f].vertices[1] = src->vertices[1];
  264.     group->faces[f].vertices[2] = src->vertices[2];
  265.     group->face_colours[f] = BR_COLOUR_RGBA(src->red, src->grn, src->blu, src->index);
  266.     group->faces[f].eqn.v[0] = src->n.v[0];
  267.     group->faces[f].eqn.v[1] = src->n.v[1];
  268.     group->faces[f].eqn.v[2] = src->n.v[2];
  269.     group->faces[f].eqn.v[3] = src->d;
  270.     group->face_user[f] = src - model->faces;
  271. }
  272.  
  273. // IDA: void __usercall PrepareGroups(br_model *model@<EAX>)
  274. void PrepareGroups(br_model* model) {
  275.     br_qsort_cbfn* vertex_compare_smoothing;
  276.     br_qsort_cbfn* vertex_compare_groups;
  277.     void (*smoothing_fn)(br_model*, br_scalar, prep_vertex**, prep_vertex**);
  278.     //void* vp; // Pierre-Marie Baty -- unused variable
  279.     br_size_t block_size;
  280.     prep_vertex* temp_verts;
  281.     prep_vertex* gtvp;
  282.     prep_vertex** sorted_vertices;
  283.     br_face* fp;
  284.     int g;
  285.     int f;
  286.     int v;
  287.     int i;
  288.     int ntemps;
  289.     int count;
  290.     int nf;
  291.     int nv;
  292.     int ng;
  293.     int old_count;
  294.     br_scalar crease_limit;
  295.     v11model* v11m;
  296.     v11group* v11g;
  297.     v11face* v11f;
  298.     fmt_vertex* v11v;
  299.     br_colour* v11fcolours;
  300.     br_colour* v11vcolours;
  301.     br_uint_16* v11fuser;
  302.     br_uint_16* v11vuser;
  303.     br_face** sorted_faces;
  304.     char* cp;
  305.  
  306.     if (model->flags & BR_MODF_DONT_WELD) {
  307.         vertex_compare_smoothing = TVCompare_XYZ;
  308.         vertex_compare_groups = TVCompare_MVN;
  309.     } else {
  310.         vertex_compare_smoothing = TVCompare_XYZ;
  311.         vertex_compare_groups = TVCompare_MXYZUVN;
  312.     }
  313.  
  314.     if (model->flags & BR_MODF_CREASE) {
  315.         crease_limit = BR_COS(model->crease_angle);
  316.         smoothing_fn = SmoothingCreased;
  317.     } else {
  318.         crease_limit = BR_SCALAR(0.0);
  319.         smoothing_fn = Smoothing;
  320.     }
  321.  
  322.     compareModel = model;
  323.  
  324.     ntemps = model->nfaces * 3;
  325.  
  326.     block_size = ntemps * (sizeof(*temp_verts) + sizeof(*sorted_vertices)) + model->nfaces * sizeof(sorted_faces);
  327.     temp_verts = BrScratchAllocate(block_size);
  328.  
  329.     BrMemSet(temp_verts, 0, block_size);
  330.  
  331.     sorted_vertices = (struct prep_vertex**)(temp_verts + ntemps);
  332.     sorted_faces = (struct br_face**)(sorted_vertices + ntemps);
  333.  
  334.     gtvp = temp_verts;
  335.     for (i = 0, f = 0, fp = model->faces; f < model->nfaces; f++, fp++) {
  336.         sorted_faces[f] = fp;
  337.         for (v = 0; v < 3; v++, i++, gtvp++) {
  338.  
  339.             if (model->flags & BR_MODF_CUSTOM_NORMALS) {
  340.                 TELL_ME_IF_WE_PASS_THIS_WAY();
  341.                 // gtvp->n.v[0] = model->vertices[fp->vertices[v]].n.v[0];
  342.                 // gtvp->n.v[1] = model->vertices[fp->vertices[v]].n.v[1];
  343.                 // gtvp->n.v[2] = model->vertices[fp->vertices[v]].n.v[2];
  344.             }
  345.  
  346.             gtvp->v = fp->vertices[v];
  347.             gtvp->f = f;
  348.  
  349.             sorted_vertices[i] = gtvp;
  350.         }
  351.  
  352.         if (fp->smoothing == 0)
  353.             fp->smoothing = (br_uint_16)~0;
  354.     }
  355.  
  356.     BrQsort(sorted_faces, model->nfaces, sizeof(*sorted_faces), FacesCompare);
  357.  
  358.     if (!(model->flags & BR_MODF_CUSTOM_NORMALS)) {
  359.  
  360.         BrQsort(sorted_vertices, ntemps, sizeof(*sorted_vertices), vertex_compare_smoothing);
  361.         for (v = 0, i = 0; v < ntemps - 1; v++) {
  362.             if (vertex_compare_smoothing(sorted_vertices + v, sorted_vertices + v + 1)) {
  363.                 smoothing_fn(model, crease_limit, sorted_vertices + i, sorted_vertices + v + 1);
  364.                 i = v + 1;
  365.             }
  366.         }
  367.  
  368.         smoothing_fn(model, crease_limit, sorted_vertices + i, sorted_vertices + ntemps);
  369.     }
  370.  
  371.     BrQsort(sorted_vertices, ntemps, sizeof(*sorted_vertices), vertex_compare_groups);
  372.  
  373.     for (v = 0, nv = 1; v < ntemps - 1; v++)
  374.         if (vertex_compare_groups(sorted_vertices + v, sorted_vertices + v + 1))
  375.             nv++;
  376.  
  377.     for (f = 1, ng = 1; f < model->nfaces; f++) {
  378.         if (sorted_faces[f]->material != sorted_faces[f - 1]->material) {
  379.             ng++;
  380.         }
  381.     }
  382.  
  383.     nf = model->nfaces;
  384.  
  385.     block_size = PREP_ALIGN(sizeof(struct v11model)) + PREP_ALIGN(ng * sizeof(struct v11group)) +
  386.  
  387.         PREP_ALIGN(nf * sizeof(*v11g->faces)) +
  388.  
  389.         PREP_ALIGN(nv * sizeof(*v11g->vertices)) +
  390.  
  391.         PREP_ALIGN(nf * sizeof(br_colour)) + PREP_ALIGN(nv * sizeof(br_colour)) + nv * sizeof(br_int_16) + nf * sizeof(br_int_16);
  392.  
  393.     if (model->prepared && block_size > ((struct v11model*)(model->prepared))->size) {
  394.         BrResFree(model->prepared);
  395.         model->prepared = NULL;
  396.     }
  397.  
  398.     if (model->prepared == NULL) {
  399.         model->prepared = BrResAllocate(model, block_size, BR_MEMORY_PREPARED_MODEL);
  400.         ((struct v11model*)(model->prepared))->size = block_size;
  401.     }
  402.  
  403.     cp = model->prepared;
  404.  
  405.     v11m = (void*)cp;
  406.     cp += PREP_ALIGN(sizeof(struct v11model));
  407.     v11g = (void*)cp;
  408.     cp += PREP_ALIGN(ng * sizeof(struct v11group));
  409.  
  410.     v11f = (void*)cp;
  411.     cp += PREP_ALIGN(nf * sizeof(struct v11face));
  412.  
  413.     v11v = (void*)cp;
  414.     cp += PREP_ALIGN(nv * sizeof(struct fmt_vertex));
  415.  
  416.     v11vcolours = (void*)cp;
  417.     cp += PREP_ALIGN(nv * sizeof(br_colour));
  418.     v11fcolours = (void*)cp;
  419.     cp += PREP_ALIGN(nf * sizeof(br_colour));
  420.  
  421.     v11vuser = (void*)cp;
  422.     cp += nv * sizeof(br_uint_16);
  423.     v11fuser = (void*)cp;
  424.     cp += nf * sizeof(br_uint_16);
  425.  
  426.     v11m->groups = v11g;
  427.     v11m->ngroups = ng;
  428.  
  429.     v11g[0].faces = v11f;
  430.     v11g[0].face_colours = v11fcolours;
  431.     v11g[0].face_user = v11fuser;
  432.     v11g[0].stored = sorted_faces[0]->material ? sorted_faces[0]->material->stored : NULL;
  433.     v11g[0].nfaces = 0;
  434.  
  435.     for (f = 0, g = 0; f < model->nfaces - 1; f++) {
  436.  
  437.         CopyFace(v11g + g, v11g[g].nfaces, sorted_faces[f], model);
  438.         v11g[g].nfaces++;
  439.  
  440.         if (sorted_faces[f]->material != sorted_faces[f + 1]->material) {
  441.             g++;
  442.             v11g[g].faces = v11f + f + 1;
  443.             v11g[g].face_colours = v11fcolours + f + 1;
  444.             v11g[g].face_user = v11fuser + f + 1;
  445.             v11g[g].stored = sorted_faces[f + 1]->material ? sorted_faces[f + 1]->material->stored : NULL;
  446.             v11g[g].nfaces = 0;
  447.         }
  448.     }
  449.  
  450.     CopyFace(v11g + g, v11g[g].nfaces, sorted_faces[f], model);
  451.     v11g[g].nfaces++;
  452.     v11g[0].vertices = v11v;
  453.  
  454.     v11g[0].vertex_colours = v11vcolours;
  455.     v11g[0].vertex_user = v11vuser;
  456.  
  457.     v11g[0].nvertices = 1;
  458.     CopyVertex(v11g, 0, sorted_vertices[0], model);
  459.  
  460.     for (v = 0, g = 0, count = 0; v < ntemps - 1; v++) {
  461.  
  462.         if (model->faces[sorted_vertices[v]->f].material != model->faces[sorted_vertices[v + 1]->f].material) {
  463.             g++;
  464.             v11g[g].vertices = v11v + count + 1;
  465.             v11g[g].vertex_colours = v11vcolours + count + 1;
  466.             v11g[g].vertex_user = v11vuser + count + 1;
  467.             v11g[g].nvertices = 0;
  468.         }
  469.  
  470.         old_count = count;
  471.         if (vertex_compare_groups(sorted_vertices + v, sorted_vertices + v + 1)) {
  472.  
  473.             count++;
  474.             sorted_vertices[v]->v = count;
  475.             CopyVertex(v11g + g, v11g[g].nvertices, sorted_vertices[v + 1], model);
  476.             v11g[g].nvertices++;
  477.         }
  478.         sorted_vertices[v]->v = old_count;
  479.     }
  480.  
  481.     sorted_vertices[v]->v = count;
  482.  
  483.     for (g = 0; g < ng; g++) {
  484.         for (f = 0; f < v11g[g].nfaces; f++) {
  485.             i = v11g[g].vertices - v11v;
  486.             v = v11g[g].face_user[f] * 3;
  487.             v11g[g].faces[f].vertices[0] = temp_verts[v + 0].v - i;
  488.             v11g[g].faces[f].vertices[1] = temp_verts[v + 1].v - i;
  489.             v11g[g].faces[f].vertices[2] = temp_verts[v + 2].v - i;
  490.         }
  491.     }
  492.     BrScratchFree(temp_verts);
  493. }
  494.  
  495. // IDA: void __usercall PrepareBoundingRadius(br_model *model@<EAX>)
  496. void PrepareBoundingRadius(br_model* model) {
  497.     float d;
  498.     float max = 0.0f;
  499.     int v;
  500.     br_vertex* vp;
  501.  
  502.     for (v = 0; v < model->nvertices; v++) {
  503.         vp = &model->vertices[v];
  504.         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];
  505.         if (d > max) {
  506.             max = d;
  507.         }
  508.     }
  509.     model->radius = BrFloatSqrt(max);
  510. }
  511.  
  512. // IDA: void __usercall PrepareBoundingBox(br_model *model@<EAX>)
  513. void PrepareBoundingBox(br_model* model) {
  514.     int axis;
  515.     int v;
  516.     br_vertex* vp;
  517.     br_scalar x;
  518.  
  519.     vp = &model->vertices[0];
  520.     for (axis = 0; axis < 3; axis++) {
  521.         model->bounds.min.v[axis] = vp->p.v[axis];
  522.         model->bounds.max.v[axis] = vp->p.v[axis];
  523.     }
  524.  
  525.     for (v = 1; v < model->nvertices; v++) {
  526.         vp = &model->vertices[v];
  527.         for (axis = 0; axis < 3; axis++) {
  528.             x = vp->p.v[axis];
  529.             if (x > model->bounds.max.v[axis]) {
  530.                 model->bounds.max.v[axis] = x;
  531.             }
  532.             if (x < model->bounds.min.v[axis]) {
  533.                 model->bounds.min.v[axis] = x;
  534.             }
  535.         }
  536.     }
  537. }
  538.  
  539. // IDA: void __usercall RegenerateFaceNormals(v11model *v11m@<EAX>)
  540. void RegenerateFaceNormals(v11model* v11m) {
  541.     int g;
  542.     int f;
  543.     v11face* fp;
  544.     LOG_TRACE("(%p)", v11m);
  545.  
  546.     for (g = 0; g < v11m->ngroups; g++) {
  547.         for (f = 0; f < v11m->groups[g].nfaces; f++) {
  548.             fp = &v11m->groups[g].faces[f];
  549.             BrPlaneEquation(&fp->eqn,
  550.                 &v11m->groups->vertices[fp->vertices[0]].p,
  551.                 &v11m->groups->vertices[fp->vertices[1]].p,
  552.                 &v11m->groups->vertices[fp->vertices[2]].p);
  553.         }
  554.     }
  555. }
  556.  
  557. // IDA: void __usercall RegenerateVertexNormals(v11model *v11m@<EAX>)
  558. void RegenerateVertexNormals(v11model* v11m) {
  559.     int g;
  560.     int v;
  561.     int f;
  562.     v11face* fp;
  563.     fmt_vertex* vp;
  564.     br_vector3* normals;
  565.     LOG_TRACE("(%p)", v11m);
  566.  
  567.     for (g = 0; g < v11m->ngroups; g++) {
  568.         normals = BrScratchAllocate(v11m->groups[g].nvertices * sizeof(br_vector3));
  569.         BrMemSet(normals, 0, v11m->groups[g].nvertices * sizeof(br_vector3));
  570.         for (f = 0; f < v11m->groups[g].nfaces; f++) {
  571.             fp = &v11m->groups[g].faces[f];
  572.             normals[fp->vertices[0]].v[0] += fp->eqn.v[0];
  573.             normals[fp->vertices[0]].v[1] += fp->eqn.v[1];
  574.             normals[fp->vertices[0]].v[2] += fp->eqn.v[2];
  575.             normals[fp->vertices[1]].v[0] += fp->eqn.v[0];
  576.             normals[fp->vertices[1]].v[1] += fp->eqn.v[1];
  577.             normals[fp->vertices[1]].v[2] += fp->eqn.v[2];
  578.             normals[fp->vertices[2]].v[0] += fp->eqn.v[0];
  579.             normals[fp->vertices[2]].v[1] += fp->eqn.v[1];
  580.             normals[fp->vertices[2]].v[2] += fp->eqn.v[2];
  581.         }
  582.         for (v = 0; v < v11m->groups[g].nvertices; v++) {
  583.             vp = &v11m->groups[g].vertices[v];
  584.             // FIXME: use inlined variant? BR_VECTOR3_NORMALISE (unsure about exact naming)
  585.             BrVector3Normalise(&vp->n, &normals[v]);
  586.         }
  587.  
  588.         BrScratchFree(normals);
  589.     }
  590. }
  591.  
  592. // IDA: void __cdecl BrModelUpdate(br_model *model, br_uint_16 flags)
  593. void BrModelUpdate(br_model* model, br_uint_16 flags) {
  594.     int g;
  595.     int f;
  596.     int v;
  597.     v11model* v11m;
  598.     fmt_vertex* fvp;
  599.     //v11face* ffp; // Pierre-Marie Baty -- unused variable
  600.     br_vertex* vp;
  601.     br_face* fp;
  602.     LOG_TRACE("(%p, %d)", model, flags);
  603.  
  604.     if (model->flags & BR_MODF_PREPREPARED) {
  605.         return;
  606.     }
  607.     if (model->faces == NULL || model->vertices == NULL) {
  608.         BrFailure("BrModelUpdate: model has no faces or vertices (%s)", model->identifier != NULL ? model->identifier : "<NULL>");
  609.     }
  610.     if (flags & BR_MODU_PIVOT) {
  611.         flags |= BR_MODU_VERTEX_POSITIONS;
  612.     }
  613.     if (model->flags & (BR_MODF_KEEP_ORIGINAL | BR_MODF_GENERATE_TAGS)) {
  614.         model->flags |= BR_MODF_UPDATEABLE;
  615.     }
  616.     if (!(model->flags & BR_MODF_CUSTOM_BOUNDS) && (flags & (BR_MODU_PRIMITIVE_COLOURS | BR_MODU_VERTEX_NORMALS | BR_MODU_VERTEX_POSITIONS))) {
  617.         PrepareBoundingRadius(model);
  618.         PrepareBoundingBox(model);
  619.     }
  620.     if (!model->prepared || flags & 0xFFD0) {
  621.         if (!model->faces || !model->vertices) {
  622.             return;
  623.         }
  624.         PrepareFaceNormals(model);
  625.         f = 0;
  626.         fp = model->faces;
  627.         model->flags &= ~MODF_USES_DEFAULT;
  628.         for (f = 0; f < model->nfaces; f++) {
  629.             fp = &model->faces[f];
  630.             if (!fp->material) {
  631.                 model->flags |= MODF_USES_DEFAULT;
  632.             }
  633.  
  634.             for (v = 0; v < 3; v++) {
  635.                 if (fp->vertices[v] >= model->nvertices) {
  636.                     BrFailure("face references invalid vertex f=%d v=%d", f, v);
  637.                 }
  638.             }
  639.         }
  640.  
  641.         PrepareGroups(model);
  642.         v11m = model->prepared;
  643.  
  644.         if (v11m) {
  645.             for (g = 0; g < v11m->ngroups; g++) {
  646.                 // prepareEdges(&v11m->groups[g], model);
  647.             }
  648.         } else {
  649.             LOG_DEBUG("has prepared model FALSE");
  650.         }
  651.     } else {
  652.  
  653.         // some additional code paths might exist, but maybe not used?
  654.         if (flags != BR_MODU_VERTEX_POSITIONS) {
  655.             TELL_ME_IF_WE_PASS_THIS_WAY();
  656.         }
  657.  
  658.         v11m = model->prepared;
  659.  
  660.         if (model->vertices && (flags & BR_MODU_VERTEX_POSITIONS)) {
  661.             for (g = 0; g < v11m->ngroups; g++) {
  662.                 for (v = 0; v < v11m->groups[g].nvertices; v++) {
  663.                     fvp = &v11m->groups[g].vertices[v];
  664.                     vp = model->vertices + v11m->groups[g].vertex_user[v];
  665.  
  666.                     if (flags & BR_MODU_VERTEX_POSITIONS) {
  667.                         fvp->p.v[0] = vp->p.v[0] - model->pivot.v[0];
  668.                         fvp->p.v[1] = vp->p.v[1] - model->pivot.v[1];
  669.                         fvp->p.v[2] = vp->p.v[2] - model->pivot.v[2];
  670.                     }
  671.                 }
  672.             }
  673.         }
  674.  
  675.         if (flags & BR_MODU_VERTEX_POSITIONS) {
  676.             if (!(model->flags & BR_MODF_CUSTOM_NORMALS)) {
  677.                 RegenerateVertexNormals(v11m);
  678.             }
  679.             RegenerateFaceNormals(v11m);
  680.         }
  681.     }
  682.  
  683.     if (!(model->flags & BR_MODF_UPDATEABLE)) {
  684.         if (model->faces) {
  685.             BrResFree(model->faces);
  686.         }
  687.         if (model->vertices) {
  688.             BrResFree(model->vertices);
  689.         }
  690.         model->vertices = NULL;
  691.         model->nfaces = 0;
  692.         model->nvertices = 0;
  693.         model->faces = NULL;
  694.     }
  695.  
  696.     if (model->stored) {
  697.         ((br_object*)model->stored)->dispatch->_free((br_object*)model->stored);
  698.         model->stored = NULL;
  699.     }
  700.  
  701.     // Added by dethrace
  702.     gHarness_platform.Renderer_BufferModel(model);
  703. }
  704.  
  705. // IDA: void __usercall BrModelClear(br_model *model@<EAX>)
  706. void BrModelClear(br_model* model) {
  707.     LOG_TRACE("(%p)", model);
  708.  
  709.     // remove prepared mesh
  710.     if (model->prepared != NULL) {
  711.         BrResFree(model->prepared);
  712.         model->prepared = NULL;
  713.     }
  714.     if (model->stored != NULL) {
  715.         ((br_object*)model->stored)->dispatch->_free((br_object*)model->stored);
  716.         model->stored = NULL;
  717.     }
  718. }
  719.