00001
00002 #include "revolt.h"
00003 #include "draw.h"
00004 #include "dx.h"
00005 #include "main.h"
00006 #include "world.h"
00007 #include "camera.h"
00008 #include "geom.h"
00009 #include "model.h"
00010 #include "text.h"
00011 #include "texture.h"
00012 #include "level.h"
00013 #include "mirror.h"
00014 #include "timing.h"
00015
00016
00017
00018 BUCKET_ENV BucketEnvStill, BucketEnvStillFog, BucketEnvStillClip, BucketEnvStillClipFog;
00019 BUCKET_ENV BucketEnvRoll, BucketEnvRollFog, BucketEnvRollClip, BucketEnvRollClipFog;
00020 BUCKET_TEX0 BucketRGB, BucketFogRGB, BucketClipRGB, BucketClipFogRGB;
00021 BUCKET_TEX1 Bucket[MAX_POLY_BUCKETS], BucketFog[MAX_POLY_BUCKETS], BucketClip[MAX_POLY_BUCKETS], BucketClipFog[MAX_POLY_BUCKETS];
00022 VERTEX_TEX0 DrawVertsTEX0[8];
00023 VERTEX_TEX1 DrawVertsTEX1[8];
00024 VERTEX_TEX2 DrawVertsTEX2[8];
00025 DRAW_SEMI_POLY SemiPoly[MAX_SEMI_POLYS];
00026 WORLD_MESH_FX WorldMeshFx[MAX_WORLD_MESH_FX];
00027 MODEL_MESH_FX ModelMeshFx[MAX_MODEL_MESH_FX];
00028 long SemiCount, WorldMeshFxCount, ModelMeshFxCount;
00029
00030 static unsigned short ClipVertNum, ClipVertFree;
00031 static unsigned short ClipVertList[2][8];
00032 static VERTEX_TEX1 ClipVert[32];
00033 static long Poly3dCount;
00034 static DRAW_3D_POLY Poly3d[MAX_3D_POLYS];
00035 static VEC JumpSparkOffset[JUMPSPARK_OFFSET_NUM];
00036 static long JumpSparkTime, JumpSparkOff, JumpSparkSinTime;
00037 static float JumpSparkSinDiv;
00038
00039
00040
00041
00042 static long SemiShellGap[] = {13, 4, 1};
00043
00045
00047
00048 void InitPolyBuckets(void)
00049 {
00050 long i;
00051
00052
00053
00054 BucketEnvStill.CurrentIndex = BucketEnvStill.Index;
00055 BucketEnvStill.CurrentVerts = BucketEnvStill.Verts;
00056
00057 BucketEnvStillFog.CurrentIndex = BucketEnvStillFog.Index;
00058 BucketEnvStillFog.CurrentVerts = BucketEnvStillFog.Verts;
00059
00060 BucketEnvStillClip.CurrentIndex = BucketEnvStillClip.Index;
00061 BucketEnvStillClip.CurrentVerts = BucketEnvStillClip.Verts;
00062
00063 BucketEnvStillClipFog.CurrentIndex = BucketEnvStillClipFog.Index;
00064 BucketEnvStillClipFog.CurrentVerts = BucketEnvStillClipFog.Verts;
00065
00066 BucketEnvRoll.CurrentIndex = BucketEnvRoll.Index;
00067 BucketEnvRoll.CurrentVerts = BucketEnvRoll.Verts;
00068
00069 BucketEnvRollFog.CurrentIndex = BucketEnvRollFog.Index;
00070 BucketEnvRollFog.CurrentVerts = BucketEnvRollFog.Verts;
00071
00072 BucketEnvRollClip.CurrentIndex = BucketEnvRollClip.Index;
00073 BucketEnvRollClip.CurrentVerts = BucketEnvRollClip.Verts;
00074
00075 BucketEnvRollClipFog.CurrentIndex = BucketEnvRollClipFog.Index;
00076 BucketEnvRollClipFog.CurrentVerts = BucketEnvRollClipFog.Verts;
00077
00078
00079
00080 BucketRGB.CurrentIndex = BucketRGB.Index;
00081 BucketRGB.CurrentVerts = BucketRGB.Verts;
00082
00083 BucketFogRGB.CurrentIndex = BucketFogRGB.Index;
00084 BucketFogRGB.CurrentVerts = BucketFogRGB.Verts;
00085
00086 BucketClipRGB.CurrentIndex = BucketClipRGB.Index;
00087 BucketClipRGB.CurrentVerts = BucketClipRGB.Verts;
00088
00089 BucketClipFogRGB.CurrentIndex = BucketClipFogRGB.Index;
00090 BucketClipFogRGB.CurrentVerts = BucketClipFogRGB.Verts;
00091
00092
00093
00094 for (i = 0 ; i < MAX_POLY_BUCKETS ; i++)
00095 {
00096 Bucket[i].CurrentIndex = Bucket[i].Index;
00097 Bucket[i].CurrentVerts = Bucket[i].Verts;
00098
00099 BucketFog[i].CurrentIndex = BucketFog[i].Index;
00100 BucketFog[i].CurrentVerts = BucketFog[i].Verts;
00101
00102 BucketClip[i].CurrentIndex = BucketClip[i].Index;
00103 BucketClip[i].CurrentVerts = BucketClip[i].Verts;
00104
00105 BucketClipFog[i].CurrentIndex = BucketClipFog[i].Index;
00106 BucketClipFog[i].CurrentVerts = BucketClipFog[i].Verts;
00107 }
00108 }
00109
00111
00113
00114 void KillPolyBuckets(void)
00115 {
00116 }
00117
00119
00121
00122 void FlushPolyBuckets(void)
00123 {
00124 short i;
00125
00126
00127
00128 if (BucketRGB.CurrentVerts != BucketRGB.Verts)
00129 {
00130 FOG_OFF();
00131 SET_TPAGE(-1);
00132 FlushOneBucketTEX0(&BucketRGB, FALSE);
00133 }
00134
00135 if (BucketFogRGB.CurrentVerts != BucketFogRGB.Verts)
00136 {
00137 FOG_ON();
00138 SET_TPAGE(-1);
00139 FlushOneBucketTEX0(&BucketFogRGB, FALSE);
00140 }
00141
00142 if (BucketClipRGB.CurrentVerts != BucketClipRGB.Verts)
00143 {
00144 FOG_OFF();
00145 SET_TPAGE(-1);
00146 FlushOneBucketTEX0(&BucketClipRGB, TRUE);
00147 }
00148
00149 if (BucketClipFogRGB.CurrentVerts != BucketClipFogRGB.Verts)
00150 {
00151 FOG_ON();
00152 SET_TPAGE(-1);
00153 FlushOneBucketTEX0(&BucketClipFogRGB, TRUE);
00154 }
00155
00156
00157
00158 for (i = 0 ; i < MAX_POLY_BUCKETS ; i++)
00159 {
00160 if (Bucket[i].CurrentVerts != Bucket[i].Verts)
00161 {
00162 FOG_OFF();
00163 SET_TPAGE(i);
00164 FlushOneBucketTEX1(&Bucket[i], FALSE);
00165 }
00166
00167 if (BucketFog[i].CurrentVerts != BucketFog[i].Verts)
00168 {
00169 FOG_ON();
00170 SET_TPAGE(i);
00171 FlushOneBucketTEX1(&BucketFog[i], FALSE);
00172 }
00173
00174 if (BucketClip[i].CurrentVerts != BucketClip[i].Verts)
00175 {
00176 FOG_OFF();
00177 SET_TPAGE(i);
00178 FlushOneBucketTEX1(&BucketClip[i], TRUE);
00179 }
00180
00181 if (BucketClipFog[i].CurrentVerts != BucketClipFog[i].Verts)
00182 {
00183 FOG_ON();
00184 SET_TPAGE(i);
00185 FlushOneBucketTEX1(&BucketClipFog[i], TRUE);
00186 }
00187 }
00188
00189
00190
00191 FOG_OFF();
00192 }
00193
00195
00197
00198 void FlushEnvBuckets(void)
00199 {
00200
00201
00202
00203 ZWRITE_OFF();
00204 ALPHA_ON();
00205
00206 ALPHA_SRC(D3DBLEND_ONE);
00207 ALPHA_DEST(D3DBLEND_ONE);
00208
00209
00210
00211 if (BucketEnvStill.CurrentVerts != BucketEnvStill.Verts)
00212 {
00213 FOG_OFF();
00214 SET_TPAGE(TPAGE_ENVSTILL);
00215 FlushOneBucketEnv(&BucketEnvStill, FALSE);
00216 }
00217
00218 if (BucketEnvStillFog.CurrentVerts != BucketEnvStillFog.Verts)
00219 {
00220 FOG_ON();
00221 SET_TPAGE(TPAGE_ENVSTILL);
00222 FlushOneBucketEnv(&BucketEnvStillFog, FALSE);
00223 }
00224
00225 if (BucketEnvStillClip.CurrentVerts != BucketEnvStillClip.Verts)
00226 {
00227 FOG_OFF();
00228 SET_TPAGE(TPAGE_ENVSTILL);
00229 FlushOneBucketEnv(&BucketEnvStillClip, TRUE);
00230 }
00231
00232 if (BucketEnvStillClipFog.CurrentVerts != BucketEnvStillClipFog.Verts)
00233 {
00234 FOG_ON();
00235 SET_TPAGE(TPAGE_ENVSTILL);
00236 FlushOneBucketEnv(&BucketEnvStillClipFog, TRUE);
00237 }
00238
00239
00240
00241 if (BucketEnvRoll.CurrentVerts != BucketEnvRoll.Verts)
00242 {
00243 FOG_OFF();
00244 SET_TPAGE(TPAGE_ENVROLL);
00245 FlushOneBucketEnv(&BucketEnvRoll, FALSE);
00246 }
00247
00248 if (BucketEnvRollFog.CurrentVerts != BucketEnvRollFog.Verts)
00249 {
00250 FOG_ON();
00251 SET_TPAGE(TPAGE_ENVROLL);
00252 FlushOneBucketEnv(&BucketEnvRollFog, FALSE);
00253 }
00254
00255 if (BucketEnvRollClip.CurrentVerts != BucketEnvRollClip.Verts)
00256 {
00257 FOG_OFF();
00258 SET_TPAGE(TPAGE_ENVROLL);
00259 FlushOneBucketEnv(&BucketEnvRollClip, TRUE);
00260 }
00261
00262 if (BucketEnvRollClipFog.CurrentVerts != BucketEnvRollClipFog.Verts)
00263 {
00264 FOG_ON();
00265 SET_TPAGE(TPAGE_ENVROLL);
00266 FlushOneBucketEnv(&BucketEnvRollClipFog, TRUE);
00267 }
00268
00269
00270
00271 FOG_OFF();
00272 ALPHA_OFF();
00273 ZWRITE_ON();
00274 }
00275
00277
00279
00280 void FlushOneBucketTEX0(BUCKET_TEX0 *bucket, long clip)
00281 {
00282 DWORD flag;
00283
00284 if (clip) flag = D3DDP_DONOTUPDATEEXTENTS;
00285 else flag = D3DDP_DONOTUPDATEEXTENTS | D3DDP_DONOTCLIP;
00286
00287 D3Ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, FVF_TEX0, bucket->Verts, (DWORD)(bucket->CurrentVerts - bucket->Verts), bucket->Index, (DWORD)(bucket->CurrentIndex - bucket->Index), flag);
00288
00289 bucket->CurrentIndex = bucket->Index;
00290 bucket->CurrentVerts = bucket->Verts;
00291 }
00292
00294
00296
00297 void FlushOneBucketTEX1(BUCKET_TEX1 *bucket, long clip)
00298 {
00299 DWORD flag;
00300
00301 if (clip) flag = D3DDP_DONOTUPDATEEXTENTS;
00302 else flag = D3DDP_DONOTUPDATEEXTENTS | D3DDP_DONOTCLIP;
00303
00304 D3Ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, FVF_TEX1, bucket->Verts, (DWORD)(bucket->CurrentVerts - bucket->Verts), bucket->Index, (DWORD)(bucket->CurrentIndex - bucket->Index), flag);
00305
00306 bucket->CurrentIndex = bucket->Index;
00307 bucket->CurrentVerts = bucket->Verts;
00308 }
00309
00311
00313
00314 void FlushOneBucketEnv(BUCKET_ENV *bucket, long clip)
00315 {
00316 DWORD flag;
00317
00318 if (clip) flag = D3DDP_DONOTUPDATEEXTENTS;
00319 else flag = D3DDP_DONOTUPDATEEXTENTS | D3DDP_DONOTCLIP;
00320
00321 D3Ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, FVF_TEX1, bucket->Verts, (DWORD)(bucket->CurrentVerts - bucket->Verts), bucket->Index, (DWORD)(bucket->CurrentIndex - bucket->Index), flag);
00322
00323 bucket->CurrentIndex = bucket->Index;
00324 bucket->CurrentVerts = bucket->Verts;
00325 }
00326
00328
00330
00331 void Reset3dPolyList(void)
00332 {
00333 Poly3dCount = 0;
00334 }
00335
00337
00339
00340 void Draw3dPolyList(void)
00341 {
00342 long i, j;
00343 DRAW_3D_POLY *poly;
00344 VERTEX_TEX1 *verts;
00345
00346
00347
00348 if (!Poly3dCount) return;
00349
00350
00351
00352 poly = Poly3d;
00353
00354 for (i = Poly3dCount ; i ; i--, poly++)
00355 {
00356
00357
00358
00359 if (poly->SemiType != -1)
00360 {
00361 if (SEMI_POLY_FREE())
00362 {
00363 SEMI_POLY_SETUP(verts, poly->Fog, poly->VertNum, poly->Tpage, TRUE, poly->SemiType);
00364 for (j = 0 ; j < poly->VertNum ; j++)
00365 {
00366 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &poly->Pos[j], (REAL*)&verts[j]);
00367 verts[j].color = poly->Verts[j].color;
00368 verts[j].specular = poly->Verts[j].specular;
00369 verts[j].tu = poly->Verts[j].tu;
00370 verts[j].tv = poly->Verts[j].tv;
00371 }
00372 }
00373 }
00374
00375
00376
00377 else
00378 {
00379 for (j = 0 ; j < poly->VertNum ; j++)
00380 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &poly->Pos[j], (REAL*)&poly->Verts[j]);
00381
00382 SET_TPAGE((short)poly->Tpage);
00383
00384 if (poly->Fog)
00385 {
00386 FOG_ON();
00387 }
00388 else
00389 {
00390 FOG_OFF();
00391 }
00392
00393 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX1, poly->Verts, poly->VertNum, D3DDP_DONOTUPDATEEXTENTS);
00394 }
00395 }
00396
00397
00398
00399 FOG_OFF();
00400 }
00401
00403
00405
00406 DRAW_3D_POLY *Get3dPoly(void)
00407 {
00408
00409
00410
00411 if (Poly3dCount == MAX_3D_POLYS)
00412 return NULL;
00413
00414
00415
00416 return &Poly3d[Poly3dCount++];
00417 }
00418
00420
00422
00423 void DrawNearClipPolyTEX0(VEC *pos, long *rgb, long vertnum)
00424 {
00425 long newvertnum, i, lmul, newrgb[8];
00426 float mul, z0, z1, z[8];
00427 VEC *vec0, *vec1, newpos[8];
00428 MODEL_RGB *rgb0, *rgb1, *rgbout;
00429
00430
00431
00432 newvertnum = 0;
00433
00434 for (i = 0 ; i < vertnum ; i++)
00435 z[i] = pos[i].v[X] * ViewMatrixScaled.m[RZ] + pos[i].v[Y] * ViewMatrixScaled.m[UZ] + pos[i].v[Z] * ViewMatrixScaled.m[LZ] + ViewTransScaled.v[Z];
00436
00437 for (i = 0 ; i < vertnum ; i++)
00438 {
00439 vec0 = &pos[i];
00440 vec1 = &pos[(i + 1) % vertnum];
00441 z0 = z[i];
00442 z1 = z[(i + 1) % vertnum];
00443
00444 if (z0 >= 0)
00445 {
00446 newpos[newvertnum] = pos[i];
00447 newrgb[newvertnum] = rgb[i];
00448 newvertnum++;
00449
00450 if (z1 < 0)
00451 {
00452 mul = z0 / (z0 - z1);
00453
00454 newpos[newvertnum].v[X] = vec0->v[X] + (vec1->v[X] - vec0->v[X]) * mul;
00455 newpos[newvertnum].v[Y] = vec0->v[Y] + (vec1->v[Y] - vec0->v[Y]) * mul;
00456 newpos[newvertnum].v[Z] = vec0->v[Z] + (vec1->v[Z] - vec0->v[Z]) * mul;
00457
00458 FTOL(mul * 256, lmul);
00459
00460 rgb0 = (MODEL_RGB*)&rgb[i];
00461 rgb1 = (MODEL_RGB*)&rgb[(i + 1) % vertnum];
00462 rgbout = (MODEL_RGB*)&newrgb[newvertnum];
00463
00464 rgbout->a = rgb0->a + (unsigned char)(((rgb1->a - rgb0->a) * lmul) >> 8);
00465 rgbout->r = rgb0->r + (unsigned char)(((rgb1->r - rgb0->r) * lmul) >> 8);
00466 rgbout->g = rgb0->g + (unsigned char)(((rgb1->g - rgb0->g) * lmul) >> 8);
00467 rgbout->b = rgb0->b + (unsigned char)(((rgb1->b - rgb0->b) * lmul) >> 8);
00468
00469 newvertnum++;
00470 }
00471 }
00472 else
00473 {
00474 if (z1 >= RenderSettings.NearClip)
00475 {
00476 mul = z1 / (z1 - z0);
00477
00478 newpos[newvertnum].v[X] = vec1->v[X] + (vec0->v[X] - vec1->v[X]) * mul;
00479 newpos[newvertnum].v[Y] = vec1->v[Y] + (vec0->v[Y] - vec1->v[Y]) * mul;
00480 newpos[newvertnum].v[Z] = vec1->v[Z] + (vec0->v[Z] - vec1->v[Z]) * mul;
00481
00482 FTOL(mul * 256, lmul);
00483
00484 rgb0 = (MODEL_RGB*)&rgb[(i + 1) % vertnum];
00485 rgb1 = (MODEL_RGB*)&rgb[i];
00486 rgbout = (MODEL_RGB*)&newrgb[newvertnum];
00487
00488 rgbout->a = rgb0->a + (unsigned char)(((rgb1->a - rgb0->a) * lmul) >> 8);
00489 rgbout->r = rgb0->r + (unsigned char)(((rgb1->r - rgb0->r) * lmul) >> 8);
00490 rgbout->g = rgb0->g + (unsigned char)(((rgb1->g - rgb0->g) * lmul) >> 8);
00491 rgbout->b = rgb0->b + (unsigned char)(((rgb1->b - rgb0->b) * lmul) >> 8);
00492
00493 newvertnum++;
00494 }
00495 }
00496 }
00497
00498 if (!newvertnum)
00499 return;
00500
00501
00502
00503 for (i = 0 ; i < newvertnum ; i++)
00504 {
00505 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &newpos[i], &DrawVertsTEX0[i].sx);
00506 DrawVertsTEX0[i].color = newrgb[i];
00507 }
00508
00509
00510
00511 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX0, DrawVertsTEX0, newvertnum, D3DDP_DONOTUPDATEEXTENTS);
00512 }
00513
00515
00517
00518 void ResetSemiList(void)
00519 {
00520 SemiCount = 0;
00521 }
00522
00524
00526
00527 void DrawSemiList(void)
00528 {
00529 long i, j, k, gap;
00530 float z;
00531 DRAW_SEMI_POLY *poly, swap;
00532
00533
00534
00535 if (!SemiCount) return;
00536
00537
00538
00539 ALPHA_ON();
00540 ZWRITE_OFF();
00541
00542
00543
00544 poly = SemiPoly;
00545
00546 for (i = SemiCount ; i ; i--, poly++)
00547 {
00548 z = 0.0f;
00549
00550 if (poly->Tpage == -1)
00551 for (j = 0 ; j < poly->VertNum ; j++) z += 1.0f / poly->VertsRGB[j].rhw;
00552 else
00553 for (j = 0 ; j < poly->VertNum ; j++) z += 1.0f / poly->Verts[j].rhw;
00554
00555 poly->z += z / j;
00556 }
00557
00558
00559
00560 for (k = 0 ; k < 3 ; k++)
00561 {
00562 gap = SemiShellGap[k];
00563 for (i = gap ; i < SemiCount ; i++)
00564 {
00565 swap = SemiPoly[i];
00566 for (j = i - gap ; j >= 0 && swap.z > SemiPoly[j].z ; j -= gap)
00567 {
00568 SemiPoly[j + gap] = SemiPoly[j];
00569 }
00570 SemiPoly[j + gap] = swap;
00571 }
00572 }
00573
00574
00575
00576 poly = SemiPoly;
00577 for (i = SemiCount ; i ; i--, poly++)
00578 {
00579
00580
00581
00582 SET_TPAGE((short)poly->Tpage);
00583
00584 if (poly->Fog)
00585 {
00586 FOG_ON();
00587 }
00588 else
00589 {
00590 FOG_OFF();
00591 }
00592
00593 if (!poly->SemiType)
00594 {
00595 ALPHA_SRC(D3DBLEND_SRCALPHA);
00596 ALPHA_DEST(D3DBLEND_INVSRCALPHA);
00597 }
00598 else if (poly->SemiType == 1)
00599 {
00600 ALPHA_SRC(D3DBLEND_ONE);
00601 ALPHA_DEST(D3DBLEND_ONE);
00602 }
00603 else
00604 {
00605 ALPHA_SRC(D3DBLEND_ZERO);
00606 ALPHA_DEST(D3DBLEND_INVSRCCOLOR);
00607 }
00608
00609
00610
00611 if (poly->Tpage == -1)
00612 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX0, poly->VertsRGB, poly->VertNum, poly->DrawFlag);
00613 else
00614 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX1, poly->Verts, poly->VertNum, poly->DrawFlag);
00615 }
00616
00617
00618
00619 FOG_OFF();
00620 }
00621
00623
00625
00626 void DrawFacingPolyMirror(VEC *pos, FACING_POLY *poly, long semi, float zbias)
00627 {
00628 float screen[4];
00629 float xadd, yadd;
00630 float z, fog, mirrorfog;
00631 VERTEX_TEX1 *vert;
00632 float mirroradd, mirrory;
00633
00634
00635
00636 DrawFacingPoly(pos, poly, semi, zbias);
00637
00638
00639
00640 if (!RenderSettings.Mirror)
00641 return;
00642
00643 if (!GetMirrorPlane(pos))
00644 return;
00645
00646 if (ViewCameraPos.v[Y] >= MirrorHeight)
00647 return;
00648
00649 mirroradd = MirrorHeight - pos->v[Y];
00650 if (mirroradd <= -MIRROR_OVERLAP_TOL)
00651 return;
00652
00653
00654
00655 mirrory = MirrorHeight + mirroradd;
00656
00657
00658
00659 z = pos->v[X] * ViewMatrixScaled.m[RZ] + mirrory * ViewMatrixScaled.m[UZ] + pos->v[Z] * ViewMatrixScaled.m[LZ] + ViewTransScaled.v[Z];
00660 if (z < RenderSettings.NearClip || z >= RenderSettings.FarClip)
00661 return;
00662
00663 screen[0] = (pos->v[X] * ViewMatrixScaled.m[RX] + mirrory * ViewMatrixScaled.m[UX] + pos->v[Z] * ViewMatrixScaled.m[LX] + ViewTransScaled.v[X]) / z + RenderSettings.GeomCentreX;
00664 screen[1] = (pos->v[X] * ViewMatrixScaled.m[RY] + mirrory * ViewMatrixScaled.m[UY] + pos->v[Z] * ViewMatrixScaled.m[LY] + ViewTransScaled.v[Y]) / z + RenderSettings.GeomCentreY;
00665
00666 screen[3] = 1 / z;
00667 screen[2] = GET_ZBUFFER(z + zbias);
00668
00669
00670
00671 if (semi == -1)
00672 {
00673 vert = DrawVertsTEX1;
00674 }
00675 else
00676 {
00677 if (!SEMI_POLY_FREE()) return;
00678 SEMI_POLY_SETUP(vert, TRUE, 4, poly->Tpage, TRUE, semi);
00679 }
00680
00681
00682
00683 xadd = (poly->Xsize * RenderSettings.MatScaleX) / z;
00684 yadd = (poly->Ysize * RenderSettings.MatScaleY) / z;
00685
00686
00687
00688 vert[0].sx = vert[3].sx = screen[0] - xadd;
00689 vert[1].sx = vert[2].sx = screen[0] + xadd;
00690
00691 vert[0].sy = vert[1].sy = screen[1] + yadd;
00692 vert[2].sy = vert[3].sy = screen[1] - yadd;
00693
00694 vert[0].sz = vert[1].sz = vert[2].sz = vert[3].sz = screen[2];
00695 vert[0].rhw = vert[1].rhw = vert[2].rhw = vert[3].rhw = screen[3];
00696
00697
00698
00699 vert[0].color = vert[1].color = vert[2].color = vert[3].color = poly->RGB;
00700
00701
00702
00703 vert[0].tu = vert[3].tu = poly->U;
00704 vert[1].tu = vert[2].tu = poly->U + poly->Usize;
00705
00706 vert[0].tv = vert[1].tv = poly->V;
00707 vert[2].tv = vert[3].tv = poly->V + poly->Vsize;
00708
00709
00710
00711 mirrorfog = GET_MIRROR_FOG(mirroradd);
00712 if (mirrorfog < 0) mirrorfog = 0;
00713
00714 fog = (RenderSettings.FarClip - z) * RenderSettings.FogMul;
00715 if (fog > 255) fog = 255;
00716 fog -= mirrorfog;
00717 if (fog < 0) fog = 0;
00718 vert[0].specular = vert[1].specular = vert[2].specular = vert[3].specular = FTOL3(fog) << 24;
00719
00720
00721
00722 if (semi == -1)
00723 {
00724 SET_TPAGE(poly->Tpage);
00725 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX1, vert, 4, D3DDP_DONOTUPDATEEXTENTS);
00726 }
00727 }
00728
00730
00732
00733 void DrawFacingPoly(VEC *pos, FACING_POLY *poly, long semi, float zbias)
00734 {
00735 float screen[4];
00736 float xadd, yadd;
00737 float z, fog;
00738 VERTEX_TEX1 *vert;
00739
00740
00741
00742 z = pos->v[X] * ViewMatrixScaled.m[RZ] + pos->v[Y] * ViewMatrixScaled.m[UZ] + pos->v[Z] * ViewMatrixScaled.m[LZ] + ViewTransScaled.v[Z];
00743 if (z < RenderSettings.NearClip || z >= RenderSettings.FarClip)
00744 return;
00745
00746 screen[0] = (pos->v[X] * ViewMatrixScaled.m[RX] + pos->v[Y] * ViewMatrixScaled.m[UX] + pos->v[Z] * ViewMatrixScaled.m[LX] + ViewTransScaled.v[X]) / z + RenderSettings.GeomCentreX;
00747 screen[1] = (pos->v[X] * ViewMatrixScaled.m[RY] + pos->v[Y] * ViewMatrixScaled.m[UY] + pos->v[Z] * ViewMatrixScaled.m[LY] + ViewTransScaled.v[Y]) / z + RenderSettings.GeomCentreY;
00748
00749 screen[3] = 1 / z;
00750 screen[2] = GET_ZBUFFER(z + zbias);
00751
00752
00753
00754 if (semi == -1)
00755 {
00756 vert = DrawVertsTEX1;
00757 }
00758 else
00759 {
00760 if (!SEMI_POLY_FREE()) return;
00761 SEMI_POLY_SETUP(vert, TRUE, 4, poly->Tpage, TRUE, semi);
00762 }
00763
00764
00765
00766 xadd = (poly->Xsize * RenderSettings.MatScaleX) / z;
00767 yadd = (poly->Ysize * RenderSettings.MatScaleY) / z;
00768
00769
00770
00771 vert[0].sx = vert[3].sx = screen[0] - xadd;
00772 vert[1].sx = vert[2].sx = screen[0] + xadd;
00773
00774 vert[0].sy = vert[1].sy = screen[1] - yadd;
00775 vert[2].sy = vert[3].sy = screen[1] + yadd;
00776
00777 vert[0].sz = vert[1].sz = vert[2].sz = vert[3].sz = screen[2];
00778 vert[0].rhw = vert[1].rhw = vert[2].rhw = vert[3].rhw = screen[3];
00779
00780
00781
00782 vert[0].color = vert[1].color = vert[2].color = vert[3].color = poly->RGB;
00783
00784
00785
00786 vert[0].tu = vert[3].tu = poly->U;
00787 vert[1].tu = vert[2].tu = poly->U + poly->Usize;
00788
00789 vert[0].tv = vert[1].tv = poly->V;
00790 vert[2].tv = vert[3].tv = poly->V + poly->Vsize;
00791
00792
00793
00794 fog = (RenderSettings.FarClip - z) * RenderSettings.FogMul;
00795 if (fog > 255) fog = 255;
00796 else if (fog < 0) fog = 0;
00797 vert[0].specular = vert[1].specular = vert[2].specular = vert[3].specular = FTOL3(fog) << 24;
00798
00799
00800
00801 if (semi == -1)
00802 {
00803 SET_TPAGE(poly->Tpage);
00804 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX1, vert, 4, D3DDP_DONOTUPDATEEXTENTS);
00805 }
00806 }
00807
00809
00811
00812 void DrawFacingPolyRotMirror(VEC *pos, MAT *mat, FACING_POLY *poly, long semi, float zbias)
00813 {
00814 float fog, mirrorfog;
00815 VEC trans;
00816 VEC v0, v1, v2, v3;
00817 MAT mat2, mat3, mat4;
00818 VERTEX_TEX1 *vert;
00819 float mirroradd, mirrory;
00820
00821
00822
00823 DrawFacingPolyRot(pos, mat, poly, semi, zbias);
00824
00825
00826
00827 if (!RenderSettings.Mirror)
00828 return;
00829
00830 if (!GetMirrorPlane(pos))
00831 return;
00832
00833 if (ViewCameraPos.v[Y] >= MirrorHeight)
00834 return;
00835
00836 mirroradd = MirrorHeight - pos->v[Y];
00837 if (mirroradd <= -MIRROR_OVERLAP_TOL)
00838 return;
00839
00840
00841
00842 mirrory = MirrorHeight + mirroradd;
00843
00844
00845
00846 trans.v[Z] = pos->v[X] * ViewMatrixScaled.m[RZ] + mirrory * ViewMatrixScaled.m[UZ] + pos->v[Z] * ViewMatrixScaled.m[LZ] + ViewTransScaled.v[Z];
00847 if (trans.v[Z] < RenderSettings.NearClip - 128 || trans.v[Z] >= RenderSettings.FarClip + 128)
00848 return;
00849
00850 trans.v[X] = pos->v[X] * ViewMatrixScaled.m[RX] + mirrory * ViewMatrixScaled.m[UX] + pos->v[Z] * ViewMatrixScaled.m[LX] + ViewTransScaled.v[X];
00851 trans.v[Y] = pos->v[X] * ViewMatrixScaled.m[RY] + mirrory * ViewMatrixScaled.m[UY] + pos->v[Z] * ViewMatrixScaled.m[LY] + ViewTransScaled.v[Y];
00852
00853
00854
00855 if (semi == -1)
00856 {
00857 vert = DrawVertsTEX1;
00858 }
00859 else
00860 {
00861 if (!SEMI_POLY_FREE()) return;
00862 SEMI_POLY_SETUP(vert, TRUE, 4, poly->Tpage, TRUE, semi);
00863 }
00864
00865
00866
00867 CopyMat(mat, &mat4);
00868 mat4.m[UX] = -mat4.m[UX];
00869 mat4.m[UY] = -mat4.m[UY];
00870 mat4.m[UZ] = -mat4.m[UZ];
00871
00872 BuildLookMatrixForward(pos, &ViewCameraPos, &mat2);
00873 MulMatrix(&ViewMatrixScaled, &mat2, &mat3);
00874 MulMatrix(&mat3, &mat4, &mat2);
00875
00876
00877
00878 SetVector(&v0, -poly->Xsize, -poly->Ysize, 0);
00879 SetVector(&v1, poly->Xsize, -poly->Ysize, 0);
00880 SetVector(&v2, poly->Xsize, poly->Ysize, 0);
00881 SetVector(&v3, -poly->Xsize, poly->Ysize, 0);
00882
00883
00884
00885 RotTransPersVectorZbias(&mat2, &trans, &v0, &vert[0].sx, zbias);
00886 RotTransPersVectorZbias(&mat2, &trans, &v1, &vert[1].sx, zbias);
00887 RotTransPersVectorZbias(&mat2, &trans, &v2, &vert[2].sx, zbias);
00888 RotTransPersVectorZbias(&mat2, &trans, &v3, &vert[3].sx, zbias);
00889
00890
00891
00892 vert[0].color = vert[1].color = vert[2].color = vert[3].color = poly->RGB;
00893
00894
00895
00896 vert[0].tu = vert[3].tu = poly->U;
00897 vert[1].tu = vert[2].tu = poly->U + poly->Usize;
00898
00899 vert[0].tv = vert[1].tv = poly->V;
00900 vert[2].tv = vert[3].tv = poly->V + poly->Vsize;
00901
00902
00903
00904 mirrorfog = GET_MIRROR_FOG(mirroradd);
00905 if (mirrorfog < 0) mirrorfog = 0;
00906
00907 fog = (RenderSettings.FarClip - 1 / vert[0].rhw) * RenderSettings.FogMul;
00908 if (fog > 255) fog = 255;
00909 fog -= mirrorfog;
00910 if (fog < 0) fog = 0;
00911 vert[0].specular = FTOL3(fog) << 24;
00912
00913 fog = (RenderSettings.FarClip - 1 / vert[1].rhw) * RenderSettings.FogMul;
00914 if (fog > 255) fog = 255;
00915 fog -= mirrorfog;
00916 if (fog < 0) fog = 0;
00917 vert[1].specular = FTOL3(fog) << 24;
00918
00919 fog = (RenderSettings.FarClip - 1 / vert[2].rhw) * RenderSettings.FogMul;
00920 if (fog > 255) fog = 255;
00921 fog -= mirrorfog;
00922 if (fog < 0) fog = 0;
00923 vert[2].specular = FTOL3(fog) << 24;
00924
00925 fog = (RenderSettings.FarClip - 1 / vert[3].rhw) * RenderSettings.FogMul;
00926 if (fog > 255) fog = 255;
00927 fog -= mirrorfog;
00928 if (fog < 0) fog = 0;
00929 vert[3].specular = FTOL3(fog) << 24;
00930
00931
00932
00933 if (semi == -1)
00934 {
00935 SET_TPAGE(poly->Tpage);
00936 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX1, vert, 4, D3DDP_DONOTUPDATEEXTENTS);
00937 }
00938 }
00939
00941
00943
00944 void DrawFacingPolyRot(VEC *pos, MAT *mat, FACING_POLY *poly, long semi, float zbias)
00945 {
00946 float fog;
00947 VEC trans;
00948 VEC v0, v1, v2, v3;
00949 MAT mat2, mat3;
00950 VERTEX_TEX1 *vert;
00951
00952
00953
00954 trans.v[Z] = pos->v[X] * ViewMatrixScaled.m[RZ] + pos->v[Y] * ViewMatrixScaled.m[UZ] + pos->v[Z] * ViewMatrixScaled.m[LZ] + ViewTransScaled.v[Z];
00955 if (trans.v[Z] < RenderSettings.NearClip - 128 || trans.v[Z] >= RenderSettings.FarClip + 128)
00956 return;
00957
00958 trans.v[X] = pos->v[X] * ViewMatrixScaled.m[RX] + pos->v[Y] * ViewMatrixScaled.m[UX] + pos->v[Z] * ViewMatrixScaled.m[LX] + ViewTransScaled.v[X];
00959 trans.v[Y] = pos->v[X] * ViewMatrixScaled.m[RY] + pos->v[Y] * ViewMatrixScaled.m[UY] + pos->v[Z] * ViewMatrixScaled.m[LY] + ViewTransScaled.v[Y];
00960
00961
00962
00963 if (semi == -1)
00964 {
00965 vert = DrawVertsTEX1;
00966 }
00967 else
00968 {
00969 if (!SEMI_POLY_FREE()) return;
00970 SEMI_POLY_SETUP(vert, TRUE, 4, poly->Tpage, TRUE, semi);
00971 }
00972
00973
00974
00975 BuildLookMatrixForward(pos, &ViewCameraPos, &mat2);
00976 MulMatrix(&ViewMatrixScaled, &mat2, &mat3);
00977 MulMatrix(&mat3, mat, &mat2);
00978
00979
00980
00981 SetVector(&v0, -poly->Xsize, -poly->Ysize, 0);
00982 SetVector(&v1, poly->Xsize, -poly->Ysize, 0);
00983 SetVector(&v2, poly->Xsize, poly->Ysize, 0);
00984 SetVector(&v3, -poly->Xsize, poly->Ysize, 0);
00985
00986
00987
00988 RotTransPersVectorZbias(&mat2, &trans, &v0, &vert[0].sx, zbias);
00989 RotTransPersVectorZbias(&mat2, &trans, &v1, &vert[1].sx, zbias);
00990 RotTransPersVectorZbias(&mat2, &trans, &v2, &vert[2].sx, zbias);
00991 RotTransPersVectorZbias(&mat2, &trans, &v3, &vert[3].sx, zbias);
00992
00993
00994
00995 vert[0].color = vert[1].color = vert[2].color = vert[3].color = poly->RGB;
00996
00997
00998
00999 vert[0].tu = vert[3].tu = poly->U;
01000 vert[1].tu = vert[2].tu = poly->U + poly->Usize;
01001
01002 vert[0].tv = vert[1].tv = poly->V;
01003 vert[2].tv = vert[3].tv = poly->V + poly->Vsize;
01004
01005
01006
01007 fog = (RenderSettings.FarClip - 1 / vert[0].rhw) * RenderSettings.FogMul;
01008 if (fog > 255) fog = 255;
01009 else if (fog < 0) fog = 0;
01010 vert[0].specular = FTOL3(fog) << 24;
01011
01012 fog = (RenderSettings.FarClip - 1 / vert[1].rhw) * RenderSettings.FogMul;
01013 if (fog > 255) fog = 255;
01014 else if (fog < 0) fog = 0;
01015 vert[1].specular = FTOL3(fog) << 24;
01016
01017 fog = (RenderSettings.FarClip - 1 / vert[2].rhw) * RenderSettings.FogMul;
01018 if (fog > 255) fog = 255;
01019 else if (fog < 0) fog = 0;
01020 vert[2].specular = FTOL3(fog) << 24;
01021
01022 fog = (RenderSettings.FarClip - 1 / vert[3].rhw) * RenderSettings.FogMul;
01023 if (fog > 255) fog = 255;
01024 else if (fog < 0) fog = 0;
01025 vert[3].specular = FTOL3(fog) << 24;
01026
01027
01028
01029 if (semi == -1)
01030 {
01031 SET_TPAGE(poly->Tpage);
01032 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX1, vert, 4, D3DDP_DONOTUPDATEEXTENTS);
01033 }
01034 }
01035
01037
01039
01040 void InitRenderStates(void)
01041 {
01042
01043
01044
01045 RenderAlpha = TRUE;
01046
01047 ALPHA_OFF();
01048 FOG_OFF();
01049 WIREFRAME_ON();
01050 ZBUFFER_ON();
01051 ZWRITE_ON();
01052
01053
01054
01055 #if SCREEN_DEBUG
01056 WorldPolyCount = 0;
01057 WorldDrawnCount = 0;
01058 ModelPolyCount = 0;
01059 ModelDrawnCount = 0;
01060 RenderStateChange = 0;
01061 TextureStateChange = 0;
01062 #endif
01063 }
01064
01066
01068
01069 void SetNearFar(REAL n, REAL f)
01070 {
01071 RenderSettings.NearClip = n;
01072 RenderSettings.FarClip = f;
01073
01074 RenderSettings.DrawDist = RenderSettings.FarClip - RenderSettings.NearClip;
01075 RenderSettings.FarDivDist = RenderSettings.FarClip / RenderSettings.DrawDist;
01076 RenderSettings.FarMulNear = RenderSettings.FarClip * RenderSettings.NearClip;
01077 }
01078
01080
01082
01083 void SetFogVars(REAL fogstart, REAL vertstart, REAL vertend)
01084 {
01085
01086
01087
01088 RenderSettings.FogStart = fogstart;
01089 RenderSettings.FogDist = RenderSettings.FarClip - RenderSettings.FogStart;
01090 if (RenderSettings.FogDist <= 0) RenderSettings.FogMul = 256, RenderSettings.FogStart += 0xffff;
01091 else RenderSettings.FogMul = 256 / RenderSettings.FogDist;
01092
01093 RenderSettings.VertFogStart = vertstart;
01094 RenderSettings.VertFogEnd = vertend;
01095 if (RenderSettings.VertFogStart == RenderSettings.VertFogEnd) RenderSettings.VertFogMul = 0;
01096 else RenderSettings.VertFogMul = 256 / (RenderSettings.VertFogEnd - RenderSettings.VertFogStart);
01097 if (RenderSettings.VertFogMul) RenderSettings.FogStart = 0;
01098 }
01099
01101
01103
01104 void DrawAxis(MAT *mat, VEC *pos)
01105 {
01106 FACING_POLY fp;
01107 VEC in, out;
01108
01109
01110
01111 fp.Tpage = TPAGE_FONT;
01112 fp.Xsize = 8;
01113 fp.Ysize = 8;
01114 fp.Usize = FONT_UWIDTH / 256.0f;
01115 fp.Vsize = FONT_VHEIGHT / 256.0f;
01116 fp.RGB = 0xffffff;
01117
01118
01119
01120 SetVector(&in, 64, 0, 0);
01121 RotVector(mat, &in, &out);
01122 AddVector(&out, pos, &out);
01123
01124 fp.U = 221.0f / 256.0f;
01125 fp.V = 34.0f / 256.0f;
01126 DrawFacingPoly(&out, &fp, -1, 0);
01127
01128 DrawLine(pos, &out, 0xff0000, 0xff0000);
01129
01130
01131
01132 SetVector(&in, 0, 64, 0);
01133 RotVector(mat, &in, &out);
01134 AddVector(&out, pos, &out);
01135
01136 fp.U = 234.0f / 256.0f;
01137 fp.V = 34.0f / 256.0f;
01138 DrawFacingPoly(&out, &fp, -1, 0);
01139
01140 DrawLine(pos, &out, 0x00ff00, 0x00ff00);
01141
01142
01143
01144 SetVector(&in, 0, 0, 64);
01145 RotVector(mat, &in, &out);
01146 AddVector(&out, pos, &out);
01147
01148 fp.U = 0.0f / 256.0f;
01149 fp.V = 51.0f / 256.0f;
01150 DrawFacingPoly(&out, &fp, -1, 0);
01151
01152 DrawLine(pos, &out, 0x0000ff, 0x0000ff);
01153 }
01154
01156
01158
01159 void DumpImage(char handle, float x, float y, float w, float h, float u, float v, float tw, float th, unsigned long col)
01160 {
01161 long i;
01162 float xstart, ystart, xsize, ysize;
01163
01164
01165
01166 xstart = x * RenderSettings.GeomScaleX + ScreenLeftClip;
01167 ystart = y * RenderSettings.GeomScaleY + ScreenTopClip;
01168
01169 xsize = w * RenderSettings.GeomScaleX;
01170 ysize = h * RenderSettings.GeomScaleY;
01171
01172
01173
01174 SET_TPAGE(handle);
01175
01176
01177
01178 for (i = 0 ; i < 4 ; i++)
01179 {
01180 DrawVertsTEX1[i].color = col;
01181 DrawVertsTEX1[i].rhw = 1;
01182 }
01183
01184
01185
01186 DrawVertsTEX1[0].sx = DrawVertsTEX1[3].sx = xstart;
01187 DrawVertsTEX1[1].sx = DrawVertsTEX1[2].sx = xstart + xsize;
01188 DrawVertsTEX1[0].sy = DrawVertsTEX1[1].sy = ystart;
01189 DrawVertsTEX1[2].sy = DrawVertsTEX1[3].sy = ystart + ysize;
01190
01191
01192
01193 DrawVertsTEX1[0].tu = DrawVertsTEX1[3].tu = u;
01194 DrawVertsTEX1[1].tu = DrawVertsTEX1[2].tu = u + tw;
01195 DrawVertsTEX1[0].tv = DrawVertsTEX1[1].tv = v;
01196 DrawVertsTEX1[2].tv = DrawVertsTEX1[3].tv = v + th;
01197
01198
01199
01200 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX1, DrawVertsTEX1, 4, D3DDP_DONOTUPDATEEXTENTS);
01201 }
01202
01204
01206
01207 void DrawMousePointer(unsigned long color)
01208 {
01209 char i;
01210 float x, y, xs, ys, tu, tv;
01211
01212
01213
01214 for (i = 0 ; i < 4 ; i++)
01215 {
01216 DrawVertsTEX1[i].color = color;
01217 DrawVertsTEX1[i].rhw = 1;
01218 }
01219
01220
01221
01222 x = MouseXpos * RenderSettings.GeomScaleX + ScreenLeftClip;
01223 y = MouseYpos * RenderSettings.GeomScaleY + ScreenTopClip;
01224 xs = 12 * RenderSettings.GeomScaleX;
01225 ys = 16 * RenderSettings.GeomScaleY;
01226
01227 DrawVertsTEX1[0].sx = x;
01228 DrawVertsTEX1[0].sy = y;
01229
01230 DrawVertsTEX1[1].sx = x + xs;
01231 DrawVertsTEX1[1].sy = y;
01232
01233 DrawVertsTEX1[2].sx = x + xs;
01234 DrawVertsTEX1[2].sy = y + ys;
01235
01236 DrawVertsTEX1[3].sx = x;
01237 DrawVertsTEX1[3].sy = y + ys;
01238
01239
01240
01241 tu = 234.0f;
01242 tv = 68.0f;
01243
01244 DrawVertsTEX1[0].tu = tu / 256;
01245 DrawVertsTEX1[0].tv = tv / 256;
01246
01247 DrawVertsTEX1[1].tu = (tu + 12) / 256;
01248 DrawVertsTEX1[1].tv = tv / 256;
01249
01250 DrawVertsTEX1[2].tu = (tu + 12) / 256;
01251 DrawVertsTEX1[2].tv = (tv + 16) / 256;
01252
01253 DrawVertsTEX1[3].tu = tu / 256;
01254 DrawVertsTEX1[3].tv = (tv + 16) / 256;
01255
01256
01257
01258 D3Ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN, FVF_TEX1, DrawVertsTEX1, 4, D3DDP_DONOTUPDATEEXTENTS);
01259 }
01260
01262
01264
01265 BOOL LoadBitmap(char *bitmap, HBITMAP *hbm)
01266 {
01267 *hbm = (HBITMAP)LoadImage(NULL, bitmap, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
01268 return (BOOL)*hbm;
01269 }
01270
01272
01274
01275 BOOL FreeBitmap(HBITMAP hbm)
01276 {
01277 return (BOOL)DeleteObject(hbm);
01278 }
01279
01281
01283
01284 BOOL BlitBitmap(HBITMAP hbm, IDirectDrawSurface4 **surface)
01285 {
01286 HRESULT r;
01287 BITMAP bm;
01288 HDC dcimage, dc;
01289
01290
01291
01292 GetObject(hbm, sizeof(bm), &bm);
01293
01294
01295
01296 dcimage = CreateCompatibleDC(NULL);
01297 SelectObject(dcimage, hbm);
01298 r = (*surface)->GetDC(&dc);
01299
01300
01301
01302 if (r == DD_OK)
01303 r = StretchBlt(dc, 0, 0, ScreenXsize, ScreenYsize, dcimage, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
01304
01305
01306
01307 (*surface)->ReleaseDC(dc);
01308 DeleteDC(dcimage);
01309
01310
01311
01312 return (r == DD_OK);
01313 }
01314
01315
01316
01318
01319
01320
01322
01323 void DrawCollPoly(NEWCOLLPOLY *poly)
01324 {
01325 long col, vertnum;
01326 REAL normDotUp;
01327 VEC pos[4];
01328 long rgb[4];
01329
01330
01331 vertnum = GetCollPolyVertices(poly, &pos[0], &pos[1], &pos[2], &pos[3]);
01332 Assert(vertnum >= 3 && vertnum <= 4);
01333
01334
01335 normDotUp = ONE - VecDotVec(&DownVec, PlaneNormal(&poly->Plane));
01336 col = (long)(127 * normDotUp);
01337 if (poly->Type & NON_PLANAR) {
01338
01339 } else {
01340 col |= col << 8 | col << 16 | col << 24;
01341 }
01342
01343
01344 rgb[0] = 0xff0000;
01345 rgb[1] = 0x00ff00;
01346 rgb[2] = 0x0000ff;
01347 rgb[3] = 0xffff00;
01348
01349
01350 DrawNearClipPolyTEX0(pos, rgb, vertnum);
01351 }
01352
01354
01356
01357 void DrawBoundingBox(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax, long c0, long c1, long c2, long c3, long c4, long c5)
01358 {
01359 VEC v0;
01360 VEC v1;
01361 VEC v2;
01362 VEC v3;
01363 VEC v4;
01364 VEC v5;
01365 VEC v6;
01366 VEC v7;
01367 VEC pos[4];
01368 long col[4];
01369
01370
01371
01372 SET_TPAGE(-1);
01373
01374
01375
01376 SetVector(&v0, xmin, ymin, zmin);
01377 SetVector(&v1, xmax, ymin, zmin);
01378 SetVector(&v2, xmin, ymax, zmin);
01379 SetVector(&v3, xmax, ymax, zmin);
01380 SetVector(&v4, xmin, ymin, zmax);
01381 SetVector(&v5, xmax, ymin, zmax);
01382 SetVector(&v6, xmin, ymax, zmax);
01383 SetVector(&v7, xmax, ymax, zmax);
01384
01385
01386
01387 pos[0] = v4;
01388 pos[1] = v0;
01389 pos[2] = v2;
01390 pos[3] = v6;
01391 col[0] = col[1] = col[2] = col[3] = c0;
01392 DrawNearClipPolyTEX0(pos, col, 4);
01393
01394
01395
01396 pos[0] = v1;
01397 pos[1] = v5;
01398 pos[2] = v7;
01399 pos[3] = v3;
01400 col[0] = col[1] = col[2] = col[3] = c1;
01401 DrawNearClipPolyTEX0(pos, col, 4);
01402
01403
01404
01405 pos[0] = v4;
01406 pos[1] = v5;
01407 pos[2] = v1;
01408 pos[3] = v0;
01409 col[0] = col[1] = col[2] = col[3] = c2;
01410 DrawNearClipPolyTEX0(pos, col, 4);
01411
01412
01413
01414 pos[0] = v2;
01415 pos[1] = v3;
01416 pos[2] = v7;
01417 pos[3] = v6;
01418 col[0] = col[1] = col[2] = col[3] = c3;
01419 DrawNearClipPolyTEX0(pos, col, 4);
01420
01421
01422
01423 pos[0] = v0;
01424 pos[1] = v1;
01425 pos[2] = v3;
01426 pos[3] = v2;
01427 col[0] = col[1] = col[2] = col[3] = c4;
01428 DrawNearClipPolyTEX0(pos, col, 4);
01429
01430
01431
01432 pos[0] = v4;
01433 pos[1] = v5;
01434 pos[2] = v7;
01435 pos[3] = v6;
01436 col[0] = col[1] = col[2] = col[3] = c5;
01437 DrawNearClipPolyTEX0(pos, col, 4);
01438 }
01439
01441
01443
01444 void DrawCubeNormals(WORLD_MODEL *m)
01445 {
01446 long i;
01447 WORLD_VERTEX *v;
01448 VEC point1, point2;
01449
01450
01451
01452 v = m->VertPtr;
01453 for (i = 0 ; i < m->VertNum + m->PolyNum ; i++, v++)
01454 {
01455 point1.v[X] = v->x;
01456 point1.v[Y] = v->y;
01457 point1.v[Z] = v->z;
01458
01459 point2.v[X] = point1.v[X] + (v->nx * 64);
01460 point2.v[Y] = point1.v[Y] + (v->ny * 64);
01461 point2.v[Z] = point1.v[Z] + (v->nz * 64);
01462
01463 DrawLine(&point1, &point2, 0xffffff, 0);
01464 }
01465 }
01466
01468
01470
01471 bool DrawConvex(CONVEX *skin, INDEX count)
01472 {
01473 long i, j, c0, c1;
01474
01475
01476
01477 if (!skin)
01478 return FALSE;
01479
01480
01481
01482 for ( i = 0 ; i < count ; i++)
01483 {
01484
01485
01486
01487 switch (i % 3)
01488 {
01489 case 0:
01490 c0 = 0xff0000;
01491 c1 = 0xff0000;
01492 break;
01493 case 1:
01494 c0 = 0x00ff00;
01495 c1 = 0x00ff00;
01496 break;
01497 case 2:
01498 c0 = 0x0000ff;
01499 c1 = 0x0000ff;
01500 break;
01501 }
01502
01503
01504
01505 for (j = 0 ; j < skin[i].NEdges ; j++)
01506 {
01507 DrawLine(&skin[i].Pts[skin[i].Edges[j].Vtx[0]], &skin[i].Pts[skin[i].Edges[j].Vtx[1]], c0, c1);
01508 }
01509 }
01510
01511
01512
01513 return TRUE;
01514 }
01515
01517
01519
01520 void DrawLine(VEC *v0, VEC *v1, long col0, long col1)
01521 {
01522 float mul;
01523 long lmul;
01524 VEC delta;
01525 MODEL_RGB *rgb0, *rgb1;
01526
01527
01528
01529 RotTransVector(&ViewMatrixScaled, &ViewTransScaled, v0, (VEC*)&DrawVertsTEX0[0].sx);
01530 RotTransVector(&ViewMatrixScaled, &ViewTransScaled, v1, (VEC*)&DrawVertsTEX0[1].sx);
01531
01532
01533
01534 if (DrawVertsTEX0[0].sz < 1)
01535 {
01536 if (DrawVertsTEX0[1].sz < 1)
01537 return;
01538
01539 SubVector((VEC*)&DrawVertsTEX0[1].sx, (VEC*)&DrawVertsTEX0[0].sx, &delta);
01540 mul = (1 - DrawVertsTEX0[0].sz) / (DrawVertsTEX0[1].sz - DrawVertsTEX0[0].sz);
01541 DrawVertsTEX0[0].sx += delta.v[X] * mul;
01542 DrawVertsTEX0[0].sy += delta.v[Y] * mul;
01543 DrawVertsTEX0[0].sz += delta.v[Z] * mul;
01544
01545 FTOL(mul * 256, lmul);
01546 rgb0 = (MODEL_RGB*)&col0;
01547 rgb1 = (MODEL_RGB*)&col1;
01548 rgb0->r = (unsigned char)((rgb0->r * (256 - lmul) + rgb1->r * lmul) >> 8);
01549 rgb0->g = (unsigned char)((rgb0->g * (256 - lmul) + rgb1->g * lmul) >> 8);
01550 rgb0->b = (unsigned char)((rgb0->b * (256 - lmul) + rgb1->b * lmul) >> 8);
01551 }
01552
01553 else if (DrawVertsTEX0[1].sz < 1)
01554 {
01555 SubVector((VEC*)&DrawVertsTEX0[0].sx, (VEC*)&DrawVertsTEX0[1].sx, &delta);
01556 mul = (1 - DrawVertsTEX0[1].sz) / (DrawVertsTEX0[0].sz - DrawVertsTEX0[1].sz);
01557 DrawVertsTEX0[1].sx += delta.v[X] * mul;
01558 DrawVertsTEX0[1].sy += delta.v[Y] * mul;
01559 DrawVertsTEX0[1].sz += delta.v[Z] * mul;
01560
01561 FTOL(mul * 256, lmul);
01562 rgb0 = (MODEL_RGB*)&col1;
01563 rgb1 = (MODEL_RGB*)&col0;
01564 rgb0->r = (unsigned char)((rgb0->r * (256 - lmul) + rgb1->r * lmul) >> 8);
01565 rgb0->g = (unsigned char)((rgb0->g * (256 - lmul) + rgb1->g * lmul) >> 8);
01566 rgb0->b = (unsigned char)((rgb0->b * (256 - lmul) + rgb1->b * lmul) >> 8);
01567 }
01568
01569
01570
01571 DrawVertsTEX0[0].sx = DrawVertsTEX0[0].sx / DrawVertsTEX0[0].sz + RenderSettings.GeomCentreX;
01572 DrawVertsTEX0[0].sy = DrawVertsTEX0[0].sy / DrawVertsTEX0[0].sz + RenderSettings.GeomCentreY;
01573 DrawVertsTEX0[0].rhw = 1 / DrawVertsTEX0[0].sz;
01574 DrawVertsTEX0[0].sz = GET_ZBUFFER(DrawVertsTEX0[0].sz);
01575
01576 DrawVertsTEX0[1].sx = DrawVertsTEX0[1].sx / DrawVertsTEX0[1].sz + RenderSettings.GeomCentreX;
01577 DrawVertsTEX0[1].sy = DrawVertsTEX0[1].sy / DrawVertsTEX0[1].sz + RenderSettings.GeomCentreY;
01578 DrawVertsTEX0[1].rhw = 1 / DrawVertsTEX0[1].sz;
01579 DrawVertsTEX0[1].sz = GET_ZBUFFER(DrawVertsTEX0[1].sz);
01580
01581
01582
01583 DrawVertsTEX0[0].color = col0;
01584 DrawVertsTEX0[1].color = col1;
01585
01586 SET_TPAGE(-1);
01587 D3Ddevice->DrawPrimitive(D3DPT_LINELIST, FVF_TEX0, DrawVertsTEX0, 2, D3DDP_DONOTUPDATEEXTENTS);
01588 }
01589
01591
01593
01594 void DrawTriClip(VERTEX_TEX1 *v0, VERTEX_TEX1 *v1, VERTEX_TEX1 *v2)
01595 {
01596
01597
01598
01599 ClipVertNum = 3;
01600 ClipVertFree = 3;
01601
01602 ClipVertList[0][0] = 0;
01603 ClipVertList[0][1] = 1;
01604 ClipVertList[0][2] = 2;
01605
01606 ClipVert[0] = *v0;
01607 ClipVert[1] = *v1;
01608 ClipVert[2] = *v2;
01609
01610
01611
01612 DrawFanClip();
01613 }
01614
01616
01618
01619 void DrawQuadClip(VERTEX_TEX1 *v0, VERTEX_TEX1 *v1, VERTEX_TEX1 *v2, VERTEX_TEX1 *v3)
01620 {
01621
01622
01623
01624 ClipVertNum = 4;
01625 ClipVertFree = 4;
01626
01627 ClipVertList[0][0] = 0;
01628 ClipVertList[0][1] = 1;
01629 ClipVertList[0][2] = 2;
01630 ClipVertList[0][3] = 3;
01631
01632 ClipVert[0] = *v0;
01633 ClipVert[1] = *v1;
01634 ClipVert[2] = *v2;
01635 ClipVert[3] = *v3;
01636
01637
01638
01639 DrawFanClip();
01640 }
01641
01643
01645
01646 void DrawFanClip(void)
01647 {
01648 short i, newcount;
01649 VERTEX_TEX1 *vert0, *vert1;
01650
01651
01652
01653 for (i = newcount = 0 ; i < ClipVertNum ; i++)
01654 {
01655 vert0 = ClipVert + ClipVertList[0][i];
01656 vert1 = ClipVert + ClipVertList[0][(i + 1) % ClipVertNum];
01657
01658 if (vert0->sy >= ScreenTopClip)
01659 {
01660 ClipVertList[1][newcount++] = ClipVertList[0][i];
01661
01662 if (vert1->sy < ScreenTopClip)
01663 {
01664 ClipLineTEX1(vert0, vert1, (vert0->sy - ScreenTopClip) / (vert0->sy - vert1->sy), ClipVert + ClipVertFree);
01665 ClipVertList[1][newcount++] = ClipVertFree++;
01666 }
01667 }
01668 else
01669 {
01670 if (vert1->sy >= ScreenTopClip)
01671 {
01672 ClipLineTEX1(vert1, vert0, (vert1->sy - ScreenTopClip) / (vert1->sy - vert0->sy), ClipVert + ClipVertFree);
01673 ClipVertList[1][newcount++] = ClipVertFree++;
01674 }
01675 }
01676 }
01677
01678 ClipVertNum = newcount;
01679
01680
01681
01682 for (i = newcount = 0 ; i < ClipVertNum ; i++)
01683 {
01684 vert0 = ClipVert + ClipVertList[1][i];
01685 vert1 = ClipVert + ClipVertList[1][(i + 1) % ClipVertNum];
01686
01687 if (vert0->sy <= ScreenBottomClip)
01688 {
01689 ClipVertList[0][newcount++] = ClipVertList[1][i];
01690
01691 if (vert1->sy > ScreenBottomClip)
01692 {
01693 ClipLineTEX1(vert0, vert1, (ScreenBottomClip - vert0->sy) / (vert1->sy - vert0->sy), ClipVert + ClipVertFree);
01694 ClipVertList[0][newcount++] = ClipVertFree++;
01695 }
01696 }
01697 else
01698 {
01699 if (vert1->sy <= ScreenBottomClip)
01700 {
01701 ClipLineTEX1(vert1, vert0, (ScreenBottomClip - vert1->sy) / (vert0->sy - vert1->sy), ClipVert + ClipVertFree);
01702 ClipVertList[0][newcount++] = ClipVertFree++;
01703 }
01704 }
01705 }
01706
01707 ClipVertNum = newcount;
01708
01709
01710
01711 for (i = newcount = 0 ; i < ClipVertNum ; i++)
01712 {
01713 vert0 = ClipVert + ClipVertList[0][i];
01714 vert1 = ClipVert + ClipVertList[0][(i + 1) % ClipVertNum];
01715
01716 if (vert0->sx >= ScreenLeftClip)
01717 {
01718 ClipVertList[1][newcount++] = ClipVertList[0][i];
01719
01720 if (vert1->sx < ScreenLeftClip)
01721 {
01722 ClipLineTEX1(vert0, vert1, (vert0->sx - ScreenLeftClip) / (vert0->sx - vert1->sx), ClipVert + ClipVertFree);
01723 ClipVertList[1][newcount++] = ClipVertFree++;
01724 }
01725 }
01726 else
01727 {
01728 if (vert1->sx >= ScreenLeftClip)
01729 {
01730 ClipLineTEX1(vert1, vert0, (vert1->sx - ScreenLeftClip) / (vert1->sx - vert0->sx), ClipVert + ClipVertFree);
01731 ClipVertList[1][newcount++] = ClipVertFree++;
01732 }
01733 }
01734 }
01735
01736 ClipVertNum = newcount;
01737
01738
01739
01740 for (i = newcount = 0 ; i < ClipVertNum ; i++)
01741 {
01742 vert0 = ClipVert + ClipVertList[1][i];
01743 vert1 = ClipVert + ClipVertList[1][(i + 1) % ClipVertNum];
01744
01745 if (vert0->sx <= ScreenRightClip)
01746 {
01747 ClipVertList[0][newcount++] = ClipVertList[1][i];
01748
01749 if (vert1->sx > ScreenRightClip)
01750 {
01751 ClipLineTEX1(vert0, vert1, (ScreenRightClip - vert0->sx) / (vert1->sx - vert0->sx), ClipVert + ClipVertFree);
01752 ClipVertList[0][newcount++] = ClipVertFree++;
01753 }
01754 }
01755 else
01756 {
01757 if (vert1->sx <= ScreenRightClip)
01758 {
01759 ClipLineTEX1(vert1, vert0, (ScreenRightClip - vert1->sx) / (vert0->sx - vert1->sx), ClipVert + ClipVertFree);
01760 ClipVertList[0][newcount++] = ClipVertFree++;
01761 }
01762 }
01763 }
01764
01765 ClipVertNum = newcount;
01766
01767
01768
01769 D3Ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, D3DFVF_TLVERTEX, ClipVert, 32, ClipVertList[0], ClipVertNum, D3DDP_DONOTUPDATEEXTENTS | D3DDP_DONOTCLIP);
01770 }
01771
01773
01775
01776 void ClipLineTEX0(VERTEX_TEX0 *v0, VERTEX_TEX0 *v1, float mul, VERTEX_TEX0 *out)
01777 {
01778 long lmul;
01779 float zout;
01780 MODEL_RGB *rgb0, *rgb1, *rgbout;
01781
01782
01783
01784 out->sx = v0->sx + (v1->sx - v0->sx) * mul;
01785 out->sy = v0->sy + (v1->sy - v0->sy) * mul;
01786 out->rhw = v0->rhw + (v1->rhw - v0->rhw) * mul;
01787 zout = 1.0f / out->rhw;
01788 out->sz = GET_ZBUFFER(zout);
01789
01790
01791
01792 FTOL(mul * 256, lmul);
01793
01794 out->specular = v0->specular + ((((v1->specular >> 24) - (v0->specular >> 24)) * lmul) << 16);
01795
01796 rgb0 = (MODEL_RGB*)&v0->color;
01797 rgb1 = (MODEL_RGB*)&v1->color;
01798 rgbout = (MODEL_RGB*)&out->color;
01799
01800 rgbout->r = rgb0->r + (unsigned char)(((rgb1->r - rgb0->r) * lmul) >> 8);
01801 rgbout->g = rgb0->g + (unsigned char)(((rgb1->g - rgb0->g) * lmul) >> 8);
01802 rgbout->b = rgb0->b + (unsigned char)(((rgb1->b - rgb0->b) * lmul) >> 8);
01803 }
01804
01806
01808
01809 void ClipLineTEX1(VERTEX_TEX1 *v0, VERTEX_TEX1 *v1, float mul, VERTEX_TEX1 *out)
01810 {
01811 long lmul;
01812 float z0, z1, zout, zmul;
01813 MODEL_RGB *rgb0, *rgb1, *rgbout;
01814
01815
01816
01817 out->sx = v0->sx + (v1->sx - v0->sx) * mul;
01818 out->sy = v0->sy + (v1->sy - v0->sy) * mul;
01819 out->rhw = v0->rhw + (v1->rhw - v0->rhw) * mul;
01820 zout = 1.0f / out->rhw;
01821 out->sz = GET_ZBUFFER(zout);
01822
01823
01824
01825 z0 = 1.0f / v0->rhw;
01826 z1 = 1.0f / v1->rhw;
01827 zmul = (zout - z0) / (z1 - z0);
01828
01829 out->tu = v0->tu + (v1->tu - v0->tu) * zmul;
01830 out->tv = v0->tv + (v1->tv - v0->tv) * zmul;
01831
01832
01833
01834 FTOL(mul * 256, lmul);
01835
01836 out->specular = v0->specular + ((((v1->specular >> 24) - (v0->specular >> 24)) * lmul) << 16);
01837
01838 rgb0 = (MODEL_RGB*)&v0->color;
01839 rgb1 = (MODEL_RGB*)&v1->color;
01840 rgbout = (MODEL_RGB*)&out->color;
01841
01842 rgbout->r = rgb0->r + (unsigned char)(((rgb1->r - rgb0->r) * lmul) >> 8);
01843 rgbout->g = rgb0->g + (unsigned char)(((rgb1->g - rgb0->g) * lmul) >> 8);
01844 rgbout->b = rgb0->b + (unsigned char)(((rgb1->b - rgb0->b) * lmul) >> 8);
01845 }
01846
01848
01850
01851 void SaveFrontBuffer(char *file)
01852 {
01853 DDSURFACEDESC2 ddsd;
01854 BITMAPFILEHEADER bf;
01855 BITMAPINFOHEADER bi;
01856 FILE *fp;
01857 DWORD y, x;
01858 short *p, r, g, b;
01859 short outbuf[1600];
01860
01861
01862
01863 fp = fopen(file, "wb");
01864 if (!fp) return;
01865
01866
01867
01868 ddsd.dwSize = sizeof(ddsd);
01869 while (FrontBuffer->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL) != DD_OK);
01870
01871
01872
01873 bf.bfType = MAKEWORD((BYTE)'B',(BYTE)'M');
01874 bf.bfSize = sizeof(bf) + sizeof(bi) + ScreenXsize * ScreenYsize * sizeof(short);
01875 bf.bfReserved1 = 0;
01876 bf.bfReserved2 = 0;
01877 bf.bfOffBits = sizeof(bf) + sizeof(bi);
01878
01879 fwrite(&bf, sizeof(bf), 1, fp);
01880
01881 bi.biSize = sizeof(BITMAPINFOHEADER);
01882 bi.biWidth = ScreenXsize;
01883 bi.biHeight = ScreenYsize;
01884 bi.biPlanes = 1;
01885 bi.biBitCount = 16;
01886 bi.biCompression = BI_RGB;
01887 bi.biSizeImage = 0;
01888 bi.biXPelsPerMeter = 0;
01889 bi.biYPelsPerMeter = 0;
01890 bi.biClrUsed = 0;
01891 bi.biClrImportant = 0;
01892
01893 fwrite(&bi, sizeof(bi), 1, fp);
01894
01895
01896
01897 p = (short*)ddsd.lpSurface;
01898 p += ddsd.lPitch * (ScreenYsize - 1) / 2;
01899
01900 if (ddsd.ddpfPixelFormat.dwGBitMask & 1024)
01901 {
01902 for (y = 0 ; y < ScreenYsize ; y++)
01903 {
01904 for (x = 0 ; x < ScreenXsize ; x++)
01905 {
01906 b = p[x] & 31;
01907 g = (p[x] >> 6) & 31;
01908 r = (p[x] >> 11) & 31;
01909 outbuf[x] = b | (g << 5) | (r << 10);
01910 }
01911 fwrite(outbuf, sizeof(short), ScreenXsize, fp);
01912 p -= ddsd.lPitch / 2;
01913 }
01914 }
01915 else
01916 {
01917 for (y = 0 ; y < ScreenYsize ; y++)
01918 {
01919 fwrite(p, sizeof(short), ScreenXsize, fp);
01920 p -= ddsd.lPitch / 2;
01921 }
01922 }
01923
01924
01925
01926 FrontBuffer->Unlock(NULL);
01927
01928
01929
01930 fclose(fp);
01931 }
01932
01934
01936
01937 void ResetMeshFxList(void)
01938 {
01939 WorldMeshFxCount = 0;
01940 ModelMeshFxCount = 0;
01941 }
01942
01944
01946
01947 void AddWorldMeshFx(void (*checker)(void *data), void *data)
01948 {
01949
01950
01951
01952 if (WorldMeshFxCount >= MAX_WORLD_MESH_FX)
01953 return;
01954
01955
01956
01957 WorldMeshFx[WorldMeshFxCount].Checker = checker;
01958 WorldMeshFx[WorldMeshFxCount].Data = data;
01959 WorldMeshFxCount++;
01960 }
01961
01963
01965
01966 void AddModelMeshFx(void (*checker)(void *data), void *data)
01967 {
01968
01969
01970
01971 if (ModelMeshFxCount >= MAX_MODEL_MESH_FX)
01972 return;
01973
01974
01975
01976 ModelMeshFx[ModelMeshFxCount].Checker = checker;
01977 ModelMeshFx[ModelMeshFxCount].Data = data;
01978 ModelMeshFxCount++;
01979 }
01980
01982
01984
01985 void InitJumpSparkOffsets(void)
01986 {
01987 long i;
01988
01989 for (i = 0 ; i < JUMPSPARK_OFFSET_NUM ; i++)
01990 {
01991 SetVector(&JumpSparkOffset[i], frand(4.0f) - 2.0f, frand(4.0f) - 2.0f, frand(4.0f) - 2.0f);
01992 }
01993 }
01994
01996
01998
01999 void DrawJumpSpark(VEC *v1, VEC *v2)
02000 {
02001 long i, steps, offset;
02002 VEC delta, pos, vec, start, end, svec;
02003 REAL len, fsteps, mul, dx1, dy1, dx2, dy2, ang, s, sadd, smul;
02004 REAL dx[JUMPSPARK_STEP_MAX], dy[JUMPSPARK_STEP_MAX];
02005 VERTEX_TEX0 points[JUMPSPARK_STEP_MAX + 1];
02006 VERTEX_TEX1 *verts;
02007 FACING_POLY poly;
02008 MAT mat;
02009
02010
02011
02012 SubVector(v2, v1, &delta);
02013 len = Length(&delta);
02014 fsteps = len / JUMPSPARK_STEP_LEN;
02015 if (fsteps > JUMPSPARK_STEP_MAX)
02016 fsteps = JUMPSPARK_STEP_MAX;
02017
02018 FTOL(fsteps, steps);
02019 fsteps = (float)steps;
02020
02021
02022
02023 CopyVec(v1, &pos);
02024 mul = 1.0f / fsteps;
02025 VecMulScalar(&delta, mul);
02026
02027 i = TIME2MS(TimerCurrent) / 20;
02028 if (i != JumpSparkTime)
02029 {
02030 JumpSparkTime = i;
02031 JumpSparkOff = rand() % JUMPSPARK_OFFSET_NUM;
02032 }
02033
02034 offset = JumpSparkOff;
02035
02036 CrossProduct(&delta, &ViewCameraMatrix.mv[U], &vec);
02037 CrossProduct(&vec, &delta, &svec);
02038 NormalizeVector(&svec);
02039
02040 s = (float)TIME2MS(TimerCurrent) / 100.0f;
02041
02042 i = TIME2MS(TimerCurrent) / 500;
02043 if (i != JumpSparkSinTime)
02044 {
02045 JumpSparkSinTime = i;
02046 JumpSparkSinDiv = frand(6.0f) + 9.0f;
02047 }
02048 sadd = len / fsteps / JumpSparkSinDiv;
02049
02050 smul = (float)sin((float)TIME2MS(TimerCurrent) / 300.0f) + 3.0f;
02051
02052 for (i = 0 ; i < steps + 1; i++)
02053 {
02054 CopyVec(&pos, &vec);
02055
02056
02057 {
02058 vec.v[X] += JumpSparkOffset[offset].v[X];
02059 vec.v[Y] += JumpSparkOffset[offset].v[Y];
02060 vec.v[Z] += JumpSparkOffset[offset].v[Z];
02061
02062 mul = (float)sin(s) * smul;
02063 VecPlusEqScalarVec(&vec, mul, &svec);
02064 }
02065
02066 if (!i)
02067 CopyVec(&vec, &start)
02068
02069 if (i == steps)
02070 CopyVec(&vec, &end)
02071
02072 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &vec, (float*)&points[i]);
02073 AddVector(&pos, &delta, &pos);
02074
02075 offset++;
02076 offset %= JUMPSPARK_OFFSET_NUM;
02077
02078 s += sadd;
02079 }
02080
02081
02082
02083 for (i = 0 ; i < steps ; i++)
02084 {
02085 dx1 = points[i + 1].sx - points[i].sx;
02086 dy1 = points[i + 1].sy - points[i].sy;
02087 mul = 4.0f / (float)sqrt(dx1 * dx1 + dy1 * dy1) * points[i].rhw * RenderSettings.GeomPers;
02088 dy[i] = dx1 * mul;
02089 dx[i] = -dy1 * mul;
02090 }
02091
02092
02093
02094 for (i = 0 ; i < steps ; i++)
02095 {
02096
02097
02098
02099 if (!SEMI_POLY_FREE()) return;
02100 SEMI_POLY_SETUP_ZBIAS(verts, FALSE, 4, TPAGE_FX1, TRUE, 1, -128.0f);
02101
02102
02103
02104 if (!i)
02105 {
02106 dx1 = dx[i] * 0.75f;
02107 dy1 = dy[i] * 0.75f;
02108 }
02109 else
02110 {
02111 dx1 = dx2;
02112 dy1 = dy2;
02113 }
02114
02115
02116
02117 if (i == steps - 1)
02118 {
02119 dx2 = dx[i] * 0.75f;
02120 dy2 = dy[i] * 0.75f;
02121 }
02122 else
02123 {
02124 dx2 = dx[i] + dx[i + 1];
02125 dy2 = dy[i] + dy[i + 1];
02126 mul = 4.0f / (float)sqrt(dx2 * dx2 + dy2 * dy2) * points[i + 1].rhw * RenderSettings.GeomPers;
02127 dx2 *= mul;
02128 dy2 *= mul;
02129 }
02130
02131
02132
02133 verts[0].sx = points[i].sx - dx1;
02134 verts[0].sy = points[i].sy - dy1;
02135
02136 verts[1].sx = points[i + 1].sx - dx2;
02137 verts[1].sy = points[i + 1].sy - dy2;
02138
02139 verts[2].sx = points[i + 1].sx + dx2;
02140 verts[2].sy = points[i + 1].sy + dy2;
02141
02142 verts[3].sx = points[i].sx + dx1;
02143 verts[3].sy = points[i].sy + dy1;
02144
02145 verts[0].sz = verts[3].sz = points[i].sz;
02146 verts[1].sz = verts[2].sz = points[i + 1].sz;
02147 verts[0].rhw = verts[3].rhw = points[i].rhw;
02148 verts[1].rhw = verts[2].rhw = points[i + 1].rhw;
02149
02150 verts[0].tu = verts[3].tu = 216.0f / 256.0f;
02151 verts[1].tu = verts[2].tu = 223.0f / 256.0f;
02152 verts[0].tv = verts[1].tv = 33.0f / 256.0f;
02153 verts[2].tv = verts[3].tv = 47.0f / 256.0f;
02154
02155 verts[0].color = verts[1].color = verts[2].color = verts[3].color = 0xffffff;
02156 }
02157
02158
02159
02160 poly.Xsize = poly.Ysize = (float)(TIME2MS(TimerCurrent) % 100) / 25.0f + 4.0f;
02161 poly.U = 192.0f / 256.0f;
02162 poly.V = 64.0f / 256.0f;
02163 poly.Usize = poly.Vsize = 64.0f / 256.0f;
02164 poly.Tpage = TPAGE_FX1;
02165 poly.RGB = 0x8080ff;
02166
02167 ang = (float)TIME2MS(TimerCurrent) / 10000.0f;
02168
02169 RotMatrixZ(&mat, ang);
02170 DrawFacingPolyRot(&start, &mat, &poly, 1, -16.0f);
02171 DrawFacingPolyRot(&end, &mat, &poly, 1, -16.0f);
02172
02173 RotMatrixZ(&mat, ang * 2.0f);
02174 DrawFacingPolyRot(&start, &mat, &poly, 1, -16.0f);
02175 DrawFacingPolyRot(&end, &mat, &poly, 1, -16.0f);
02176 }
02177
02178 void DrawJumpSpark2(VEC *v1, VEC *v2)
02179 {
02180 long i, steps, offset;
02181 VEC delta, pos, vec, start, end, svec;
02182 REAL len, fsteps, mul, dx1, dy1, dx2, dy2, s, sadd, smul;
02183 REAL dx[JUMPSPARK_STEP_MAX], dy[JUMPSPARK_STEP_MAX];
02184 VERTEX_TEX0 points[JUMPSPARK_STEP_MAX + 1];
02185 VERTEX_TEX1 *verts;
02186
02187
02188
02189 SubVector(v2, v1, &delta);
02190 len = Length(&delta);
02191 fsteps = len / JUMPSPARK_STEP_LEN;
02192 if (fsteps > JUMPSPARK_STEP_MAX)
02193 fsteps = JUMPSPARK_STEP_MAX;
02194
02195 FTOL(fsteps, steps);
02196 fsteps = (float)steps;
02197
02198
02199
02200 CopyVec(v1, &pos);
02201 mul = 1.0f / fsteps;
02202 VecMulScalar(&delta, mul);
02203
02204 i = TIME2MS(TimerCurrent) / 20;
02205 if (i != JumpSparkTime)
02206 {
02207 JumpSparkTime = i;
02208 JumpSparkOff = rand() % JUMPSPARK_OFFSET_NUM;
02209 }
02210
02211 offset = JumpSparkOff;
02212
02213 CrossProduct(&delta, &ViewCameraMatrix.mv[U], &vec);
02214 CrossProduct(&vec, &delta, &svec);
02215 NormalizeVector(&svec);
02216
02217 s = (float)TIME2MS(TimerCurrent) / 100.0f;
02218
02219 i = TIME2MS(TimerCurrent) / 500;
02220 if (i != JumpSparkSinTime)
02221 {
02222 JumpSparkSinTime = i;
02223 JumpSparkSinDiv = frand(6.0f) + 9.0f;
02224 }
02225 sadd = len / fsteps / JumpSparkSinDiv;
02226
02227 smul = (float)sin((float)TIME2MS(TimerCurrent) / 300.0f) + 3.0f;
02228
02229 for (i = 0 ; i < steps + 1; i++)
02230 {
02231 CopyVec(&pos, &vec);
02232
02233
02234 {
02235 vec.v[X] += JumpSparkOffset[offset].v[X];
02236 vec.v[Y] += JumpSparkOffset[offset].v[Y];
02237 vec.v[Z] += JumpSparkOffset[offset].v[Z];
02238
02239 mul = (float)sin(s) * smul;
02240 VecPlusEqScalarVec(&vec, mul, &svec);
02241 }
02242
02243 if (!i)
02244 CopyVec(&vec, &start)
02245
02246 if (i == steps)
02247 CopyVec(&vec, &end)
02248
02249 RotTransPersVector(&ViewMatrixScaled, &ViewTransScaled, &vec, (float*)&points[i]);
02250 AddVector(&pos, &delta, &pos);
02251
02252 offset++;
02253 offset %= JUMPSPARK_OFFSET_NUM;
02254
02255 s += sadd;
02256 }
02257
02258
02259
02260 for (i = 0 ; i < steps ; i++)
02261 {
02262 dx1 = points[i + 1].sx - points[i].sx;
02263 dy1 = points[i + 1].sy - points[i].sy;
02264 mul = 4.0f / (float)sqrt(dx1 * dx1 + dy1 * dy1) * points[i].rhw * RenderSettings.GeomPers;
02265 dy[i] = dx1 * mul;
02266 dx[i] = -dy1 * mul;
02267 }
02268
02269
02270
02271 for (i = 0 ; i < steps ; i++)
02272 {
02273
02274
02275
02276 if (!SEMI_POLY_FREE()) return;
02277 SEMI_POLY_SETUP_ZBIAS(verts, FALSE, 4, TPAGE_FX1, TRUE, 1, -128.0f);
02278
02279
02280
02281 if (!i)
02282 {
02283 dx1 = 0;
02284 dy1 = 0;
02285 }
02286 else
02287 {
02288 dx1 = dx2;
02289 dy1 = dy2;
02290 }
02291
02292
02293
02294 if (i == steps - 1)
02295 {
02296 dx2 = 0;
02297 dy2 = 0;
02298 }
02299 else
02300 {
02301 dx2 = dx[i] + dx[i + 1];
02302 dy2 = dy[i] + dy[i + 1];
02303 mul = 4.0f / (float)sqrt(dx2 * dx2 + dy2 * dy2) * points[i + 1].rhw * RenderSettings.GeomPers;
02304 dx2 *= mul;
02305 dy2 *= mul;
02306 }
02307
02308
02309
02310 verts[0].sx = points[i].sx - dx1;
02311 verts[0].sy = points[i].sy - dy1;
02312
02313 verts[1].sx = points[i + 1].sx - dx2;
02314 verts[1].sy = points[i + 1].sy - dy2;
02315
02316 verts[2].sx = points[i + 1].sx + dx2;
02317 verts[2].sy = points[i + 1].sy + dy2;
02318
02319 verts[3].sx = points[i].sx + dx1;
02320 verts[3].sy = points[i].sy + dy1;
02321
02322 verts[0].sz = verts[3].sz = points[i].sz;
02323 verts[1].sz = verts[2].sz = points[i + 1].sz;
02324 verts[0].rhw = verts[3].rhw = points[i].rhw;
02325 verts[1].rhw = verts[2].rhw = points[i + 1].rhw;
02326
02327 verts[0].tu = verts[3].tu = 216.0f / 256.0f;
02328 verts[1].tu = verts[2].tu = 223.0f / 256.0f;
02329 verts[0].tv = verts[1].tv = 33.0f / 256.0f;
02330 verts[2].tv = verts[3].tv = 47.0f / 256.0f;
02331
02332 verts[0].color = verts[1].color = verts[2].color = verts[3].color = 0xffffff;
02333 }
02334 }