00001
00002
00003
00004
00006
00007 #include "Revolt.h"
00008 #include "Model.h"
00009 #include "Play.h"
00010 #include "Particle.h"
00011 #include "Aerial.h"
00012 #include "NewColl.h"
00013 #include "Body.h"
00014 #include "main.h"
00015 #include "Wheel.h"
00016 #include "Car.h"
00017 #include "DrawObj.h"
00018 #include "Shadow.h"
00019 #include "Light.h"
00020 #include "Draw.h"
00021 #include "Geom.h"
00022 #include "camera.h"
00023 #include "dx.h"
00024 #include "input.h"
00025 #include "ctrlread.h"
00026 #include "object.h"
00027 #include "control.h"
00028 #include "player.h"
00029 #include "visibox.h"
00030 #include "timing.h"
00031 #include "registry.h"
00032 #include "mirror.h"
00033 #include "ai.h"
00034 #include "ghost.h"
00035 #include "text.h"
00036 #include "spark.h"
00037 #include "obj_init.h"
00038
00039
00040
00041 void DrawTarget(PLAYER *player);
00042
00043
00044
00045
00046 FACING_POLY SunFacingPoly, DragonFireFacingPoly;
00047
00048
00049
00050 CAR_SHADOW_TABLE CarShadowTable[] = {
00051
00052 -37, 37, 77, -70, -8,
00053 32, 0, 32, 64,
00054
00055 -37, 37, 81, -79, -8,
00056 224, 0, 32, 64,
00057
00058 -52, 52, 115, -124, -8,
00059 128, 0, 32, 64,
00060
00061 -40, 40, 85, -90, -8,
00062 160, 0, 32, 64,
00063
00064 -44, 44, 95, -93, -8,
00065 128, 64, 32, 64,
00066
00067 -39, 39, 89, -86, -8,
00068 192, 0, 32, 64,
00069
00070 -44, 44, 84, -97, -8,
00071 192, 64, 32, 64,
00072
00073 -35, 35, 76, -69, -8,
00074 32, 192, 32, 64,
00075
00076 -45, 45, 76, -92, -8,
00077 96, 0, 32, 64,
00078
00079 -49, 49, 118, -97, -8,
00080 160, 64, 32, 64,
00081
00082 -51, 51, 107, -100, -8,
00083 0, 64, 32, 64,
00084
00085 -41, 41, 84, -81, -8,
00086 160, 128, 32, 64,
00087
00088 -64, 64, 132, -127, -8,
00089 96, 64, 32, 64,
00090
00091 -40, 40, 82, -82, -8,
00092 64, 0, 32, 64,
00093
00094 -38, 38, 94, -67, -8,
00095 32, 128, 32, 64,
00096
00097 -34, 34, 63, -69, -8,
00098 0, 0, 32, 64,
00099
00100 -38, 38, 74, -72, -8,
00101 192, 128, 32, 64,
00102
00103 -56, 56, 132, -108, -8,
00104 64, 64, 32, 64,
00105
00106 -41, 41, 75, -85, -8,
00107 96, 128, 32, 64,
00108
00109 -34, 34, 75, -59, -8,
00110 224, 128, 32, 64,
00111
00112 -55, 55, 115, -110, -8,
00113 32, 64, 32, 64,
00114
00115 -38, 38, 86, -77, -8,
00116 0, 128, 32, 64,
00117
00118 -60, 60, 60, -60, -8,
00119 0, 0, 1, 1,
00120
00121 -43, 43, 92, -86, -8,
00122 128, 128, 32, 64,
00123
00124 -37, 37, 82, -68, -8,
00125 0, 192, 32, 64,
00126
00127 -38, 38, 70, -89, -8,
00128 224, 64, 32, 64,
00129
00130 -42, 42, 96, -81, -8,
00131 64, 128, 32, 64,
00132 };
00133
00135
00137
00138 long TestSphereToFrustum(VEC *pos, float rad, float *z)
00139 {
00140 float l, r, t, b;
00141
00142
00143
00144 *z = pos->v[X] * ViewMatrix.m[RZ] + pos->v[Y] * ViewMatrix.m[UZ] + pos->v[Z] * ViewMatrix.m[LZ] + ViewTrans.v[Z];
00145 if (*z + rad < RenderSettings.NearClip || *z - rad >= RenderSettings.FarClip) return SPHERE_OUT;
00146
00147 if ((l = PlaneDist(&CameraPlaneLeft, pos)) >= rad) return SPHERE_OUT;
00148 if ((r = PlaneDist(&CameraPlaneRight, pos)) >= rad) return SPHERE_OUT;
00149 if ((b = PlaneDist(&CameraPlaneBottom, pos)) >= rad) return SPHERE_OUT;
00150 if ((t = PlaneDist(&CameraPlaneTop, pos)) >= rad) return SPHERE_OUT;
00151
00152
00153
00154 if (l > -rad || r > -rad || b > -rad || t > -rad || *z - rad < RenderSettings.NearClip || *z + rad >= RenderSettings.FarClip) return SPHERE_CLIP;
00155 return SPHERE_IN;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00188
00190
00191 void BuildAllCarWorldMatrices(void)
00192 {
00193 PLAYER *player;
00194
00195
00196
00197 GhostSineCount += TimeFactor / 20;
00198 GhostSinePos = (float)sin(GhostSineCount) * 128;
00199
00200
00201
00202 for (player = PLR_PlayerHead ; player ; player = player->next)
00203 {
00204 BuildCarMatricesNew(&player->car);
00205 }
00206 }
00207
00209
00210
00211
00212
00214
00215 void BuildCarMatricesNew(CAR *car)
00216 {
00217 WHEEL *wheel;
00218 SUSPENSION *susp;
00219 VEC tmpVec;
00220 VEC fixedPos;
00221 MAT tmpMat, tmpMat2;
00222 REAL scale;
00223 int iWheel;
00224
00225
00226
00227 RotTransVector(&car->Body->Centre.WMatrix, &car->Body->Centre.Pos, &car->BodyOffset, &car->BodyWorldPos);
00228
00229
00230
00231 for (iWheel = 0; iWheel < CAR_NWHEELS; iWheel++)
00232 {
00233 wheel = &car->Wheel[iWheel];
00234 susp = &car->Sus[iWheel];
00235
00236
00237
00238 VecPlusScalarVec(&car->WheelOffset[iWheel], wheel->Pos, &DownVec, &fixedPos);
00239
00240
00241
00242 if (CarHasSpring(car, iWheel))
00243 {
00244 BuildLookMatrixDown(&car->SuspOffset[iWheel], &fixedPos, &tmpMat);
00245 SubVector(&fixedPos, &car->SuspOffset[iWheel], &tmpVec);
00246 scale = Length(&tmpVec) / susp->SpringLen;
00247 VecMulScalar(&tmpMat.mv[U], scale);
00248
00249 MulMatrix(&car->Body->Centre.WMatrix, &tmpMat, &susp->SpringCarMatrix);
00250 RotTransVector(&car->Body->Centre.WMatrix, &car->Body->Centre.Pos, &car->SuspOffset[iWheel], &susp->SpringWorldPos);
00251 }
00252
00253
00254
00255 if (CarHasAxle(car, iWheel))
00256 {
00257 BuildLookMatrixForward(&car->AxleOffset[iWheel], &fixedPos, &tmpMat);
00258 SubVector(&fixedPos, &car->AxleOffset[iWheel], &tmpVec);
00259 scale = Length(&tmpVec) / susp->AxleLen;
00260 VecMulScalar(&tmpMat.mv[L], scale);
00261
00262 MulMatrix(&car->Body->Centre.WMatrix, &tmpMat, &susp->AxleCarMatrix);
00263 RotTransVector(&car->Body->Centre.WMatrix, &car->Body->Centre.Pos, &car->AxleOffset[iWheel], &susp->AxleWorldPos);
00264 }
00265
00266
00267
00268 if (CarHasPin(car, iWheel))
00269 {
00270 BuildLookMatrixDown(&car->SuspOffset[iWheel], &fixedPos, &tmpMat);
00271 VecMulScalar(&tmpMat.mv[U], -susp->PinLen);
00272
00273 MulMatrix(&car->Body->Centre.WMatrix, &tmpMat, &susp->PinCarMatrix);
00274 RotTransVector(&car->Body->Centre.WMatrix, &car->Body->Centre.Pos, &fixedPos, &susp->PinWorldPos);
00275 }
00276
00277 if (CarHasSpinner(car)) {
00278 BuildRotation3D(car->Spinner.Axis.v[X], car->Spinner.Axis.v[Y], car->Spinner.Axis.v[Z], TimeStep * car->Spinner.AngVel, &tmpMat);
00279 MatMulTransMat(&tmpMat, &car->Spinner.Matrix, &tmpMat2);
00280 TransMat(&tmpMat2, &car->Spinner.Matrix);
00281 MulMatrix(&car->Body->Centre.WMatrix, &car->Spinner.Matrix, &car->Spinner.CarMatrix);
00282
00283 RotTransVector(&car->Body->Centre.WMatrix, &car->Body->Centre.Pos, &car->Models->OffSpinner, &car->Spinner.WorldPos);
00284 }
00285 }
00286 }
00287
00289
00291
00292 void DrawAllCars(void)
00293 {
00294 PLAYER *player;
00295
00296
00297
00298 if (GhostSolid)
00299 GHO_GhostPlayer->type = PLAYER_LOCAL;
00300
00301 for (player = PLR_PlayerHead ; player ; player = player->next) if (player->type != PLAYER_GHOST)
00302 {
00303 DrawCar(&player->car);
00304 if (player->PickupTarget != NULL)
00305 {
00306 DrawTarget(player);
00307 }
00308 }
00309
00310 if (GhostSolid)
00311 GHO_GhostPlayer->type = PLAYER_GHOST;
00312 }
00313
00315
00317
00318 void DrawAllGhostCars(void)
00319 {
00320 PLAYER *player;
00321
00322
00323
00324 if (GhostSolid)
00325 return;
00326
00327 ZWRITE_ON();
00328 ALPHA_ON();
00329 ALPHA_SRC(D3DBLEND_SRCALPHA);
00330 ALPHA_DEST(D3DBLEND_INVSRCALPHA);
00331
00332
00333
00334 for (player = PLR_PlayerHead ; player ; player = player->next) if (player->type == PLAYER_GHOST)
00335 {
00336 DrawCarGhost(&player->car);
00337 }
00338
00339 FlushPolyBuckets();
00340 }
00341
00343
00345
00346 void DrawCar(CAR *car)
00347 {
00348 long ii, visflag, envrgb = car->Models->EnvRGB;
00349 REAL z, flod;
00350 BOUNDING_BOX box;
00351 short flag = MODEL_PLAIN;
00352 char lod, lod2;
00353
00354
00355
00356 car->Rendered = FALSE;
00357
00358
00359
00360 box.Xmin = car->Body->Centre.Pos.v[X] - CAR_RADIUS;
00361 box.Xmax = car->Body->Centre.Pos.v[X] + CAR_RADIUS;
00362 box.Ymin = car->Body->Centre.Pos.v[Y] - CAR_RADIUS;
00363 box.Ymax = car->Body->Centre.Pos.v[Y] + CAR_RADIUS;
00364 box.Zmin = car->Body->Centre.Pos.v[Z] - CAR_RADIUS;
00365 box.Zmax = car->Body->Centre.Pos.v[Z] + CAR_RADIUS;
00366
00367
00368
00369 if (TestObjectVisiboxes(&box))
00370 return;
00371
00372
00373
00374 visflag = TestSphereToFrustum(&car->Body->Centre.Pos, CAR_RADIUS, &z);
00375 if (visflag == SPHERE_OUT) return;
00376 if (visflag == SPHERE_IN) flag |= MODEL_DONOTCLIP;
00377
00378
00379
00380 car->Rendered = TRUE;
00381
00382
00383
00384 flod = z / CAR_LOD_BIAS - 2;
00385 if (flod < 0) flod = 0;
00386 if (flod > MAX_CAR_LOD - 1) flod = MAX_CAR_LOD - 1;
00387 FTOL(flod, lod);
00388
00389
00390
00391 if (z + CAR_RADIUS > RenderSettings.FogStart && DxState.Fog)
00392 {
00393 ModelVertFog = (car->Body->Centre.Pos.v[1] - RenderSettings.VertFogStart) * RenderSettings.VertFogMul;
00394 if (ModelVertFog < 0) ModelVertFog = 0;
00395 if (ModelVertFog > 255) ModelVertFog = 255;
00396
00397 flag |= MODEL_FOG;
00398 FOG_ON();
00399 }
00400
00401
00402
00403 if (CheckObjectLight(&car->Body->Centre.Pos, &box, CAR_RADIUS))
00404 {
00405 flag |= MODEL_LIT;
00406 }
00407
00408
00409
00410 if (car->AddLit)
00411 {
00412
00413 ModelAddLit = car->AddLit;
00414 flag |= MODEL_ADDLIT;
00415 }
00416
00417
00418
00419 if (car->DrawScale != 1.0f)
00420 {
00421 ModelScale = car->DrawScale;
00422 flag |= MODEL_SCALE;
00423 }
00424
00425
00426
00427 if (RenderSettings.Mirror)
00428 {
00429 if (GetMirrorPlane(&car->Body->Centre.Pos))
00430 {
00431 if (ViewCameraPos.v[Y] < MirrorHeight)
00432 flag |= MODEL_MIRROR;
00433 }
00434 }
00435
00436
00437
00438 SetEnvActive(&car->Body->Centre.Pos, &car->Body->Centre.WMatrix, &car->EnvMatrix, envrgb, 0.0f, 0.0f, 1.0f);
00439
00440
00441 lod2 = lod;
00442 while (!car->Models->Body[lod2].PolyNum) lod2--;
00443 if (flag & MODEL_LIT) AddModelLight(&car->Models->Body[lod2], &car->BodyWorldPos, &car->Body->Centre.WMatrix);
00444 DrawModel(&car->Models->Body[lod2], &car->Body->Centre.WMatrix, &car->BodyWorldPos, flag | MODEL_ENV);
00445
00446
00447
00448 for (ii = 0; ii < CAR_NWHEELS; ii++)
00449 {
00450
00451
00452
00453 if (IsWheelPresent(&car->Wheel[ii]))
00454 {
00455 lod2 = lod;
00456 while (!car->Models->Wheel[ii][lod2].PolyNum) lod2--;
00457 if (flag & MODEL_LIT) AddModelLight(&car->Models->Wheel[ii][lod2], &car->Wheel[ii].WPos, &car->Wheel[ii].WMatrix);
00458 DrawModel(&car->Models->Wheel[ii][lod2], &car->Wheel[ii].WMatrix, &car->Wheel[ii].WPos, flag);
00459 }
00460
00461
00462
00463 if (CarHasSpring(car, ii))
00464 {
00465 lod2 = lod;
00466 while (!car->Models->Spring[ii][lod2].PolyNum) lod2--;
00467 if (flag & MODEL_LIT) AddModelLightSimple(&car->Models->Spring[ii][lod2], &car->Sus[ii].SpringWorldPos);
00468 DrawModel(&car->Models->Spring[ii][lod2], &car->Sus[ii].SpringCarMatrix, &car->Sus[ii].SpringWorldPos, flag);
00469 }
00470
00471
00472
00473 if (CarHasAxle(car, ii))
00474 {
00475 lod2 = lod;
00476 while (!car->Models->Axle[ii][lod2].PolyNum) lod2--;
00477 if (flag & MODEL_LIT) AddModelLightSimple(&car->Models->Axle[ii][lod2], &car->Sus[ii].AxleWorldPos);
00478 DrawModel(&car->Models->Axle[ii][lod2], &car->Sus[ii].AxleCarMatrix, &car->Sus[ii].AxleWorldPos, flag);
00479 }
00480
00481
00482
00483 if (CarHasPin(car, ii))
00484 {
00485 lod2 = lod;
00486 while (!car->Models->Pin[ii][lod2].PolyNum) lod2--;
00487 if (flag & MODEL_LIT) AddModelLightSimple(&car->Models->Pin[ii][lod2], &car->Sus[ii].PinWorldPos);
00488 DrawModel(&car->Models->Pin[ii][lod2], &car->Sus[ii].PinCarMatrix, &car->Sus[ii].PinWorldPos, flag);
00489 }
00490 }
00491
00492
00493
00494 if (CarHasSpinner(car))
00495 {
00496 lod2 = lod;
00497 while (!car->Models->Spinner[lod2].PolyNum) lod2--;
00498 if (flag & MODEL_LIT) AddModelLightSimple(&car->Models->Spinner[lod2], &car->Spinner.WorldPos);
00499 DrawModel(&car->Models->Spinner[lod2], &car->Spinner.CarMatrix, &car->Spinner.WorldPos, flag);
00500 }
00501
00502
00503
00504 #if SHOW_PHYSICS_INFO
00505 if (CAR_DrawCarAxes) {
00506 DrawAxis(&car->Body->Centre.WMatrix, &car->Body->Centre.Pos);
00507 }
00508 if (CAR_DrawCarBBoxes) {
00509 ALPHA_ON();
00510 ALPHA_SRC(D3DBLEND_ONE);
00511 ALPHA_DEST(D3DBLEND_ONE);
00512
00513 DrawCarBoundingBoxes(car);
00514
00515 ALPHA_OFF();
00516 }
00517 #endif
00518
00519
00520
00521 if (CarHasAerial(car))
00522 {
00523 DrawCarAerial2(&car->Aerial, car->Models->Aerial[0], car->Models->Aerial[1], flag);
00524 }
00525
00526
00527
00528 if (flag & MODEL_FOG)
00529 FOG_OFF();
00530 }
00531
00533
00535
00536 void DrawCarGhost(CAR *car)
00537 {
00538 long ii, visflag;
00539 REAL z, flod;
00540 BOUNDING_BOX box;
00541 short flag = MODEL_GHOST;
00542 char lod, lod2;
00543
00544
00545
00546 car->Rendered = FALSE;
00547
00548
00549
00550 box.Xmin = car->Body->Centre.Pos.v[X] - CAR_RADIUS;
00551 box.Xmax = car->Body->Centre.Pos.v[X] + CAR_RADIUS;
00552 box.Ymin = car->Body->Centre.Pos.v[Y] - CAR_RADIUS;
00553 box.Ymax = car->Body->Centre.Pos.v[Y] + CAR_RADIUS;
00554 box.Zmin = car->Body->Centre.Pos.v[Z] - CAR_RADIUS;
00555 box.Zmax = car->Body->Centre.Pos.v[Z] + CAR_RADIUS;
00556
00557
00558
00559 if (TestObjectVisiboxes(&box))
00560 return;
00561
00562
00563
00564 visflag = TestSphereToFrustum(&car->Body->Centre.Pos, CAR_RADIUS, &z);
00565 if (visflag == SPHERE_OUT) return;
00566 if (visflag == SPHERE_IN) flag |= MODEL_DONOTCLIP;
00567
00568
00569
00570 car->Rendered = TRUE;
00571
00572
00573
00574 flod = z / CAR_LOD_BIAS - 2;
00575 if (flod < 0) flod = 0;
00576 if (flod > MAX_CAR_LOD - 1) flod = MAX_CAR_LOD - 1;
00577 FTOL(flod, lod);
00578
00579
00580
00581 if (z + CAR_RADIUS > RenderSettings.FogStart && DxState.Fog)
00582 {
00583 ModelVertFog = (car->Body->Centre.Pos.v[1] - RenderSettings.VertFogStart) * RenderSettings.VertFogMul;
00584 if (ModelVertFog < 0) ModelVertFog = 0;
00585 if (ModelVertFog > 255) ModelVertFog = 255;
00586
00587 flag |= MODEL_FOG;
00588 FOG_ON();
00589 }
00590
00591
00592
00593 GhostSineOffset = car->BodyOffset.v[Z];
00594 lod2 = lod;
00595 while (!car->Models->Body[lod2].PolyNum) lod2--;
00596 DrawModel(&car->Models->Body[lod2], &car->Body->Centre.WMatrix, &car->BodyWorldPos, flag);
00597
00598
00599
00600 for (ii = 0; ii < CAR_NWHEELS; ii++)
00601 {
00602
00603
00604
00605 if (IsWheelPresent(&car->Wheel[ii]))
00606 {
00607 GhostSineOffset = car->WheelOffset[ii].v[Z];
00608 lod2 = lod;
00609 while (!car->Models->Wheel[ii][lod2].PolyNum) lod2--;
00610 DrawModel(&car->Models->Wheel[ii][lod2], &car->Wheel[ii].WMatrix, &car->Wheel[ii].WPos, flag);
00611 }
00612
00613
00614
00615 if (CarHasSpring(car, ii))
00616 {
00617 GhostSineOffset = car->SuspOffset[ii].v[Z];
00618 lod2 = lod;
00619 while (!car->Models->Spring[ii][lod2].PolyNum) lod2--;
00620 DrawModel(&car->Models->Spring[ii][lod2], &car->Sus[ii].SpringCarMatrix, &car->Sus[ii].SpringWorldPos, flag);
00621 }
00622
00623
00624
00625 if (CarHasAxle(car, ii))
00626 {
00627 GhostSineOffset = car->AxleOffset[ii].v[Z];
00628 lod2 = lod;
00629 while (!car->Models->Axle[ii][lod2].PolyNum) lod2--;
00630 DrawModel(&car->Models->Axle[ii][lod2], &car->Sus[ii].AxleCarMatrix, &car->Sus[ii].AxleWorldPos, flag);
00631 }
00632
00633
00634
00635 if (CarHasPin(car, ii))
00636 {
00637 GhostSineOffset = car->SuspOffset[ii].v[Z];
00638 lod2 = lod;
00639 while (!car->Models->Pin[ii][lod2].PolyNum) lod2--;
00640 DrawModel(&car->Models->Pin[ii][lod2], &car->Sus[ii].PinCarMatrix, &car->Sus[ii].PinWorldPos, flag);
00641 }
00642 }
00643
00644
00645
00646 if (CarHasSpinner(car))
00647 {
00648 GhostSineOffset = car->SpinnerOffset.v[Z];
00649 lod2 = lod;
00650 while (!car->Models->Spinner[lod2].PolyNum) lod2--;
00651 DrawModel(&car->Models->Spinner[lod2], &car->Spinner.CarMatrix, &car->Spinner.WorldPos, flag);
00652 }
00653
00654
00655
00656 #if SHOW_PHYSICS_INFO
00657 if (CAR_DrawCarAxes) {
00658 DrawAxis(&car->Body->Centre.WMatrix, &car->Body->Centre.Pos);
00659 }
00660 if (CAR_DrawCarBBoxes) {
00661 ALPHA_ON();
00662 ALPHA_SRC(D3DBLEND_ONE);
00663 ALPHA_DEST(D3DBLEND_ONE);
00664 ZWRITE_OFF();
00665
00666 DrawCarBoundingBoxes(car);
00667
00668 ZWRITE_ON();
00669 ALPHA_OFF();
00670 }
00671 #endif
00672
00673
00674
00675 GhostSineOffset = car->AerialOffset.v[Z];
00676 if (CarHasAerial(car))
00677 {
00678 DrawCarAerial2(&car->Aerial, car->Models->Aerial[0], car->Models->Aerial[1], flag);
00679 }
00680
00681
00682
00683 if (flag & MODEL_FOG)
00684 FOG_OFF();
00685 }
00686
00688
00690
00691 void DrawAllCarShadows(void)
00692 {
00693 VEC s0, s1, s2, s3;
00694 VEC p0, p1, p2, p3;
00695 CAR *car;
00696 PLAYER *player;
00697 CAR_SHADOW_TABLE *sh;
00698
00699
00700
00701 if (!RenderSettings.Shadow)
00702 return;
00703
00704
00705
00706 ALPHA_ON();
00707 ALPHA_SRC(D3DBLEND_ZERO);
00708 ALPHA_DEST(D3DBLEND_INVSRCCOLOR);
00709
00710 ZWRITE_OFF();
00711 SET_TPAGE(TPAGE_SHADOW);
00712
00713
00714
00715 for (player = PLR_PlayerHead ; player ; player = player->next)
00716 {
00717 car = &player->car;
00718 sh = &CarShadowTable[car->CarID];
00719
00720 if (car->Rendered)
00721 {
00722 SetVector(&s0, sh->Left, sh->Height, sh->Front);
00723 SetVector(&s1, sh->Right, sh->Height, sh->Front);
00724 SetVector(&s2, sh->Right, sh->Height, sh->Back);
00725 SetVector(&s3, sh->Left, sh->Height, sh->Back);
00726
00727 RotTransVector(&car->Body->Centre.WMatrix, &car->Body->Centre.Pos, &s0, &p0);
00728 RotTransVector(&car->Body->Centre.WMatrix, &car->Body->Centre.Pos, &s1, &p1);
00729 RotTransVector(&car->Body->Centre.WMatrix, &car->Body->Centre.Pos, &s2, &p2);
00730 RotTransVector(&car->Body->Centre.WMatrix, &car->Body->Centre.Pos, &s3, &p3);
00731
00732 DrawShadow(&p0, &p1, &p2, &p3, sh->tu / 256.0f, sh->tv / 256.0f, sh->twidth / 256.0f, sh->theight / 256.0f, 0x808080, -2.0f, 0.0f, -1, TPAGE_SHADOW, NULL);
00733
00734
00735 #if FALSE
00736 if (player == GHO_GhostPlayer) continue;
00737
00738 if (Keys[DIK_1]) sh->Left--;
00739 if (Keys[DIK_2]) sh->Left++;
00740 if (Keys[DIK_3]) sh->Right--;
00741 if (Keys[DIK_4]) sh->Right++;
00742 if (Keys[DIK_5]) sh->Front--;
00743 if (Keys[DIK_6]) sh->Front++;
00744 if (Keys[DIK_7]) sh->Back--;
00745 if (Keys[DIK_8]) sh->Back++;
00746 if (Keys[DIK_MINUS]) sh->Height--;
00747 if (Keys[DIK_EQUALS]) sh->Height++;
00748
00749 BeginTextState();
00750 char buf[128];
00751 wsprintf(buf, "%d %d %d %d %d", (long)sh->Left, (long)sh->Right, (long)sh->Front, (long)sh->Back, (long)sh->Height);
00752 DumpText(128, 128, 12, 16, 0xff00ff, buf);
00753 #endif
00754 }
00755 }
00756 }
00757
00759
00760
00761
00763
00764 void DrawCarAerial2(AERIAL *aerial, MODEL *secModel, MODEL *topModel, short flag)
00765 {
00766 int iSec;
00767 VEC thisPos;
00768 VEC lastPos;
00769 MAT wMatrix;
00770
00771
00772 CopyVec(&aerial->Section[0].Pos, &lastPos);
00773
00774 for (iSec = AERIAL_START; iSec < AERIAL_NTOTSECTIONS; iSec++) {
00775
00776
00777 Interpolate3D(
00778 &aerial->Section[0].Pos,
00779 &aerial->Section[AERIAL_SKIP].Pos,
00780 &aerial->Section[AERIAL_LASTSECTION].Pos,
00781 iSec * AERIAL_UNITLEN,
00782 &thisPos);
00783
00784
00785 VecMinusVec(&thisPos, &lastPos, &wMatrix.mv[U]);
00786
00787
00788 BuildMatrixFromUp(&wMatrix);
00789
00790 NormalizeVec(&wMatrix.mv[L]);
00791
00792
00793 if (iSec != AERIAL_NTOTSECTIONS - 1) {
00794 if (flag & MODEL_LIT) {
00795 AddModelLightSimple(secModel, &thisPos);
00796 }
00797 DrawModel(secModel, &wMatrix, &thisPos, flag);
00798 } else {
00799 if (flag & MODEL_LIT) {
00800 AddModelLightSimple(topModel, &thisPos);
00801 }
00802 DrawModel(topModel, &wMatrix, &thisPos, flag);
00803 }
00804
00805 CopyVec(&thisPos, &lastPos);
00806 }
00807 }
00808
00810
00811
00812
00814
00815 void DrawCarBoundingBoxes(CAR *car)
00816 {
00817 int iSkin;
00818 CONVEX *pSkin;
00819 int iWheel;
00820 WHEEL *pWheel;
00821
00822
00823 int iCol = 0;
00824 int nCols = 6;
00825 long cols[][3] = {
00826 {0x000022, 0x000022, 0x000022},
00827 {0x002200, 0x002200, 0x002200},
00828 {0x220000, 0x220000, 0x220000},
00829 {0x002222, 0x002222, 0x002222},
00830 {0x222200, 0x222200, 0x222200},
00831 {0x220022, 0x220022, 0x220022},
00832 };
00833
00834
00835 DrawBoundingBox(
00836 car->BBox.XMin,
00837 car->BBox.XMax,
00838 car->BBox.YMin,
00839 car->BBox.YMax,
00840 car->BBox.ZMin,
00841 car->BBox.ZMax,
00842 cols[iCol][0], cols[iCol][1], cols[iCol][2],
00843 cols[iCol][0], cols[iCol][1], cols[iCol][2]);
00844 iCol++;
00845 if (iCol == nCols) iCol = 0;
00846
00847
00848 DrawBoundingBox(
00849 car->Body->CollSkin.BBox.XMin,
00850 car->Body->CollSkin.BBox.XMax,
00851 car->Body->CollSkin.BBox.YMin,
00852 car->Body->CollSkin.BBox.YMax,
00853 car->Body->CollSkin.BBox.ZMin,
00854 car->Body->CollSkin.BBox.ZMax,
00855 cols[iCol][0], cols[iCol][1], cols[iCol][2],
00856 cols[iCol][0], cols[iCol][1], cols[iCol][2]);
00857 iCol++;
00858 if (iCol == nCols) iCol = 0;
00859
00860
00861
00862 for (iSkin = 0; iSkin < car->Body->CollSkin.NConvex; iSkin++) {
00863 pSkin = &car->Body->CollSkin.WorldConvex[iSkin];
00864
00865 DrawBoundingBox(
00866 pSkin->BBox.XMin,
00867 pSkin->BBox.XMax,
00868 pSkin->BBox.YMin,
00869 pSkin->BBox.YMax,
00870 pSkin->BBox.ZMin,
00871 pSkin->BBox.ZMax,
00872 cols[iCol][0], cols[iCol][1], cols[iCol][2],
00873 cols[iCol][0], cols[iCol][1], cols[iCol][2]);
00874 iCol++;
00875 if (iCol == nCols) iCol = 0;
00876 }
00877
00878
00879 for (iWheel = 0; iWheel < CAR_NWHEELS; iWheel++) {
00880 pWheel = &car->Wheel[iWheel];
00881 if (!IsWheelPresent(pWheel)) continue;
00882
00883 DrawBoundingBox(
00884 pWheel->BBox.XMin + pWheel->CentrePos.v[X],
00885 pWheel->BBox.XMax + pWheel->CentrePos.v[X],
00886 pWheel->BBox.YMin + pWheel->CentrePos.v[Y],
00887 pWheel->BBox.YMax + pWheel->CentrePos.v[Y],
00888 pWheel->BBox.ZMin + pWheel->CentrePos.v[Z],
00889 pWheel->BBox.ZMax + pWheel->CentrePos.v[Z],
00890 cols[iCol][0], cols[iCol][1], cols[iCol][2],
00891 cols[iCol][0], cols[iCol][1], cols[iCol][2]);
00892 iCol++;
00893 if (iCol == nCols) iCol = 0;
00894 }
00895
00896 }
00897
00898
00899
00901
00902
00903
00905
00906 void DrawSkidMarks()
00907 {
00908 int iSkid, j;
00909 int currentSkid;
00910 SKIDMARK *skid;
00911 REAL z;
00912
00913
00914 if (!WHL_NSkids || !RenderSettings.Skid) return;
00915
00916
00917 ALPHA_ON();
00918 ALPHA_SRC(D3DBLEND_ZERO);
00919 ALPHA_DEST(D3DBLEND_INVSRCCOLOR);
00920
00921 ZWRITE_OFF();
00922 SET_TPAGE(TPAGE_SHADOW);
00923
00924 DrawVertsTEX1[0].tu = 224.0f / 256.0f;
00925 DrawVertsTEX1[0].tv = 194.0f / 256.0f;
00926
00927 DrawVertsTEX1[1].tu = 256.0f / 256.0f;
00928 DrawVertsTEX1[1].tv = 194.0f / 256.0f;
00929
00930 DrawVertsTEX1[2].tu = 256.0f / 256.0f;
00931 DrawVertsTEX1[2].tv = 254.0f / 256.0f;
00932
00933 DrawVertsTEX1[3].tu = 224.0f / 256.0f;
00934 DrawVertsTEX1[3].tv = 254.0f / 256.0f;
00935
00936
00937
00938 currentSkid = WHL_SkidHead;
00939 for (iSkid = 0; iSkid < WHL_NSkids; iSkid++) {
00940
00941
00942 currentSkid--;
00943 Wrap(currentSkid, 0, SKID_MAX_SKIDS);
00944 skid = &WHL_SkidMark[currentSkid];
00945
00946
00947 if (skid->VisiMask & CamVisiMask) continue;
00948 z = skid->Centre.v[X] * ViewMatrix.m[RZ] + skid->Centre.v[Y] * ViewMatrix.m[UZ] + skid->Centre.v[Z] * ViewMatrix.m[LZ] + ViewTrans.v[Z];
00949 if (z + SKID_HALF_LEN < RenderSettings.NearClip || z - SKID_HALF_LEN >= RenderSettings.FarClip) continue;
00950
00951
00952 for (j = 0 ; j < 4 ; j++)
00953 {
00954 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &skid->Corner[j], (REAL*)&DrawVertsTEX1[j]);
00955 DrawVertsTEX1[j].color = skid->RGB;
00956 }
00957 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX1, DrawVertsTEX1, 4, D3DDP_DONOTUPDATEEXTENTS);
00958 }
00959 }
00960
00962
00964
00965 void DrawObjects(void)
00966 {
00967 OBJECT *obj;
00968
00969 for (obj = OBJ_ObjectHead; obj; obj = obj->next)
00970 {
00971 if (obj->renderhandler && obj->flag.Draw)
00972
00973 {
00974 obj->renderhandler(obj);
00975 }
00976 }
00977 }
00978
00980
00982
00983 void RenderObject(OBJECT *obj)
00984 {
00985 if (obj->DefaultModel != -1)
00986 obj->renderflag.visible |= RenderObjectModel(&obj->body.Centre.WMatrix, &obj->body.Centre.Pos, &LevelModel[obj->DefaultModel].Model, obj->EnvRGB, obj->renderflag);
00987 }
00988
00990
00992
00993 bool RenderObjectModel(MAT *mat, VEC *pos, MODEL *model, long envrgb, struct renderflags renderflag)
00994 {
00995 REAL z;
00996 BOUNDING_BOX box;
00997 long visflag;
00998 short flag = MODEL_PLAIN;
00999
01000
01001
01002 box.Xmin = pos->v[X] - model->Radius;
01003 box.Xmax = pos->v[X] + model->Radius;
01004 box.Ymin = pos->v[Y] - model->Radius;
01005 box.Ymax = pos->v[Y] + model->Radius;
01006 box.Zmin = pos->v[Z] - model->Radius;
01007 box.Zmax = pos->v[Z] + model->Radius;
01008
01009
01010
01011 if (TestObjectVisiboxes(&box))
01012 return FALSE;
01013
01014
01015
01016 visflag = TestSphereToFrustum(pos, model->Radius, &z);
01017 if (visflag == SPHERE_OUT) return FALSE;
01018 if (visflag == SPHERE_IN) flag |= MODEL_DONOTCLIP;
01019
01020
01021
01022 if (renderflag.envmap)
01023 {
01024 flag |= MODEL_ENV;
01025 SetEnvStatic(pos, mat, envrgb, 0.0f, 0.0f, 1.0f);
01026 }
01027
01028
01029
01030 if (renderflag.light)
01031 {
01032 if (CheckObjectLight(pos, &box, model->Radius))
01033 {
01034 flag |= MODEL_LIT;
01035 AddModelLight(model, pos, mat);
01036 }
01037 }
01038
01039
01040
01041 if (renderflag.reflect && RenderSettings.Mirror)
01042 {
01043 if (GetMirrorPlane(pos))
01044 {
01045 if (ViewCameraPos.v[Y] < MirrorHeight)
01046 flag |= MODEL_MIRROR;
01047 }
01048 }
01049
01050
01051
01052 if (renderflag.fog && z + model->Radius > RenderSettings.FogStart && DxState.Fog)
01053 {
01054 ModelVertFog = (pos->v[Y] - RenderSettings.VertFogStart) * RenderSettings.VertFogMul;
01055 if (ModelVertFog < 0) ModelVertFog = 0;
01056 if (ModelVertFog > 255) ModelVertFog = 255;
01057
01058 flag |= MODEL_FOG;
01059 FOG_ON();
01060 }
01061
01062
01063
01064 if (renderflag.glare)
01065 flag |= MODEL_GLARE;
01066
01067
01068
01069 if (renderflag.meshfx)
01070 {
01071 CheckModelMeshFx(model, mat, pos, &flag);
01072 }
01073
01074
01075
01076 DrawModel(model, mat, pos, flag);
01077
01078
01079
01080 if (flag & MODEL_FOG)
01081 FOG_OFF();
01082
01083
01084
01085 return TRUE;
01086 }
01087
01089
01091
01092 void RenderPlanet(OBJECT *obj)
01093 {
01094 REAL z;
01095 BOUNDING_BOX box;
01096 long visflag;
01097 VEC *pos = &obj->body.Centre.Pos;
01098 MAT *mat = &obj->body.Centre.WMatrix;
01099 MODEL *model = &LevelModel[obj->DefaultModel].Model;
01100 PLANET_OBJ *planet = (PLANET_OBJ*)obj->Data;
01101 short flag = MODEL_PLAIN;
01102
01103
01104
01105 box.Xmin = pos->v[X] - model->Radius;
01106 box.Xmax = pos->v[X] + model->Radius;
01107 box.Ymin = pos->v[Y] - model->Radius;
01108 box.Ymax = pos->v[Y] + model->Radius;
01109 box.Zmin = pos->v[Z] - model->Radius;
01110 box.Zmax = pos->v[Z] + model->Radius;
01111
01112
01113
01114 if (planet->VisiMask & CamVisiMask)
01115 return;
01116
01117
01118
01119 visflag = TestSphereToFrustum(pos, model->Radius, &z);
01120 if (visflag == SPHERE_OUT) return;
01121 if (visflag == SPHERE_IN) flag |= MODEL_DONOTCLIP;
01122
01123
01124
01125 obj->renderflag.visible = TRUE;
01126
01127
01128
01129 if (CheckObjectLight(pos, &box, model->Radius))
01130 {
01131 flag |= MODEL_LIT;
01132 AddModelLight(model, pos, mat);
01133 }
01134
01135
01136
01137 if (z + model->Radius > RenderSettings.FogStart && DxState.Fog)
01138 {
01139 ModelVertFog = (pos->v[Y] - RenderSettings.VertFogStart) * RenderSettings.VertFogMul;
01140 if (ModelVertFog < 0) ModelVertFog = 0;
01141 if (ModelVertFog > 255) ModelVertFog = 255;
01142
01143 flag |= MODEL_FOG;
01144 FOG_ON();
01145 }
01146
01147
01148
01149 CheckModelMeshFx(model, mat, pos, &flag);
01150
01151
01152
01153 DrawModel(model, mat, pos, flag);
01154
01155
01156
01157 if (flag & MODEL_FOG)
01158 FOG_OFF();
01159 }
01160
01162
01164
01165 void RenderSun(OBJECT *obj)
01166 {
01167 long i, starnum;
01168 REAL z, fog, zres, zbuf;
01169 MAT mat, mat2;
01170 VEC vec;
01171 SUN_OBJ *sun = (SUN_OBJ*)obj->Data;
01172
01173
01174
01175 if (sun->VisiMask & CamVisiMask)
01176 return;
01177
01178
01179
01180 if (TestSphereToFrustum(&obj->body.Centre.Pos, 6144, &z) == SPHERE_OUT)
01181 return;
01182
01183
01184
01185 obj->renderflag.visible = TRUE;
01186
01187
01188
01189 for (i = 0 ; i < SUN_OVERLAY_NUM ; i++)
01190 {
01191 RotMatrixZ(&mat, sun->Overlay[i].Rot);
01192 SunFacingPoly.RGB = sun->Overlay[i].rgb;
01193 DrawFacingPolyRot(&obj->body.Centre.Pos, &mat, &SunFacingPoly, 1, 0);
01194 }
01195
01196
01197
01198 RotMatrixY(&mat2, (float)TIME2MS(CurrentTimer()) / 100000.0f);
01199 MulMatrix(&ViewMatrixScaled, &mat2, &mat);
01200 RotTransVector(&ViewMatrixScaled, &ViewTransScaled, &obj->body.Centre.Pos, &vec);
01201
01202 zres = (float)(1 << ZedBufferFormat.dwZBufferBitDepth);
01203 zbuf = (zres - 1.0f) / zres;
01204
01205 starnum = 0;
01206
01207 for (i = 0 ; i < SUN_STAR_NUM ; i++)
01208 {
01209 z = sun->Star[i].Pos.v[X] * mat.m[RZ] + sun->Star[i].Pos.v[Y] * mat.m[UZ] + sun->Star[i].Pos.v[Z] * mat.m[LZ] + vec.v[Z];
01210 if (z < RenderSettings.NearClip || z >= RenderSettings.FarClip) continue;
01211
01212 sun->Verts[starnum].sx = (sun->Star[i].Pos.v[X] * mat.m[RX] + sun->Star[i].Pos.v[Y] * mat.m[UX] + sun->Star[i].Pos.v[Z] * mat.m[LX] + vec.v[X]) / z + RenderSettings.GeomCentreX;
01213 sun->Verts[starnum].sy = (sun->Star[i].Pos.v[X] * mat.m[RY] + sun->Star[i].Pos.v[Y] * mat.m[UY] + sun->Star[i].Pos.v[Z] * mat.m[LY] + vec.v[Y]) / z + RenderSettings.GeomCentreY;
01214
01215 sun->Verts[starnum].rhw = 1.0f;
01216 sun->Verts[starnum].sz = zbuf;
01217
01218 sun->Verts[starnum].color = sun->Star[i].rgb;
01219
01220 fog = (RenderSettings.FarClip - z) * RenderSettings.FogMul;
01221 if (fog > 255) fog = 255;
01222 else if (fog < 0) fog = 0;
01223 sun->Verts[starnum].specular = FTOL3(fog) << 24;
01224
01225 starnum++;
01226 }
01227
01228 FOG_ON();
01229 SET_TPAGE(-1);
01230
01231 D3Ddevice->DrawPrimitive(D3DPT_POINTLIST, FVF_TEX0, sun->Verts, starnum, D3DDP_DONOTUPDATEEXTENTS);
01232
01233 FOG_OFF();
01234 }
01235
01237
01239
01240 void RenderPlane(OBJECT *obj)
01241 {
01242 bool vis1, vis2;
01243 PLANE_OBJ *plane = (PLANE_OBJ*)obj->Data;
01244
01245
01246
01247 if (obj->DefaultModel != -1)
01248 vis1 = RenderObjectModel(&obj->body.Centre.WMatrix, &obj->body.Centre.Pos, &LevelModel[obj->DefaultModel].Model, obj->EnvRGB, obj->renderflag);
01249 else
01250 vis1 = FALSE;
01251
01252
01253
01254 if (plane->PropModel != -1)
01255 vis2 = RenderObjectModel(&plane->PropMatrix, &plane->PropPos, &LevelModel[plane->PropModel].Model, obj->EnvRGB, obj->renderflag);
01256 else
01257 vis2 = FALSE;
01258
01259
01260
01261 obj->renderflag.visible |= (vis1 || vis2);
01262 }
01263
01265
01267
01268 void RenderCopter(OBJECT *obj)
01269 {
01270 bool vis1, vis2, vis3;
01271 COPTER_OBJ *copter = (COPTER_OBJ*)obj->Data;
01272
01273
01274
01275 if (obj->DefaultModel != -1)
01276 vis1 = RenderObjectModel(&obj->body.Centre.WMatrix, &obj->body.Centre.Pos, &LevelModel[obj->DefaultModel].Model, obj->EnvRGB, obj->renderflag);
01277 else
01278 vis1 = FALSE;
01279
01280
01281
01282 if (copter->BladeModel1 != -1)
01283 vis2 = RenderObjectModel(&copter->BladeMatrix1, &copter->BladePos1, &LevelModel[copter->BladeModel1].Model, obj->EnvRGB, obj->renderflag);
01284 else
01285 vis2 = FALSE;
01286
01287
01288
01289 if (copter->BladeModel2 != -1)
01290 vis3 = RenderObjectModel(&copter->BladeMatrix2, &copter->BladePos2, &LevelModel[copter->BladeModel2].Model, obj->EnvRGB, obj->renderflag);
01291 else
01292 vis3 = FALSE;
01293
01294
01295
01296 obj->renderflag.visible |= (vis1 || vis2 || vis3);
01297
01298
01299
01300
01301 }
01302
01304
01306
01307 void RenderDragon(OBJECT *obj)
01308 {
01309 bool vis1, vis2;
01310 long i;
01311 DRAGON_OBJ *dragon = (DRAGON_OBJ*)obj->Data;
01312
01313
01314
01315 if (dragon->BodyModel != -1)
01316 vis1 = RenderObjectModel(&obj->body.Centre.WMatrix, &obj->body.Centre.Pos, &LevelModel[dragon->BodyModel].Model, obj->EnvRGB, obj->renderflag);
01317 else
01318 vis1 = FALSE;
01319
01320
01321
01322 if (dragon->HeadModel != -1)
01323 vis2 = RenderObjectModel(&obj->body.Centre.WMatrix, &obj->body.Centre.Pos, &LevelModel[dragon->HeadModel].Model, obj->EnvRGB, obj->renderflag);
01324 else
01325 vis2 = FALSE;
01326
01327
01328
01329 obj->renderflag.visible |= (vis1 || vis2);
01330
01331
01332
01333 for (i = 0 ; i < DRAGON_FIRE_NUM ; i++) if (dragon->Fire[i].Time)
01334 {
01335 DragonFireFacingPoly.Xsize = dragon->Fire[i].Size;
01336 DragonFireFacingPoly.Ysize = dragon->Fire[i].Size;
01337 DragonFireFacingPoly.RGB = dragon->Fire[i].rgb;
01338 DrawFacingPolyRot(&dragon->Fire[i].Pos, &dragon->Fire[i].Matrix, &DragonFireFacingPoly, 1, 0);
01339 }
01340 }
01341
01342
01344
01345
01346
01348
01349 void DrawGridCollPolys(COLLGRID *grid)
01350 {
01351 int iPoly;
01352
01353 SET_TPAGE(-1);
01354
01355 for (iPoly = 0; iPoly < grid->NCollPolys; iPoly++)
01356 {
01357 DrawCollPoly(grid->CollPolyPtr[iPoly]);
01358 }
01359 }
01360
01361
01363
01364
01365
01367
01368 void RenderTrolley(OBJECT *obj)
01369 {
01370 BuildCarMatricesNew(&obj->player->car);
01371 DrawCar(&obj->player->car);
01372 }
01373
01375
01377
01378 void RenderTrain(OBJECT *obj)
01379 {
01380 TRAIN_OBJ *train = (TRAIN_OBJ*)obj->Data;
01381 MAT mat1, mat2;
01382
01383
01384
01385 if (obj->DefaultModel != -1)
01386 obj->renderflag.visible |= RenderObjectModel(&obj->body.Centre.WMatrix, &obj->body.Centre.Pos, &LevelModel[obj->DefaultModel].Model, obj->EnvRGB, obj->renderflag);
01387
01388
01389
01390 obj->renderflag.envmap = FALSE;
01391
01392 if (train->FrontWheel)
01393 {
01394 RotMatrixX(&mat1, train->TimeFront);
01395 MulMatrix(&obj->body.Centre.WMatrix, &mat1, &mat2);
01396
01397 RenderObjectModel(&mat2, &train->WheelPos[2], &LevelModel[train->FrontWheel].Model, obj->EnvRGB, obj->renderflag);
01398 RenderObjectModel(&mat2, &train->WheelPos[3], &LevelModel[train->FrontWheel].Model, obj->EnvRGB, obj->renderflag);
01399 }
01400
01401 if (train->BackWheel)
01402 {
01403 RotMatrixX(&mat1, train->TimeBack);
01404 MulMatrix(&obj->body.Centre.WMatrix, &mat1, &mat2);
01405
01406 RenderObjectModel(&mat2, &train->WheelPos[0], &LevelModel[train->BackWheel].Model, obj->EnvRGB, obj->renderflag);
01407 RenderObjectModel(&mat2, &train->WheelPos[1], &LevelModel[train->BackWheel].Model, obj->EnvRGB, obj->renderflag);
01408 }
01409
01410 obj->renderflag.envmap = TRUE;
01411 }
01412
01414
01416
01417 void RenderStrobe(OBJECT *obj)
01418 {
01419 FACING_POLY poly;
01420 STROBE_OBJ *strobe = (STROBE_OBJ*)obj->Data;
01421 MAT mat;
01422 REAL ang;
01423
01424
01425
01426 RenderObject(obj);
01427
01428
01429
01430 if (strobe->Glow && obj->Light && obj->renderflag.visible)
01431 {
01432 FOG_ON();
01433
01434 poly.Xsize = poly.Ysize = strobe->Glow * 64.0f + 16.0f;
01435 poly.U = 128.0f / 256.0f;
01436 poly.V = 0.0f / 256.0f;
01437 poly.Usize = poly.Vsize = 64.0f / 256.0f;
01438 poly.Tpage = TPAGE_FX1;
01439 poly.RGB = obj->Light->r << 16 | obj->Light->g << 8 | obj->Light->b;
01440
01441 DrawFacingPoly(&strobe->LightPos, &poly, 1, -256);
01442
01443 poly.U = 192.0f / 256.0f;
01444 poly.V = 64.0f / 256.0f;
01445
01446
01447 ang = TIME2MS(CurrentTimer()) / 5000.0f;
01448
01449 RotMatrixZ(&mat, ang);
01450 DrawFacingPolyRot(&strobe->LightPos, &mat, &poly, 1, -256);
01451
01452 RotMatrixZ(&mat, ang * 2.0f);
01453 DrawFacingPolyRot(&strobe->LightPos, &mat, &poly, 1, -256);
01454
01455 FOG_OFF();
01456 }
01457 }
01458
01460
01462
01463 void RenderPickup(OBJECT *obj)
01464 {
01465 long col, i, alpha;
01466 MODEL *model = &LevelModel[obj->DefaultModel].Model;
01467 PICKUP_OBJ *pickup = (PICKUP_OBJ*)obj->Data;
01468 FACING_POLY poly;
01469 MAT mat;
01470 REAL size;
01471
01472
01473
01474 switch (pickup->Mode)
01475 {
01476
01477
01478
01479 case 0:
01480 return;
01481
01482
01483
01484 case 1:
01485
01486
01487
01488 if (pickup->Timer > 0.5f)
01489 {
01490 if (model->PolyPtr->Type & POLY_SEMITRANS)
01491 {
01492 for (i = 0 ; i < model->PolyNum ; i++)
01493 {
01494 model->PolyPtr[i].Type &= ~POLY_SEMITRANS;
01495 }
01496 }
01497
01498 RenderObject(obj);
01499 }
01500
01501
01502
01503 if (pickup->Timer < 0.75f)
01504 {
01505 FTOL((float)sin(pickup->Timer * 4.0f / 3.0f * PI) * 255.0f, col);
01506
01507 size = (float)sin(pickup->Timer * 4.0f / 3.0f * PI) * 64.0f + 32;
01508
01509 poly.Xsize = poly.Ysize = size;
01510
01511 poly.Usize = poly.Vsize = 64.0f / 256.0f;
01512 poly.Tpage = TPAGE_FX1;
01513
01514 poly.U = 193.0f / 256.0f;
01515 poly.V = 64.0f / 256.0f;
01516 poly.RGB = (col >> 1) | (col << 8) | (col << 16);
01517
01518 RotMatrixZ(&mat, pickup->Timer / 4.0f);
01519 DrawFacingPolyRotMirror(&obj->body.Centre.Pos, &mat, &poly, 1, -256);
01520
01521 RotMatrixZ(&mat, pickup->Timer / 2.0f + 0.5f);
01522 DrawFacingPolyRotMirror(&obj->body.Centre.Pos, &mat, &poly, 1, -256);
01523
01524 poly.U = 128.0f / 256.0f;
01525 poly.V = 0.0f / 256.0f;
01526 poly.RGB = (col) | (col << 8) | (col << 16);
01527
01528 RotMatrixZ(&mat, 0.0f);
01529 DrawFacingPolyRotMirror(&obj->body.Centre.Pos, &mat, &poly, 1, -256);
01530 }
01531
01532 break;
01533
01534
01535
01536 case 2:
01537
01538
01539
01540 FTOL(-pickup->Timer * 255.0f + 255.0f, alpha);
01541
01542 for (i = 0 ; i < model->PolyNum ; i++)
01543 {
01544 model->PolyPtr[i].Type |= POLY_SEMITRANS;
01545 model->PolyRGB[i].rgb[0].a = (unsigned char)alpha;
01546 model->PolyRGB[i].rgb[1].a = (unsigned char)alpha;
01547 model->PolyRGB[i].rgb[2].a = (unsigned char)alpha;
01548 model->PolyRGB[i].rgb[3].a = (unsigned char)alpha;
01549 }
01550
01551
01552
01553 RenderObject(obj);
01554
01555 break;
01556 }
01557 }
01558
01560
01562
01563 void RenderDissolveModel(OBJECT *obj)
01564 {
01565 DISSOLVE_OBJ *dissolve = (DISSOLVE_OBJ*)obj->Data;
01566
01567
01568
01569 obj->renderflag.visible |= RenderObjectModel(&obj->body.Centre.WMatrix, &obj->body.Centre.Pos, &dissolve->Model, dissolve->EnvRGB, obj->renderflag);
01570 }
01571
01573
01575
01576 void RenderLaser(OBJECT *obj)
01577 {
01578 int ii, nBits;
01579 long col, size, visflag;
01580 REAL delta, bitLen, dRLen, ang, dx, dy, dt, dLen, widMod, z;
01581 VEC sPos, ePos, dR;
01582 MAT mat;
01583 FACING_POLY poly;
01584 VERTEX_TEX1 *vert;
01585 LASER_OBJ *laser = (LASER_OBJ *)obj->Data;
01586
01587
01588 if (CamVisiMask & laser->VisiMask) {
01589 return;
01590 }
01591
01592
01593 visflag = TestSphereToFrustum(&obj->body.Centre.Pos, obj->body.CollSkin.Radius, &z);
01594 if (visflag == SPHERE_OUT) {
01595 return;
01596 }
01597
01598
01599 obj->renderflag.visible = TRUE;
01600
01601
01602 VecEqScalarVec(&dR, laser->Dist, &laser->Delta);
01603 dRLen = VecLen(&dR);
01604 if (dRLen > SMALL_REAL) {
01605 VecDivScalar(&dR, dRLen);
01606 nBits = 1 + (int)(dRLen / 100.0f);
01607 bitLen = dRLen / (REAL)nBits;
01608 } else {
01609 return;
01610 }
01611
01612
01613 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &obj->body.Centre.Pos, (REAL*)&DrawVertsTEX1[0]);
01614 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &laser->Dest, (REAL*)&DrawVertsTEX1[1]);
01615 dx = DrawVertsTEX1[1].sx - DrawVertsTEX1[0].sx;
01616 dy = DrawVertsTEX1[1].sy - DrawVertsTEX1[0].sy;
01617 dLen = (REAL)sqrt(dx * dx + dy * dy);
01618 dt = dx;
01619 dx = dy / dLen;
01620 dy = -dt / dLen;
01621
01622
01623
01624 CopyVec(&obj->body.Centre.Pos, &sPos);
01625 size = ((TIME2MS(TimerCurrent) + laser->Phase) % 100l);
01626 widMod = (REAL)size * laser->RandWidth / 100.0f;
01627 for (ii = 0; ii < nBits; ii++) {
01628
01629 VecPlusScalarVec(&sPos, bitLen, &dR, &ePos);
01630
01631
01632 if (!SEMI_POLY_FREE()) return;
01633 SEMI_POLY_SETUP(vert, FALSE, 4, TPAGE_FX1, TRUE, TRUE);
01634
01635 vert[3].tu = 225.0f / 256.0f;
01636 vert[3].tv = 33.0f / 256.0f;
01637
01638 vert[0].tu = 239.0f / 256.0f;
01639 vert[0].tv = 33.0f / 256.0f;
01640
01641 vert[1].tu = 239.0f / 256.0f;
01642 vert[1].tv = 47.0f / 256.0f;
01643
01644 vert[2].tu = 225.0f / 256.0f;
01645 vert[2].tv = 47.0f / 256.0f;
01646
01647
01648 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &sPos, (REAL*)&vert[0]);
01649 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &ePos, (REAL*)&vert[2]);
01650
01651 delta = vert[0].rhw;
01652 vert[1].sx = vert[0].sx + dx * (laser->Width + widMod) * delta * RenderSettings.GeomPers;
01653 vert[1].sy = vert[0].sy + dy * (laser->Width + widMod) * delta * RenderSettings.GeomPers;
01654 vert[1].sz = vert[0].sz;
01655 vert[1].rhw = vert[0].rhw;
01656 vert[0].sx -= dx * (laser->Width + widMod) * delta * RenderSettings.GeomPers;
01657 vert[0].sy -= dy * (laser->Width + widMod) * delta * RenderSettings.GeomPers;
01658
01659 delta = vert[2].rhw;
01660 vert[3].sx = vert[2].sx - dx * (laser->Width + widMod) * delta * RenderSettings.GeomPers;
01661 vert[3].sy = vert[2].sy - dy * (laser->Width + widMod) * delta * RenderSettings.GeomPers;
01662 vert[3].sz = vert[2].sz;
01663 vert[3].rhw = vert[2].rhw;
01664 vert[2].sx += dx * (laser->Width + widMod) * delta * RenderSettings.GeomPers;
01665 vert[2].sy += dy * (laser->Width + widMod) * delta * RenderSettings.GeomPers;
01666
01667 vert[0].color = 0x888888;
01668 vert[1].color = 0x888888;
01669 vert[2].color = 0x888888;
01670 vert[3].color = 0x888888;
01671
01672 VecPlusEqScalarVec(&sPos, bitLen, &dR);
01673 }
01674
01675 FOG_ON();
01676 col = 0xff3333;
01677 poly.Usize = poly.Vsize = 64.0f / 256.0f;
01678 poly.Tpage = TPAGE_FX1;
01679 poly.RGB = (col >> 1) | (col << 8) | (col << 16);
01680 poly.U = 192.0f / 256.0f;
01681 poly.V = 64.0f / 256.0f;
01682
01683
01684 ang = TIME2MS(TimerCurrent) / 10000.0f;
01685 size = (long)((TIME2MS(TimerCurrent) % 100l) - 50l);
01686 poly.Xsize = poly.Ysize = (2 * laser->Width) + (size / 5);
01687 RotMatrixZ(&mat, ang);
01688 DrawFacingPolyRotMirror(&sPos, &mat, &poly, 1, -16);
01689
01690 ang = TIME2MS(TimerCurrent) / 5000.0f;
01691 size = (long)((TIME2MS(TimerCurrent) % 200l) - 100l);
01692 poly.Xsize = poly.Ysize = (2 * laser->Width) + (size / 10);
01693 RotMatrixZ(&mat, ang);
01694 DrawFacingPolyRotMirror(&sPos, &mat, &poly, 1, -16);
01695
01696 FOG_OFF();
01697
01698
01699
01700
01701 }
01702
01704
01705
01706
01708
01709 void DrawTarget(PLAYER *player)
01710 {
01711 long mod, col;
01712 REAL ang;
01713 MAT mat;
01714 FACING_POLY poly;
01715
01716 FOG_ON();
01717
01718 col = 0xff;
01719 poly.Usize = poly.Vsize = 64.0f / 256.0f;
01720 poly.Tpage = TPAGE_FX1;
01721 poly.RGB = (col >> 1) | (col << 8) | (col << 16);
01722 poly.U = 192.0f / 256.0f;
01723 poly.V = 64.0f / 256.0f;
01724
01725 mod = TIME2MS(TimerCurrent) % 10000;
01726 ang = mod / Real(10000);
01727 poly.Xsize = poly.Ysize = Real(30);
01728
01729 RotMatrixZ(&mat, ang);
01730 DrawFacingPolyRotMirror(&player->PickupTarget->player->car.Body->Centre.Pos, &mat, &poly, 1, -256);
01731
01732 FOG_OFF();
01733 }
01734
01736
01738
01739 void RenderSplash(OBJECT *obj)
01740 {
01741 long i, frame, rgb;
01742 REAL tu, tv;
01743 SPLASH_OBJ *splash = (SPLASH_OBJ *)obj->Data;
01744 SPLASH_POLY *spoly;
01745 VERTEX_TEX1 *vert;
01746
01747
01748
01749 spoly = splash->Poly;
01750 for (i = 0 ; i < SPLASH_POLY_NUM ; i++, spoly++) if (spoly->Frame < 16.0f)
01751 {
01752
01753
01754
01755 if (!SEMI_POLY_FREE()) return;
01756 SEMI_POLY_SETUP(vert, FALSE, 4, TPAGE_FX3, TRUE, 1);
01757
01758
01759
01760 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &spoly->Pos[0], &vert[0].sx);
01761 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &spoly->Pos[1], &vert[1].sx);
01762 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &spoly->Pos[2], &vert[2].sx);
01763 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &spoly->Pos[3], &vert[3].sx);
01764
01765
01766
01767 FTOL(spoly->Frame, frame);
01768
01769 tu = frame * 16.0f + 1.0f;
01770 tv = 1.0f;
01771
01772 vert[0].tu = vert[3].tu = tu / 256.0f;
01773 vert[1].tu = vert[2].tu = (tu + 14.0f) / 256.0f;
01774 vert[0].tv = vert[1].tv = tv / 256.0f;
01775 vert[2].tv = vert[3].tv = (tv + 30.0f) / 256.0f;
01776
01777 FTOL((16.0f - spoly->Frame) * 8.0f, rgb);
01778 rgb |= rgb << 8 | rgb << 16;
01779 vert[0].color = vert[1].color = vert[2].color = vert[3].color = rgb;
01780 }
01781 }
01782
01783
01785
01786
01787
01789 void RenderSpeedup(OBJECT *obj)
01790 {
01791 VEC sPos, ePos, pPos, vel, dR;
01792 PLAYER *player;
01793 bool playerNear = FALSE;
01794
01795 SPEEDUP_OBJ *speedup = (SPEEDUP_OBJ *)obj->Data;
01796
01797 RenderObjectModel(&obj->body.Centre.WMatrix, &speedup->PostPos[0], &LevelModel[obj->DefaultModel].Model, obj->EnvRGB, obj->renderflag);
01798 RenderObjectModel(&obj->body.Centre.WMatrix, &speedup->PostPos[1], &LevelModel[obj->DefaultModel].Model, obj->EnvRGB, obj->renderflag);
01799
01800 if ((TimerCurrent % 1000ul) < 500) {
01801 speedup->HeightMod[0] += TimeStep * (frand(70) + 70.0f);
01802 speedup->HeightMod[1] += TimeStep * (frand(70) + 70.0f);
01803 } else {
01804 speedup->HeightMod[0] -= TimeStep * (frand(70) + 70.0f);
01805 speedup->HeightMod[1] -= TimeStep * (frand(70) + 70.0f);
01806 }
01807 if (speedup->HeightMod[0] > SPEEDUP_GEN_HEIGHT) speedup->HeightMod[0] = frand(2 * SPEEDUP_GEN_HEIGHT) - SPEEDUP_GEN_HEIGHT;
01808 if (speedup->HeightMod[0] < -SPEEDUP_GEN_HEIGHT) speedup->HeightMod[0] = frand(2 * SPEEDUP_GEN_HEIGHT) - SPEEDUP_GEN_HEIGHT;
01809 if (speedup->HeightMod[1] > SPEEDUP_GEN_HEIGHT) speedup->HeightMod[1] = frand(2 * SPEEDUP_GEN_HEIGHT) - SPEEDUP_GEN_HEIGHT;
01810 if (speedup->HeightMod[1] < -SPEEDUP_GEN_HEIGHT) speedup->HeightMod[1] = frand(2 * SPEEDUP_GEN_HEIGHT) - SPEEDUP_GEN_HEIGHT;
01811
01812 ScalarVecPlusScalarVec(SPEEDUP_GEN_WIDTH, &obj->body.Centre.WMatrix.mv[R], -speedup->Height + speedup->HeightMod[0], &obj->body.Centre.WMatrix.mv[U], &sPos);
01813 VecPlusEqVec(&sPos, &speedup->PostPos[0]);
01814 ScalarVecPlusScalarVec(-SPEEDUP_GEN_WIDTH, &obj->body.Centre.WMatrix.mv[R], -speedup->Height + speedup->HeightMod[1], &obj->body.Centre.WMatrix.mv[U], &ePos);
01815 VecPlusEqVec(&ePos, &speedup->PostPos[1]);
01816
01817
01818 for (player = PLR_PlayerHead; player != NULL; player = player->next) {
01819
01820 CopyVec(&player->car.Aerial.Section[AERIAL_LASTSECTION].Pos, &pPos);
01821 VecMinusVec(&sPos, &pPos, &dR);
01822 if (VecDotVec(&dR, &dR) > 4 * speedup->Width * speedup->Width) continue;
01823 VecMinusVec(&ePos, &pPos, &dR);
01824 if (VecDotVec(&dR, &dR) > 4 * speedup->Width * speedup->Width) continue;
01825
01826 playerNear = TRUE;
01827 DrawJumpSpark2(&sPos, &pPos);
01828 DrawJumpSpark2(&ePos, &pPos);
01829 DrawJumpSpark2(&player->car.Aerial.Section[2].Pos, &player->car.Aerial.Section[1].Pos);
01830 DrawJumpSpark2(&player->car.Aerial.Section[1].Pos, &player->car.Aerial.Section[0].Pos);
01831
01832 }
01833
01834 if (!playerNear) {
01835 DrawJumpSpark2(&sPos, &ePos);
01836 }
01837
01838
01839 VecEqScalarVec(&vel, 300, &obj->body.Centre.WMatrix.mv[R]);
01840 CreateSpark(SPARK_ELECTRIC, &sPos, &vel, 200, 0);
01841 NegateVec(&vel);
01842 CreateSpark(SPARK_ELECTRIC, &ePos, &vel, 200, 0);
01843
01844
01845 }