Subversion Repositories Games.Carmageddon

Rev

Rev 18 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "skidmark.h"
  2. #include "brender/brender.h"
  3. #include "globvars.h"
  4. #include "globvrbm.h"
  5. #include "harness/trace.h"
  6. #include "loading.h"
  7. #include "oil.h"
  8. #include "piping.h"
  9. #include <float.h>
  10. #include <math.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13.  
  14. char* gBoring_material_names[2] = { "OILSMEAR.MAT", "ROBSMEAR.MAT" };
  15. char* gMaterial_names[2] = { "OILSMEAR.MAT", "GIBSMEAR.MAT" };
  16. tSkid gSkids[100];
  17.  
  18. // IDA: void __usercall StretchMark(tSkid *pMark@<EAX>, br_vector3 *pFrom@<EDX>, br_vector3 *pTo@<EBX>, br_scalar pTexture_start)
  19. void StretchMark(tSkid* pMark, br_vector3* pFrom, br_vector3* pTo, br_scalar pTexture_start) {
  20.     br_vector3 temp;
  21.     br_vector3* rows;
  22.     br_scalar len;
  23.     br_model* model;
  24.     LOG_TRACE("(%p, %p, %p, %f)", pMark, pFrom, pTo, pTexture_start);
  25.  
  26.     rows = (br_vector3*)&pMark->actor->t.t.mat;
  27.     BrVector3Sub(&temp, pTo, pFrom);
  28.     len = BrVector3Length(&temp);
  29.  
  30.     rows[2].v[0] = pMark->normal.v[2] * temp.v[1] - pMark->normal.v[1] * temp.v[2];
  31.     rows[2].v[1] = pMark->normal.v[0] * temp.v[2] - pMark->normal.v[2] * temp.v[0];
  32.     rows[2].v[2] = pMark->normal.v[1] * temp.v[0] - pMark->normal.v[0] * temp.v[1];
  33.  
  34.     if (len > BR_SCALAR_EPSILON) {
  35.         rows[2].v[0] = 0.05f / len * rows[2].v[0];
  36.         rows[2].v[1] = 0.05f / len * rows[2].v[1];
  37.         rows[2].v[2] = 0.05f / len * rows[2].v[2];
  38.         rows->v[0] = len / len * temp.v[0];
  39.         rows->v[1] = len / len * temp.v[1];
  40.         rows->v[2] = len / len * temp.v[2];
  41.         BrVector3Add(&temp, pTo, pFrom);
  42.         BrVector3Scale(&pMark->pos, &temp, 0.5f);
  43.         rows[3] = pMark->pos;
  44.         model = pMark->actor->model;
  45.         model->vertices[1].map.v[0] = pTexture_start / 0.05f;
  46.         model->vertices[0].map.v[0] = model->vertices[1].map.v[0];
  47.         model->vertices[3].map.v[0] = (pTexture_start + len) / 0.05f;
  48.         model->vertices[2].map.v[0] = model->vertices[3].map.v[0];
  49.         BrModelUpdate(model, BR_MODU_ALL);
  50.     }
  51. }
  52.  
  53. // IDA: br_material* __usercall MaterialFromIndex@<EAX>(int pIndex@<EAX>)
  54. br_material* MaterialFromIndex(int pIndex) {
  55.     LOG_TRACE("(%d)", pIndex);
  56.  
  57.     if (pIndex > -2) {
  58.         return gCurrent_race.material_modifiers[pIndex].skid_mark_material;
  59.     } else {
  60.         return gMaterial[-2 - pIndex];
  61.     }
  62. }
  63.  
  64. // IDA: void __usercall AdjustSkid(int pSkid_num@<EAX>, br_matrix34 *pMatrix@<EDX>, int pMaterial_index@<EBX>)
  65. void AdjustSkid(int pSkid_num, br_matrix34* pMatrix, int pMaterial_index) {
  66.     LOG_TRACE("(%d, %p, %d)", pSkid_num, pMatrix, pMaterial_index);
  67.  
  68.     gSkids[pSkid_num].actor->t.t.mat = *pMatrix;
  69.     gSkids[pSkid_num].pos.v[0] = pMatrix->m[3][0];
  70.     gSkids[pSkid_num].pos.v[1] = pMatrix->m[3][1];
  71.     gSkids[pSkid_num].pos.v[2] = pMatrix->m[3][2];
  72.     gSkids[pSkid_num].actor->material = MaterialFromIndex(pMaterial_index);
  73.     gSkids[pSkid_num].actor->render_style = BR_RSTYLE_DEFAULT;
  74. }
  75.  
  76. // IDA: int __usercall FarFromLine2D@<EAX>(br_vector3 *pPt@<EAX>, br_vector3 *pL1@<EDX>, br_vector3 *pL2@<EBX>)
  77. int FarFromLine2D(br_vector3* pPt, br_vector3* pL1, br_vector3* pL2) {
  78.     br_vector2 line;
  79.     br_vector2 to_pt;
  80.     br_scalar line_len;
  81.     br_scalar cross;
  82.     LOG_TRACE("(%p, %p, %p)", pPt, pL1, pL2);
  83.  
  84.     line.v[0] = pL2->v[0] - pL1->v[0];
  85.     line.v[1] = pL2->v[2] - pL1->v[2];
  86.     to_pt.v[0] = pPt->v[0] - pL2->v[0];
  87.     to_pt.v[1] = pPt->v[2] - pL2->v[2];
  88.     cross = -line.v[0] * to_pt.v[1] + to_pt.v[0] * line.v[1];
  89.     line_len = sqrtf(line.v[0] * line.v[0] + line.v[1] * line.v[1]);
  90.     return fabs(cross) > line_len * 0.050000001;
  91. }
  92.  
  93. // IDA: int __usercall Reflex2D@<EAX>(br_vector3 *pPt@<EAX>, br_vector3 *pL1@<EDX>, br_vector3 *pL2@<EBX>)
  94. int Reflex2D(br_vector3* pPt, br_vector3* pL1, br_vector3* pL2) {
  95.     br_vector2 line;
  96.     br_vector2 to_pt;
  97.     LOG_TRACE("(%p, %p, %p)", pPt, pL1, pL2);
  98.  
  99.     line.v[0] = pL2->v[0] - pL1->v[0];
  100.     line.v[1] = pL2->v[2] - pL1->v[2];
  101.     to_pt.v[0] = pPt->v[0] - pL2->v[0];
  102.     to_pt.v[1] = pPt->v[2] - pL2->v[2];
  103.     return to_pt.v[1] * line.v[1] + to_pt.v[0] * line.v[0] < 0.0;
  104. }
  105.  
  106. // IDA: void __cdecl InitSkids()
  107. void InitSkids(void) {
  108.     int skid;
  109.     int mat;
  110.     int sl;
  111.     br_model* square;
  112.     char* str;
  113. #if defined(DETHRACE_FIX_BUGS)
  114.     char mat_name[32];
  115. #endif
  116.     LOG_TRACE("()");
  117.  
  118.     for (mat = 0; mat < COUNT_OF(gMaterial_names); mat++) {
  119.         if (gProgram_state.sausage_eater_mode) {
  120.             str = gBoring_material_names[mat];
  121.         } else {
  122.             str = gMaterial_names[mat];
  123.         }
  124.         gMaterial[mat] = BrMaterialFind(str);
  125.         if (gMaterial[mat] == NULL) {
  126.             if (gProgram_state.sausage_eater_mode) {
  127.                 str = gBoring_material_names[mat];
  128.             } else {
  129.                 str = gMaterial_names[mat];
  130.             }
  131.  
  132. #if defined(DETHRACE_FIX_BUGS)
  133.             // Avoid modification of read-only data by strtok.
  134.             strcpy(mat_name, str);
  135.             str = mat_name;
  136. #endif
  137.             sl = strlen(strtok(str, "."));
  138.             strcpy(str + sl, ".PIX");
  139.             BrMapAdd(LoadPixelmap(str));
  140.             strcpy(str + sl, ".MAT");
  141.             gMaterial[mat] = LoadMaterial(str);
  142.             if (gMaterial[mat]) {
  143.                 BrMaterialAdd(gMaterial[mat]);
  144.             } else {
  145.                 BrFatal("..\\..\\source\\common\\skidmark.c", 207, "Couldn't find %s", gMaterial_names[mat]);
  146.             }
  147.         }
  148.     }
  149.  
  150.     for (skid = 0; skid < COUNT_OF(gSkids); skid++) {
  151.         gSkids[skid].actor = BrActorAllocate(BR_ACTOR_MODEL, NULL);
  152.         BrActorAdd(gNon_track_actor, gSkids[skid].actor);
  153.         gSkids[skid].actor->t.t.mat.m[1][1] = 0.01f;
  154.         gSkids[skid].actor->render_style = BR_RSTYLE_NONE;
  155.         square = BrModelAllocate(NULL, 4, 2);
  156.         BrVector3Set(&square->vertices[0].p, -0.5f, 1.0f, -0.5f);
  157.         BrVector3Set(&square->vertices[1].p, -0.5f, 1.0f, 0.5f);
  158.         BrVector3Set(&square->vertices[2].p, 0.5f, 1.0f, 0.5f);
  159.         BrVector3Set(&square->vertices[3].p, 0.5f, 1.0f, -0.5f);
  160.         BrVector2Set(&square->vertices[0].map, 0.0f, 0.0f);
  161.         BrVector2Set(&square->vertices[1].map, 0.0f, 1.0f);
  162.         BrVector2Set(&square->vertices[2].map, 1.0f, 1.0f);
  163.         BrVector2Set(&square->vertices[3].map, 1.0f, 0.0f);
  164.         square->faces[0].vertices[0] = 0;
  165.         square->faces[0].vertices[1] = 1;
  166.         square->faces[0].vertices[2] = 2;
  167.         square->faces[0].smoothing = 1;
  168.         square->faces[1].vertices[0] = 0;
  169.         square->faces[1].vertices[1] = 2;
  170.         square->faces[1].vertices[2] = 3;
  171.         square->faces[1].smoothing = 1;
  172.         square->flags |= BR_MODF_KEEP_ORIGINAL;
  173.         BrModelAdd(square);
  174.         gSkids[skid].actor->model = square;
  175.     }
  176. }
  177.  
  178. // IDA: void __usercall HideSkid(int pSkid_num@<EAX>)
  179. void HideSkid(int pSkid_num) {
  180.     LOG_TRACE("(%d)", pSkid_num);
  181.  
  182.     gSkids[pSkid_num].actor->render_style = BR_RSTYLE_NONE;
  183. }
  184.  
  185. // IDA: void __cdecl HideSkids()
  186. void HideSkids(void) {
  187.     int skid;
  188.     LOG_TRACE("()");
  189.  
  190.     for (skid = 0; skid < COUNT_OF(gSkids); skid++) {
  191.         HideSkid(skid);
  192.     }
  193. }
  194.  
  195. // IDA: br_scalar __usercall SkidLen@<ST0>(int pSkid@<EAX>)
  196. br_scalar SkidLen(int pSkid) {
  197.     LOG_TRACE("(%d)", pSkid);
  198.  
  199.     return sqrtf(
  200.         gSkids[pSkid].actor->t.t.mat.m[0][2] * gSkids[pSkid].actor->t.t.mat.m[0][2]
  201.         + gSkids[pSkid].actor->t.t.mat.m[0][1] * gSkids[pSkid].actor->t.t.mat.m[0][1]
  202.         + gSkids[pSkid].actor->t.t.mat.m[0][0] * gSkids[pSkid].actor->t.t.mat.m[0][0]);
  203. }
  204.  
  205. // IDA: void __usercall SkidSection(tCar_spec *pCar@<EAX>, int pWheel_num@<EDX>, br_vector3 *pPos@<EBX>, int pMaterial_index@<ECX>)
  206. void SkidSection(tCar_spec* pCar, int pWheel_num, br_vector3* pPos, int pMaterial_index) {
  207.     static tU16 skid;
  208.     br_material* material;
  209.     LOG_TRACE("(%p, %d, %p, %d)", pCar, pWheel_num, pPos, pMaterial_index);
  210.  
  211.     if (BrVector3Dot(&pCar->prev_nor[pWheel_num], &pCar->nor[pWheel_num]) < 0.99699998
  212.         || fabs(BrVector3Dot(&pCar->nor[pWheel_num], pPos) - BrVector3Dot(&pCar->prev_skid_pos[pWheel_num], &pCar->nor[pWheel_num])) > 0.0099999998) {
  213.         pCar->old_skidding &= ~(1 << pWheel_num);
  214.         pCar->old_skid[pWheel_num] = -1;
  215.         return;
  216.     }
  217.  
  218.     material = MaterialFromIndex(pMaterial_index);
  219.     if (pCar->old_skid[pWheel_num] >= COUNT_OF(gSkids)
  220.         || gSkids[pCar->old_skid[pWheel_num]].actor->material != material
  221.         || SkidLen(pCar->old_skid[pWheel_num]) > 0.5
  222.         || FarFromLine2D(pPos, &pCar->skid_line_start[pWheel_num], &pCar->skid_line_end[pWheel_num])
  223.         || Reflex2D(pPos, &pCar->skid_line_start[pWheel_num], &pCar->prev_skid_pos[pWheel_num])) {
  224.  
  225.         pCar->skid_line_start[pWheel_num] = pCar->prev_skid_pos[pWheel_num];
  226.         pCar->skid_line_end[pWheel_num] = *pPos;
  227.         gSkids[skid].actor->render_style = BR_RSTYLE_DEFAULT;
  228.         gSkids[skid].actor->material = material;
  229.         gSkids[skid].normal = pCar->nor[pWheel_num];
  230.         StretchMark(&gSkids[skid], &pCar->prev_skid_pos[pWheel_num], pPos, pCar->total_length[pWheel_num]);
  231.         PipeSingleSkidAdjustment(skid, &gSkids[skid].actor->t.t.mat, pMaterial_index);
  232.         pCar->old_skid[pWheel_num] = skid;
  233.         skid = (skid + 1) % COUNT_OF(gSkids);
  234.     } else {
  235.         StretchMark(&gSkids[pCar->old_skid[pWheel_num]], &pCar->skid_line_start[pWheel_num], pPos, pCar->total_length[pWheel_num]);
  236.         PipeSingleSkidAdjustment(pCar->old_skid[pWheel_num], &gSkids[pCar->old_skid[pWheel_num]].actor->t.t.mat, pMaterial_index);
  237.     }
  238. }
  239.  
  240. // IDA: void __usercall SkidMark(tCar_spec *pCar@<EAX>, int pWheel_num@<EDX>)
  241. void SkidMark(tCar_spec* pCar, int pWheel_num) {
  242.     br_vector3 pos;
  243.     br_vector3 world_pos;
  244.     br_vector3 disp;
  245.     br_vector3 spesh_to_wheel;
  246.     int material_index;
  247.     br_scalar dist;
  248.     br_scalar dist2;
  249.     int on_ground;
  250.     //br_material* material; // Pierre-Marie Baty -- unused variable
  251.     LOG_TRACE("(%p, %d)", pCar, pWheel_num);
  252.  
  253.     on_ground = pCar->susp_height[pWheel_num >> 1] > pCar->oldd[pWheel_num];
  254.     if (!on_ground) {
  255.         pCar->special_start[pWheel_num].v[0] = FLT_MAX;
  256.     }
  257.     if (pCar->blood_remaining[pWheel_num] != 0 && on_ground) {
  258.         pCar->new_skidding |= 1 << pWheel_num;
  259.         material_index = -3;
  260.     } else if (pCar->oil_remaining[pWheel_num] != 0 && on_ground) {
  261.         pCar->new_skidding |= 1 << pWheel_num;
  262.         material_index = -2;
  263.     } else {
  264.         material_index = pCar->material_index[pWheel_num];
  265.         if (!gCurrent_race.material_modifiers[material_index].skid_mark_material) {
  266.             pCar->old_skidding &= ~(1 << pWheel_num);
  267.             return;
  268.         }
  269.     }
  270.  
  271.     if (((1 << pWheel_num) & pCar->new_skidding) != 0 || ((1 << pWheel_num) & pCar->old_skidding) != 0) {
  272.         if ((pWheel_num & 1) != 0) {
  273.             pos.v[0] = pCar->bounds[1].max.v[0] - 0.1725f;
  274.         } else {
  275.             pos.v[0] = pCar->bounds[1].min.v[0] + 0.1725f;
  276.         }
  277.         pos.v[1] = pCar->wpos[pWheel_num].v[1] - pCar->oldd[pWheel_num];
  278.         pos.v[2] = pCar->wpos[pWheel_num].v[2];
  279.         BrMatrix34ApplyP(&world_pos, &pos, &pCar->car_master_actor->t.t.mat);
  280.         BrVector3InvScale(&world_pos, &world_pos, WORLD_SCALE);
  281.         if (pCar->special_start[pWheel_num].v[0] != FLT_MAX) {
  282.  
  283.             BrVector3Sub(&spesh_to_wheel, &world_pos, &pCar->special_start[pWheel_num]);
  284.             dist = BrVector3Length(&spesh_to_wheel);
  285.             if (dist <= BR_SCALAR_EPSILON || (BrVector3Dot(&pCar->direction, &spesh_to_wheel) / dist < 0.70700002)) {
  286.                 return;
  287.             }
  288.             world_pos = pCar->special_start[pWheel_num];
  289.             pCar->special_start[pWheel_num].v[0] = FLT_MAX;
  290.         }
  291.         if (((1 << pWheel_num) & pCar->new_skidding) != 0) {
  292.             if (((1 << pWheel_num) & pCar->old_skidding) != 0) {
  293.                 BrVector3Sub(&disp, &world_pos, &pCar->prev_skid_pos[pWheel_num]);
  294.                 dist2 = BrVector3Length(&disp);
  295.                 if (dist2 < 0.05f) {
  296.                     return;
  297.                 }
  298.                 SkidSection(pCar, pWheel_num, &world_pos, material_index);
  299.                 pCar->total_length[pWheel_num] = pCar->total_length[pWheel_num] + dist2;
  300.                 pCar->oil_remaining[pWheel_num] = pCar->oil_remaining[pWheel_num] - dist2;
  301.                 if (pCar->oil_remaining[pWheel_num] < 0.0f) {
  302.                     pCar->oil_remaining[pWheel_num] = 0.0f;
  303.                 }
  304.                 pCar->blood_remaining[pWheel_num] = pCar->blood_remaining[pWheel_num] - dist2;
  305.                 if (pCar->blood_remaining[pWheel_num] < 0.0f) {
  306.                     pCar->blood_remaining[pWheel_num] = 0.0f;
  307.                 }
  308.             } else {
  309.                 pCar->old_skidding |= 1 << pWheel_num;
  310.                 pCar->total_length[pWheel_num] = 0.0f;
  311.                 pCar->old_skid[pWheel_num] = -1;
  312.             }
  313.         } else {
  314.             pCar->old_skidding &= ~(1 << pWheel_num);
  315.         }
  316.         pCar->prev_skid_pos[pWheel_num] = world_pos;
  317.         pCar->prev_nor[pWheel_num] = pCar->nor[pWheel_num];
  318.     }
  319. }
  320.  
  321. // IDA: void __usercall InitCarSkidStuff(tCar_spec *pCar@<EAX>)
  322. void InitCarSkidStuff(tCar_spec* pCar) {
  323.     int wheel;
  324.     LOG_TRACE("(%p)", pCar);
  325.  
  326.     pCar->old_skidding = 0;
  327.     for (wheel = 0; wheel < 4; wheel++) {
  328.         pCar->special_start[wheel].v[0] = FLT_MAX;
  329.         pCar->blood_remaining[wheel] = 0.0f;
  330.         pCar->oil_remaining[wheel] = 0.0f;
  331.     }
  332. }
  333.  
  334. // IDA: void __cdecl SkidsPerFrame()
  335. void SkidsPerFrame(void) {
  336.     int skid;
  337.     LOG_TRACE("()");
  338.  
  339.     for (skid = 0; skid < COUNT_OF(gSkids); skid++) {
  340.         if (gSkids[skid].actor->render_style != BR_RSTYLE_NONE) {
  341.             EnsureGroundDetailVisible(&gSkids[skid].actor->t.t.translate.t, &gSkids[skid].normal, &gSkids[skid].pos);
  342.         }
  343.     }
  344. }
  345.  
  346. // IDA: void __cdecl RemoveMaterialsFromSkidmarks()
  347. void RemoveMaterialsFromSkidmarks(void) {
  348.     //int skid; // Pierre-Marie Baty -- unused variable
  349.     LOG_TRACE("()");
  350.     NOT_IMPLEMENTED();
  351. }
  352.