| | 1 | #include "system.h" |
| | 2 | #include "prototyp.h" |
| | 3 | #include <math.h> |
| | 4 | #include "stratdef.h" |
| | 5 | #include "frustum.h" |
| | 6 | #include "npc_marine.h" |
| | 7 | #include "corpse.h" |
| | 8 | #include "debris.h" |
| | 9 | #include "weaponbehaviour.h" |
| | 10 | #include "bh_types.h" |
| | 11 | #include "pldghost.h" |
| | 12 | #include "userprofile.h" |
| | 13 | #include "weapons.h" |
| | 14 | #include "lighting.h" |
| | 15 | #include "hud.h" |
| | 16 | #include "bh_light.h" |
| | 17 | #include <assert.h> |
| | 18 | |
| | 19 | extern void GetMorphDisplay(MORPHDISPLAY *md, DISPLAYBLOCK *dptr); |
| | 20 | extern void Decal_Output(const DECAL *decalPtr, RENDERVERTEX *renderVerticesPtr); |
| | 21 | extern void SkyPolygon_Output(RENDERVERTEX *renderVerticesPtr); |
| | 22 | extern void ZBufferedCloakedPolygon_Output(POLYHEADER *inputPolyPtr, RENDERVERTEX *renderVerticesPtr); |
| | 23 | extern void ZBufferedGouraudTexturedPolygon_Output(POLYHEADER *inputPolyPtr, RENDERVERTEX *renderVerticesPtr); |
| | 24 | extern void ZBufferedGouraudPolygon_Output(POLYHEADER *inputPolyPtr, RENDERVERTEX *renderVerticesPtr); |
| | 25 | extern void PredatorThermalVisionPolygon_Output(RENDERVERTEX *renderVerticesPtr); |
| | 26 | extern void Particle_Output(PARTICLE *particlePtr, RENDERVERTEX *renderVerticesPtr); |
| | 27 | extern void DoPlayersWeaponHModel(DISPLAYBLOCK *dptr); |
| | 28 | |
| | 29 | #define ALIENS_LIFEFORCE_GLOW_COLOUR 0x20ff8080 |
| | 30 | #define MARINES_LIFEFORCE_GLOW_COLOUR 0x208080ff |
| | 31 | #define PREDATORS_LIFEFORCE_GLOW_COLOUR 0x2080ff80 |
| | 32 | #define MAX_NO_OF_TRANSLUCENT_POLYGONS 1000 |
| | 33 | |
| | 34 | #define SPATIAL_SHOCKWAVE 0 |
| | 35 | |
| | 36 | #define MaxLightsPerObject 100 /* Sources lighting the object */ |
| | 37 | int DrawingAReflection; |
| | 38 | extern DISPLAYBLOCK* ActiveBlockList[]; |
| | 39 | extern int NumActiveBlocks; |
| | 40 | |
| | 41 | extern int CloakingPhase; |
| | 42 | extern int CloudyImageNumber; |
| | 43 | extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock; |
| | 44 | |
| | 45 | static LIGHTBLOCK *LightSourcesForObject[MaxLightsPerObject]; |
| | 46 | static DISPLAYBLOCK *Global_ODB_Ptr; |
| | 47 | static struct shapeheader *Global_ShapeHeaderPtr; |
| | 48 | static int* Global_ShapePoints; |
| | 49 | static int* Global_ShapeNormals; |
| | 50 | static int* Global_ShapeVNormals; |
| | 51 | static int HierarchicalObjectsLowestYValue; |
| | 52 | static int ObjectCounter = 0; |
| | 53 | static int NumLightSourcesForObject; |
| | 54 | |
| | 55 | static float Source[3]; |
| | 56 | static float Dest[3]; |
| | 57 | static float ViewMatrix[12]; |
| | 58 | static float ObjectViewMatrix[12]; |
| | 59 | |
| | 60 | static VECTORCH ObjectCentre; |
| | 61 | |
| | 62 | MATRIXCH LToVMat; |
| | 63 | EULER LToVMat_Euler; |
| | 64 | MATRIXCH WToLMat; |
| | 65 | VECTORCH LocalView; |
| | 66 | |
| | 67 | int TripTasticPhase; |
| | 68 | int MirroringActive = 0; |
| | 69 | int MirroringAxis = -149*2; |
| | 70 | int NumberOfHeatSources; |
| | 71 | float CameraZoomScale; |
| | 72 | |
| | 73 | struct render_polygon RenderPolygon; |
| | 74 | RENDERVERTEX VerticesBuffer[9]; |
| | 75 | |
| | 76 | static void (*VertexIntensity)(RENDERVERTEX *renderVertexPtr); |
| | 77 | |
| | 78 | VECTORCH RotatedPts[maxrotpts]; |
| | 79 | |
| | 80 | MORPHDISPLAY MorphDisplay; |
| | 81 | VECTORCH MorphedPts[1024]; |
| | 82 | |
| | 83 | static struct |
| | 84 | { |
| | 85 | /* stamp used for lazy evaluation */ |
| | 86 | int Stamp; |
| | 87 | |
| | 88 | /* colour scalings */ |
| | 89 | uint8_t R; |
| | 90 | uint8_t G; |
| | 91 | uint8_t B; |
| | 92 | |
| | 93 | /* specular colour */ |
| | 94 | uint8_t SpecularR; |
| | 95 | uint8_t SpecularG; |
| | 96 | uint8_t SpecularB; |
| | 97 | |
| | 98 | } ColourIntensityArray[maxrotpts]; |
| | 99 | |
| | 100 | static struct |
| | 101 | { |
| | 102 | struct render_polygon polygon; |
| | 103 | struct polyheader polygon_header; |
| | 104 | |
| | 105 | } TranslucentPolygons[MAX_NO_OF_TRANSLUCENT_POLYGONS]; |
| | 106 | |
| | 107 | static int CurrentNumberOfTranslucentPolygons = 0; |
| | 108 | static const int* VertexNumberPtr = (int*)1; |
| | 109 | |
| | 110 | HEATSOURCE HeatSourceList[MAX_NUMBER_OF_HEAT_SOURCES]; |
| | 111 | |
| | 112 | static void LightSourcesInRangeOfObject(DISPLAYBLOCK *dptr) |
| | 113 | { |
| | 114 | int i,j; |
| | 115 | NumLightSourcesForObject = 0; |
| | 116 | |
| | 117 | /* Light Sources attached to other objects */ |
| | 118 | |
| | 119 | for(i=0; (i < NumActiveBlocks) && (NumLightSourcesForObject < MaxLightsPerObject); i++) |
| | 120 | { |
| | 121 | DISPLAYBLOCK *dptr2 = ActiveBlockList[i]; |
| | 122 | |
| | 123 | for(j=0; j < dptr2->ObNumLights && (NumLightSourcesForObject < MaxLightsPerObject); j++) |
| | 124 | { |
| | 125 | LIGHTBLOCK *lptr = dptr2->ObLights[j]; |
| | 126 | |
| | 127 | if (!lptr->LightBright || !(lptr->RedScale || lptr->GreenScale || lptr->BlueScale)) |
| | 128 | continue; |
| | 129 | |
| | 130 | if ((PlayerStatus.VisionMode == VISION_MODE_IMAGEINTENSIFIER) && (lptr->LightFlags & LFlag_PreLitSource)) |
| | 131 | continue; |
| | 132 | |
| | 133 | if(!(dptr->ObFlags3 & ObFlag3_PreLit && lptr->LightFlags & LFlag_PreLitSource)) |
| | 134 | { |
| | 135 | VECTORCH vertexToLight; |
| | 136 | |
| | 137 | if (DrawingAReflection) |
| | 138 | vertexToLight.vx = (MirroringAxis - lptr->LightWorld.vx) - dptr->ObWorld.vx; |
| | 139 | else |
| | 140 | vertexToLight.vx = lptr->LightWorld.vx - dptr->ObWorld.vx; |
| | 141 | |
| | 142 | vertexToLight.vy = lptr->LightWorld.vy - dptr->ObWorld.vy; |
| | 143 | vertexToLight.vz = lptr->LightWorld.vz - dptr->ObWorld.vz; |
| | 144 | |
| | 145 | int distanceToLight = Approximate3dMagnitude(&vertexToLight); |
| | 146 | |
| | 147 | if(distanceToLight < (lptr->LightRange + dptr->extent.radius)) |
| | 148 | { |
| | 149 | LightSourcesForObject[NumLightSourcesForObject++] = lptr; |
| | 150 | |
| | 151 | /* Transform the light position to local space */ |
| | 152 | |
| | 153 | RotateAndCopyVector(&vertexToLight, &lptr->LocalLP, &WToLMat); |
| | 154 | } |
| | 155 | } |
| | 156 | } |
| | 157 | } |
| | 158 | |
| | 159 | { |
| | 160 | extern LIGHTELEMENT LightElementStorage[]; |
| | 161 | extern int NumActiveLightElements; |
| | 162 | |
| | 163 | for(i=0; i < NumActiveLightElements; i++) |
| | 164 | { |
| | 165 | LIGHTBLOCK *lptr = &LightElementStorage[i].LightBlock; |
| | 166 | VECTORCH vertexToLight; |
| | 167 | |
| | 168 | vertexToLight.vx = lptr->LightWorld.vx - dptr->ObWorld.vx; |
| | 169 | vertexToLight.vy = lptr->LightWorld.vy - dptr->ObWorld.vy; |
| | 170 | vertexToLight.vz = lptr->LightWorld.vz - dptr->ObWorld.vz; |
| | 171 | |
| | 172 | int distanceToLight = Approximate3dMagnitude(&vertexToLight); |
| | 173 | |
| | 174 | if(distanceToLight < (lptr->LightRange + dptr->extent.radius) ) |
| | 175 | { |
| | 176 | LightSourcesForObject[NumLightSourcesForObject] = lptr; |
| | 177 | NumLightSourcesForObject++; |
| | 178 | |
| | 179 | /* Transform the light position to local space */ |
| | 180 | RotateAndCopyVector(&vertexToLight, &lptr->LocalLP, &WToLMat); |
| | 181 | } |
| | 182 | } |
| | 183 | } |
| | 184 | } |
| | 185 | |
| | 186 | static void SetupShapePipeline(DISPLAYBLOCK * dptr) |
| | 187 | { |
| | 188 | Global_ODB_Ptr = dptr; |
| | 189 | Global_ShapeHeaderPtr = dptr->ShapeData; |
| | 190 | Global_ShapePoints = *(Global_ShapeHeaderPtr->points); |
| | 191 | Global_ShapeNormals = Global_ShapeHeaderPtr->sh_normals ? *(Global_ShapeHeaderPtr->sh_normals) : 0; |
| | 192 | Global_ShapeVNormals = Global_ShapeHeaderPtr->sh_vnormals ? *(Global_ShapeHeaderPtr->sh_vnormals) : 0; |
| | 193 | |
| | 194 | ObjectCounter++; |
| | 195 | |
| | 196 | /* |
| | 197 | Create the Local -> View Matrix |
| | 198 | |
| | 199 | LToVMat = VDB_Mat * ObMat |
| | 200 | |
| | 201 | "Get the points into View Space, then apply the Local Transformation" |
| | 202 | */ |
| | 203 | |
| | 204 | MatrixMultiply(&Global_VDB.VDB_Mat, &dptr->ObMat, <oVMat); |
| | 205 | MatrixToEuler(<oVMat, <oVMat_Euler); |
| | 206 | |
| | 207 | /* |
| | 208 | Create the World -> Local Matrix |
| | 209 | |
| | 210 | WToLMat = Transposed Local Matrix |
| | 211 | */ |
| | 212 | |
| | 213 | WToLMat = dptr->ObMat; |
| | 214 | TransposeMatrixCH(&WToLMat); |
| | 215 | |
| | 216 | /* |
| | 217 | |
| | 218 | Transform the View World Location to Local Space |
| | 219 | |
| | 220 | -> Make the View Loc. relative to the Object View Space Centre |
| | 221 | -> Rotate this vector using WToLMat |
| | 222 | |
| | 223 | */ |
| | 224 | |
| | 225 | LocalView.vx = Global_VDB.VDB_World.vx - dptr->ObWorld.vx; |
| | 226 | LocalView.vy = Global_VDB.VDB_World.vy - dptr->ObWorld.vy; |
| | 227 | LocalView.vz = Global_VDB.VDB_World.vz - dptr->ObWorld.vz; |
| | 228 | |
| | 229 | RotateVector(&LocalView, &WToLMat); |
| | 230 | |
| | 231 | /* Find out which light sources are in range of of the object */ |
| | 232 | LightSourcesInRangeOfObject(dptr); |
| | 233 | } |
| | 234 | |
| | 235 | static void VertexIntensity_Pred_Thermal(RENDERVERTEX *renderVertexPtr) |
| | 236 | { |
| | 237 | int vertexNumber = *VertexNumberPtr; |
| | 238 | |
| | 239 | if(ColourIntensityArray[vertexNumber].Stamp == ObjectCounter) |
| | 240 | { |
| | 241 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R; |
| | 242 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G; |
| | 243 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B; |
| | 244 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR; |
| | 245 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG; |
| | 246 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB; |
| | 247 | } |
| | 248 | else |
| | 249 | { |
| | 250 | int redI = 0,specular = 0; |
| | 251 | int blueI = ONE_FIXED / 2; |
| | 252 | |
| | 253 | { |
| | 254 | VECTORCH *vertexNormalPtr = ((VECTORCH *)Global_ShapeVNormals) + vertexNumber; |
| | 255 | VECTORCH *vertexPtr = ((VECTORCH *)Global_ShapePoints) + vertexNumber; |
| | 256 | VECTORCH vertexToLight; |
| | 257 | int i; |
| | 258 | |
| | 259 | for(i=0; i < NumLightSourcesForObject; i++) |
| | 260 | { |
| | 261 | LIGHTBLOCK *lptr = LightSourcesForObject[i]; |
| | 262 | |
| | 263 | if (lptr->LightFlags & LFlag_PreLitSource) |
| | 264 | continue; |
| | 265 | |
| | 266 | vertexToLight.vx = lptr->LocalLP.vx - vertexPtr->vx; |
| | 267 | vertexToLight.vy = lptr->LocalLP.vy - vertexPtr->vy; |
| | 268 | vertexToLight.vz = lptr->LocalLP.vz - vertexPtr->vz; |
| | 269 | |
| | 270 | int distanceToLight = Approximate3dMagnitude(&vertexToLight); |
| | 271 | |
| | 272 | if(distanceToLight < lptr->LightRange) |
| | 273 | { |
| | 274 | int idot = MUL_FIXED(lptr->LightRange-distanceToLight,lptr->BrightnessOverRange); |
| | 275 | |
| | 276 | if( (distanceToLight > 0) && !(Global_ODB_Ptr->ObFlags3 & ObFlag3_NoLightDot)) |
| | 277 | { |
| | 278 | int dotproduct = MUL_FIXED(vertexNormalPtr->vx,vertexToLight.vx) |
| | 279 | + MUL_FIXED(vertexNormalPtr->vy,vertexToLight.vy) |
| | 280 | + MUL_FIXED(vertexNormalPtr->vz,vertexToLight.vz); |
| | 281 | |
| | 282 | if(dotproduct > 0) |
| | 283 | { |
| | 284 | idot = WideMulNarrowDiv(idot,dotproduct,distanceToLight); |
| | 285 | redI += idot; |
| | 286 | } |
| | 287 | } |
| | 288 | |
| | 289 | if (lptr->LightFlags & LFlag_Thermal) |
| | 290 | specular += idot; |
| | 291 | } |
| | 292 | } |
| | 293 | } |
| | 294 | |
| | 295 | if (renderVertexPtr->Z > 5000) |
| | 296 | { |
| | 297 | int a = (renderVertexPtr->Z - 5000); |
| | 298 | |
| | 299 | if (a > 4096) |
| | 300 | blueI = (blueI*4096)/a; |
| | 301 | } |
| | 302 | |
| | 303 | blueI >>= 8; |
| | 304 | |
| | 305 | if(redI >= ONE_FIXED) |
| | 306 | redI = (ONE_FIXED - 1); |
| | 307 | |
| | 308 | redI >>=8; |
| | 309 | |
| | 310 | specular >>= 6; |
| | 311 | |
| | 312 | if (specular >= 255) |
| | 313 | specular = 255; |
| | 314 | |
| | 315 | /* KJL 12:41:54 05/10/98 - red/green swapped, whilst testing colours */ |
| | 316 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R = 0; |
| | 317 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B = blueI; |
| | 318 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G = redI/2; |
| | 319 | |
| | 320 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR = specular; |
| | 321 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG = specular; |
| | 322 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB = specular; |
| | 323 | |
| | 324 | ColourIntensityArray[vertexNumber].Stamp = ObjectCounter; |
| | 325 | } |
| | 326 | } |
| | 327 | |
| | 328 | static void VertexIntensity_Pred_SeeAliens(RENDERVERTEX *renderVertexPtr) |
| | 329 | { |
| | 330 | int vertexNumber = *VertexNumberPtr; |
| | 331 | |
| | 332 | if(ColourIntensityArray[vertexNumber].Stamp == ObjectCounter) |
| | 333 | { |
| | 334 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R; |
| | 335 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G; |
| | 336 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B; |
| | 337 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR; |
| | 338 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG; |
| | 339 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB; |
| | 340 | } |
| | 341 | else |
| | 342 | { |
| | 343 | int redI = 0,specular = 0; |
| | 344 | int blueI = ONE_FIXED/2; |
| | 345 | |
| | 346 | ColourIntensityArray[vertexNumber].Stamp = ObjectCounter; |
| | 347 | |
| | 348 | { |
| | 349 | VECTORCH *vertexPtr = ((VECTORCH *)Global_ShapePoints) + vertexNumber; |
| | 350 | VECTORCH vertexToLight; |
| | 351 | int i; |
| | 352 | |
| | 353 | for(i=0; i < NumLightSourcesForObject; i++) |
| | 354 | { |
| | 355 | LIGHTBLOCK *lptr = LightSourcesForObject[i]; |
| | 356 | |
| | 357 | if (lptr->LightFlags & LFlag_PreLitSource) |
| | 358 | continue; |
| | 359 | |
| | 360 | vertexToLight.vx = lptr->LocalLP.vx - vertexPtr->vx; |
| | 361 | vertexToLight.vy = lptr->LocalLP.vy - vertexPtr->vy; |
| | 362 | vertexToLight.vz = lptr->LocalLP.vz - vertexPtr->vz; |
| | 363 | |
| | 364 | int distanceToLight = Approximate3dMagnitude(&vertexToLight); |
| | 365 | |
| | 366 | if(distanceToLight < lptr->LightRange) |
| | 367 | { |
| | 368 | int idot = MUL_FIXED(lptr->LightRange-distanceToLight,lptr->BrightnessOverRange); |
| | 369 | |
| | 370 | redI += idot; |
| | 371 | |
| | 372 | if(lptr->LightFlags & LFlag_Electrical) |
| | 373 | specular += idot; |
| | 374 | } |
| | 375 | } |
| | 376 | } |
| | 377 | |
| | 378 | redI >>=11; |
| | 379 | |
| | 380 | if(redI > 255) |
| | 381 | redI = 255; |
| | 382 | |
| | 383 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G = redI; |
| | 384 | |
| | 385 | if (renderVertexPtr->Z > 5000) |
| | 386 | { |
| | 387 | int a = renderVertexPtr->Z - 5000; |
| | 388 | |
| | 389 | if (a > 4096) |
| | 390 | blueI = (blueI*4096)/a; |
| | 391 | } |
| | 392 | |
| | 393 | /* KJL 12:41:54 05/10/98 - red/green swapped, whilst testing colours */ |
| | 394 | blueI >>= 9; |
| | 395 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R = blueI; |
| | 396 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B = 0; |
| | 397 | |
| | 398 | specular >>=10; |
| | 399 | |
| | 400 | if(specular > 255) |
| | 401 | specular = 255; |
| | 402 | |
| | 403 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR = specular; |
| | 404 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG = specular; |
| | 405 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB = specular; |
| | 406 | } |
| | 407 | } |
| | 408 | |
| | 409 | static void VertexIntensity_Pred_SeePredatorTech(RENDERVERTEX *renderVertexPtr) |
| | 410 | { |
| | 411 | int vertexNumber = *VertexNumberPtr; |
| | 412 | |
| | 413 | if(ColourIntensityArray[vertexNumber].Stamp == ObjectCounter) |
| | 414 | { |
| | 415 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R; |
| | 416 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G; |
| | 417 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B; |
| | 418 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR; |
| | 419 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG; |
| | 420 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB; |
| | 421 | } |
| | 422 | else |
| | 423 | { |
| | 424 | int redI = 0; |
| | 425 | int blueI = ONE_FIXED-1; |
| | 426 | |
| | 427 | ColourIntensityArray[vertexNumber].Stamp = ObjectCounter; |
| | 428 | |
| | 429 | { |
| | 430 | VECTORCH *vertexPtr = ((VECTORCH *)Global_ShapePoints) + vertexNumber; |
| | 431 | VECTORCH vertexToLight; |
| | 432 | int i; |
| | 433 | |
| | 434 | for(i=0; i < NumLightSourcesForObject; i++) |
| | 435 | { |
| | 436 | LIGHTBLOCK *lptr = LightSourcesForObject[i]; |
| | 437 | |
| | 438 | if (lptr->LightFlags & LFlag_PreLitSource) |
| | 439 | continue; |
| | 440 | |
| | 441 | vertexToLight.vx = lptr->LocalLP.vx - vertexPtr->vx; |
| | 442 | vertexToLight.vy = lptr->LocalLP.vy - vertexPtr->vy; |
| | 443 | vertexToLight.vz = lptr->LocalLP.vz - vertexPtr->vz; |
| | 444 | |
| | 445 | int distanceToLight = Approximate3dMagnitude(&vertexToLight); |
| | 446 | |
| | 447 | if(distanceToLight < lptr->LightRange) |
| | 448 | redI += MUL_FIXED(lptr->LightRange - distanceToLight, lptr->BrightnessOverRange); |
| | 449 | } |
| | 450 | } |
| | 451 | |
| | 452 | if (renderVertexPtr->Z > 5000) |
| | 453 | { |
| | 454 | int a = (renderVertexPtr->Z - 5000); |
| | 455 | |
| | 456 | if (a > 4096) |
| | 457 | blueI = (blueI*4096)/a; |
| | 458 | } |
| | 459 | |
| | 460 | blueI >>=8; |
| | 461 | |
| | 462 | redI >>=9; |
| | 463 | |
| | 464 | if (redI > 255) |
| | 465 | redI = 255; |
| | 466 | |
| | 467 | /* KJL 12:41:54 05/10/98 - red/green swapped, whilst testing colours */ |
| | 468 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R = 255; |
| | 469 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B = 255; |
| | 470 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G = blueI; |
| | 471 | |
| | 472 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR = 255; |
| | 473 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG = redI; |
| | 474 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB = 255; |
| | 475 | } |
| | 476 | } |
| | 477 | |
| | 478 | static void VertexIntensity_ImageIntensifier(RENDERVERTEX *renderVertexPtr) |
| | 479 | { |
| | 480 | int vertexNumber = *VertexNumberPtr; |
| | 481 | |
| | 482 | if(ColourIntensityArray[vertexNumber].Stamp == ObjectCounter) |
| | 483 | { |
| | 484 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R; |
| | 485 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G; |
| | 486 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B; |
| | 487 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR; |
| | 488 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG; |
| | 489 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB; |
| | 490 | } |
| | 491 | else |
| | 492 | { |
| | 493 | int specular = 0; |
| | 494 | |
| | 495 | ColourIntensityArray[vertexNumber].Stamp = ObjectCounter; |
| | 496 | |
| | 497 | { |
| | 498 | VECTORCH *vertexNormalPtr = ((VECTORCH *)Global_ShapeVNormals) + vertexNumber; |
| | 499 | VECTORCH *vertexPtr = ((VECTORCH *)Global_ShapePoints) + vertexNumber; |
| | 500 | VECTORCH vertexToLight; |
| | 501 | int distanceToLight, i; |
| | 502 | |
| | 503 | for(i=0; i < NumLightSourcesForObject; i++) |
| | 504 | { |
| | 505 | LIGHTBLOCK *lptr = LightSourcesForObject[i]; |
| | 506 | |
| | 507 | vertexToLight.vx = lptr->LocalLP.vx - vertexPtr->vx; |
| | 508 | vertexToLight.vy = lptr->LocalLP.vy - vertexPtr->vy; |
| | 509 | vertexToLight.vz = lptr->LocalLP.vz - vertexPtr->vz; |
| | 510 | |
| | 511 | { |
| | 512 | int dx = abs(vertexToLight.vx); |
| | 513 | int dy = abs(vertexToLight.vy); |
| | 514 | int dz = abs(vertexToLight.vz); |
| | 515 | |
| | 516 | if (dx > dy) |
| | 517 | { |
| | 518 | if (dx > dz) |
| | 519 | distanceToLight = dx + ((dy+dz)>>2); |
| | 520 | else |
| | 521 | distanceToLight = dz + ((dy+dx)>>2); |
| | 522 | } |
| | 523 | else |
| | 524 | { |
| | 525 | if (dy > dz) |
| | 526 | distanceToLight = dy + ((dx+dz)>>2); |
| | 527 | else |
| | 528 | distanceToLight = dz + ((dx+dy)>>2); |
| | 529 | } |
| | 530 | } |
| | 531 | |
| | 532 | if(distanceToLight < lptr->LightRange) |
| | 533 | { |
| | 534 | int idot = MUL_FIXED(lptr->LightRange-distanceToLight, lptr->BrightnessOverRange); |
| | 535 | |
| | 536 | if(distanceToLight > 0) |
| | 537 | { |
| | 538 | int dotproduct = MUL_FIXED(vertexNormalPtr->vx,vertexToLight.vx) |
| | 539 | + MUL_FIXED(vertexNormalPtr->vy,vertexToLight.vy) |
| | 540 | + MUL_FIXED(vertexNormalPtr->vz,vertexToLight.vz); |
| | 541 | |
| | 542 | if(dotproduct > 0) |
| | 543 | idot = WideMulNarrowDiv(idot,dotproduct,distanceToLight) + idot/4; |
| | 544 | else |
| | 545 | idot /= 4; |
| | 546 | } |
| | 547 | |
| | 548 | if(idot < 0) |
| | 549 | { |
| | 550 | assert(idot >= 0); |
| | 551 | } |
| | 552 | |
| | 553 | specular += idot; |
| | 554 | } |
| | 555 | } |
| | 556 | } |
| | 557 | |
| | 558 | int greenI = 255; |
| | 559 | |
| | 560 | if (renderVertexPtr->Z > 5000) |
| | 561 | { |
| | 562 | int a = renderVertexPtr->Z - 5000; |
| | 563 | |
| | 564 | if (a > 4096) |
| | 565 | greenI = (greenI*4096)/a; |
| | 566 | } |
| | 567 | |
| | 568 | renderVertexPtr->G = greenI; |
| | 569 | ColourIntensityArray[vertexNumber].G = greenI; |
| | 570 | |
| | 571 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R = 0; |
| | 572 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B = 0; |
| | 573 | |
| | 574 | specular >>= 7; |
| | 575 | |
| | 576 | if (specular > 254) |
| | 577 | specular = 254; |
| | 578 | |
| | 579 | assert(specular >= 0 && specular <= 254); |
| | 580 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR = specular; |
| | 581 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG = specular; |
| | 582 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB = specular; |
| | 583 | } |
| | 584 | } |
| | 585 | |
| | 586 | static void VertexIntensity_Alien_Sense(RENDERVERTEX *renderVertexPtr) |
| | 587 | { |
| | 588 | int vertexNumber = *VertexNumberPtr; |
| | 589 | renderVertexPtr->SpecularR = renderVertexPtr->SpecularG = renderVertexPtr->SpecularB = 0; |
| | 590 | |
| | 591 | if(ColourIntensityArray[vertexNumber].Stamp == ObjectCounter) |
| | 592 | { |
| | 593 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R; |
| | 594 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G; |
| | 595 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B; |
| | 596 | } |
| | 597 | else |
| | 598 | { |
| | 599 | int intensity = 255; |
| | 600 | ColourIntensityArray[vertexNumber].Stamp = ObjectCounter; |
| | 601 | |
| | 602 | if (renderVertexPtr->Z > 5000) |
| | 603 | { |
| | 604 | int a = renderVertexPtr->Z - 5000; |
| | 605 | |
| | 606 | if (a > 1024) |
| | 607 | intensity = (intensity*1024)/a; |
| | 608 | } |
| | 609 | |
| | 610 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R = intensity; |
| | 611 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G = intensity; |
| | 612 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B = intensity; |
| | 613 | } |
| | 614 | } |
| | 615 | |
| | 616 | static void VertexIntensity_Standard_Opt(RENDERVERTEX *renderVertexPtr) |
| | 617 | { |
| | 618 | int vertexNumber = *VertexNumberPtr; |
| | 619 | |
| | 620 | if(ColourIntensityArray[vertexNumber].Stamp == ObjectCounter) |
| | 621 | { |
| | 622 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R; |
| | 623 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G; |
| | 624 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B; |
| | 625 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR; |
| | 626 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG; |
| | 627 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB; |
| | 628 | } |
| | 629 | else |
| | 630 | { |
| | 631 | int redI = 0,greenI = 0,blueI = 0; |
| | 632 | int specularR = 0,specularG = 0,specularB = 0; |
| | 633 | |
| | 634 | ColourIntensityArray[vertexNumber].Stamp = ObjectCounter; |
| | 635 | |
| | 636 | { |
| | 637 | VECTORCH *vertexNormalPtr = ((VECTORCH *)Global_ShapeVNormals) + vertexNumber; |
| | 638 | VECTORCH *vertexPtr = ((VECTORCH *)Global_ShapePoints) + vertexNumber; |
| | 639 | VECTORCH vertexToLight; |
| | 640 | int distanceToLight, i; |
| | 641 | |
| | 642 | if(Global_ShapeHeaderPtr->shapeflags & ShapeFlag_PreLit) |
| | 643 | { |
| | 644 | unsigned int packedI = Global_ShapeHeaderPtr->prelighting[vertexNumber]; |
| | 645 | blueI = (packedI & 255) * 257; |
| | 646 | |
| | 647 | packedI >>= 8; |
| | 648 | greenI = (packedI & 255) * 257; |
| | 649 | |
| | 650 | packedI >>= 8; |
| | 651 | redI = (packedI & 255) * 257; |
| | 652 | } |
| | 653 | |
| | 654 | for(i = 0; i < NumLightSourcesForObject; i++) |
| | 655 | { |
| | 656 | LIGHTBLOCK *lptr = LightSourcesForObject[i]; |
| | 657 | |
| | 658 | vertexToLight.vx = lptr->LocalLP.vx - vertexPtr->vx; |
| | 659 | vertexToLight.vy = lptr->LocalLP.vy - vertexPtr->vy; |
| | 660 | vertexToLight.vz = lptr->LocalLP.vz - vertexPtr->vz; |
| | 661 | |
| | 662 | { |
| | 663 | int dx = abs(vertexToLight.vx); |
| | 664 | int dy = abs(vertexToLight.vy); |
| | 665 | int dz = abs(vertexToLight.vz); |
| | 666 | |
| | 667 | if (dx > dy) |
| | 668 | { |
| | 669 | if (dx > dz) |
| | 670 | distanceToLight = dx + ((dy+dz)>>2); |
| | 671 | else |
| | 672 | distanceToLight = dz + ((dy+dx)>>2); |
| | 673 | } |
| | 674 | else |
| | 675 | { |
| | 676 | if (dy > dz) |
| | 677 | distanceToLight = dy + ((dx+dz)>>2); |
| | 678 | else |
| | 679 | distanceToLight = dz + ((dx+dy)>>2); |
| | 680 | } |
| | 681 | } |
| | 682 | |
| | 683 | if(distanceToLight < lptr->LightRange) |
| | 684 | { |
| | 685 | int idot = MUL_FIXED(lptr->LightRange-distanceToLight, lptr->BrightnessOverRange); |
| | 686 | |
| | 687 | if(distanceToLight > 0) |
| | 688 | { |
| | 689 | int dotproduct = MUL_FIXED(vertexNormalPtr->vx,vertexToLight.vx) |
| | 690 | + MUL_FIXED(vertexNormalPtr->vy,vertexToLight.vy) |
| | 691 | + MUL_FIXED(vertexNormalPtr->vz,vertexToLight.vz); |
| | 692 | |
| | 693 | if(dotproduct > 0) |
| | 694 | idot = (WideMulNarrowDiv(idot,dotproduct,distanceToLight)+idot/4)/2; |
| | 695 | else |
| | 696 | idot /= 8; |
| | 697 | } |
| | 698 | |
| | 699 | int r = MUL_FIXED(idot,lptr->RedScale); |
| | 700 | int g = MUL_FIXED(idot,lptr->GreenScale); |
| | 701 | int b = MUL_FIXED(idot,lptr->BlueScale); |
| | 702 | |
| | 703 | redI += r; |
| | 704 | greenI += g; |
| | 705 | blueI += b; |
| | 706 | |
| | 707 | if( !(lptr->LightFlags & LFlag_PreLitSource) && !(lptr->LightFlags & LFlag_NoSpecular) ) |
| | 708 | { |
| | 709 | specularR += r; |
| | 710 | specularG += g; |
| | 711 | specularB += b; |
| | 712 | } |
| | 713 | } |
| | 714 | } |
| | 715 | } |
| | 716 | |
| | 717 | if(Global_ODB_Ptr->SpecialFXFlags & SFXFLAG_ONFIRE) |
| | 718 | { |
| | 719 | specularR >>= 2; |
| | 720 | specularG >>= 2; |
| | 721 | specularB >>= 2; |
| | 722 | |
| | 723 | redI >>= 1; |
| | 724 | greenI >>= 1; |
| | 725 | blueI >>= 1; |
| | 726 | } |
| | 727 | |
| | 728 | /* Intensity for Textures */ |
| | 729 | redI >>= 8; |
| | 730 | |
| | 731 | if(redI > 255) |
| | 732 | redI = 255; |
| | 733 | |
| | 734 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R = redI; |
| | 735 | |
| | 736 | greenI >>= 8; |
| | 737 | |
| | 738 | if(greenI > 255) |
| | 739 | greenI = 255; |
| | 740 | |
| | 741 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G = greenI; |
| | 742 | |
| | 743 | blueI >>= 8; |
| | 744 | |
| | 745 | if(blueI > 255) |
| | 746 | blueI = 255; |
| | 747 | |
| | 748 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B = blueI; |
| | 749 | |
| | 750 | specularR >>= 10; |
| | 751 | |
| | 752 | if(specularR > 255) |
| | 753 | specularR = 255; |
| | 754 | |
| | 755 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR = specularR; |
| | 756 | |
| | 757 | specularG >>= 10; |
| | 758 | |
| | 759 | if(specularG > 255) |
| | 760 | specularG = 255; |
| | 761 | |
| | 762 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG = specularG; |
| | 763 | |
| | 764 | specularB >>= 10; |
| | 765 | |
| | 766 | if(specularB > 255) |
| | 767 | specularB = 255; |
| | 768 | |
| | 769 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB = specularB; |
| | 770 | } |
| | 771 | } |
| | 772 | |
| | 773 | static void VertexIntensity_FullBright(RENDERVERTEX *renderVertexPtr) |
| | 774 | { |
| | 775 | int vertexNumber = *VertexNumberPtr; |
| | 776 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R = 255; |
| | 777 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G = 255; |
| | 778 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B = 255; |
| | 779 | |
| | 780 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR = 0; |
| | 781 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG = 0; |
| | 782 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB = 0; |
| | 783 | } |
| | 784 | |
| | 785 | static void VertexIntensity_DiscoInferno(RENDERVERTEX *renderVertexPtr) |
| | 786 | { |
| | 787 | int vertexNumber = *VertexNumberPtr; |
| | 788 | |
| | 789 | if(ColourIntensityArray[vertexNumber].Stamp == ObjectCounter) |
| | 790 | { |
| | 791 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R; |
| | 792 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G; |
| | 793 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B; |
| | 794 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR; |
| | 795 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG; |
| | 796 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB; |
| | 797 | } |
| | 798 | else |
| | 799 | { |
| | 800 | int redI = 0,greenI = 0,blueI = 0; |
| | 801 | int specularR = 0,specularG = 0,specularB = 0; |
| | 802 | |
| | 803 | ColourIntensityArray[vertexNumber].Stamp = ObjectCounter; |
| | 804 | |
| | 805 | { |
| | 806 | VECTORCH *vertexNormalPtr = ((VECTORCH *)Global_ShapeVNormals) + vertexNumber; |
| | 807 | VECTORCH *vertexPtr = ((VECTORCH *)Global_ShapePoints) + vertexNumber; |
| | 808 | VECTORCH vertexToLight; |
| | 809 | int distanceToLight, i; |
| | 810 | |
| | 811 | if(Global_ShapeHeaderPtr->shapeflags & ShapeFlag_PreLit) |
| | 812 | { |
| | 813 | unsigned int packedI = Global_ShapeHeaderPtr->prelighting[vertexNumber]; |
| | 814 | blueI = (packedI & 255) * 257; |
| | 815 | |
| | 816 | packedI >>= 8; |
| | 817 | greenI = (packedI & 255) * 257; |
| | 818 | |
| | 819 | packedI >>= 8; |
| | 820 | redI = (packedI & 255) * 257; |
| | 821 | } |
| | 822 | |
| | 823 | for(i=0; i < NumLightSourcesForObject; i++) |
| | 824 | { |
| | 825 | LIGHTBLOCK *lptr = LightSourcesForObject[i]; |
| | 826 | |
| | 827 | vertexToLight.vx = lptr->LocalLP.vx - vertexPtr->vx; |
| | 828 | vertexToLight.vy = lptr->LocalLP.vy - vertexPtr->vy; |
| | 829 | vertexToLight.vz = lptr->LocalLP.vz - vertexPtr->vz; |
| | 830 | |
| | 831 | { |
| | 832 | int dx = abs(vertexToLight.vx); |
| | 833 | int dy = abs(vertexToLight.vy); |
| | 834 | int dz = abs(vertexToLight.vz); |
| | 835 | |
| | 836 | if (dx > dy) |
| | 837 | { |
| | 838 | if (dx > dz) |
| | 839 | distanceToLight = dx + ((dy+dz)>>2); |
| | 840 | else |
| | 841 | distanceToLight = dz + ((dy+dx)>>2); |
| | 842 | } |
| | 843 | else |
| | 844 | { |
| | 845 | if (dy > dz) |
| | 846 | distanceToLight = dy + ((dx+dz)>>2); |
| | 847 | else |
| | 848 | distanceToLight = dz + ((dx+dy)>>2); |
| | 849 | } |
| | 850 | } |
| | 851 | |
| | 852 | if(distanceToLight < lptr->LightRange) |
| | 853 | { |
| | 854 | int idot = MUL_FIXED(lptr->LightRange-distanceToLight, lptr->BrightnessOverRange); |
| | 855 | |
| | 856 | if(distanceToLight > 0) |
| | 857 | { |
| | 858 | int dotproduct = MUL_FIXED(vertexNormalPtr->vx,vertexToLight.vx) |
| | 859 | + MUL_FIXED(vertexNormalPtr->vy,vertexToLight.vy) |
| | 860 | + MUL_FIXED(vertexNormalPtr->vz,vertexToLight.vz); |
| | 861 | |
| | 862 | if(dotproduct > 0) |
| | 863 | idot = (WideMulNarrowDiv(idot,dotproduct,distanceToLight)+idot/4)/2; |
| | 864 | else |
| | 865 | idot /= 8; |
| | 866 | } |
| | 867 | |
| | 868 | int r = MUL_FIXED(idot,lptr->RedScale); |
| | 869 | int g = MUL_FIXED(idot,lptr->GreenScale); |
| | 870 | int b = MUL_FIXED(idot,lptr->BlueScale); |
| | 871 | |
| | 872 | redI += r; |
| | 873 | greenI += g; |
| | 874 | blueI += b; |
| | 875 | |
| | 876 | if(!(lptr->LightFlags & LFlag_PreLitSource) && !(lptr->LightFlags & LFlag_NoSpecular)) |
| | 877 | { |
| | 878 | specularR += r; |
| | 879 | specularG += g; |
| | 880 | specularB += b; |
| | 881 | } |
| | 882 | } |
| | 883 | } |
| | 884 | } |
| | 885 | |
| | 886 | if(Global_ODB_Ptr->SpecialFXFlags & SFXFLAG_ONFIRE) |
| | 887 | { |
| | 888 | specularR >>= 2; |
| | 889 | specularG >>= 2; |
| | 890 | specularB >>= 2; |
| | 891 | |
| | 892 | redI >>= 1; |
| | 893 | greenI >>= 1; |
| | 894 | blueI >>= 1; |
| | 895 | } |
| | 896 | |
| | 897 | { |
| | 898 | int i = redI + greenI + blueI; |
| | 899 | int si = specularR + specularG + specularB; |
| | 900 | |
| | 901 | VECTORCH vertex = *(((VECTORCH *)Global_ShapePoints)+vertexNumber); |
| | 902 | vertex.vx += Global_ODB_Ptr->ObWorld.vx; |
| | 903 | vertex.vy += Global_ODB_Ptr->ObWorld.vy; |
| | 904 | vertex.vz += Global_ODB_Ptr->ObWorld.vz; |
| | 905 | |
| | 906 | int r = GetSin((vertex.vx+CloakingPhase)&4095); |
| | 907 | r = MUL_FIXED(r,r); |
| | 908 | redI = MUL_FIXED(r,i); |
| | 909 | specularR = MUL_FIXED(r,si); |
| | 910 | |
| | 911 | int g = GetSin((vertex.vy+CloakingPhase/2)&4095); |
| | 912 | g = MUL_FIXED(g,g); |
| | 913 | greenI = MUL_FIXED(g,i); |
| | 914 | specularG = MUL_FIXED(g,si); |
| | 915 | |
| | 916 | int b = GetSin((vertex.vz+CloakingPhase*3)&4095); |
| | 917 | b = MUL_FIXED(b,b); |
| | 918 | blueI = MUL_FIXED(b,i); |
| | 919 | specularB = MUL_FIXED(b,si); |
| | 920 | } |
| | 921 | |
| | 922 | /* Intensity for Textures */ |
| | 923 | redI >>= 8; |
| | 924 | |
| | 925 | if(redI > 255) |
| | 926 | redI = 255; |
| | 927 | |
| | 928 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R = redI; |
| | 929 | |
| | 930 | greenI >>= 8; |
| | 931 | |
| | 932 | if(greenI > 255) |
| | 933 | greenI = 255; |
| | 934 | |
| | 935 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G = greenI; |
| | 936 | |
| | 937 | blueI >>= 8; |
| | 938 | |
| | 939 | if(blueI > 255) |
| | 940 | blueI = 255; |
| | 941 | |
| | 942 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B = blueI; |
| | 943 | |
| | 944 | specularR >>= 10; |
| | 945 | |
| | 946 | if(specularR > 255) |
| | 947 | specularR = 255; |
| | 948 | |
| | 949 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR = specularR; |
| | 950 | |
| | 951 | specularG >>= 10; |
| | 952 | |
| | 953 | if(specularG > 255) |
| | 954 | specularG = 255; |
| | 955 | |
| | 956 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG = specularG; |
| | 957 | |
| | 958 | specularB >>= 10; |
| | 959 | |
| | 960 | if(specularB > 255) |
| | 961 | specularB = 255; |
| | 962 | |
| | 963 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB = specularB; |
| | 964 | } |
| | 965 | } |
| | 966 | |
| | 967 | static void VertexIntensity_Underwater(RENDERVERTEX *renderVertexPtr) |
| | 968 | { |
| | 969 | int vertexNumber = *VertexNumberPtr; |
| | 970 | |
| | 971 | if(ColourIntensityArray[vertexNumber].Stamp == ObjectCounter) |
| | 972 | { |
| | 973 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R; |
| | 974 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G; |
| | 975 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B; |
| | 976 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR; |
| | 977 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG; |
| | 978 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB; |
| | 979 | } |
| | 980 | else |
| | 981 | { |
| | 982 | int redI = 0, greenI = 0, blueI = 0; |
| | 983 | int specularR = 0,specularG = 0,specularB = 0; |
| | 984 | |
| | 985 | ColourIntensityArray[vertexNumber].Stamp = ObjectCounter; |
| | 986 | |
| | 987 | { |
| | 988 | VECTORCH *vertexNormalPtr = ((VECTORCH *)Global_ShapeVNormals) + vertexNumber; |
| | 989 | VECTORCH *vertexPtr = ((VECTORCH *)Global_ShapePoints) + vertexNumber; |
| | 990 | VECTORCH vertexToLight; |
| | 991 | int distanceToLight, i; |
| | 992 | |
| | 993 | if(Global_ShapeHeaderPtr->shapeflags & ShapeFlag_PreLit) |
| | 994 | { |
| | 995 | unsigned int packedI = Global_ShapeHeaderPtr->prelighting[vertexNumber]; |
| | 996 | blueI = (packedI & 255) * 257; |
| | 997 | |
| | 998 | packedI >>= 8; |
| | 999 | greenI = (packedI & 255) * 257; |
| | 1000 | |
| | 1001 | packedI >>= 8; |
| | 1002 | redI = (packedI & 255) * 257; |
| | 1003 | } |
| | 1004 | |
| | 1005 | for(i=0; i < NumLightSourcesForObject; i++) |
| | 1006 | { |
| | 1007 | LIGHTBLOCK *lptr = LightSourcesForObject[i]; |
| | 1008 | |
| | 1009 | vertexToLight.vx = lptr->LocalLP.vx - vertexPtr->vx; |
| | 1010 | vertexToLight.vy = lptr->LocalLP.vy - vertexPtr->vy; |
| | 1011 | vertexToLight.vz = lptr->LocalLP.vz - vertexPtr->vz; |
| | 1012 | |
| | 1013 | { |
| | 1014 | int dx = abs(vertexToLight.vx); |
| | 1015 | int dy = abs(vertexToLight.vy); |
| | 1016 | int dz = abs(vertexToLight.vz); |
| | 1017 | |
| | 1018 | if (dx > dy) |
| | 1019 | { |
| | 1020 | if (dx > dz) |
| | 1021 | distanceToLight = dx + ((dy+dz)>>2); |
| | 1022 | else |
| | 1023 | distanceToLight = dz + ((dy+dx)>>2); |
| | 1024 | } |
| | 1025 | else |
| | 1026 | { |
| | 1027 | if (dy > dz) |
| | 1028 | distanceToLight = dy + ((dx+dz)>>2); |
| | 1029 | else |
| | 1030 | distanceToLight = dz + ((dx+dy)>>2); |
| | 1031 | } |
| | 1032 | } |
| | 1033 | |
| | 1034 | if(distanceToLight < lptr->LightRange) |
| | 1035 | { |
| | 1036 | int idot = MUL_FIXED(lptr->LightRange-distanceToLight,lptr->BrightnessOverRange); |
| | 1037 | |
| | 1038 | if(distanceToLight > 0) |
| | 1039 | { |
| | 1040 | int dotproduct = MUL_FIXED(vertexNormalPtr->vx,vertexToLight.vx) |
| | 1041 | + MUL_FIXED(vertexNormalPtr->vy,vertexToLight.vy) |
| | 1042 | + MUL_FIXED(vertexNormalPtr->vz,vertexToLight.vz); |
| | 1043 | |
| | 1044 | if(dotproduct > 0) |
| | 1045 | idot = (WideMulNarrowDiv(idot,dotproduct,distanceToLight)+idot/4)/2; |
| | 1046 | else |
| | 1047 | idot /= 8; |
| | 1048 | } |
| | 1049 | |
| | 1050 | int r = MUL_FIXED(idot,lptr->RedScale); |
| | 1051 | int g = MUL_FIXED(idot,lptr->GreenScale); |
| | 1052 | int b = MUL_FIXED(idot,lptr->BlueScale); |
| | 1053 | |
| | 1054 | redI += r; |
| | 1055 | greenI += g; |
| | 1056 | blueI += b; |
| | 1057 | |
| | 1058 | if(!(lptr->LightFlags & LFlag_PreLitSource) && !(lptr->LightFlags & LFlag_NoSpecular) ) |
| | 1059 | { |
| | 1060 | specularR += r; |
| | 1061 | specularG += g; |
| | 1062 | specularB += b; |
| | 1063 | } |
| | 1064 | } |
| | 1065 | } |
| | 1066 | } |
| | 1067 | |
| | 1068 | if(Global_ODB_Ptr->SpecialFXFlags & SFXFLAG_ONFIRE) |
| | 1069 | { |
| | 1070 | specularR >>= 2; |
| | 1071 | specularG >>= 2; |
| | 1072 | specularB >>= 2; |
| | 1073 | |
| | 1074 | redI >>= 1; |
| | 1075 | greenI >>= 1; |
| | 1076 | blueI >>= 1; |
| | 1077 | } |
| | 1078 | |
| | 1079 | if (specularB < renderVertexPtr->Z*4) |
| | 1080 | specularB = renderVertexPtr->Z*4; |
| | 1081 | |
| | 1082 | /* Intensity for Textures */ |
| | 1083 | redI >>= 8; |
| | 1084 | |
| | 1085 | if(redI > 255) |
| | 1086 | redI = 255; |
| | 1087 | |
| | 1088 | renderVertexPtr->R = ColourIntensityArray[vertexNumber].R = redI; |
| | 1089 | |
| | 1090 | greenI >>= 8; |
| | 1091 | |
| | 1092 | if(greenI > 255) |
| | 1093 | greenI = 255; |
| | 1094 | |
| | 1095 | renderVertexPtr->G = ColourIntensityArray[vertexNumber].G = greenI; |
| | 1096 | |
| | 1097 | blueI >>= 8; |
| | 1098 | |
| | 1099 | if(blueI > 255) |
| | 1100 | blueI = 255; |
| | 1101 | |
| | 1102 | renderVertexPtr->B = ColourIntensityArray[vertexNumber].B = blueI; |
| | 1103 | |
| | 1104 | specularR >>= 10; |
| | 1105 | |
| | 1106 | if(specularR > 255) |
| | 1107 | specularR = 255; |
| | 1108 | |
| | 1109 | renderVertexPtr->SpecularR = ColourIntensityArray[vertexNumber].SpecularR = specularR; |
| | 1110 | |
| | 1111 | specularG >>= 10; |
| | 1112 | |
| | 1113 | if(specularG > 255) |
| | 1114 | specularG = 255; |
| | 1115 | |
| | 1116 | renderVertexPtr->SpecularG = ColourIntensityArray[vertexNumber].SpecularG = specularG; |
| | 1117 | |
| | 1118 | specularB >>= 10; |
| | 1119 | |
| | 1120 | if(specularB > 255) |
| | 1121 | specularB = 255; |
| | 1122 | |
| | 1123 | renderVertexPtr->SpecularB = ColourIntensityArray[vertexNumber].SpecularB = specularB; |
| | 1124 | } |
| | 1125 | } |
| | 1126 | |
| | 1127 | static void PredatorThermalVisionPolygon_Construct(POLYHEADER *polyPtr) |
| | 1128 | { |
| | 1129 | RENDERVERTEX *renderVerticesPtr = VerticesBuffer; |
| | 1130 | int i = RenderPolygon.NumberOfVertices; |
| | 1131 | |
| | 1132 | VertexNumberPtr = &polyPtr->Poly1stPt; |
| | 1133 | |
| | 1134 | do |
| | 1135 | { |
| | 1136 | VECTORCH *vertexPtr = &RotatedPts[*VertexNumberPtr]; |
| | 1137 | renderVerticesPtr->X = vertexPtr->vx; |
| | 1138 | renderVerticesPtr->Y = vertexPtr->vy; |
| | 1139 | renderVerticesPtr->Z = vertexPtr->vz; |
| | 1140 | |
| | 1141 | { |
| | 1142 | int alpha; |
| | 1143 | if (Global_ODB_Ptr->SpecialFXFlags & SFXFLAG_ISAFFECTEDBYHEAT) |
| | 1144 | { |
| | 1145 | int distanceFromHeatSource = 100000; |
| | 1146 | int sourceNumber = NumberOfHeatSources; |
| | 1147 | |
| | 1148 | while(sourceNumber--) |
| | 1149 | { |
| | 1150 | VECTORCH mag; |
| | 1151 | mag.vx = vertexPtr->vx - HeatSourceList[sourceNumber].Position.vx; |
| | 1152 | mag.vy = vertexPtr->vy - HeatSourceList[sourceNumber].Position.vy; |
| | 1153 | mag.vz = vertexPtr->vz - HeatSourceList[sourceNumber].Position.vz; |
| | 1154 | |
| | 1155 | int m = Approximate3dMagnitude(&mag) * 64; |
| | 1156 | |
| | 1157 | if(m < distanceFromHeatSource) |
| | 1158 | distanceFromHeatSource = m; |
| | 1159 | } |
| | 1160 | |
| | 1161 | alpha = distanceFromHeatSource + (GetSin(CloakingPhase & 4095) >> 3); |
| | 1162 | |
| | 1163 | if (alpha > 65536) |
| | 1164 | alpha = 65536; |
| | 1165 | } |
| | 1166 | else |
| | 1167 | { |
| | 1168 | alpha = 65536; |
| | 1169 | } |
| | 1170 | |
| | 1171 | { |
| | 1172 | int brightness = MUL_FIXED(MUL_FIXED(alpha, alpha), 1275); |
| | 1173 | |
| | 1174 | if (brightness < 256) |
| | 1175 | { |
| | 1176 | renderVerticesPtr->R = 255; |
| | 1177 | renderVerticesPtr->G = brightness; |
| | 1178 | renderVerticesPtr->B = 0; |
| | 1179 | } |
| | 1180 | else if (brightness < 255 + 256) |
| | 1181 | { |
| | 1182 | int b = brightness - 255; |
| | 1183 | renderVerticesPtr->R = (255-b); |
| | 1184 | renderVerticesPtr->G = 255; |
| | 1185 | renderVerticesPtr->B = 0; |
| | 1186 | } |
| | 1187 | else if (brightness < 255 * 2 + 256) |
| | 1188 | { |
| | 1189 | int b = brightness-255*2; |
| | 1190 | renderVerticesPtr->R = 0; |
| | 1191 | renderVerticesPtr->G = 255; |
| | 1192 | renderVerticesPtr->B = b; |
| | 1193 | } |
| | 1194 | else if (brightness < 255 * 3 + 256) |
| | 1195 | { |
| | 1196 | int b = brightness-255*3; |
| | 1197 | renderVerticesPtr->R = 0; |
| | 1198 | renderVerticesPtr->G = 255-b; |
| | 1199 | renderVerticesPtr->B = 255; |
| | 1200 | } |
| | 1201 | else |
| | 1202 | { |
| | 1203 | int b = brightness-255*4; |
| | 1204 | renderVerticesPtr->R = 0; |
| | 1205 | renderVerticesPtr->G = 0; |
| | 1206 | renderVerticesPtr->B = 255-b/2; |
| | 1207 | } |
| | 1208 | } |
| | 1209 | } |
| | 1210 | |
| | 1211 | renderVerticesPtr++; |
| | 1212 | VertexNumberPtr++; |
| | 1213 | |
| | 1214 | } while(--i); |
| | 1215 | } |
| | 1216 | |
| | 1217 | static int PolygonWithinFrustrum(POLYHEADER *polyPtr) |
| | 1218 | { |
| | 1219 | int* vertexNumberPtr = &polyPtr->Poly1stPt; |
| | 1220 | |
| | 1221 | if (polyPtr->PolyFlags & iflag_notvis) |
| | 1222 | return 0; |
| | 1223 | |
| | 1224 | char inFrustrumFlag = 0; |
| | 1225 | char noClippingFlag = INSIDE_FRUSTRUM; |
| | 1226 | RenderPolygon.NumberOfVertices = 0; |
| | 1227 | |
| | 1228 | while(*vertexNumberPtr != -1) |
| | 1229 | { |
| | 1230 | int vertexNumber = *vertexNumberPtr++; |
| | 1231 | |
| | 1232 | inFrustrumFlag |= FrustrumFlagForVertex[vertexNumber]; |
| | 1233 | noClippingFlag &= FrustrumFlagForVertex[vertexNumber]; |
| | 1234 | |
| | 1235 | /* count the number of points in the polygon; this is used for all the loops that follow */ |
| | 1236 | RenderPolygon.NumberOfVertices++; |
| | 1237 | } |
| | 1238 | |
| | 1239 | if (inFrustrumFlag != INSIDE_FRUSTRUM) |
| | 1240 | return 0; |
| | 1241 | |
| | 1242 | /* at this point we know that the poly is inside the view frustrum */ |
| | 1243 | |
| | 1244 | /* if not a sprite, test direction of poly */ |
| | 1245 | if (!(polyPtr->PolyFlags & iflag_no_bfc)) |
| | 1246 | { |
| | 1247 | VECTORCH pop; |
| | 1248 | VECTORCH *normalPtr = (VECTORCH*)(Global_ShapeNormals + polyPtr->PolyNormalIndex); |
| | 1249 | |
| | 1250 | if(Global_ODB_Ptr->ObMorphCtrl) |
| | 1251 | { |
| | 1252 | VECTORCH *shape1PointsPtr; |
| | 1253 | VECTORCH *shape2PointsPtr; |
| | 1254 | |
| | 1255 | /* Set up the morph data */ |
| | 1256 | GetMorphDisplay(&MorphDisplay, Global_ODB_Ptr); |
| | 1257 | |
| | 1258 | struct shapeheader *shape1Ptr = MorphDisplay.md_sptr1; |
| | 1259 | |
| | 1260 | switch(MorphDisplay.md_lerp) |
| | 1261 | { |
| | 1262 | case 0x0000: |
| | 1263 | { |
| | 1264 | shape1PointsPtr = (VECTORCH *)*shape1Ptr->points; |
| | 1265 | pop = shape1PointsPtr[polyPtr->Poly1stPt]; |
| | 1266 | } |
| | 1267 | break; |
| | 1268 | case 0xffff: |
| | 1269 | { |
| | 1270 | struct shapeheader* shape2Ptr = MorphDisplay.md_sptr2; |
| | 1271 | |
| | 1272 | shape2PointsPtr = (VECTORCH *)*shape2Ptr->points; |
| | 1273 | pop = shape2PointsPtr[polyPtr->Poly1stPt]; |
| | 1274 | } |
| | 1275 | break; |
| | 1276 | default: |
| | 1277 | { |
| | 1278 | struct shapeheader* shape2Ptr = MorphDisplay.md_sptr2; |
| | 1279 | |
| | 1280 | shape1PointsPtr = (VECTORCH *)(*shape1Ptr->points); |
| | 1281 | shape2PointsPtr = (VECTORCH *)(*shape2Ptr->points); |
| | 1282 | |
| | 1283 | { |
| | 1284 | VECTORCH vertex1 = shape1PointsPtr[polyPtr->Poly1stPt]; |
| | 1285 | VECTORCH vertex2 = shape2PointsPtr[polyPtr->Poly1stPt]; |
| | 1286 | |
| | 1287 | if( (vertex1.vx == vertex2.vx && vertex1.vy == vertex2.vy && vertex1.vz == vertex2.vz) ) |
| | 1288 | { |
| | 1289 | pop = vertex1; |
| | 1290 | } |
| | 1291 | else |
| | 1292 | { |
| | 1293 | /* KJL 15:27:20 05/22/97 - I've changed this to speed things up, If a vertex |
| | 1294 | component has a magnitude greater than 32768 things will go wrong. */ |
| | 1295 | pop.vx = vertex1.vx + (((vertex2.vx-vertex1.vx)*MorphDisplay.md_lerp)>>16); |
| | 1296 | pop.vy = vertex1.vy + (((vertex2.vy-vertex1.vy)*MorphDisplay.md_lerp)>>16); |
| | 1297 | pop.vz = vertex1.vz + (((vertex2.vz-vertex1.vz)*MorphDisplay.md_lerp)>>16); |
| | 1298 | } |
| | 1299 | } |
| | 1300 | } |
| | 1301 | } |
| | 1302 | } |
| | 1303 | else |
| | 1304 | { |
| | 1305 | /* Get the 1st polygon point as the POP */ |
| | 1306 | VECTORCH *pointsArray = (VECTORCH*)(Global_ShapePoints); |
| | 1307 | pop = pointsArray[polyPtr->Poly1stPt]; |
| | 1308 | } |
| | 1309 | |
| | 1310 | pop.vx -= LocalView.vx; |
| | 1311 | pop.vy -= LocalView.vy; |
| | 1312 | pop.vz -= LocalView.vz; |
| | 1313 | |
| | 1314 | if (DotProduct(&pop, normalPtr) > 0) |
| | 1315 | return 0; |
| | 1316 | } |
| | 1317 | |
| | 1318 | /* yes, we need to draw poly */ |
| | 1319 | return (noClippingFlag == INSIDE_FRUSTRUM) ? 2 : 1; |
| | 1320 | } |
| | 1321 | |
| | 1322 | static void PredatorThermalVision_ShapePipeline(struct shapeheader* shapePtr) |
| | 1323 | { |
| | 1324 | int numitems = shapePtr->numitems; |
| | 1325 | int** itemArrayPtr = shapePtr->items; |
| | 1326 | |
| | 1327 | assert(numitems); |
| | 1328 | |
| | 1329 | do |
| | 1330 | { |
| | 1331 | POLYHEADER *polyPtr = (POLYHEADER*) (*itemArrayPtr++); |
| | 1332 | |
| | 1333 | int pif = PolygonWithinFrustrum(polyPtr); |
| | 1334 | |
| | 1335 | if (pif) |
| | 1336 | { |
| | 1337 | PredatorThermalVisionPolygon_Construct(polyPtr); |
| | 1338 | |
| | 1339 | if (pif != 2) |
| | 1340 | { |
| | 1341 | GouraudPolygon_ClipWithZ(); |
| | 1342 | |
| | 1343 | if(RenderPolygon.NumberOfVertices < 3) |
| | 1344 | continue; |
| | 1345 | |
| | 1346 | GouraudPolygon_ClipWithNegativeX(); |
| | 1347 | |
| | 1348 | if(RenderPolygon.NumberOfVertices < 3) |
| | 1349 | continue; |
| | 1350 | |
| | 1351 | GouraudPolygon_ClipWithPositiveY(); |
| | 1352 | |
| | 1353 | if(RenderPolygon.NumberOfVertices < 3) |
| | 1354 | continue; |
| | 1355 | |
| | 1356 | GouraudPolygon_ClipWithNegativeY(); |
| | 1357 | |
| | 1358 | if(RenderPolygon.NumberOfVertices < 3) |
| | 1359 | continue; |
| | 1360 | |
| | 1361 | GouraudPolygon_ClipWithPositiveX(); |
| | 1362 | |
| | 1363 | if(RenderPolygon.NumberOfVertices < 3) |
| | 1364 | continue; |
| | 1365 | |
| | 1366 | PredatorThermalVisionPolygon_Output(RenderPolygon.Vertices); |
| | 1367 | } |
| | 1368 | else |
| | 1369 | { |
| | 1370 | PredatorThermalVisionPolygon_Output(VerticesBuffer); |
| | 1371 | } |
| | 1372 | } |
| | 1373 | |
| | 1374 | } while(--numitems); |
| | 1375 | } |
| | 1376 | |
| | 1377 | /* |
| | 1378 | WideMul2NarrowDiv |
| | 1379 | |
| | 1380 | This function takes two pairs of integers, adds their 64-bit products |
| | 1381 | together, divides the summed product with another integer and then returns |
| | 1382 | the result of that divide, which is also an integer. |
| | 1383 | |
| | 1384 | */ |
| | 1385 | |
| | 1386 | static int WideMul2NarrowDiv(int a, int b, int c, int d) |
| | 1387 | { |
| | 1388 | int64_t a_b = (int64_t)a * (int64_t)b; |
| | 1389 | int64_t c_d = (int64_t)c * (int64_t)d; |
| | 1390 | |
| | 1391 | return (a_b + c_d)/c; |
| | 1392 | } |
| | 1393 | |
| | 1394 | static void CreateTxAnimUVArray(intptr_t * txa_data, int* uv_array, int* shapeitemptr) |
| | 1395 | { |
| | 1396 | int Orient, Scale; |
| | 1397 | int OrientX, OrientY; |
| | 1398 | int ScaleX, ScaleY; |
| | 1399 | POLYHEADER *pheader = (POLYHEADER*) shapeitemptr; |
| | 1400 | |
| | 1401 | /* The sequence will have been copied across by the control block */ |
| | 1402 | |
| | 1403 | int sequence = *txa_data++; |
| | 1404 | TXANIMHEADER **txah_ptr = (TXANIMHEADER **) txa_data; |
| | 1405 | TXANIMHEADER *txah = txah_ptr[sequence]; |
| | 1406 | TXANIMFRAME *txaf = txah->txa_framedata; |
| | 1407 | |
| | 1408 | /* Because the current frame can be set from outside, clamp it first */ |
| | 1409 | |
| | 1410 | if(txah->txa_currentframe < 0) |
| | 1411 | txah->txa_currentframe = 0; |
| | 1412 | |
| | 1413 | if(txah->txa_currentframe >= txah->txa_maxframe) |
| | 1414 | txah->txa_currentframe = txah->txa_maxframe - 1; |
| | 1415 | |
| | 1416 | /* Frame # */ |
| | 1417 | |
| | 1418 | int CurrentFrame = txah->txa_currentframe >> 16; |
| | 1419 | int Alpha = txah->txa_currentframe - (CurrentFrame << 16); |
| | 1420 | int OneMinusAlpha = ONE_FIXED - Alpha; |
| | 1421 | |
| | 1422 | /* Start and End Frame */ |
| | 1423 | |
| | 1424 | int NextFrame = CurrentFrame + 1; |
| | 1425 | |
| | 1426 | if(NextFrame >= txah->txa_numframes) |
| | 1427 | NextFrame = 0; |
| | 1428 | |
| | 1429 | TXANIMFRAME *txaf0 = &txaf[CurrentFrame]; |
| | 1430 | TXANIMFRAME *txaf1 = &txaf[NextFrame]; |
| | 1431 | |
| | 1432 | /* |
| | 1433 | |
| | 1434 | Write the image index back to the item by overwriting the shape data. |
| | 1435 | This is not elegant but it is one of the kind of things you expect to |
| | 1436 | have happen when a major new feature is retro-fitted to a system. |
| | 1437 | |
| | 1438 | */ |
| | 1439 | |
| | 1440 | #define ClrTxIndex 0xffff0000 /* AND with this to clear the low 16-bits */ |
| | 1441 | |
| | 1442 | pheader->PolyColour &= ClrTxIndex; |
| | 1443 | pheader->PolyColour |= txaf0->txf_image; |
| | 1444 | |
| | 1445 | int* txaf0_uv = txaf0->txf_uvdata; |
| | 1446 | int* txaf1_uv = txaf1->txf_uvdata; |
| | 1447 | |
| | 1448 | // Calculate UVs |
| | 1449 | |
| | 1450 | int *iptr = uv_array; |
| | 1451 | |
| | 1452 | if(txah->txa_flags & txa_flag_interpolate_uvs) |
| | 1453 | { |
| | 1454 | int i = txaf0->txf_numuvs; |
| | 1455 | |
| | 1456 | for(; i; i--) |
| | 1457 | { |
| | 1458 | iptr[0] = MUL_FIXED(txaf0_uv[0], OneMinusAlpha) + MUL_FIXED(txaf1_uv[0], Alpha); |
| | 1459 | |
| | 1460 | iptr[1] = MUL_FIXED(txaf0_uv[1], OneMinusAlpha) + MUL_FIXED(txaf1_uv[1], Alpha); |
| | 1461 | |
| | 1462 | // printf("%d, %d\n", iptr[0] >> 16, iptr[1] >> 16); |
| | 1463 | |
| | 1464 | txaf0_uv += 2; |
| | 1465 | txaf1_uv += 2; |
| | 1466 | iptr += 2; |
| | 1467 | } |
| | 1468 | } |
| | 1469 | else |
| | 1470 | { |
| | 1471 | int i = txaf0->txf_numuvs; |
| | 1472 | |
| | 1473 | for(; i; i--) |
| | 1474 | { |
| | 1475 | iptr[0] = txaf0_uv[0]; |
| | 1476 | iptr[1] = txaf0_uv[1]; |
| | 1477 | |
| | 1478 | // printf("%d, %d\n", iptr[0] >> 16, iptr[1] >> 16); |
| | 1479 | |
| | 1480 | txaf0_uv += 2; |
| | 1481 | iptr += 2; |
| | 1482 | } |
| | 1483 | } |
| | 1484 | |
| | 1485 | // Interpolate Orient and Scale |
| | 1486 | |
| | 1487 | int o1 = txaf0->txf_orient; |
| | 1488 | int o2 = txaf1->txf_orient; |
| | 1489 | |
| | 1490 | if(o1 == o2) |
| | 1491 | { |
| | 1492 | Orient = o1; |
| | 1493 | } |
| | 1494 | else |
| | 1495 | { |
| | 1496 | int od = o1 - o2; |
| | 1497 | |
| | 1498 | if(od < 0) |
| | 1499 | od = -od; |
| | 1500 | |
| | 1501 | if(od >= deg180) |
| | 1502 | { |
| | 1503 | o1 <<= (32 - 12); |
| | 1504 | o1 >>= (32 - 12); |
| | 1505 | o2 <<= (32 - 12); |
| | 1506 | o2 >>= (32 - 12); |
| | 1507 | } |
| | 1508 | |
| | 1509 | Orient = MUL_FIXED(o1, OneMinusAlpha) + MUL_FIXED(o2, Alpha); |
| | 1510 | Orient &= wrap360; |
| | 1511 | } |
| | 1512 | |
| | 1513 | if(txaf0->txf_scale == txaf1->txf_scale) |
| | 1514 | Scale = txaf0->txf_scale; |
| | 1515 | else |
| | 1516 | Scale = WideMul2NarrowDiv(txaf0->txf_scale, OneMinusAlpha, txaf1->txf_scale, Alpha); |
| | 1517 | |
| | 1518 | // Interpolate Orient and Scale Origins |
| | 1519 | |
| | 1520 | if(txaf0->txf_orientx == txaf1->txf_orientx) |
| | 1521 | OrientX = txaf0->txf_orientx; |
| | 1522 | else |
| | 1523 | OrientX = MUL_FIXED(txaf0->txf_orientx, OneMinusAlpha) + MUL_FIXED(txaf1->txf_orientx, Alpha); |
| | 1524 | |
| | 1525 | if(txaf0->txf_orienty == txaf1->txf_orienty) |
| | 1526 | OrientY = txaf0->txf_orienty; |
| | 1527 | else |
| | 1528 | OrientY = MUL_FIXED(txaf0->txf_orienty, OneMinusAlpha) + MUL_FIXED(txaf1->txf_orienty, Alpha); |
| | 1529 | |
| | 1530 | if(txaf0->txf_scalex == txaf1->txf_scalex) |
| | 1531 | ScaleX = txaf0->txf_scalex; |
| | 1532 | else |
| | 1533 | ScaleX = MUL_FIXED(txaf0->txf_scalex, OneMinusAlpha) + MUL_FIXED(txaf1->txf_scalex, Alpha); |
| | 1534 | |
| | 1535 | if(txaf0->txf_scaley == txaf1->txf_scaley) |
| | 1536 | ScaleY = txaf0->txf_scaley; |
| | 1537 | else |
| | 1538 | ScaleY = MUL_FIXED(txaf0->txf_scaley, OneMinusAlpha) + MUL_FIXED(txaf1->txf_scaley, Alpha); |
| | 1539 | |
| | 1540 | /* |
| | 1541 | printf("Alpha = %d\n", Alpha); |
| | 1542 | printf("OneMinusAlpha = %d\n", OneMinusAlpha); |
| | 1543 | printf("Orient = %d\n", Orient); |
| | 1544 | printf("txaf0->txf_scale = %d\n", txaf0->txf_scale); |
| | 1545 | printf("txaf1->txf_scale = %d\n", txaf1->txf_scale); |
| | 1546 | printf("Scale = %d\n", Scale); |
| | 1547 | */ |
| | 1548 | |
| | 1549 | #if 1 |
| | 1550 | // Rotate UV Array |
| | 1551 | |
| | 1552 | if(Orient) |
| | 1553 | { |
| | 1554 | int i = txaf0->txf_numuvs; |
| | 1555 | int sin = GetSin(Orient); |
| | 1556 | int cos = GetCos(Orient); |
| | 1557 | iptr = uv_array; |
| | 1558 | |
| | 1559 | for(; i; i--) |
| | 1560 | { |
| | 1561 | int x = iptr[0] - OrientX; |
| | 1562 | int y = iptr[1] - OrientY; |
| | 1563 | int x1 = MUL_FIXED(x, cos) - MUL_FIXED(y, sin); |
| | 1564 | int y1 = MUL_FIXED(x, sin) + MUL_FIXED(y, cos); |
| | 1565 | |
| | 1566 | iptr[0] = x1 + OrientX; |
| | 1567 | iptr[1] = y1 + OrientY; |
| | 1568 | |
| | 1569 | iptr += 2; |
| | 1570 | } |
| | 1571 | } |
| | 1572 | |
| | 1573 | // Scale UV Array |
| | 1574 | |
| | 1575 | if(Scale != ONE_FIXED) |
| | 1576 | { |
| | 1577 | int i = txaf0->txf_numuvs; |
| | 1578 | iptr = uv_array; |
| | 1579 | |
| | 1580 | for(; i; i--) |
| | 1581 | { |
| | 1582 | int x = iptr[0] - ScaleX; |
| | 1583 | int y = iptr[1] - ScaleY; |
| | 1584 | |
| | 1585 | x = MUL_FIXED(x, Scale); |
| | 1586 | y = MUL_FIXED(y, Scale); |
| | 1587 | |
| | 1588 | iptr[0] = x + ScaleX; |
| | 1589 | iptr[1] = y + ScaleY; |
| | 1590 | |
| | 1591 | iptr += 2; |
| | 1592 | } |
| | 1593 | } |
| | 1594 | #endif |
| | 1595 | |
| | 1596 | /* |
| | 1597 | printf("Current Frame = %d\n", txah->txa_currentframe); |
| | 1598 | printf("Current Frame = %d\n", CurrentFrame); |
| | 1599 | printf("Next Frame = %d\n", NextFrame); |
| | 1600 | printf("Alpha = %d\n", Alpha); |
| | 1601 | */ |
| | 1602 | |
| | 1603 | } |
| | 1604 | |
| | 1605 | static void PredatorSeeAliensVisionPolygon_Construct(POLYHEADER *polyPtr) |
| | 1606 | { |
| | 1607 | int alpha; |
| | 1608 | // get ptr to uv coords for this polygon |
| | 1609 | int* texture_defn_ptr = Global_ShapeHeaderPtr->sh_textures[(polyPtr->PolyColour >> TxDefn)]; |
| | 1610 | RENDERVERTEX* renderVerticesPtr = VerticesBuffer; |
| | 1611 | int i = RenderPolygon.NumberOfVertices; |
| | 1612 | |
| | 1613 | VertexNumberPtr = &polyPtr->Poly1stPt; |
| | 1614 | |
| | 1615 | if(polyPtr->PolyFlags & iflag_txanim) |
| | 1616 | { |
| | 1617 | // Create the UV array |
| | 1618 | int uv_array[18]; |
| | 1619 | CreateTxAnimUVArray((intptr_t*)texture_defn_ptr, uv_array, (int*)polyPtr); |
| | 1620 | texture_defn_ptr = uv_array; |
| | 1621 | } |
| | 1622 | |
| | 1623 | if( (Global_ODB_Ptr->SpecialFXFlags & SFXFLAG_MELTINGINTOGROUND) && (Global_ODB_Ptr->ObFlags2 < ONE_FIXED) ) |
| | 1624 | { |
| | 1625 | alpha = Global_ODB_Ptr->ObFlags2 >> 8; |
| | 1626 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL; |
| | 1627 | } |
| | 1628 | else |
| | 1629 | { |
| | 1630 | alpha = 0; |
| | 1631 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_OFF; |
| | 1632 | } |
| | 1633 | |
| | 1634 | do |
| | 1635 | { |
| | 1636 | VECTORCH *vertexPtr = &RotatedPts[*VertexNumberPtr]; |
| | 1637 | |
| | 1638 | if(polyPtr->PolyFlags & iflag_txanim) |
| | 1639 | { |
| | 1640 | renderVerticesPtr->U = texture_defn_ptr[0]; |
| | 1641 | renderVerticesPtr->V = texture_defn_ptr[1]; |
| | 1642 | } |
| | 1643 | else |
| | 1644 | { |
| | 1645 | renderVerticesPtr->U = texture_defn_ptr[0] << 16; |
| | 1646 | renderVerticesPtr->V = texture_defn_ptr[1] << 16; |
| | 1647 | } |
| | 1648 | |
| | 1649 | renderVerticesPtr->X = vertexPtr->vx; |
| | 1650 | renderVerticesPtr->Y = vertexPtr->vy; |
| | 1651 | renderVerticesPtr->Z = vertexPtr->vz; |
| | 1652 | |
| | 1653 | { |
| | 1654 | VECTORCH mag = RotatedPts[*VertexNumberPtr]; //*(((VECTORCH *)Global_ShapeVNormals) + *VertexNumberPtr); |
| | 1655 | int colour; |
| | 1656 | mag.vx = vertexPtr->vx - Global_ODB_Ptr->ObView.vx; |
| | 1657 | mag.vy = vertexPtr->vy - Global_ODB_Ptr->ObView.vy; |
| | 1658 | mag.vz = vertexPtr->vz - Global_ODB_Ptr->ObView.vz; |
| | 1659 | |
| | 1660 | colour = GetSin(((mag.vx+mag.vy+mag.vz)*8+CloakingPhase)&4095); |
| | 1661 | colour = MUL_FIXED(colour,colour); |
| | 1662 | renderVerticesPtr->B = MUL_FIXED(colour,255); |
| | 1663 | renderVerticesPtr->R = renderVerticesPtr->B/2; |
| | 1664 | renderVerticesPtr->G = renderVerticesPtr->B/2; |
| | 1665 | |
| | 1666 | colour = MUL_FIXED(colour,colour); |
| | 1667 | colour = MUL_FIXED(colour,colour); |
| | 1668 | |
| | 1669 | renderVerticesPtr->SpecularR = colour/1024; |
| | 1670 | renderVerticesPtr->SpecularG = colour/1024; |
| | 1671 | renderVerticesPtr->SpecularB = colour/1024; |
| | 1672 | renderVerticesPtr->A = alpha; |
| | 1673 | } |
| | 1674 | |
| | 1675 | texture_defn_ptr += 2; |
| | 1676 | renderVerticesPtr++; |
| | 1677 | VertexNumberPtr++; |
| | 1678 | |
| | 1679 | } while(--i); |
| | 1680 | } |
| | 1681 | |
| | 1682 | static void PredatorSeeAliensVision_ShapePipeline(struct shapeheader* shapePtr) |
| | 1683 | { |
| | 1684 | int numitems = shapePtr->numitems; |
| | 1685 | int** itemArrayPtr = shapePtr->items; |
| | 1686 | |
| | 1687 | assert(numitems); |
| | 1688 | |
| | 1689 | do |
| | 1690 | { |
| | 1691 | POLYHEADER *polyPtr = (POLYHEADER*) (*itemArrayPtr++); |
| | 1692 | |
| | 1693 | switch (polyPtr->PolyItemType) |
| | 1694 | { |
| | 1695 | case I_ZB_Gouraud3dTexturedPolygon: |
| | 1696 | case I_ZB_Gouraud2dTexturedPolygon: |
| | 1697 | { |
| | 1698 | int pif = PolygonWithinFrustrum(polyPtr); |
| | 1699 | |
| | 1700 | if (pif) |
| | 1701 | { |
| | 1702 | PredatorSeeAliensVisionPolygon_Construct(polyPtr); |
| | 1703 | |
| | 1704 | if (pif != 2) |
| | 1705 | { |
| | 1706 | GouraudTexturedPolygon_ClipWithZ(); |
| | 1707 | |
| | 1708 | if(RenderPolygon.NumberOfVertices < 3) |
| | 1709 | continue; |
| | 1710 | |
| | 1711 | GouraudTexturedPolygon_ClipWithNegativeX(); |
| | 1712 | |
| | 1713 | if(RenderPolygon.NumberOfVertices < 3) |
| | 1714 | continue; |
| | 1715 | |
| | 1716 | GouraudTexturedPolygon_ClipWithPositiveY(); |
| | 1717 | |
| | 1718 | if(RenderPolygon.NumberOfVertices < 3) |
| | 1719 | continue; |
| | 1720 | |
| | 1721 | GouraudTexturedPolygon_ClipWithNegativeY(); |
| | 1722 | |
| | 1723 | if(RenderPolygon.NumberOfVertices < 3) |
| | 1724 | continue; |
| | 1725 | |
| | 1726 | GouraudTexturedPolygon_ClipWithPositiveX(); |
| | 1727 | |
| | 1728 | if(RenderPolygon.NumberOfVertices < 3) |
| | 1729 | continue; |
| | 1730 | |
| | 1731 | ZBufferedGouraudTexturedPolygon_Output(polyPtr, RenderPolygon.Vertices); |
| | 1732 | } |
| | 1733 | else |
| | 1734 | { |
| | 1735 | ZBufferedGouraudTexturedPolygon_Output(polyPtr, VerticesBuffer); |
| | 1736 | } |
| | 1737 | } |
| | 1738 | } |
| | 1739 | default: |
| | 1740 | break; |
| | 1741 | } |
| | 1742 | |
| | 1743 | } while(--numitems); |
| | 1744 | } |
| | 1745 | |
| | 1746 | static void CloakedPolygon_Construct(POLYHEADER *polyPtr, int CloakingMode) |
| | 1747 | { |
| | 1748 | RENDERVERTEX *renderVerticesPtr = VerticesBuffer; |
| | 1749 | int i = RenderPolygon.NumberOfVertices; |
| | 1750 | |
| | 1751 | // get ptr to uv coords for this polygon |
| | 1752 | int *texture_defn_ptr = Global_ShapeHeaderPtr->sh_textures[(polyPtr->PolyColour >> TxDefn)]; |
| | 1753 | |
| | 1754 | VertexNumberPtr = &polyPtr->Poly1stPt; |
| | 1755 | |
| | 1756 | do |
| | 1757 | { |
| | 1758 | VECTORCH *vertexPtr = &RotatedPts[*VertexNumberPtr]; |
| | 1759 | renderVerticesPtr->X = vertexPtr->vx; |
| | 1760 | renderVerticesPtr->Y = vertexPtr->vy; |
| | 1761 | renderVerticesPtr->Z = vertexPtr->vz; |
| | 1762 | renderVerticesPtr->U = texture_defn_ptr[0] << 16; |
| | 1763 | renderVerticesPtr->V = texture_defn_ptr[1] << 16; |
| | 1764 | |
| | 1765 | VertexIntensity(renderVerticesPtr); |
| | 1766 | |
| | 1767 | { |
| | 1768 | VECTORCH mag; |
| | 1769 | |
| | 1770 | mag.vx = abs(vertexPtr->vx - ObjectCentre.vx); |
| | 1771 | mag.vy = abs(vertexPtr->vy - MUL_FIXED(ObjectCentre.vy, 87381)); |
| | 1772 | mag.vz = abs(vertexPtr->vz - ObjectCentre.vz); |
| | 1773 | |
| | 1774 | int alpha = GetSin(((mag.vx+mag.vy+mag.vz)*8+CloakingPhase)&4095); |
| | 1775 | |
| | 1776 | alpha = MUL_FIXED(alpha, alpha); |
| | 1777 | |
| | 1778 | if (alpha > CloakingMode) |
| | 1779 | alpha = CloakingMode; |
| | 1780 | |
| | 1781 | alpha /= 256; |
| | 1782 | |
| | 1783 | if (alpha > 255) |
| | 1784 | alpha = 255; |
| | 1785 | |
| | 1786 | renderVerticesPtr->A = alpha; |
| | 1787 | |
| | 1788 | if(CloakingMode > ONE_FIXED) |
| | 1789 | { |
| | 1790 | alpha = GetSin(((mag.vx+mag.vy+mag.vz)+CloakingPhase)&4095); |
| | 1791 | alpha = MUL_FIXED(alpha, alpha)>>8; |
| | 1792 | |
| | 1793 | if(alpha == 255) |
| | 1794 | { |
| | 1795 | renderVerticesPtr->A = 255; |
| | 1796 | renderVerticesPtr->G = 128; |
| | 1797 | renderVerticesPtr->B = 255; |
| | 1798 | } |
| | 1799 | } |
| | 1800 | } |
| | 1801 | |
| | 1802 | renderVerticesPtr++; |
| | 1803 | VertexNumberPtr++; |
| | 1804 | texture_defn_ptr += 2; |
| | 1805 | |
| | 1806 | } while(--i); |
| | 1807 | } |
| | 1808 | |
| | 1809 | static void AddToTranslucentPolyList(const POLYHEADER *inputPolyPtr, const RENDERVERTEX *renderVerticesPtr) |
| | 1810 | { |
| | 1811 | if (CurrentNumberOfTranslucentPolygons < MAX_NO_OF_TRANSLUCENT_POLYGONS) |
| | 1812 | { |
| | 1813 | // copy the data to the list for processing later |
| | 1814 | unsigned int i; |
| | 1815 | TranslucentPolygons[CurrentNumberOfTranslucentPolygons].polygon.NumberOfVertices = RenderPolygon.NumberOfVertices; |
| | 1816 | |
| | 1817 | for (i=0; i < RenderPolygon.NumberOfVertices; i++) |
| | 1818 | TranslucentPolygons[CurrentNumberOfTranslucentPolygons].polygon.Vertices[i] = *renderVerticesPtr++; |
| | 1819 | |
| | 1820 | TranslucentPolygons[CurrentNumberOfTranslucentPolygons++].polygon_header = *inputPolyPtr; |
| | 1821 | } |
| | 1822 | } |
| | 1823 | |
| | 1824 | static void GouraudPolygon_Construct(const POLYHEADER *polyPtr) |
| | 1825 | { |
| | 1826 | RENDERVERTEX *renderVerticesPtr = VerticesBuffer; |
| | 1827 | int i = RenderPolygon.NumberOfVertices; |
| | 1828 | VertexNumberPtr = &polyPtr->Poly1stPt; |
| | 1829 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_OFF; |
| | 1830 | |
| | 1831 | do |
| | 1832 | { |
| | 1833 | renderVerticesPtr->X = RotatedPts[*VertexNumberPtr].vx; |
| | 1834 | renderVerticesPtr->Y = RotatedPts[*VertexNumberPtr].vy; |
| | 1835 | renderVerticesPtr->Z = RotatedPts[*VertexNumberPtr].vz; |
| | 1836 | VertexIntensity(renderVerticesPtr); |
| | 1837 | renderVerticesPtr->R = renderVerticesPtr->G = (renderVerticesPtr->B + renderVerticesPtr->R + renderVerticesPtr->G) / 3; |
| | 1838 | renderVerticesPtr->B = 0; |
| | 1839 | renderVerticesPtr++; |
| | 1840 | VertexNumberPtr++; |
| | 1841 | |
| | 1842 | } while(--i); |
| | 1843 | } |
| | 1844 | |
| | 1845 | static void GouraudTexturedPolygon_Construct(const POLYHEADER *polyPtr) |
| | 1846 | { |
| | 1847 | /* get ptr to uv coords for this polygon */ |
| | 1848 | int *texture_defn_ptr = Global_ShapeHeaderPtr->sh_textures[(polyPtr->PolyColour >> TxDefn)]; |
| | 1849 | |
| | 1850 | RENDERVERTEX *renderVerticesPtr = VerticesBuffer; |
| | 1851 | int i = RenderPolygon.NumberOfVertices; |
| | 1852 | |
| | 1853 | VertexNumberPtr = &polyPtr->Poly1stPt; |
| | 1854 | |
| | 1855 | /* If this texture is animated the UV array must be calculated */ |
| | 1856 | |
| | 1857 | if(polyPtr->PolyFlags & iflag_txanim) |
| | 1858 | { |
| | 1859 | /* Create the UV array */ |
| | 1860 | int uv_array[18]; |
| | 1861 | CreateTxAnimUVArray((intptr_t*)texture_defn_ptr, uv_array, (int*)polyPtr); |
| | 1862 | texture_defn_ptr = uv_array; |
| | 1863 | |
| | 1864 | do |
| | 1865 | { |
| | 1866 | VECTORCH *vertexPtr = &RotatedPts[*VertexNumberPtr]; |
| | 1867 | |
| | 1868 | switch(UserProfile.active_bonus) |
| | 1869 | { |
| | 1870 | case CHEATMODE_NONACTIVE: |
| | 1871 | default: |
| | 1872 | renderVerticesPtr->X = vertexPtr->vx; |
| | 1873 | renderVerticesPtr->Y = vertexPtr->vy; |
| | 1874 | renderVerticesPtr->Z = vertexPtr->vz; |
| | 1875 | break; |
| | 1876 | case CHEATMODE_TRIPTASTIC: |
| | 1877 | { |
| | 1878 | renderVerticesPtr->X = vertexPtr->vx+GetSin((CloakingPhase*2 +vertexPtr->vz)&4095)/1024; |
| | 1879 | renderVerticesPtr->Y = vertexPtr->vy+GetSin((CloakingPhase-3000 +vertexPtr->vx)&4095)/1024; |
| | 1880 | renderVerticesPtr->Z = vertexPtr->vz+GetSin((CloakingPhase*3+239+vertexPtr->vy)&4095)/1024; |
| | 1881 | } |
| | 1882 | break; |
| | 1883 | case CHEATMODE_UNDERWATER: |
| | 1884 | { |
| | 1885 | renderVerticesPtr->X = vertexPtr->vx+(GetSin((CloakingPhase/2 +vertexPtr->vz)&4095))/1024; |
| | 1886 | renderVerticesPtr->Y = vertexPtr->vy+(GetSin((CloakingPhase-3000+vertexPtr->vx)&4095))/1024; |
| | 1887 | renderVerticesPtr->Z = vertexPtr->vz+(GetSin((CloakingPhase/3+239+vertexPtr->vy)&4095))/1024; |
| | 1888 | } |
| | 1889 | } |
| | 1890 | |
| | 1891 | renderVerticesPtr->U = texture_defn_ptr[0]; |
| | 1892 | renderVerticesPtr->V = texture_defn_ptr[1]; |
| | 1893 | |
| | 1894 | if( (Global_ODB_Ptr->SpecialFXFlags & SFXFLAG_MELTINGINTOGROUND) && (Global_ODB_Ptr->ObFlags2 < ONE_FIXED) ) |
| | 1895 | { |
| | 1896 | renderVerticesPtr->A = Global_ODB_Ptr->ObFlags2 >> 8; |
| | 1897 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL; |
| | 1898 | } |
| | 1899 | else if (polyPtr->PolyFlags & iflag_transparent) |
| | 1900 | { |
| | 1901 | renderVerticesPtr->A = 128; |
| | 1902 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL; |
| | 1903 | } |
| | 1904 | else |
| | 1905 | { |
| | 1906 | switch(UserProfile.active_bonus) |
| | 1907 | { |
| | 1908 | case CHEATMODE_NONACTIVE: |
| | 1909 | default: |
| | 1910 | renderVerticesPtr->A = 255; |
| | 1911 | break; |
| | 1912 | case CHEATMODE_TRIPTASTIC: |
| | 1913 | renderVerticesPtr->A = TripTasticPhase; |
| | 1914 | break; |
| | 1915 | case CHEATMODE_MOTIONBLUR: |
| | 1916 | renderVerticesPtr->A = 128; |
| | 1917 | } |
| | 1918 | |
| | 1919 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_OFF; |
| | 1920 | } |
| | 1921 | |
| | 1922 | if (polyPtr->PolyFlags & iflag_nolight) |
| | 1923 | { |
| | 1924 | switch (PlayerStatus.VisionMode) |
| | 1925 | { |
| | 1926 | default: |
| | 1927 | case VISION_MODE_NORMAL: |
| | 1928 | { |
| | 1929 | renderVerticesPtr->R = renderVerticesPtr->G = renderVerticesPtr->B = 255; |
| | 1930 | renderVerticesPtr->SpecularR = renderVerticesPtr->SpecularG = renderVerticesPtr->SpecularB = 0; |
| | 1931 | } |
| | 1932 | break; |
| | 1933 | case VISION_MODE_IMAGEINTENSIFIER: |
| | 1934 | { |
| | 1935 | renderVerticesPtr->R = renderVerticesPtr->B = 0; |
| | 1936 | renderVerticesPtr->G = 255; |
| | 1937 | renderVerticesPtr->SpecularR = renderVerticesPtr->SpecularG = renderVerticesPtr->SpecularB = 0; |
| | 1938 | } |
| | 1939 | break; |
| | 1940 | case VISION_MODE_PRED_THERMAL: |
| | 1941 | { |
| | 1942 | renderVerticesPtr->R = renderVerticesPtr->G = 0; |
| | 1943 | renderVerticesPtr->B = 255; |
| | 1944 | renderVerticesPtr->SpecularR = renderVerticesPtr->SpecularG = renderVerticesPtr->SpecularB = 0; |
| | 1945 | } |
| | 1946 | break; |
| | 1947 | case VISION_MODE_PRED_SEEALIENS: |
| | 1948 | { |
| | 1949 | renderVerticesPtr->R = 255; |
| | 1950 | renderVerticesPtr->G = renderVerticesPtr->B = 0; |
| | 1951 | renderVerticesPtr->SpecularR = renderVerticesPtr->SpecularG = renderVerticesPtr->SpecularB = 0; |
| | 1952 | } |
| | 1953 | break; |
| | 1954 | case VISION_MODE_PRED_SEEPREDTECH: |
| | 1955 | { |
| | 1956 | renderVerticesPtr->R = renderVerticesPtr->B = 0; |
| | 1957 | renderVerticesPtr->G = 255; |
| | 1958 | renderVerticesPtr->SpecularR = renderVerticesPtr->SpecularB = 255; |
| | 1959 | renderVerticesPtr->SpecularG = 0; |
| | 1960 | } |
| | 1961 | } |
| | 1962 | } |
| | 1963 | else |
| | 1964 | { |
| | 1965 | VertexIntensity(renderVerticesPtr); |
| | 1966 | } |
| | 1967 | |
| | 1968 | renderVerticesPtr++; |
| | 1969 | VertexNumberPtr++; |
| | 1970 | |
| | 1971 | texture_defn_ptr += 2; |
| | 1972 | |
| | 1973 | } while(--i); |
| | 1974 | } |
| | 1975 | else |
| | 1976 | { |
| | 1977 | do |
| | 1978 | { |
| | 1979 | VECTORCH *vertexPtr = &RotatedPts[*VertexNumberPtr]; |
| | 1980 | #if SPATIAL_SHOCKWAVE |
| | 1981 | { |
| | 1982 | int d = Magnitude(vertexPtr); |
| | 1983 | int a = (CloakingPhase&16383)+4000; |
| | 1984 | int u = d-a; |
| | 1985 | int offset; |
| | 1986 | |
| | 1987 | if (u > 0 && u < 8192) |
| | 1988 | { |
| | 1989 | VECTORCH n = *vertexPtr; |
| | 1990 | Normalise(&n); |
| | 1991 | u <<= 3; |
| | 1992 | offset = MUL_FIXED(MUL_FIXED(2*u,ONE_FIXED-u),8000) + MUL_FIXED(MUL_FIXED(u,u),8192 ); |
| | 1993 | assert(offset>=0 && offset<=8192); |
| | 1994 | renderVerticesPtr->X = MUL_FIXED(n.vx,d);//a+offset*2); |
| | 1995 | renderVerticesPtr->Y = MUL_FIXED(n.vy,d);//a+offset*2); |
| | 1996 | renderVerticesPtr->Z = MUL_FIXED(n.vz,a+offset); |
| | 1997 | } |
| | 1998 | else |
| | 1999 | { |
| | 2000 | renderVerticesPtr->X = vertexPtr->vx; |
| | 2001 | renderVerticesPtr->Y = vertexPtr->vy; |
| | 2002 | renderVerticesPtr->Z = vertexPtr->vz; |
| | 2003 | } |
| | 2004 | } |
| | 2005 | #else |
| | 2006 | switch(UserProfile.active_bonus) |
| | 2007 | { |
| | 2008 | case CHEATMODE_NONACTIVE: |
| | 2009 | default: |
| | 2010 | { |
| | 2011 | renderVerticesPtr->X = vertexPtr->vx; |
| | 2012 | renderVerticesPtr->Y = vertexPtr->vy; |
| | 2013 | renderVerticesPtr->Z = vertexPtr->vz; |
| | 2014 | } |
| | 2015 | break; |
| | 2016 | case CHEATMODE_TRIPTASTIC: |
| | 2017 | { |
| | 2018 | renderVerticesPtr->X = vertexPtr->vx+GetSin((CloakingPhase*2 + vertexPtr->vz) & 4095)/1024; |
| | 2019 | renderVerticesPtr->Y = vertexPtr->vy+GetSin((CloakingPhase-3000 + vertexPtr->vx) & 4095)/1024; |
| | 2020 | renderVerticesPtr->Z = vertexPtr->vz+GetSin((CloakingPhase*3+239 + vertexPtr->vy) & 4095)/1024; |
| | 2021 | } |
| | 2022 | break; |
| | 2023 | case CHEATMODE_UNDERWATER: |
| | 2024 | { |
| | 2025 | renderVerticesPtr->X = vertexPtr->vx+(GetSin((CloakingPhase/2 + vertexPtr->vz)&4095))/1024; |
| | 2026 | renderVerticesPtr->Y = vertexPtr->vy+(GetSin((CloakingPhase - 3000 + vertexPtr->vx)&4095))/1024; |
| | 2027 | renderVerticesPtr->Z = vertexPtr->vz+(GetSin((CloakingPhase/3+239 + vertexPtr->vy)&4095))/1024; |
| | 2028 | } |
| | 2029 | } |
| | 2030 | #endif |
| | 2031 | |
| | 2032 | renderVerticesPtr->U = texture_defn_ptr[0] << 16; |
| | 2033 | renderVerticesPtr->V = texture_defn_ptr[1] << 16; |
| | 2034 | |
| | 2035 | if( (Global_ODB_Ptr->SpecialFXFlags & SFXFLAG_MELTINGINTOGROUND) && (Global_ODB_Ptr->ObFlags2 < ONE_FIXED) ) |
| | 2036 | { |
| | 2037 | renderVerticesPtr->A = Global_ODB_Ptr->ObFlags2 >> 8; |
| | 2038 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL; |
| | 2039 | } |
| | 2040 | else if (polyPtr->PolyFlags & iflag_transparent) |
| | 2041 | { |
| | 2042 | renderVerticesPtr->A = 128; |
| | 2043 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL; |
| | 2044 | } |
| | 2045 | else |
| | 2046 | { |
| | 2047 | switch(UserProfile.active_bonus) |
| | 2048 | { |
| | 2049 | case CHEATMODE_NONACTIVE: |
| | 2050 | default: |
| | 2051 | renderVerticesPtr->A = 255; |
| | 2052 | break; |
| | 2053 | case CHEATMODE_TRIPTASTIC: |
| | 2054 | renderVerticesPtr->A = TripTasticPhase; |
| | 2055 | break; |
| | 2056 | case CHEATMODE_MOTIONBLUR: |
| | 2057 | renderVerticesPtr->A = 128; |
| | 2058 | } |
| | 2059 | |
| | 2060 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_OFF; |
| | 2061 | } |
| | 2062 | |
| | 2063 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL; |
| | 2064 | |
| | 2065 | if (polyPtr->PolyFlags & iflag_nolight) |
| | 2066 | { |
| | 2067 | switch (PlayerStatus.VisionMode) |
| | 2068 | { |
| | 2069 | default: |
| | 2070 | case VISION_MODE_NORMAL: |
| | 2071 | { |
| | 2072 | renderVerticesPtr->R = renderVerticesPtr->G = renderVerticesPtr->B = 255; |
| | 2073 | renderVerticesPtr->SpecularR = renderVerticesPtr->SpecularG = renderVerticesPtr->SpecularB = 0; |
| | 2074 | } |
| | 2075 | break; |
| | 2076 | case VISION_MODE_IMAGEINTENSIFIER: |
| | 2077 | { |
| | 2078 | renderVerticesPtr->R = renderVerticesPtr->B = 0; |
| | 2079 | renderVerticesPtr->G = 255; |
| | 2080 | renderVerticesPtr->SpecularR = renderVerticesPtr->SpecularG = renderVerticesPtr->SpecularB = 0; |
| | 2081 | } |
| | 2082 | break; |
| | 2083 | case VISION_MODE_PRED_THERMAL: |
| | 2084 | { |
| | 2085 | renderVerticesPtr->R = renderVerticesPtr->G = 0; |
| | 2086 | renderVerticesPtr->B = 255; |
| | 2087 | renderVerticesPtr->SpecularR = renderVerticesPtr->SpecularG = renderVerticesPtr->SpecularB = 0; |
| | 2088 | } |
| | 2089 | break; |
| | 2090 | case VISION_MODE_PRED_SEEALIENS: |
| | 2091 | { |
| | 2092 | renderVerticesPtr->R = 255; |
| | 2093 | renderVerticesPtr->G = renderVerticesPtr->B = 0; |
| | 2094 | renderVerticesPtr->SpecularR = renderVerticesPtr->SpecularG = renderVerticesPtr->SpecularB = 0; |
| | 2095 | } |
| | 2096 | break; |
| | 2097 | case VISION_MODE_PRED_SEEPREDTECH: |
| | 2098 | { |
| | 2099 | renderVerticesPtr->R = renderVerticesPtr->B = 0; |
| | 2100 | renderVerticesPtr->G = 255; |
| | 2101 | renderVerticesPtr->SpecularR = renderVerticesPtr->SpecularB = 255; |
| | 2102 | renderVerticesPtr->SpecularG = 0; |
| | 2103 | } |
| | 2104 | } |
| | 2105 | } |
| | 2106 | else |
| | 2107 | { |
| | 2108 | VertexIntensity(renderVerticesPtr); |
| | 2109 | } |
| | 2110 | |
| | 2111 | renderVerticesPtr++; |
| | 2112 | VertexNumberPtr++; |
| | 2113 | texture_defn_ptr += 2; |
| | 2114 | |
| | 2115 | } while(--i); |
| | 2116 | } |
| | 2117 | } |
| | 2118 | |
| | 2119 | struct shapeheader* GetShapeData(int shapenum) |
| | 2120 | { |
| | 2121 | return mainshapelist[shapenum]; |
| | 2122 | } |
| | 2123 | |
| | 2124 | int* GetTxAnimArrayZ(int shape, int item) |
| | 2125 | { |
| | 2126 | struct shapeheader *sptr = mainshapelist[shape]; |
| | 2127 | |
| | 2128 | if(sptr->sh_textures && sptr->items) |
| | 2129 | { |
| | 2130 | int** item_array_ptr = sptr->items; |
| | 2131 | int** shape_textures = sptr->sh_textures; |
| | 2132 | int* item_ptr = item_array_ptr[item]; |
| | 2133 | POLYHEADER *pheader = (POLYHEADER *) item_ptr; |
| | 2134 | |
| | 2135 | if(pheader->PolyFlags & iflag_txanim) |
| | 2136 | return (int*) shape_textures[(pheader->PolyColour >> TxDefn)]; |
| | 2137 | } |
| | 2138 | |
| | 2139 | return NULL; |
| | 2140 | } |
| | 2141 | |
| | 2142 | static TXANIMHEADER* GetTxAnimDataZ(int shape, int item, int sequence) |
| | 2143 | { |
| | 2144 | struct shapeheader* sptr = mainshapelist[shape]; |
| | 2145 | |
| | 2146 | if(sptr && sptr->sh_textures && sptr->items) |
| | 2147 | { |
| | 2148 | int** item_array_ptr = sptr->items; |
| | 2149 | int** shape_textures = sptr->sh_textures; |
| | 2150 | int* item_ptr = item_array_ptr[item]; |
| | 2151 | POLYHEADER *pheader = (POLYHEADER *) item_ptr; |
| | 2152 | |
| | 2153 | if(pheader->PolyFlags & iflag_txanim) |
| | 2154 | { |
| | 2155 | TXANIMHEADER **txah_ptr = (TXANIMHEADER **) shape_textures[(pheader->PolyColour >> TxDefn)]; |
| | 2156 | txah_ptr++; /* Skip sequence shadow */ |
| | 2157 | return txah_ptr[sequence]; |
| | 2158 | } |
| | 2159 | } |
| | 2160 | |
| | 2161 | return NULL; |
| | 2162 | } |
| | 2163 | |
| | 2164 | /* |
| | 2165 | |
| | 2166 | This function copies the TXANIMHEADER from the shape data item sequence |
| | 2167 | selected by the TXACTRLBLK to the TXANIMHEADER in the TXACTRLBLK |
| | 2168 | |
| | 2169 | */ |
| | 2170 | |
| | 2171 | TXANIMHEADER* GetTxAnimHeaderFromShape(TXACTRLBLK *taptr, int shape) |
| | 2172 | { |
| | 2173 | TXANIMHEADER *txah = GetTxAnimDataZ(shape, taptr->tac_item, taptr->tac_sequence); |
| | 2174 | |
| | 2175 | if(txah) |
| | 2176 | { |
| | 2177 | taptr->tac_txah.txa_flags = txah->txa_flags; |
| | 2178 | taptr->tac_txah.txa_state = txah->txa_state; |
| | 2179 | taptr->tac_txah.txa_numframes = txah->txa_numframes; |
| | 2180 | taptr->tac_txah.txa_framedata = txah->txa_framedata; |
| | 2181 | taptr->tac_txah.txa_currentframe = txah->txa_currentframe; |
| | 2182 | taptr->tac_txah.txa_maxframe = txah->txa_maxframe; |
| | 2183 | taptr->tac_txah.txa_speed = txah->txa_speed; |
| | 2184 | } |
| | 2185 | |
| | 2186 | return txah; |
| | 2187 | } |
| | 2188 | |
| | 2189 | /* |
| | 2190 | |
| | 2191 | Texture Animation Control Blocks are used to update animation. At the start |
| | 2192 | of "AddShape()" the relevant control block values are copied across to the |
| | 2193 | item TXANIMHEADER. |
| | 2194 | |
| | 2195 | */ |
| | 2196 | |
| | 2197 | static void UpdateTxAnim(TXANIMHEADER *txah) |
| | 2198 | { |
| | 2199 | int UpdateRate; |
| | 2200 | |
| | 2201 | if(txah->txa_flags & txa_flag_play) |
| | 2202 | { |
| | 2203 | /* How fast do we go? */ |
| | 2204 | |
| | 2205 | if(txah->txa_flags & txa_flag_quantiseframetime) |
| | 2206 | { |
| | 2207 | /* This option is still being designed and tested */ |
| | 2208 | |
| | 2209 | UpdateRate = txah->txa_speed & (~4096); /* 1/16th */ |
| | 2210 | |
| | 2211 | if(UpdateRate < 4096) |
| | 2212 | UpdateRate = 4096; |
| | 2213 | } |
| | 2214 | |
| | 2215 | UpdateRate = MUL_FIXED(NormalFrameTime, txah->txa_speed); |
| | 2216 | |
| | 2217 | /* Update the current frame */ |
| | 2218 | |
| | 2219 | if(txah->txa_flags & txa_flag_reverse) |
| | 2220 | { |
| | 2221 | txah->txa_currentframe -= UpdateRate; |
| | 2222 | |
| | 2223 | if(txah->txa_currentframe < 0) |
| | 2224 | { |
| | 2225 | if(txah->txa_flags & txa_flag_noloop) |
| | 2226 | txah->txa_currentframe = 0; |
| | 2227 | else |
| | 2228 | txah->txa_currentframe += txah->txa_maxframe; |
| | 2229 | } |
| | 2230 | } |
| | 2231 | else |
| | 2232 | { |
| | 2233 | txah->txa_currentframe += UpdateRate; |
| | 2234 | |
| | 2235 | if(txah->txa_currentframe >= txah->txa_maxframe) |
| | 2236 | { |
| | 2237 | if(txah->txa_flags & txa_flag_noloop) |
| | 2238 | txah->txa_currentframe = txah->txa_maxframe - 1; |
| | 2239 | else |
| | 2240 | txah->txa_currentframe -= txah->txa_maxframe; |
| | 2241 | } |
| | 2242 | } |
| | 2243 | } |
| | 2244 | } |
| | 2245 | |
| | 2246 | // Display block TXACTRLBLKS pass their data on to shape TXANIMHEADERs |
| | 2247 | |
| | 2248 | static void ControlTextureAnimation(DISPLAYBLOCK *dptr) |
| | 2249 | { |
| | 2250 | TXACTRLBLK *taptr = dptr->ObTxAnimCtrlBlks; |
| | 2251 | |
| | 2252 | while(taptr) |
| | 2253 | { |
| | 2254 | /* Update animation for the display block TXACTRLBLK */ |
| | 2255 | assert(&(taptr->tac_txah)); |
| | 2256 | UpdateTxAnim(&taptr->tac_txah); |
| | 2257 | |
| | 2258 | /* Get the TXANIMHEADER from the shape data */ |
| | 2259 | |
| | 2260 | TXANIMHEADER *txah = taptr->tac_txah_s; |
| | 2261 | |
| | 2262 | /* Copy across the current frame */ |
| | 2263 | assert(txah); |
| | 2264 | txah->txa_currentframe = taptr->tac_txah.txa_currentframe; |
| | 2265 | |
| | 2266 | int* iptr = taptr->tac_txarray; |
| | 2267 | assert(iptr); |
| | 2268 | *iptr = taptr->tac_sequence; |
| | 2269 | taptr = taptr->tac_next; |
| | 2270 | } |
| | 2271 | } |
| | 2272 | |
| | 2273 | static void RotateVertex(VECTOR2D *vertexPtr, int theta) |
| | 2274 | { |
| | 2275 | int sin = GetSin(theta); |
| | 2276 | int cos = GetCos(theta); |
| | 2277 | |
| | 2278 | int vx = MUL_FIXED(vertexPtr->vx, cos) - MUL_FIXED(vertexPtr->vy, sin); |
| | 2279 | int vy = MUL_FIXED(vertexPtr->vx, sin) + MUL_FIXED(vertexPtr->vy, cos); |
| | 2280 | |
| | 2281 | vertexPtr->vx = vx; |
| | 2282 | vertexPtr->vy = vy; |
| | 2283 | } |
| | 2284 | |
| | 2285 | static void TranslatePoint(const float *source, float *dest, const float *matrix) |
| | 2286 | { |
| | 2287 | dest[0] = matrix[ 0] * source[0] + matrix[ 1] * source[1] + matrix[ 2] * source[2] + matrix[ 3]; |
| | 2288 | dest[1] = matrix[ 4] * source[0] + matrix[ 5] * source[1] + matrix[ 6] * source[2] + matrix[ 7]; |
| | 2289 | dest[2] = matrix[ 8] * source[0] + matrix[ 9] * source[1] + matrix[10] * source[2] + matrix[11]; |
| | 2290 | } |
| | 2291 | |
| | 2292 | void TranslatePointIntoViewspace(VECTORCH * pointPtr) |
| | 2293 | { |
| | 2294 | Source[0] = pointPtr->vx; |
| | 2295 | Source[1] = pointPtr->vy; |
| | 2296 | Source[2] = pointPtr->vz; |
| | 2297 | |
| | 2298 | TranslatePoint(Source, Dest, ViewMatrix); |
| | 2299 | |
| | 2300 | pointPtr->vx = (int)Dest[0]; |
| | 2301 | pointPtr->vy = (int)Dest[1]; |
| | 2302 | pointPtr->vz = (int)Dest[2]; |
| | 2303 | } |
| | 2304 | |
| | 2305 | void RenderParticle(PARTICLE *particlePtr) |
| | 2306 | { |
| | 2307 | int particleSize = particlePtr->Size; |
| | 2308 | |
| | 2309 | { |
| | 2310 | VECTORCH translatedPosition = particlePtr->Position; |
| | 2311 | TranslatePointIntoViewspace(&translatedPosition); |
| | 2312 | VerticesBuffer[0].X = translatedPosition.vx; |
| | 2313 | VerticesBuffer[3].X = translatedPosition.vx; |
| | 2314 | VerticesBuffer[0].Y = translatedPosition.vy; |
| | 2315 | VerticesBuffer[3].Y = translatedPosition.vy; |
| | 2316 | VerticesBuffer[0].Z = translatedPosition.vz; |
| | 2317 | VerticesBuffer[3].Z = translatedPosition.vz; |
| | 2318 | } |
| | 2319 | |
| | 2320 | switch(particlePtr->ParticleID) |
| | 2321 | { |
| | 2322 | case PARTICLE_ALIEN_BLOOD: |
| | 2323 | case PARTICLE_HUMAN_BLOOD: |
| | 2324 | case PARTICLE_PREDATOR_BLOOD: |
| | 2325 | case PARTICLE_SPARK: |
| | 2326 | case PARTICLE_RICOCHET_SPARK: |
| | 2327 | case PARTICLE_EXPLOSIONFIRE: |
| | 2328 | case PARTICLE_WATERFALLSPRAY: |
| | 2329 | case PARTICLE_LASERBEAM: |
| | 2330 | case PARTICLE_PLASMABEAM: |
| | 2331 | case PARTICLE_ORANGE_SPARK: |
| | 2332 | case PARTICLE_ORANGE_PLASMA: |
| | 2333 | { |
| | 2334 | VECTORCH translatedPosition = particlePtr->Offset; |
| | 2335 | TranslatePointIntoViewspace(&translatedPosition); |
| | 2336 | VerticesBuffer[1].X = translatedPosition.vx; |
| | 2337 | VerticesBuffer[2].X = translatedPosition.vx; |
| | 2338 | VerticesBuffer[1].Y = translatedPosition.vy; |
| | 2339 | VerticesBuffer[2].Y = translatedPosition.vy; |
| | 2340 | VerticesBuffer[1].Z = translatedPosition.vz; |
| | 2341 | VerticesBuffer[2].Z = translatedPosition.vz; |
| | 2342 | |
| | 2343 | { |
| | 2344 | int deltaX = VerticesBuffer[1].X - VerticesBuffer[0].X; |
| | 2345 | int deltaY = VerticesBuffer[1].Y - VerticesBuffer[0].Y; |
| | 2346 | int splitY = 0; |
| | 2347 | |
| | 2348 | if (deltaX >= 0) |
| | 2349 | { |
| | 2350 | if (deltaY >= 0) |
| | 2351 | { |
| | 2352 | if (deltaX > deltaY) |
| | 2353 | splitY = 1; |
| | 2354 | } |
| | 2355 | else if (deltaX > -deltaY) |
| | 2356 | splitY = 1; |
| | 2357 | } |
| | 2358 | else |
| | 2359 | { |
| | 2360 | if (deltaY >= 0) |
| | 2361 | { |
| | 2362 | if (-deltaX > deltaY) |
| | 2363 | splitY = 1; |
| | 2364 | } |
| | 2365 | else if (-deltaX > -deltaY) |
| | 2366 | { |
| | 2367 | splitY = 1; |
| | 2368 | } |
| | 2369 | } |
| | 2370 | |
| | 2371 | if (splitY) |
| | 2372 | { |
| | 2373 | if (deltaX > 0) |
| | 2374 | { |
| | 2375 | /* 1 & 2 are more +ve in X */ |
| | 2376 | VerticesBuffer[0].X -= particleSize; |
| | 2377 | VerticesBuffer[0].Y -= MUL_FIXED(particleSize,87381); |
| | 2378 | VerticesBuffer[1].X += particleSize; |
| | 2379 | VerticesBuffer[1].Y -= MUL_FIXED(particleSize,87381); |
| | 2380 | VerticesBuffer[2].X += particleSize; |
| | 2381 | VerticesBuffer[2].Y += MUL_FIXED(particleSize,87381); |
| | 2382 | VerticesBuffer[3].X -= particleSize; |
| | 2383 | VerticesBuffer[3].Y += MUL_FIXED(particleSize,87381); |
| | 2384 | } |
| | 2385 | else |
| | 2386 | { |
| | 2387 | /* 1 & 2 are more -ve in X */ |
| | 2388 | VerticesBuffer[0].X += particleSize; |
| | 2389 | VerticesBuffer[0].Y -= MUL_FIXED(particleSize,87381); |
| | 2390 | VerticesBuffer[1].X -= particleSize; |
| | 2391 | VerticesBuffer[1].Y -= MUL_FIXED(particleSize,87381); |
| | 2392 | VerticesBuffer[2].X -= particleSize; |
| | 2393 | VerticesBuffer[2].Y += MUL_FIXED(particleSize,87381); |
| | 2394 | VerticesBuffer[3].X += particleSize; |
| | 2395 | VerticesBuffer[3].Y += MUL_FIXED(particleSize,87381); |
| | 2396 | } |
| | 2397 | } |
| | 2398 | else |
| | 2399 | { |
| | 2400 | if (deltaY > 0) |
| | 2401 | { |
| | 2402 | /* 1 & 2 are more +ve in Y */ |
| | 2403 | VerticesBuffer[0].X -= particleSize; |
| | 2404 | VerticesBuffer[0].Y -= MUL_FIXED(particleSize,87381); |
| | 2405 | VerticesBuffer[1].X -= particleSize; |
| | 2406 | VerticesBuffer[1].Y += MUL_FIXED(particleSize,87381); |
| | 2407 | VerticesBuffer[2].X += particleSize; |
| | 2408 | VerticesBuffer[2].Y += MUL_FIXED(particleSize,87381); |
| | 2409 | VerticesBuffer[3].X += particleSize; |
| | 2410 | VerticesBuffer[3].Y -= MUL_FIXED(particleSize,87381); |
| | 2411 | } |
| | 2412 | else |
| | 2413 | { |
| | 2414 | /* 1 & 2 are more -ve in Y */ |
| | 2415 | VerticesBuffer[0].X -= particleSize; |
| | 2416 | VerticesBuffer[0].Y += MUL_FIXED(particleSize,87381); |
| | 2417 | VerticesBuffer[1].X -= particleSize; |
| | 2418 | VerticesBuffer[1].Y -= MUL_FIXED(particleSize,87381); |
| | 2419 | VerticesBuffer[2].X += particleSize; |
| | 2420 | VerticesBuffer[2].Y -= MUL_FIXED(particleSize,87381); |
| | 2421 | VerticesBuffer[3].X += particleSize; |
| | 2422 | VerticesBuffer[3].Y += MUL_FIXED(particleSize,87381); |
| | 2423 | } |
| | 2424 | } |
| | 2425 | } |
| | 2426 | } |
| | 2427 | break; |
| | 2428 | default: |
| | 2429 | { |
| | 2430 | VECTOR2D offset[4]; |
| | 2431 | VerticesBuffer[1].X = VerticesBuffer[0].X; |
| | 2432 | VerticesBuffer[2].X = VerticesBuffer[0].X; |
| | 2433 | VerticesBuffer[1].Y = VerticesBuffer[0].Y; |
| | 2434 | VerticesBuffer[2].Y = VerticesBuffer[0].Y; |
| | 2435 | VerticesBuffer[1].Z = VerticesBuffer[0].Z; |
| | 2436 | VerticesBuffer[2].Z = VerticesBuffer[0].Z; |
| | 2437 | |
| | 2438 | offset[0].vx = -particleSize; |
| | 2439 | offset[0].vy = -particleSize; |
| | 2440 | |
| | 2441 | offset[1].vx = +particleSize; |
| | 2442 | offset[1].vy = -particleSize; |
| | 2443 | |
| | 2444 | offset[2].vx = +particleSize; |
| | 2445 | offset[2].vy = +particleSize; |
| | 2446 | |
| | 2447 | offset[3].vx = -particleSize; |
| | 2448 | offset[3].vy = +particleSize; |
| | 2449 | |
| | 2450 | switch(particlePtr->ParticleID) |
| | 2451 | { |
| | 2452 | case PARTICLE_MUZZLEFLASH: |
| | 2453 | { |
| | 2454 | int theta = FastRandom()&4095; |
| | 2455 | RotateVertex(&offset[0],theta); |
| | 2456 | RotateVertex(&offset[1],theta); |
| | 2457 | RotateVertex(&offset[2],theta); |
| | 2458 | RotateVertex(&offset[3],theta); |
| | 2459 | } |
| | 2460 | break; |
| | 2461 | case PARTICLE_SMOKECLOUD: |
| | 2462 | case PARTICLE_GUNMUZZLE_SMOKE: |
| | 2463 | case PARTICLE_FLAME: |
| | 2464 | { |
| | 2465 | int theta = (particlePtr->Offset.vx + MUL_FIXED(CloakingPhase,particlePtr->Offset.vy)) & 4095; |
| | 2466 | RotateVertex(&offset[0],theta); |
| | 2467 | RotateVertex(&offset[1],theta); |
| | 2468 | RotateVertex(&offset[2],theta); |
| | 2469 | RotateVertex(&offset[3],theta); |
| | 2470 | } |
| | 2471 | default: |
| | 2472 | break; |
| | 2473 | } |
| | 2474 | |
| | 2475 | VerticesBuffer[0].X += offset[0].vx; |
| | 2476 | VerticesBuffer[0].Y += MUL_FIXED(offset[0].vy,87381); |
| | 2477 | |
| | 2478 | VerticesBuffer[1].X += offset[1].vx; |
| | 2479 | VerticesBuffer[1].Y += MUL_FIXED(offset[1].vy,87381); |
| | 2480 | |
| | 2481 | VerticesBuffer[2].X += offset[2].vx; |
| | 2482 | VerticesBuffer[2].Y += MUL_FIXED(offset[2].vy,87381); |
| | 2483 | |
| | 2484 | VerticesBuffer[3].X += offset[3].vx; |
| | 2485 | VerticesBuffer[3].Y += MUL_FIXED(offset[3].vy,87381); |
| | 2486 | } |
| | 2487 | } |
| | 2488 | |
| | 2489 | { |
| | 2490 | int outcode = QuadWithinFrustrum(); |
| | 2491 | |
| | 2492 | if (outcode) |
| | 2493 | { |
| | 2494 | const PARTICLE_DESC *particleDescPtr = &ParticleDescription[particlePtr->ParticleID]; |
| | 2495 | RenderPolygon.NumberOfVertices = 4; |
| | 2496 | |
| | 2497 | VerticesBuffer[0].U = particleDescPtr->StartU; |
| | 2498 | VerticesBuffer[0].V = particleDescPtr->StartV; |
| | 2499 | |
| | 2500 | VerticesBuffer[1].U = particleDescPtr->EndU; |
| | 2501 | VerticesBuffer[1].V = particleDescPtr->StartV; |
| | 2502 | |
| | 2503 | VerticesBuffer[2].U = particleDescPtr->EndU; |
| | 2504 | VerticesBuffer[2].V = particleDescPtr->EndV; |
| | 2505 | |
| | 2506 | VerticesBuffer[3].U = particleDescPtr->StartU; |
| | 2507 | VerticesBuffer[3].V = particleDescPtr->EndV; |
| | 2508 | |
| | 2509 | if (outcode != 2) |
| | 2510 | { |
| | 2511 | TexturedPolygon_ClipWithZ(); |
| | 2512 | |
| | 2513 | if(RenderPolygon.NumberOfVertices < 3) |
| | 2514 | return; |
| | 2515 | |
| | 2516 | TexturedPolygon_ClipWithNegativeX(); |
| | 2517 | |
| | 2518 | if(RenderPolygon.NumberOfVertices < 3) |
| | 2519 | return; |
| | 2520 | |
| | 2521 | TexturedPolygon_ClipWithPositiveY(); |
| | 2522 | |
| | 2523 | if(RenderPolygon.NumberOfVertices < 3) |
| | 2524 | return; |
| | 2525 | |
| | 2526 | TexturedPolygon_ClipWithNegativeY(); |
| | 2527 | |
| | 2528 | if(RenderPolygon.NumberOfVertices < 3) |
| | 2529 | return; |
| | 2530 | |
| | 2531 | TexturedPolygon_ClipWithPositiveX(); |
| | 2532 | |
| | 2533 | if(RenderPolygon.NumberOfVertices < 3) |
| | 2534 | return; |
| | 2535 | |
| | 2536 | Particle_Output(particlePtr, RenderPolygon.Vertices); |
| | 2537 | } |
| | 2538 | else |
| | 2539 | { |
| | 2540 | Particle_Output(particlePtr, VerticesBuffer); |
| | 2541 | } |
| | 2542 | } |
| | 2543 | } |
| | 2544 | } |
| | 2545 | |
| | 2546 | static void FindAlienEnergySource_Recursion(HMODELCONTROLLER *controllerPtr, SECTION_DATA *sectionDataPtr, unsigned int colour) |
| | 2547 | { |
| | 2548 | /* KJL 16:29:40 10/02/98 - Recurse through hmodel */ |
| | 2549 | if ((sectionDataPtr->First_Child != NULL) && !(sectionDataPtr->flags & section_data_terminate_here)) |
| | 2550 | { |
| | 2551 | SECTION_DATA *childSectionPtr = sectionDataPtr->First_Child; |
| | 2552 | |
| | 2553 | while (childSectionPtr != NULL) |
| | 2554 | { |
| | 2555 | assert(childSectionPtr->My_Parent == sectionDataPtr); |
| | 2556 | |
| | 2557 | FindAlienEnergySource_Recursion(controllerPtr, childSectionPtr, colour); |
| | 2558 | childSectionPtr = childSectionPtr->Next_Sibling; |
| | 2559 | } |
| | 2560 | } |
| | 2561 | |
| | 2562 | if(sectionDataPtr->Shape && (sectionDataPtr->Shape->shaperadius > LocalDetailLevels.AlienEnergyViewThreshold)) |
| | 2563 | { |
| | 2564 | PARTICLE particle; |
| | 2565 | particle.Position = sectionDataPtr->World_Offset; |
| | 2566 | particle.ParticleID = PARTICLE_MUZZLEFLASH; |
| | 2567 | particle.Colour = colour; |
| | 2568 | particle.Size = sectionDataPtr->Shape->shaperadius * 2; |
| | 2569 | RenderParticle(&particle); |
| | 2570 | |
| | 2571 | //if(0) |
| | 2572 | { |
| | 2573 | VECTORCH velocity; |
| | 2574 | velocity.vx = (FastRandom() & 255) - 128; |
| | 2575 | velocity.vy = (FastRandom() & 255) - 128; |
| | 2576 | velocity.vz = 0; |
| | 2577 | //velocity.vy = -1000 - (FastRandom() & 255); |
| | 2578 | //MakeParticle(§ionDataPtr->World_Offset, &velocity, PARTICLE_SPARK); |
| | 2579 | MakeParticle(§ionDataPtr->World_Offset, &velocity, PARTICLE_PLASMATRAIL); |
| | 2580 | } |
| | 2581 | } |
| | 2582 | } |
| | 2583 | |
| | 2584 | static void DoAlienEnergyView(DISPLAYBLOCK *dispPtr) |
| | 2585 | { |
| | 2586 | HMODELCONTROLLER *controllerPtr = dispPtr->HModelControlBlock; |
| | 2587 | STRATEGYBLOCK *sbPtr = dispPtr->ObStrategyBlock; |
| | 2588 | unsigned int colour; |
| | 2589 | |
| | 2590 | switch (sbPtr->type) |
| | 2591 | { |
| | 2592 | case I_BehaviourAlien: |
| | 2593 | case I_BehaviourAlienPlayer: |
| | 2594 | case I_BehaviourQueenAlien: |
| | 2595 | case I_BehaviourFaceHugger: |
| | 2596 | case I_BehaviourXenoborg: |
| | 2597 | colour = ALIENS_LIFEFORCE_GLOW_COLOUR; |
| | 2598 | break; |
| | 2599 | case I_BehaviourPredator: |
| | 2600 | case I_BehaviourPredatorPlayer: |
| | 2601 | colour = PREDATORS_LIFEFORCE_GLOW_COLOUR; |
| | 2602 | break; |
| | 2603 | case I_BehaviourMarine: |
| | 2604 | case I_BehaviourMarinePlayer: |
| | 2605 | { |
| | 2606 | MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr); |
| | 2607 | |
| | 2608 | if (marineStatusPointer->Android) |
| | 2609 | return; |
| | 2610 | |
| | 2611 | colour = MARINES_LIFEFORCE_GLOW_COLOUR; |
| | 2612 | } |
| | 2613 | break; |
| | 2614 | case I_BehaviourNetGhost: |
| | 2615 | { |
| | 2616 | NETGHOSTDATABLOCK *ghostDataPtr = (NETGHOSTDATABLOCK *)sbPtr->dataptr; |
| | 2617 | |
| | 2618 | switch(ghostDataPtr->type) |
| | 2619 | { |
| | 2620 | case I_BehaviourAlienPlayer: |
| | 2621 | colour = ALIENS_LIFEFORCE_GLOW_COLOUR; |
| | 2622 | break; |
| | 2623 | case I_BehaviourPredatorPlayer: |
| | 2624 | colour = PREDATORS_LIFEFORCE_GLOW_COLOUR; |
| | 2625 | break; |
| | 2626 | case I_BehaviourMarinePlayer: |
| | 2627 | colour = MARINES_LIFEFORCE_GLOW_COLOUR; |
| | 2628 | break; |
| | 2629 | case I_BehaviourCorpse: |
| | 2630 | switch(ghostDataPtr->subtype) |
| | 2631 | { |
| | 2632 | case I_BehaviourAlienPlayer: |
| | 2633 | colour = ALIENS_LIFEFORCE_GLOW_COLOUR; |
| | 2634 | break; |
| | 2635 | case I_BehaviourPredatorPlayer: |
| | 2636 | colour = PREDATORS_LIFEFORCE_GLOW_COLOUR; |
| | 2637 | break; |
| | 2638 | case I_BehaviourMarinePlayer: |
| | 2639 | colour = MARINES_LIFEFORCE_GLOW_COLOUR; |
| | 2640 | default: |
| | 2641 | return; |
| | 2642 | } |
| | 2643 | default: |
| | 2644 | return; |
| | 2645 | } |
| | 2646 | } |
| | 2647 | break; |
| | 2648 | case I_BehaviourCorpse: |
| | 2649 | { |
| | 2650 | CORPSEDATABLOCK *corpseDataPtr = (CORPSEDATABLOCK *)sbPtr->dataptr; |
| | 2651 | |
| | 2652 | switch(corpseDataPtr->Type) |
| | 2653 | { |
| | 2654 | case I_BehaviourAlien: |
| | 2655 | case I_BehaviourAlienPlayer: |
| | 2656 | colour = ALIENS_LIFEFORCE_GLOW_COLOUR; |
| | 2657 | break; |
| | 2658 | case I_BehaviourMarine: |
| | 2659 | case I_BehaviourMarinePlayer: |
| | 2660 | { |
| | 2661 | if (corpseDataPtr->Android) |
| | 2662 | return; |
| | 2663 | |
| | 2664 | colour = MARINES_LIFEFORCE_GLOW_COLOUR; |
| | 2665 | } |
| | 2666 | break; |
| | 2667 | case I_BehaviourPredator: |
| | 2668 | case I_BehaviourPredatorPlayer: |
| | 2669 | colour = PREDATORS_LIFEFORCE_GLOW_COLOUR; |
| | 2670 | break; |
| | 2671 | default: |
| | 2672 | return; |
| | 2673 | } |
| | 2674 | } |
| | 2675 | break; |
| | 2676 | case I_BehaviourHierarchicalFragment: |
| | 2677 | { |
| | 2678 | HDEBRIS_BEHAV_BLOCK *debrisDataPtr = (HDEBRIS_BEHAV_BLOCK *)sbPtr->dataptr; |
| | 2679 | |
| | 2680 | switch(debrisDataPtr->Type) |
| | 2681 | { |
| | 2682 | case I_BehaviourAlien: |
| | 2683 | case I_BehaviourAlienPlayer: |
| | 2684 | colour = ALIENS_LIFEFORCE_GLOW_COLOUR; |
| | 2685 | break; |
| | 2686 | case I_BehaviourPredator: |
| | 2687 | case I_BehaviourPredatorPlayer: |
| | 2688 | colour = PREDATORS_LIFEFORCE_GLOW_COLOUR; |
| | 2689 | break; |
| | 2690 | case I_BehaviourMarine: |
| | 2691 | case I_BehaviourMarinePlayer: |
| | 2692 | if (debrisDataPtr->Android) |
| | 2693 | return; |
| | 2694 | colour = MARINES_LIFEFORCE_GLOW_COLOUR; |
| | 2695 | break; |
| | 2696 | default: |
| | 2697 | return; |
| | 2698 | } |
| | 2699 | } |
| | 2700 | break; |
| | 2701 | default: |
| | 2702 | return; |
| | 2703 | } |
| | 2704 | |
| | 2705 | if((dispPtr->SpecialFXFlags & SFXFLAG_MELTINGINTOGROUND) && (dispPtr->ObFlags2 < ONE_FIXED)) |
| | 2706 | { |
| | 2707 | unsigned int alpha = MUL_FIXED(dispPtr->ObFlags2,colour >> 24); |
| | 2708 | colour = (colour & 0xffffff) + (alpha << 24); |
| | 2709 | } |
| | 2710 | |
| | 2711 | /* KJL 16:36:12 10/02/98 - check positions are up to date */ |
| | 2712 | ProveHModel(controllerPtr, dispPtr); |
| | 2713 | |
| | 2714 | DecalSystem_Setup(); |
| | 2715 | |
| | 2716 | FindAlienEnergySource_Recursion(controllerPtr, controllerPtr->section_data, colour); |
| | 2717 | |
| | 2718 | DecalSystem_End(); |
| | 2719 | } |
| | 2720 | |
| | 2721 | static void MorphPoints(SHAPEINSTR *shapeinstrptr) |
| | 2722 | { |
| | 2723 | VECTORCH *srcPtr; |
| | 2724 | |
| | 2725 | { |
| | 2726 | /* Set up the morph data */ |
| | 2727 | |
| | 2728 | struct shapeheader* shape1Ptr = MorphDisplay.md_sptr1; |
| | 2729 | |
| | 2730 | switch(MorphDisplay.md_lerp) |
| | 2731 | { |
| | 2732 | case 0x0000: |
| | 2733 | { |
| | 2734 | srcPtr = (VECTORCH *)*shape1Ptr->points; |
| | 2735 | } |
| | 2736 | break; |
| | 2737 | case 0xffff: |
| | 2738 | { |
| | 2739 | struct shapeheader* shape2Ptr = MorphDisplay.md_sptr2; |
| | 2740 | |
| | 2741 | srcPtr = (VECTORCH *)*shape2Ptr->points; |
| | 2742 | Global_ShapePoints = *(shape2Ptr->points); |
| | 2743 | } |
| | 2744 | break; |
| | 2745 | default: |
| | 2746 | { |
| | 2747 | struct shapeheader* shape2Ptr = MorphDisplay.md_sptr2; |
| | 2748 | VECTORCH *shape1PointsPtr = (VECTORCH *)(*shape1Ptr->points); |
| | 2749 | VECTORCH *shape2PointsPtr = (VECTORCH *)(*shape2Ptr->points); |
| | 2750 | |
| | 2751 | { |
| | 2752 | int numberOfPoints = shape1Ptr->numpoints; |
| | 2753 | VECTORCH *morphedPointsPtr = (VECTORCH *) MorphedPts; |
| | 2754 | |
| | 2755 | while(numberOfPoints--) |
| | 2756 | { |
| | 2757 | VECTORCH vertex1 = *shape1PointsPtr; |
| | 2758 | VECTORCH vertex2 = *shape2PointsPtr; |
| | 2759 | |
| | 2760 | if( (vertex1.vx == vertex2.vx && vertex1.vy == vertex2.vy && vertex1.vz == vertex2.vz) ) |
| | 2761 | { |
| | 2762 | *morphedPointsPtr = vertex1; |
| | 2763 | } |
| | 2764 | else |
| | 2765 | { |
| | 2766 | /* KJL 15:27:20 05/22/97 - I've changed this to speed things up, If a vertex |
| | 2767 | component has a magnitude greater than 32768 things will go wrong. */ |
| | 2768 | morphedPointsPtr->vx = vertex1.vx + (((vertex2.vx-vertex1.vx)*MorphDisplay.md_lerp)>>16); |
| | 2769 | morphedPointsPtr->vy = vertex1.vy + (((vertex2.vy-vertex1.vy)*MorphDisplay.md_lerp)>>16); |
| | 2770 | morphedPointsPtr->vz = vertex1.vz + (((vertex2.vz-vertex1.vz)*MorphDisplay.md_lerp)>>16); |
| | 2771 | } |
| | 2772 | |
| | 2773 | shape1PointsPtr++; |
| | 2774 | shape2PointsPtr++; |
| | 2775 | morphedPointsPtr++; |
| | 2776 | } |
| | 2777 | } |
| | 2778 | |
| | 2779 | Global_ShapePoints = (int*)MorphedPts; |
| | 2780 | srcPtr = (VECTORCH *)MorphedPts; |
| | 2781 | } |
| | 2782 | } |
| | 2783 | } |
| | 2784 | |
| | 2785 | { |
| | 2786 | VECTORCH *destPtr = RotatedPts; |
| | 2787 | int i = shapeinstrptr->sh_numitems; |
| | 2788 | |
| | 2789 | for(; i; i--) |
| | 2790 | { |
| | 2791 | Source[0] = srcPtr->vx + Global_ODB_Ptr->ObWorld.vx; |
| | 2792 | Source[1] = srcPtr->vy + Global_ODB_Ptr->ObWorld.vy; |
| | 2793 | Source[2] = srcPtr->vz + Global_ODB_Ptr->ObWorld.vz; |
| | 2794 | |
| | 2795 | TranslatePoint(Source, Dest, ViewMatrix); |
| | 2796 | |
| | 2797 | destPtr->vx = (int)Dest[0]; |
| | 2798 | destPtr->vy = (int)Dest[1]; |
| | 2799 | destPtr->vz = (int)Dest[2]; |
| | 2800 | srcPtr++; |
| | 2801 | destPtr++; |
| | 2802 | } |
| | 2803 | } |
| | 2804 | } |
| | 2805 | |
| | 2806 | static void TranslateShapeVertices(SHAPEINSTR *shapeinstrptr) |
| | 2807 | { |
| | 2808 | VECTORCH *destPtr = RotatedPts; |
| | 2809 | int** shapeitemarrayptr = shapeinstrptr->sh_instr_data; |
| | 2810 | VECTORCH *srcPtr = (VECTORCH*)*shapeitemarrayptr; |
| | 2811 | int i = shapeinstrptr->sh_numitems; |
| | 2812 | |
| | 2813 | ObjectViewMatrix[0+0*4] = (float)(Global_ODB_Ptr->ObMat.mat11)/65536.0f; |
| | 2814 | ObjectViewMatrix[1+0*4] = (float)(Global_ODB_Ptr->ObMat.mat21)/65536.0f; |
| | 2815 | ObjectViewMatrix[2+0*4] = (float)(Global_ODB_Ptr->ObMat.mat31)/65536.0f; |
| | 2816 | |
| | 2817 | ObjectViewMatrix[0+1*4] = (float)(Global_ODB_Ptr->ObMat.mat12)/(65536.0f); |
| | 2818 | ObjectViewMatrix[1+1*4] = (float)(Global_ODB_Ptr->ObMat.mat22)/(65536.0f); |
| | 2819 | ObjectViewMatrix[2+1*4] = (float)(Global_ODB_Ptr->ObMat.mat32)/(65536.0f); |
| | 2820 | |
| | 2821 | ObjectViewMatrix[0+2*4] = (float)(Global_ODB_Ptr->ObMat.mat13)/65536.0f; |
| | 2822 | ObjectViewMatrix[1+2*4] = (float)(Global_ODB_Ptr->ObMat.mat23)/65536.0f; |
| | 2823 | ObjectViewMatrix[2+2*4] = (float)(Global_ODB_Ptr->ObMat.mat33)/65536.0f; |
| | 2824 | |
| | 2825 | ObjectViewMatrix[3+0*4] = Global_ODB_Ptr->ObWorld.vx; |
| | 2826 | ObjectViewMatrix[3+1*4] = Global_ODB_Ptr->ObWorld.vy; |
| | 2827 | ObjectViewMatrix[3+2*4] = Global_ODB_Ptr->ObWorld.vz; |
| | 2828 | |
| | 2829 | while(i--) |
| | 2830 | { |
| | 2831 | Source[0] = srcPtr->vx; |
| | 2832 | Source[1] = srcPtr->vy; |
| | 2833 | Source[2] = srcPtr->vz; |
| | 2834 | |
| | 2835 | TranslatePoint(Source, Dest, ObjectViewMatrix); |
| | 2836 | TranslatePoint(Dest, Source, ViewMatrix); |
| | 2837 | |
| | 2838 | destPtr->vx = (int)Source[0]; |
| | 2839 | destPtr->vy = (int)Source[1]; |
| | 2840 | destPtr->vz = (int)Source[2]; |
| | 2841 | srcPtr++; |
| | 2842 | destPtr++; |
| | 2843 | } |
| | 2844 | } |
| | 2845 | |
| | 2846 | static int predator_vision(struct shapeheader* shapePtr) |
| | 2847 | { |
| | 2848 | switch(PlayerStatus.VisionMode) |
| | 2849 | { |
| | 2850 | case VISION_MODE_PRED_THERMAL: |
| | 2851 | { |
| | 2852 | /* if we have an object with heat sources, draw it as such */ |
| | 2853 | if (NumberOfHeatSources) |
| | 2854 | { |
| | 2855 | PredatorThermalVision_ShapePipeline(shapePtr); |
| | 2856 | return 1; |
| | 2857 | } |
| | 2858 | } |
| | 2859 | return 0; |
| | 2860 | case VISION_MODE_PRED_SEEALIENS: |
| | 2861 | { |
| | 2862 | STRATEGYBLOCK *sbPtr = Global_ODB_Ptr->ObStrategyBlock; |
| | 2863 | |
| | 2864 | if(sbPtr) |
| | 2865 | { |
| | 2866 | switch (sbPtr->type) |
| | 2867 | { |
| | 2868 | case I_BehaviourAlien: |
| | 2869 | case I_BehaviourAlienPlayer: |
| | 2870 | case I_BehaviourFaceHugger: |
| | 2871 | case I_BehaviourXenoborg: |
| | 2872 | case I_BehaviourQueenAlien: |
| | 2873 | break; |
| | 2874 | case I_BehaviourHierarchicalFragment: |
| | 2875 | { |
| | 2876 | HDEBRIS_BEHAV_BLOCK *debrisDataPtr = (HDEBRIS_BEHAV_BLOCK *)sbPtr->dataptr; |
| | 2877 | |
| | 2878 | switch(debrisDataPtr->Type) |
| | 2879 | { |
| | 2880 | case I_BehaviourAlien: |
| | 2881 | case I_BehaviourQueenAlien: |
| | 2882 | case I_BehaviourFaceHugger: |
| | 2883 | case I_BehaviourXenoborg: |
| | 2884 | case I_BehaviourAlienPlayer: |
| | 2885 | break; |
| | 2886 | default: |
| | 2887 | return 0; |
| | 2888 | } |
| | 2889 | } |
| | 2890 | break; |
| | 2891 | case I_BehaviourCorpse: |
| | 2892 | { |
| | 2893 | CORPSEDATABLOCK *corpseDataPtr = (CORPSEDATABLOCK *)sbPtr->dataptr; |
| | 2894 | |
| | 2895 | switch(corpseDataPtr->Type) |
| | 2896 | { |
| | 2897 | case I_BehaviourAlien: |
| | 2898 | case I_BehaviourAlienPlayer: |
| | 2899 | case I_BehaviourFaceHugger: |
| | 2900 | case I_BehaviourXenoborg: |
| | 2901 | case I_BehaviourQueenAlien: |
| | 2902 | break; |
| | 2903 | default: |
| | 2904 | return 0; |
| | 2905 | } |
| | 2906 | } |
| | 2907 | break; |
| | 2908 | case I_BehaviourNetGhost: |
| | 2909 | { |
| | 2910 | NETGHOSTDATABLOCK *ghostDataPtr = (NETGHOSTDATABLOCK *)Global_ODB_Ptr->ObStrategyBlock->dataptr; |
| | 2911 | |
| | 2912 | switch(ghostDataPtr->type) |
| | 2913 | { |
| | 2914 | case I_BehaviourCorpse: |
| | 2915 | if (ghostDataPtr->subtype != I_BehaviourAlienPlayer) |
| | 2916 | return 0; |
| | 2917 | case I_BehaviourAlienPlayer: |
| | 2918 | case I_BehaviourAlien: |
| | 2919 | break; |
| | 2920 | default: |
| | 2921 | return 0; |
| | 2922 | } |
| | 2923 | } |
| | 2924 | break; |
| | 2925 | case I_BehaviourSpeargunBolt: |
| | 2926 | { |
| | 2927 | SPEAR_BEHAV_BLOCK *spearDataPtr = (SPEAR_BEHAV_BLOCK *)sbPtr->dataptr; |
| | 2928 | |
| | 2929 | if (spearDataPtr->SpearThroughFragment) // more flags required! |
| | 2930 | { |
| | 2931 | switch(spearDataPtr->Type) |
| | 2932 | { |
| | 2933 | case I_BehaviourAlien: |
| | 2934 | case I_BehaviourQueenAlien: |
| | 2935 | case I_BehaviourFaceHugger: |
| | 2936 | case I_BehaviourXenoborg: |
| | 2937 | case I_BehaviourAlienPlayer: |
| | 2938 | break; |
| | 2939 | default: |
| | 2940 | return 0; |
| | 2941 | } |
| | 2942 | } |
| | 2943 | } |
| | 2944 | default: |
| | 2945 | return 0; |
| | 2946 | } |
| | 2947 | |
| | 2948 | PredatorSeeAliensVision_ShapePipeline(shapePtr); |
| | 2949 | return 1; |
| | 2950 | } |
| | 2951 | } |
| | 2952 | break; |
| | 2953 | case VISION_MODE_PRED_SEEPREDTECH: |
| | 2954 | { |
| | 2955 | STRATEGYBLOCK *sbPtr = Global_ODB_Ptr->ObStrategyBlock; |
| | 2956 | |
| | 2957 | if(sbPtr) |
| | 2958 | { |
| | 2959 | switch (sbPtr->type) |
| | 2960 | { |
| | 2961 | case I_BehaviourPredator: |
| | 2962 | { |
| | 2963 | PREDATOR_STATUS_BLOCK *predData = (PREDATOR_STATUS_BLOCK *)Global_ODB_Ptr->ObStrategyBlock->dataptr; |
| | 2964 | |
| | 2965 | if (predData->CloakingEffectiveness) |
| | 2966 | return 0; |
| | 2967 | } |
| | 2968 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 2969 | break; |
| | 2970 | case I_BehaviourCorpse: |
| | 2971 | { |
| | 2972 | CORPSEDATABLOCK *corpseDataPtr = (CORPSEDATABLOCK *)sbPtr->dataptr; |
| | 2973 | |
| | 2974 | switch(corpseDataPtr->Type) |
| | 2975 | { |
| | 2976 | case I_BehaviourPredator: |
| | 2977 | case I_BehaviourPredatorPlayer: |
| | 2978 | break; |
| | 2979 | default: |
| | 2980 | return 0; |
| | 2981 | } |
| | 2982 | } |
| | 2983 | break; |
| | 2984 | case I_BehaviourHierarchicalFragment: |
| | 2985 | { |
| | 2986 | HDEBRIS_BEHAV_BLOCK *debrisDataPtr = (HDEBRIS_BEHAV_BLOCK *)sbPtr->dataptr; |
| | 2987 | |
| | 2988 | if (debrisDataPtr->Type != I_BehaviourPredator) |
| | 2989 | return 0; |
| | 2990 | } |
| | 2991 | break; |
| | 2992 | case I_BehaviourNetGhost: |
| | 2993 | { |
| | 2994 | NETGHOSTDATABLOCK *ghostDataPtr = (NETGHOSTDATABLOCK *)Global_ODB_Ptr->ObStrategyBlock->dataptr; |
| | 2995 | |
| | 2996 | if(!ghostDataPtr->CloakingEffectiveness) |
| | 2997 | { |
| | 2998 | switch(ghostDataPtr->type) |
| | 2999 | { |
| | 3000 | case I_BehaviourCorpse: |
| | 3001 | if (ghostDataPtr->subtype != I_BehaviourPredatorPlayer) |
| | 3002 | return 0; |
| | 3003 | case I_BehaviourInanimateObject: |
| | 3004 | if (ghostDataPtr->IOType != IOT_Ammo && ghostDataPtr->subtype != AMMO_PRED_DISC) |
| | 3005 | return 0; |
| | 3006 | case I_BehaviourPredator: |
| | 3007 | case I_BehaviourPredatorPlayer: |
| | 3008 | case I_BehaviourPredatorDisc_SeekTrack: |
| | 3009 | break; |
| | 3010 | default: |
| | 3011 | return 0; |
| | 3012 | } |
| | 3013 | } |
| | 3014 | } |
| | 3015 | break; |
| | 3016 | case I_BehaviourInanimateObject: |
| | 3017 | { |
| | 3018 | INANIMATEOBJECT_STATUSBLOCK* objStatPtr = (INANIMATEOBJECT_STATUSBLOCK*) sbPtr->dataptr; |
| | 3019 | |
| | 3020 | switch(objStatPtr->typeId) |
| | 3021 | { |
| | 3022 | case IOT_FieldCharge: |
| | 3023 | break; |
| | 3024 | case IOT_Weapon: |
| | 3025 | if(WEAPON_PRED_DISC == objStatPtr->subType) |
| | 3026 | break; |
| | 3027 | case IOT_Ammo: |
| | 3028 | if(AMMO_PRED_RIFLE == objStatPtr->subType) |
| | 3029 | break; |
| | 3030 | default: |
| | 3031 | return 0; |
| | 3032 | } |
| | 3033 | } |
| | 3034 | break; |
| | 3035 | case I_BehaviourSpeargunBolt: |
| | 3036 | { |
| | 3037 | SPEAR_BEHAV_BLOCK *spearDataPtr = (SPEAR_BEHAV_BLOCK *)sbPtr->dataptr; |
| | 3038 | |
| | 3039 | if (spearDataPtr->SpearThroughFragment) // more flags required! |
| | 3040 | { |
| | 3041 | switch(spearDataPtr->Type) |
| | 3042 | { |
| | 3043 | case I_BehaviourPredator: |
| | 3044 | case I_BehaviourPredatorPlayer: |
| | 3045 | break; |
| | 3046 | default: |
| | 3047 | return 0; |
| | 3048 | } |
| | 3049 | } |
| | 3050 | else |
| | 3051 | break; |
| | 3052 | } |
| | 3053 | default: |
| | 3054 | return 0; |
| | 3055 | } |
| | 3056 | |
| | 3057 | PredatorSeeAliensVision_ShapePipeline(shapePtr); |
| | 3058 | return 1; |
| | 3059 | } |
| | 3060 | } |
| | 3061 | default: |
| | 3062 | return 0; |
| | 3063 | } |
| | 3064 | |
| | 3065 | return 0; |
| | 3066 | } |
| | 3067 | |
| | 3068 | int jadda(struct shapeheader* shapeheaderptr) |
| | 3069 | { |
| | 3070 | /* interesting hack for predator cloaking */ |
| | 3071 | |
| | 3072 | int numitems = shapeheaderptr->numitems; |
| | 3073 | int **itemArrayPtr = shapeheaderptr->items; |
| | 3074 | |
| | 3075 | int CloakingEffectiveness; |
| | 3076 | |
| | 3077 | switch(Global_ODB_Ptr->ObStrategyBlock->type) |
| | 3078 | { |
| | 3079 | case I_BehaviourNetGhost: |
| | 3080 | { |
| | 3081 | NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)Global_ODB_Ptr->ObStrategyBlock->dataptr; |
| | 3082 | |
| | 3083 | if(!ghostData->CloakingEffectiveness) |
| | 3084 | return 0; |
| | 3085 | |
| | 3086 | CloakingEffectiveness = ghostData->CloakingEffectiveness; |
| | 3087 | } |
| | 3088 | break; |
| | 3089 | case I_BehaviourPredator: |
| | 3090 | { |
| | 3091 | PREDATOR_STATUS_BLOCK *predData = (PREDATOR_STATUS_BLOCK *)Global_ODB_Ptr->ObStrategyBlock->dataptr; |
| | 3092 | |
| | 3093 | if (!predData->CloakingEffectiveness) |
| | 3094 | return 0; |
| | 3095 | |
| | 3096 | CloakingEffectiveness = predData->CloakingEffectiveness; |
| | 3097 | } |
| | 3098 | default: |
| | 3099 | return 0; |
| | 3100 | } |
| | 3101 | |
| | 3102 | do |
| | 3103 | { |
| | 3104 | POLYHEADER *polyPtr = (POLYHEADER*) (*itemArrayPtr++); |
| | 3105 | int pif = PolygonWithinFrustrum(polyPtr); |
| | 3106 | |
| | 3107 | if(pif) |
| | 3108 | { |
| | 3109 | switch(polyPtr->PolyItemType) |
| | 3110 | { |
| | 3111 | case I_ZB_Gouraud3dTexturedPolygon: |
| | 3112 | case I_ZB_Gouraud2dTexturedPolygon: |
| | 3113 | CloakedPolygon_Construct(polyPtr, ((ONE_FIXED * 5 / 4) - CloakingEffectiveness)); |
| | 3114 | |
| | 3115 | if (pif != 2) |
| | 3116 | { |
| | 3117 | GouraudTexturedPolygon_ClipWithZ(); |
| | 3118 | |
| | 3119 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3120 | continue; |
| | 3121 | |
| | 3122 | GouraudTexturedPolygon_ClipWithNegativeX(); |
| | 3123 | |
| | 3124 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3125 | continue; |
| | 3126 | |
| | 3127 | GouraudTexturedPolygon_ClipWithPositiveY(); |
| | 3128 | |
| | 3129 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3130 | continue; |
| | 3131 | |
| | 3132 | GouraudTexturedPolygon_ClipWithNegativeY(); |
| | 3133 | |
| | 3134 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3135 | continue; |
| | 3136 | |
| | 3137 | GouraudTexturedPolygon_ClipWithPositiveX(); |
| | 3138 | |
| | 3139 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3140 | continue; |
| | 3141 | |
| | 3142 | ZBufferedCloakedPolygon_Output(polyPtr, RenderPolygon.Vertices); |
| | 3143 | } |
| | 3144 | else |
| | 3145 | { |
| | 3146 | ZBufferedCloakedPolygon_Output(polyPtr, VerticesBuffer); |
| | 3147 | } |
| | 3148 | break; |
| | 3149 | default: |
| | 3150 | printf("found polygon of type %d\n",polyPtr->PolyItemType); |
| | 3151 | } |
| | 3152 | } |
| | 3153 | |
| | 3154 | } while(--numitems); |
| | 3155 | |
| | 3156 | return 1; |
| | 3157 | } |
| | 3158 | |
| | 3159 | static void ShapePipeline(struct shapeheader* shapePtr) |
| | 3160 | { |
| | 3161 | int numitems = shapePtr->numitems; |
| | 3162 | int **itemArrayPtr = shapePtr->items; |
| | 3163 | |
| | 3164 | assert(numitems); |
| | 3165 | |
| | 3166 | if(Global_ODB_Ptr->ObStrategyBlock && jadda(shapePtr)) |
| | 3167 | return; |
| | 3168 | |
| | 3169 | do |
| | 3170 | { |
| | 3171 | POLYHEADER *polyPtr = (POLYHEADER*) (*itemArrayPtr++); |
| | 3172 | |
| | 3173 | int pif = PolygonWithinFrustrum(polyPtr); |
| | 3174 | |
| | 3175 | if (pif) |
| | 3176 | { |
| | 3177 | switch(polyPtr->PolyItemType) |
| | 3178 | { |
| | 3179 | case I_ZB_GouraudPolygon: |
| | 3180 | { |
| | 3181 | GouraudPolygon_Construct(polyPtr); |
| | 3182 | |
| | 3183 | if (pif != 2) |
| | 3184 | { |
| | 3185 | GouraudPolygon_ClipWithZ(); |
| | 3186 | |
| | 3187 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3188 | continue; |
| | 3189 | |
| | 3190 | GouraudPolygon_ClipWithNegativeX(); |
| | 3191 | |
| | 3192 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3193 | continue; |
| | 3194 | |
| | 3195 | GouraudPolygon_ClipWithPositiveY(); |
| | 3196 | |
| | 3197 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3198 | continue; |
| | 3199 | |
| | 3200 | GouraudPolygon_ClipWithNegativeY(); |
| | 3201 | |
| | 3202 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3203 | continue; |
| | 3204 | |
| | 3205 | GouraudPolygon_ClipWithPositiveX(); |
| | 3206 | |
| | 3207 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3208 | continue; |
| | 3209 | |
| | 3210 | ZBufferedGouraudPolygon_Output(polyPtr, RenderPolygon.Vertices); |
| | 3211 | } |
| | 3212 | else |
| | 3213 | { |
| | 3214 | ZBufferedGouraudPolygon_Output(polyPtr, VerticesBuffer); |
| | 3215 | } |
| | 3216 | } |
| | 3217 | break; |
| | 3218 | case I_ZB_Gouraud3dTexturedPolygon: |
| | 3219 | case I_ZB_Gouraud2dTexturedPolygon: |
| | 3220 | { |
| | 3221 | GouraudTexturedPolygon_Construct(polyPtr); |
| | 3222 | |
| | 3223 | if (pif != 2) |
| | 3224 | { |
| | 3225 | /* if this polygon is a quad, split it into two */ |
| | 3226 | if(RenderPolygon.NumberOfVertices == 4) |
| | 3227 | { |
| | 3228 | RENDERVERTEX TriangleVerticesBuffer[3] = { VerticesBuffer[0], VerticesBuffer[2], VerticesBuffer[3] }; |
| | 3229 | RenderPolygon.NumberOfVertices = 3; |
| | 3230 | |
| | 3231 | GouraudTexturedPolygon_ClipWithZ(); |
| | 3232 | |
| | 3233 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3234 | goto SecondTriangle; |
| | 3235 | |
| | 3236 | GouraudTexturedPolygon_ClipWithNegativeX(); |
| | 3237 | |
| | 3238 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3239 | goto SecondTriangle; |
| | 3240 | |
| | 3241 | GouraudTexturedPolygon_ClipWithPositiveY(); |
| | 3242 | |
| | 3243 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3244 | goto SecondTriangle; |
| | 3245 | |
| | 3246 | GouraudTexturedPolygon_ClipWithNegativeY(); |
| | 3247 | |
| | 3248 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3249 | goto SecondTriangle; |
| | 3250 | |
| | 3251 | GouraudTexturedPolygon_ClipWithPositiveX(); |
| | 3252 | |
| | 3253 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3254 | goto SecondTriangle; |
| | 3255 | |
| | 3256 | if (polyPtr->PolyFlags & iflag_transparent) |
| | 3257 | AddToTranslucentPolyList(polyPtr, RenderPolygon.Vertices); |
| | 3258 | else |
| | 3259 | ZBufferedGouraudTexturedPolygon_Output(polyPtr, RenderPolygon.Vertices); |
| | 3260 | |
| | 3261 | SecondTriangle: |
| | 3262 | RenderPolygon.NumberOfVertices = 3; |
| | 3263 | VerticesBuffer[0] = TriangleVerticesBuffer[0]; |
| | 3264 | VerticesBuffer[1] = TriangleVerticesBuffer[1]; |
| | 3265 | VerticesBuffer[2] = TriangleVerticesBuffer[2]; |
| | 3266 | } |
| | 3267 | |
| | 3268 | GouraudTexturedPolygon_ClipWithZ(); |
| | 3269 | |
| | 3270 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3271 | continue; |
| | 3272 | |
| | 3273 | GouraudTexturedPolygon_ClipWithNegativeX(); |
| | 3274 | |
| | 3275 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3276 | continue; |
| | 3277 | |
| | 3278 | GouraudTexturedPolygon_ClipWithPositiveY(); |
| | 3279 | |
| | 3280 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3281 | continue; |
| | 3282 | |
| | 3283 | GouraudTexturedPolygon_ClipWithNegativeY(); |
| | 3284 | |
| | 3285 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3286 | continue; |
| | 3287 | |
| | 3288 | GouraudTexturedPolygon_ClipWithPositiveX(); |
| | 3289 | |
| | 3290 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3291 | continue; |
| | 3292 | |
| | 3293 | if (polyPtr->PolyFlags & iflag_transparent) |
| | 3294 | AddToTranslucentPolyList(polyPtr, RenderPolygon.Vertices); |
| | 3295 | else |
| | 3296 | ZBufferedGouraudTexturedPolygon_Output(polyPtr, RenderPolygon.Vertices); |
| | 3297 | } |
| | 3298 | else |
| | 3299 | { |
| | 3300 | if (polyPtr->PolyFlags & iflag_transparent) |
| | 3301 | AddToTranslucentPolyList(polyPtr, VerticesBuffer); |
| | 3302 | else |
| | 3303 | ZBufferedGouraudTexturedPolygon_Output(polyPtr, VerticesBuffer); |
| | 3304 | } |
| | 3305 | } |
| | 3306 | default: |
| | 3307 | break; |
| | 3308 | } |
| | 3309 | } |
| | 3310 | |
| | 3311 | } while(--numitems); |
| | 3312 | } |
| | 3313 | |
| | 3314 | static void HandleObjectOnFire(DISPLAYBLOCK *dispPtr) |
| | 3315 | { |
| | 3316 | int noRequired = 1; |
| | 3317 | int i; |
| | 3318 | VECTORCH velocity; |
| | 3319 | |
| | 3320 | if (dispPtr->extent.radius <= LocalDetailLevels.AlienEnergyViewThreshold) |
| | 3321 | return; |
| | 3322 | |
| | 3323 | { |
| | 3324 | STRATEGYBLOCK *sbPtr = dispPtr->ObStrategyBlock; |
| | 3325 | DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr; |
| | 3326 | |
| | 3327 | velocity.vx = DIV_FIXED((dynPtr->Position.vx - dynPtr->PrevPosition.vx)*3, NormalFrameTime*4); |
| | 3328 | velocity.vy = DIV_FIXED((dynPtr->Position.vy - dynPtr->PrevPosition.vy)*3, NormalFrameTime*4); |
| | 3329 | velocity.vz = DIV_FIXED((dynPtr->Position.vz - dynPtr->PrevPosition.vz)*3, NormalFrameTime*4); |
| | 3330 | |
| | 3331 | if (dispPtr == sbPtr->DisplayBlock) |
| | 3332 | noRequired = 5; |
| | 3333 | } |
| | 3334 | |
| | 3335 | int objectIsDisappearing = ( (dispPtr->SpecialFXFlags & SFXFLAG_MELTINGINTOGROUND) && (dispPtr->ObFlags2 <= ONE_FIXED) ); |
| | 3336 | |
| | 3337 | for (i=0; i < noRequired; i++) |
| | 3338 | { |
| | 3339 | VECTORCH position; |
| | 3340 | position.vx = dispPtr->ObWorld.vx + (FastRandom() & 255)-128; |
| | 3341 | position.vy = dispPtr->ObWorld.vy + (FastRandom() & 255)-128; |
| | 3342 | position.vz = dispPtr->ObWorld.vz + (FastRandom() & 255)-128; |
| | 3343 | |
| | 3344 | if (objectIsDisappearing) |
| | 3345 | { |
| | 3346 | if ((FastRandom()&65535) < dispPtr->ObFlags2) |
| | 3347 | MakeParticle(&position, &velocity, PARTICLE_FIRE); |
| | 3348 | } |
| | 3349 | else |
| | 3350 | { |
| | 3351 | MakeParticle(&position, &velocity, PARTICLE_FIRE); |
| | 3352 | } |
| | 3353 | |
| | 3354 | if ((FastRandom() & 65535) > 32768) |
| | 3355 | MakeParticle(&position, &velocity, PARTICLE_IMPACTSMOKE); |
| | 3356 | } |
| | 3357 | } |
| | 3358 | |
| | 3359 | void AddShape(DISPLAYBLOCK *dptr) |
| | 3360 | { |
| | 3361 | struct shapeheader* shapeheaderptr = dptr->ShapeData; |
| | 3362 | |
| | 3363 | if(dptr->ObTxAnimCtrlBlks) |
| | 3364 | ControlTextureAnimation(dptr); |
| | 3365 | |
| | 3366 | SetupShapePipeline(dptr); |
| | 3367 | |
| | 3368 | TranslateShapeVertices(shapeheaderptr->sh_instruction); |
| | 3369 | TestVerticesWithFrustrum(shapeheaderptr->numpoints); |
| | 3370 | |
| | 3371 | if(!predator_vision(shapeheaderptr)) |
| | 3372 | ShapePipeline(shapeheaderptr); |
| | 3373 | |
| | 3374 | if (dptr->ObStrategyBlock) |
| | 3375 | { |
| | 3376 | if(dptr->ObStrategyBlock->DamageBlock.IsOnFire) |
| | 3377 | { |
| | 3378 | dptr->SpecialFXFlags |= SFXFLAG_ONFIRE; |
| | 3379 | HandleObjectOnFire(dptr); |
| | 3380 | } |
| | 3381 | else |
| | 3382 | dptr->SpecialFXFlags &= ~SFXFLAG_ONFIRE; |
| | 3383 | |
| | 3384 | /* |
| | 3385 | switch(dptr->ObStrategyBlock->type) |
| | 3386 | { |
| | 3387 | case I_BehaviourPlacedLight: |
| | 3388 | { |
| | 3389 | STRATEGYBLOCK *sbPtr = dptr->ObStrategyBlock; |
| | 3390 | PLACED_LIGHT_BEHAV_BLOCK* pl_bhv = sbPtr->dataptr; |
| | 3391 | |
| | 3392 | if (pl_bhv->has_corona && pl_bhv->light->LightBright |
| | 3393 | && (ModuleCurrVisArray[sbPtr->containingModule->m_index] == 2) |
| | 3394 | && (pl_bhv->light->RedScale || pl_bhv->light->GreenScale || pl_bhv->light->BlueScale)) |
| | 3395 | { |
| | 3396 | LIGHTBLOCK *lPtr = pl_bhv->light; |
| | 3397 | int colour; |
| | 3398 | |
| | 3399 | switch (PlayerStatus.VisionMode) |
| | 3400 | { |
| | 3401 | case VISION_MODE_NORMAL: |
| | 3402 | default: |
| | 3403 | { |
| | 3404 | int r = MUL_FIXED(lPtr->RedScale, lPtr->LightBright) >> 8; |
| | 3405 | int g = MUL_FIXED(lPtr->GreenScale, lPtr->LightBright) >> 8; |
| | 3406 | int b = MUL_FIXED(lPtr->BlueScale, lPtr->LightBright) >> 8; |
| | 3407 | if (r > 255) r = 255; |
| | 3408 | if (g > 255) g = 255; |
| | 3409 | if (b > 255) b = 255; |
| | 3410 | colour = 0xff000000+(r<<16)+(g<<8)+(b); |
| | 3411 | } |
| | 3412 | break; |
| | 3413 | case VISION_MODE_IMAGEINTENSIFIER: |
| | 3414 | colour = 0xffffffff; |
| | 3415 | break; |
| | 3416 | case VISION_MODE_PRED_THERMAL: |
| | 3417 | case VISION_MODE_PRED_SEEALIENS: |
| | 3418 | case VISION_MODE_PRED_SEEPREDTECH: |
| | 3419 | { |
| | 3420 | int b = MUL_FIXED(lPtr->RedScale+lPtr->GreenScale+lPtr->BlueScale, lPtr->LightBright) >> 10; |
| | 3421 | if (b > 255) b = 255; |
| | 3422 | |
| | 3423 | colour = 0xff000000+(b<<16)+((b>>1)<<8); |
| | 3424 | } |
| | 3425 | } |
| | 3426 | |
| | 3427 | { |
| | 3428 | DecalSystem_Setup(); |
| | 3429 | PARTICLE particle; |
| | 3430 | |
| | 3431 | particle.Position = dptr->ObWorld; |
| | 3432 | |
| | 3433 | particle.Colour = colour; |
| | 3434 | particle.ParticleID = PARTICLE_MUZZLEFLASH; |
| | 3435 | particle.Size = 300; |
| | 3436 | RenderParticle(&particle); |
| | 3437 | |
| | 3438 | DecalSystem_End(); |
| | 3439 | } |
| | 3440 | } |
| | 3441 | } |
| | 3442 | break; |
| | 3443 | case I_BehaviourInanimateObject: |
| | 3444 | { |
| | 3445 | INANIMATEOBJECT_STATUSBLOCK* objStatPtr = dptr->ObStrategyBlock->dataptr; |
| | 3446 | |
| | 3447 | if(objStatPtr->typeId == IOT_FieldCharge) |
| | 3448 | { |
| | 3449 | int i = 0; |
| | 3450 | DecalSystem_Setup(); |
| | 3451 | |
| | 3452 | for(; i < 63; i++) |
| | 3453 | { |
| | 3454 | PARTICLE particle; |
| | 3455 | |
| | 3456 | // SBF - 20080518 - commented out the undefined usage of particle.Position.vz |
| | 3457 | particle.Position.vy = -280+i-GetCos((CloakingPhase/16*i + i*64)&4095)/1024; |
| | 3458 | particle.Position.vx = GetCos((CloakingPhase +i*64+particle.Position.vy)&4095)/512; |
| | 3459 | particle.Position.vz = GetSin((CloakingPhase +i*64+particle.Position.vy)&4095)/512; |
| | 3460 | RotateVector(&particle.Position, &dptr->ObMat); |
| | 3461 | particle.Position.vx += dptr->ObWorld.vx; |
| | 3462 | particle.Position.vy += dptr->ObWorld.vy; |
| | 3463 | particle.Position.vz += dptr->ObWorld.vz; |
| | 3464 | particle.ParticleID = PARTICLE_MUZZLEFLASH; |
| | 3465 | particle.Colour = 0xff00007f+(FastRandom()&0x7f7f7f); |
| | 3466 | particle.Size = 40; |
| | 3467 | RenderParticle(&particle); |
| | 3468 | } |
| | 3469 | |
| | 3470 | DecalSystem_End(); |
| | 3471 | } |
| | 3472 | } |
| | 3473 | default: |
| | 3474 | break; |
| | 3475 | } |
| | 3476 | */ |
| | 3477 | } |
| | 3478 | } |
| | 3479 | |
| | 3480 | void AddModuleShape(DISPLAYBLOCK *dptr) |
| | 3481 | { |
| | 3482 | struct shapeheader* shapeheaderptr; |
| | 3483 | |
| | 3484 | if(dptr->ObMorphCtrl) |
| | 3485 | { |
| | 3486 | GetMorphDisplay(&MorphDisplay, dptr); |
| | 3487 | dptr->ObShape = MorphDisplay.md_shape1; |
| | 3488 | dptr->ShapeData = MorphDisplay.md_sptr1; |
| | 3489 | shapeheaderptr = MorphDisplay.md_sptr1; |
| | 3490 | SetupShapePipeline(dptr); |
| | 3491 | MorphPoints(shapeheaderptr->sh_instruction); |
| | 3492 | } |
| | 3493 | else |
| | 3494 | { |
| | 3495 | shapeheaderptr = dptr->ShapeData; |
| | 3496 | SetupShapePipeline(dptr); |
| | 3497 | TranslateShapeVertices(shapeheaderptr->sh_instruction); |
| | 3498 | } |
| | 3499 | |
| | 3500 | if(dptr->ObTxAnimCtrlBlks) |
| | 3501 | ControlTextureAnimation(dptr); |
| | 3502 | |
| | 3503 | TestVerticesWithFrustrum(shapeheaderptr->numpoints); |
| | 3504 | ShapePipeline(shapeheaderptr); |
| | 3505 | } |
| | 3506 | |
| | 3507 | void AttachSpearGunArrow(DISPLAYBLOCK *dptr) |
| | 3508 | { |
| | 3509 | struct shapeheader* shapeheaderptr = dptr->ShapeData; |
| | 3510 | |
| | 3511 | SetupShapePipeline(dptr); |
| | 3512 | |
| | 3513 | TranslateShapeVertices(shapeheaderptr->sh_instruction); |
| | 3514 | TestVerticesWithFrustrum(shapeheaderptr->numpoints); |
| | 3515 | ShapePipeline(shapeheaderptr); |
| | 3516 | } |
| | 3517 | |
| | 3518 | void DisplayFacehuggerOnHud(DISPLAYBLOCK *dptr) |
| | 3519 | { |
| | 3520 | if(dptr->ObStrategyBlock->DamageBlock.IsOnFire) |
| | 3521 | dptr->SpecialFXFlags |= SFXFLAG_ONFIRE; |
| | 3522 | else |
| | 3523 | dptr->SpecialFXFlags &= ~SFXFLAG_ONFIRE; |
| | 3524 | |
| | 3525 | /* |
| | 3526 | Create the Local -> View Matrix |
| | 3527 | |
| | 3528 | LToVMat = VDB_Mat * ObMat |
| | 3529 | |
| | 3530 | "Get the points into View Space, then apply the Local Transformation" |
| | 3531 | */ |
| | 3532 | |
| | 3533 | MatrixMultiply(&Global_VDB.VDB_Mat, &dptr->ObMat, <oVMat); |
| | 3534 | MatrixToEuler(<oVMat, <oVMat_Euler); |
| | 3535 | |
| | 3536 | /* |
| | 3537 | Create the World -> Local Matrix |
| | 3538 | |
| | 3539 | WToLMat = Transposed Local Matrix |
| | 3540 | */ |
| | 3541 | |
| | 3542 | WToLMat = dptr->ObMat; |
| | 3543 | TransposeMatrixCH(&WToLMat); |
| | 3544 | |
| | 3545 | /* |
| | 3546 | |
| | 3547 | Transform the View World Location to Local Space |
| | 3548 | |
| | 3549 | -> Make the View Loc. relative to the Object View Space Centre |
| | 3550 | -> Rotate this vector using WToLMat |
| | 3551 | |
| | 3552 | */ |
| | 3553 | |
| | 3554 | LocalView.vx = Global_VDB.VDB_World.vx - dptr->ObWorld.vx; |
| | 3555 | LocalView.vy = Global_VDB.VDB_World.vy - dptr->ObWorld.vy; |
| | 3556 | LocalView.vz = Global_VDB.VDB_World.vz - dptr->ObWorld.vz; |
| | 3557 | |
| | 3558 | RotateVector(&LocalView, &WToLMat); |
| | 3559 | |
| | 3560 | DoHModel(dptr); |
| | 3561 | } |
| | 3562 | |
| | 3563 | void DisplayAlienTeeth(DISPLAYBLOCK *dptr) |
| | 3564 | { |
| | 3565 | struct shapeheader* shapeheaderptr = mainshapelist[dptr->ObShape]; |
| | 3566 | dptr->ShapeData = shapeheaderptr; |
| | 3567 | SetupShapePipeline(dptr); |
| | 3568 | { |
| | 3569 | SHAPEINSTR *shapeinstrptr = shapeheaderptr->sh_instruction; |
| | 3570 | VECTORCH *destPtr = RotatedPts; |
| | 3571 | int** shapeitemarrayptr = shapeinstrptr->sh_instr_data; |
| | 3572 | VECTORCH *srcPtr = (VECTORCH*)*shapeitemarrayptr; |
| | 3573 | int i = shapeinstrptr->sh_numitems; |
| | 3574 | |
| | 3575 | while(i--) |
| | 3576 | { |
| | 3577 | destPtr->vx = (srcPtr->vx + Global_ODB_Ptr->ObView.vx); |
| | 3578 | destPtr->vy = ((srcPtr->vy + Global_ODB_Ptr->ObView.vy) * 4)/3; |
| | 3579 | destPtr->vz = (srcPtr->vz + Global_ODB_Ptr->ObView.vz); |
| | 3580 | |
| | 3581 | srcPtr++; |
| | 3582 | destPtr++; |
| | 3583 | } |
| | 3584 | } |
| | 3585 | TestVerticesWithFrustrum(shapeheaderptr->numpoints); |
| | 3586 | ShapePipeline(shapeheaderptr); |
| | 3587 | } |
| | 3588 | |
| | 3589 | void display_players_weapon() |
| | 3590 | { |
| | 3591 | DISPLAYBLOCK *dptr = &PlayerStatus.weapon; |
| | 3592 | |
| | 3593 | /* |
| | 3594 | Create the Local -> View Matrix |
| | 3595 | LToVMat = VDB_Mat * ObMat |
| | 3596 | "Get the points into View Space, then apply the Local Transformation" |
| | 3597 | */ |
| | 3598 | |
| | 3599 | MatrixMultiply(&Global_VDB.VDB_Mat, &dptr->ObMat, <oVMat); |
| | 3600 | MatrixToEuler(<oVMat, <oVMat_Euler); |
| | 3601 | |
| | 3602 | /* |
| | 3603 | Create the World -> Local Matrix |
| | 3604 | WToLMat = Transposed Local Matrix |
| | 3605 | */ |
| | 3606 | |
| | 3607 | WToLMat = dptr->ObMat; |
| | 3608 | TransposeMatrixCH(&WToLMat); |
| | 3609 | |
| | 3610 | /* |
| | 3611 | Transform the View World Location to Local Space |
| | 3612 | |
| | 3613 | -> Make the View Loc. relative to the Object View Space Centre |
| | 3614 | -> Rotate this vector using WToLMat |
| | 3615 | */ |
| | 3616 | |
| | 3617 | LocalView.vx = Global_VDB.VDB_World.vx - dptr->ObWorld.vx; |
| | 3618 | LocalView.vy = Global_VDB.VDB_World.vy - dptr->ObWorld.vy; |
| | 3619 | LocalView.vz = Global_VDB.VDB_World.vz - dptr->ObWorld.vz; |
| | 3620 | |
| | 3621 | RotateVector(&LocalView, &WToLMat); |
| | 3622 | DoPlayersWeaponHModel(dptr); |
| | 3623 | } |
| | 3624 | |
| | 3625 | static void SquishPoints(DISPLAYBLOCK * dptr) |
| | 3626 | { |
| | 3627 | struct shapeheader* shapeheaderptr = dptr->ShapeData; |
| | 3628 | int** shapeitemarrayptr = shapeheaderptr->sh_instruction->sh_instr_data; |
| | 3629 | VECTORCH *shapePts = (VECTORCH*)*shapeitemarrayptr; |
| | 3630 | int i; |
| | 3631 | int scale = dptr->ObFlags2; |
| | 3632 | |
| | 3633 | for (i=0; i < shapeheaderptr->numpoints; i++) |
| | 3634 | { |
| | 3635 | VECTORCH point = shapePts[i]; |
| | 3636 | |
| | 3637 | RotateVector(&point, &dptr->ObMat); |
| | 3638 | |
| | 3639 | point.vx = MUL_FIXED(point.vx, ONE_FIXED*3/2 - scale/2); |
| | 3640 | point.vx += dptr->ObWorld.vx; |
| | 3641 | |
| | 3642 | point.vz = MUL_FIXED(point.vz, ONE_FIXED*3/2 - scale/2); |
| | 3643 | point.vz += dptr->ObWorld.vz; |
| | 3644 | |
| | 3645 | point.vy += dptr->ObWorld.vy; |
| | 3646 | point.vy = HierarchicalObjectsLowestYValue + MUL_FIXED(point.vy - HierarchicalObjectsLowestYValue, scale); |
| | 3647 | |
| | 3648 | Source[0] = point.vx; |
| | 3649 | Source[1] = point.vy; |
| | 3650 | Source[2] = point.vz; |
| | 3651 | |
| | 3652 | TranslatePoint(Source, Dest, ViewMatrix); |
| | 3653 | |
| | 3654 | RotatedPts[i].vx = (int)Dest[0]; |
| | 3655 | RotatedPts[i].vy = (int)Dest[1]; |
| | 3656 | RotatedPts[i].vz = (int)Dest[2]; |
| | 3657 | } |
| | 3658 | } |
| | 3659 | |
| | 3660 | void AddShape2(DISPLAYBLOCK *dptr) |
| | 3661 | { |
| | 3662 | if(dptr->ObStrategyBlock->DamageBlock.IsOnFire) |
| | 3663 | dptr->SpecialFXFlags |= SFXFLAG_ONFIRE; |
| | 3664 | else |
| | 3665 | dptr->SpecialFXFlags &= ~SFXFLAG_ONFIRE; |
| | 3666 | |
| | 3667 | /* |
| | 3668 | Create the Local -> View Matrix |
| | 3669 | |
| | 3670 | LToVMat = VDB_Mat * ObMat |
| | 3671 | |
| | 3672 | "Get the points into View Space, then apply the Local Transformation" |
| | 3673 | */ |
| | 3674 | |
| | 3675 | MatrixMultiply(&Global_VDB.VDB_Mat, &dptr->ObMat, <oVMat); |
| | 3676 | MatrixToEuler(<oVMat, <oVMat_Euler); |
| | 3677 | |
| | 3678 | /* |
| | 3679 | Create the World -> Local Matrix |
| | 3680 | |
| | 3681 | WToLMat = Transposed Local Matrix |
| | 3682 | */ |
| | 3683 | |
| | 3684 | WToLMat = dptr->ObMat; |
| | 3685 | TransposeMatrixCH(&WToLMat); |
| | 3686 | |
| | 3687 | /* |
| | 3688 | |
| | 3689 | Transform the View World Location to Local Space |
| | 3690 | |
| | 3691 | -> Make the View Loc. relative to the Object View Space Centre |
| | 3692 | -> Rotate this vector using WToLMat |
| | 3693 | |
| | 3694 | */ |
| | 3695 | |
| | 3696 | LocalView.vx = Global_VDB.VDB_World.vx - dptr->ObWorld.vx; |
| | 3697 | LocalView.vy = Global_VDB.VDB_World.vy - dptr->ObWorld.vy; |
| | 3698 | LocalView.vz = Global_VDB.VDB_World.vz - dptr->ObWorld.vz; |
| | 3699 | |
| | 3700 | RotateVector(&LocalView, &WToLMat); |
| | 3701 | |
| | 3702 | ObjectCentre = dptr->ObView; |
| | 3703 | |
| | 3704 | HierarchicalObjectsLowestYValue = dptr->ObStrategyBlock->DynPtr->ObjectVertices[0].vy; |
| | 3705 | |
| | 3706 | if (AvP.PlayerType == I_Alien)// && PlayerStatus.VisionMode == VISION_MODE_NORMAL) |
| | 3707 | { |
| | 3708 | DoAlienEnergyView(dptr); |
| | 3709 | } |
| | 3710 | else if (PlayerStatus.VisionMode == VISION_MODE_PRED_THERMAL) |
| | 3711 | { |
| | 3712 | NumberOfHeatSources = 0; |
| | 3713 | FindHeatSourcesInHModel(dptr); |
| | 3714 | } |
| | 3715 | |
| | 3716 | DoHModel(dptr); |
| | 3717 | } |
| | 3718 | |
| | 3719 | void AddHierarchicalShape(DISPLAYBLOCK *dptr) |
| | 3720 | { |
| | 3721 | struct shapeheader* shapeheaderptr = dptr->ShapeData; |
| | 3722 | |
| | 3723 | /* Texture Animation Control */ |
| | 3724 | if(dptr->ObTxAnimCtrlBlks) |
| | 3725 | ControlTextureAnimation(dptr); |
| | 3726 | |
| | 3727 | SetupShapePipeline(dptr); |
| | 3728 | |
| | 3729 | switch(UserProfile.active_bonus) |
| | 3730 | { |
| | 3731 | case CHEATMODE_BALLSOFFIRE: |
| | 3732 | dptr->SpecialFXFlags |= SFXFLAG_ONFIRE; |
| | 3733 | case CHEATMODE_PIPECLEANER: |
| | 3734 | if(!dptr->ObStrategyBlock) |
| | 3735 | break; |
| | 3736 | case CHEATMODE_NONACTIVE: |
| | 3737 | default: |
| | 3738 | { |
| | 3739 | // setup the rotated points array |
| | 3740 | |
| | 3741 | if((dptr->SpecialFXFlags & SFXFLAG_MELTINGINTOGROUND) && (dptr->ObFlags2 <= ONE_FIXED)) |
| | 3742 | SquishPoints(dptr); |
| | 3743 | else |
| | 3744 | TranslateShapeVertices(shapeheaderptr->sh_instruction); |
| | 3745 | |
| | 3746 | TestVerticesWithFrustrum(shapeheaderptr->numpoints); |
| | 3747 | |
| | 3748 | if(!predator_vision(shapeheaderptr)) |
| | 3749 | ShapePipeline(shapeheaderptr); |
| | 3750 | } |
| | 3751 | } |
| | 3752 | |
| | 3753 | if (dptr->SpecialFXFlags & SFXFLAG_ONFIRE) |
| | 3754 | HandleObjectOnFire(dptr); |
| | 3755 | } |
| | 3756 | |
| | 3757 | void AddPlayersWeaponShape(DISPLAYBLOCK *dptr) |
| | 3758 | { |
| | 3759 | struct shapeheader* shapeheaderptr = dptr->ShapeData; |
| | 3760 | |
| | 3761 | SetupShapePipeline(dptr); |
| | 3762 | |
| | 3763 | /* setup the rotated points array */ |
| | 3764 | |
| | 3765 | TranslateShapeVertices(shapeheaderptr->sh_instruction); |
| | 3766 | |
| | 3767 | TestVerticesWithFrustrum(shapeheaderptr->numpoints); |
| | 3768 | |
| | 3769 | if(I_Predator == AvP.PlayerType) |
| | 3770 | { |
| | 3771 | if (PlayerStatus.cloakOn || PlayerStatus.CloakingEffectiveness) |
| | 3772 | { |
| | 3773 | int numitems = shapeheaderptr->numitems; |
| | 3774 | int **itemArrayPtr = shapeheaderptr->items; |
| | 3775 | |
| | 3776 | int a = GetSin(CloakingPhase & 4095); |
| | 3777 | a = MUL_FIXED(a, a); |
| | 3778 | int CloakingMode = ONE_FIXED * 5 / 4 - PlayerStatus.CloakingEffectiveness; |
| | 3779 | |
| | 3780 | do |
| | 3781 | { |
| | 3782 | POLYHEADER *polyPtr = (POLYHEADER*) (*itemArrayPtr++); |
| | 3783 | int pif = PolygonWithinFrustrum(polyPtr); |
| | 3784 | |
| | 3785 | if(pif) |
| | 3786 | { |
| | 3787 | switch(polyPtr->PolyItemType) |
| | 3788 | { |
| | 3789 | case I_ZB_Gouraud3dTexturedPolygon: |
| | 3790 | case I_ZB_Gouraud2dTexturedPolygon: |
| | 3791 | CloakedPolygon_Construct(polyPtr, CloakingMode); |
| | 3792 | |
| | 3793 | if (pif != 2) |
| | 3794 | { |
| | 3795 | GouraudTexturedPolygon_ClipWithZ(); |
| | 3796 | |
| | 3797 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3798 | continue; |
| | 3799 | |
| | 3800 | GouraudTexturedPolygon_ClipWithNegativeX(); |
| | 3801 | |
| | 3802 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3803 | continue; |
| | 3804 | |
| | 3805 | GouraudTexturedPolygon_ClipWithPositiveY(); |
| | 3806 | |
| | 3807 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3808 | continue; |
| | 3809 | |
| | 3810 | GouraudTexturedPolygon_ClipWithNegativeY(); |
| | 3811 | |
| | 3812 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3813 | continue; |
| | 3814 | |
| | 3815 | GouraudTexturedPolygon_ClipWithPositiveX(); |
| | 3816 | |
| | 3817 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3818 | continue; |
| | 3819 | |
| | 3820 | ZBufferedCloakedPolygon_Output(polyPtr, RenderPolygon.Vertices); |
| | 3821 | } |
| | 3822 | else |
| | 3823 | { |
| | 3824 | ZBufferedCloakedPolygon_Output(polyPtr, VerticesBuffer); |
| | 3825 | } |
| | 3826 | break; |
| | 3827 | default: |
| | 3828 | printf("found polygon of type %d\n",polyPtr->PolyItemType); |
| | 3829 | } |
| | 3830 | } |
| | 3831 | |
| | 3832 | } while(--numitems); |
| | 3833 | } |
| | 3834 | else if(VISION_MODE_PRED_SEEPREDTECH == PlayerStatus.VisionMode) |
| | 3835 | PredatorSeeAliensVision_ShapePipeline(shapeheaderptr); |
| | 3836 | else |
| | 3837 | ShapePipeline(shapeheaderptr); |
| | 3838 | } |
| | 3839 | else |
| | 3840 | { |
| | 3841 | ShapePipeline(shapeheaderptr); |
| | 3842 | } |
| | 3843 | } |
| | 3844 | |
| | 3845 | void TranslationSetup() |
| | 3846 | { |
| | 3847 | VECTORCH v = Global_VDB.VDB_World; |
| | 3848 | float p = (PredatorVisionChangeCounter / 65536.0f) + 1.0f; |
| | 3849 | float o = 1.0f; |
| | 3850 | CurrentNumberOfTranslucentPolygons = 0; // put it here just it make variable static |
| | 3851 | |
| | 3852 | if (CHEATMODE_NAUSEA == UserProfile.active_bonus) |
| | 3853 | { |
| | 3854 | p = (GetSin((CloakingPhase/3)&4095))/65536.0f; |
| | 3855 | p = 1.0f + p*p; |
| | 3856 | |
| | 3857 | o = (GetCos((CloakingPhase/5)&4095))/65536.0f; |
| | 3858 | o = 1.0f + o*o; |
| | 3859 | } |
| | 3860 | |
| | 3861 | #if 1 |
| | 3862 | ViewMatrix[0+0*4] = (float)(Global_VDB.VDB_Mat.mat11)/65536.0f*o; |
| | 3863 | ViewMatrix[1+0*4] = (float)(Global_VDB.VDB_Mat.mat21)/65536.0f*o; |
| | 3864 | ViewMatrix[2+0*4] = (float)(Global_VDB.VDB_Mat.mat31)/65536.0f*o; |
| | 3865 | #else |
| | 3866 | ViewMatrix[0+0*4] = (float)(Global_VDB.VDB_Mat.mat11)/65536.0f; |
| | 3867 | ViewMatrix[1+0*4] = (float)(Global_VDB.VDB_Mat.mat21)/65536.0f; |
| | 3868 | ViewMatrix[2+0*4] = (float)(Global_VDB.VDB_Mat.mat31)/65536.0f; |
| | 3869 | #endif |
| | 3870 | |
| | 3871 | #if 1 |
| | 3872 | ViewMatrix[0+1*4] = (float)(Global_VDB.VDB_Mat.mat12)*4.0f/(65536.0f*3.0f)*p; |
| | 3873 | ViewMatrix[1+1*4] = (float)(Global_VDB.VDB_Mat.mat22)*4.0f/(65536.0f*3.0f)*p; |
| | 3874 | ViewMatrix[2+1*4] = (float)(Global_VDB.VDB_Mat.mat32)*4.0f/(65536.0f*3.0f)*p; |
| | 3875 | #else |
| | 3876 | ViewMatrix[0+1*4] = (float)(Global_VDB.VDB_Mat.mat12)/(65536.0f); |
| | 3877 | ViewMatrix[1+1*4] = (float)(Global_VDB.VDB_Mat.mat22)/(65536.0f); |
| | 3878 | ViewMatrix[2+1*4] = (float)(Global_VDB.VDB_Mat.mat32)/(65536.0f); |
| | 3879 | #endif |
| | 3880 | |
| | 3881 | ViewMatrix[0+2*4] = (float)(Global_VDB.VDB_Mat.mat13)/65536.0f*CameraZoomScale; |
| | 3882 | ViewMatrix[1+2*4] = (float)(Global_VDB.VDB_Mat.mat23)/65536.0f*CameraZoomScale; |
| | 3883 | ViewMatrix[2+2*4] = (float)(Global_VDB.VDB_Mat.mat33)/65536.0f*CameraZoomScale; |
| | 3884 | |
| | 3885 | RotateVector(&v,&Global_VDB.VDB_Mat); |
| | 3886 | |
| | 3887 | ViewMatrix[3+0*4] = ((float)-v.vx)*o; |
| | 3888 | ViewMatrix[3+1*4] = ((float)-v.vy)*4.0f/3.0f*p; |
| | 3889 | ViewMatrix[3+2*4] = ((float)-v.vz)*CameraZoomScale; |
| | 3890 | |
| | 3891 | if (CHEATMODE_MIRROR == UserProfile.active_bonus) |
| | 3892 | { |
| | 3893 | ViewMatrix[0+0*4] = -ViewMatrix[0+0*4]; |
| | 3894 | ViewMatrix[1+0*4] = -ViewMatrix[1+0*4]; |
| | 3895 | ViewMatrix[2+0*4] = -ViewMatrix[2+0*4]; |
| | 3896 | ViewMatrix[3+0*4] = -ViewMatrix[3+0*4]; |
| | 3897 | } |
| | 3898 | } |
| | 3899 | |
| | 3900 | static void DecalPolygon_Construct(const DECAL *decalPtr) |
| | 3901 | { |
| | 3902 | DECAL_DESC *decalDescPtr = &DecalDescription[decalPtr->DecalID]; |
| | 3903 | RenderPolygon.NumberOfVertices = 4; |
| | 3904 | |
| | 3905 | VerticesBuffer[0].U = decalDescPtr->StartU+decalPtr->UOffset; |
| | 3906 | VerticesBuffer[0].V = decalDescPtr->StartV; |
| | 3907 | |
| | 3908 | VerticesBuffer[1].U = decalDescPtr->EndU+decalPtr->UOffset; |
| | 3909 | VerticesBuffer[1].V = decalDescPtr->StartV; |
| | 3910 | |
| | 3911 | VerticesBuffer[2].U = decalDescPtr->EndU+decalPtr->UOffset; |
| | 3912 | VerticesBuffer[2].V = decalDescPtr->EndV; |
| | 3913 | |
| | 3914 | VerticesBuffer[3].U = decalDescPtr->StartU+decalPtr->UOffset; |
| | 3915 | VerticesBuffer[3].V = decalDescPtr->EndV; |
| | 3916 | } |
| | 3917 | |
| | 3918 | #if MIRRORING_ON |
| | 3919 | static void RenderMirroredDecal(DECAL *decalPtr) |
| | 3920 | { |
| | 3921 | /* translate decal into view space */ |
| | 3922 | { |
| | 3923 | VECTORCH translatedPosition = decalPtr->Vertices[0]; |
| | 3924 | translatedPosition.vx = MirroringAxis - translatedPosition.vx; |
| | 3925 | TranslatePointIntoViewspace(&translatedPosition); |
| | 3926 | VerticesBuffer[0].X = translatedPosition.vx; |
| | 3927 | VerticesBuffer[0].Y = translatedPosition.vy; |
| | 3928 | VerticesBuffer[0].Z = translatedPosition.vz; |
| | 3929 | } |
| | 3930 | { |
| | 3931 | VECTORCH translatedPosition = decalPtr->Vertices[1]; |
| | 3932 | translatedPosition.vx = MirroringAxis - translatedPosition.vx; |
| | 3933 | TranslatePointIntoViewspace(&translatedPosition); |
| | 3934 | VerticesBuffer[1].X = translatedPosition.vx; |
| | 3935 | VerticesBuffer[1].Y = translatedPosition.vy; |
| | 3936 | VerticesBuffer[1].Z = translatedPosition.vz; |
| | 3937 | } |
| | 3938 | { |
| | 3939 | VECTORCH translatedPosition = decalPtr->Vertices[2]; |
| | 3940 | translatedPosition.vx = MirroringAxis - translatedPosition.vx; |
| | 3941 | TranslatePointIntoViewspace(&translatedPosition); |
| | 3942 | VerticesBuffer[2].X = translatedPosition.vx; |
| | 3943 | VerticesBuffer[2].Y = translatedPosition.vy; |
| | 3944 | VerticesBuffer[2].Z = translatedPosition.vz; |
| | 3945 | } |
| | 3946 | { |
| | 3947 | VECTORCH translatedPosition = decalPtr->Vertices[3]; |
| | 3948 | translatedPosition.vx = MirroringAxis - translatedPosition.vx; |
| | 3949 | TranslatePointIntoViewspace(&translatedPosition); |
| | 3950 | VerticesBuffer[3].X = translatedPosition.vx; |
| | 3951 | VerticesBuffer[3].Y = translatedPosition.vy; |
| | 3952 | VerticesBuffer[3].Z = translatedPosition.vz; |
| | 3953 | } |
| | 3954 | { |
| | 3955 | int outcode = DecalWithinFrustrum(decalPtr); |
| | 3956 | |
| | 3957 | if (outcode) |
| | 3958 | { |
| | 3959 | DecalPolygon_Construct(decalPtr); |
| | 3960 | |
| | 3961 | if (outcode != 2) |
| | 3962 | { |
| | 3963 | TexturedPolygon_ClipWithZ(); |
| | 3964 | |
| | 3965 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3966 | return; |
| | 3967 | |
| | 3968 | TexturedPolygon_ClipWithNegativeX(); |
| | 3969 | |
| | 3970 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3971 | return; |
| | 3972 | |
| | 3973 | TexturedPolygon_ClipWithPositiveY(); |
| | 3974 | |
| | 3975 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3976 | return; |
| | 3977 | |
| | 3978 | TexturedPolygon_ClipWithNegativeY(); |
| | 3979 | |
| | 3980 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3981 | return; |
| | 3982 | |
| | 3983 | TexturedPolygon_ClipWithPositiveX(); |
| | 3984 | |
| | 3985 | if(RenderPolygon.NumberOfVertices < 3) |
| | 3986 | return; |
| | 3987 | |
| | 3988 | Decal_Output(decalPtr,RenderPolygon.Vertices); |
| | 3989 | } |
| | 3990 | else |
| | 3991 | { |
| | 3992 | Decal_Output(decalPtr,VerticesBuffer); |
| | 3993 | } |
| | 3994 | } |
| | 3995 | } |
| | 3996 | } |
| | 3997 | #endif |
| | 3998 | |
| | 3999 | void RenderDecal(const DECAL *decalPtr) |
| | 4000 | { |
| | 4001 | /* translate decal into view space */ |
| | 4002 | { |
| | 4003 | VECTORCH translatedPosition = decalPtr->Vertices[0]; |
| | 4004 | TranslatePointIntoViewspace(&translatedPosition); |
| | 4005 | VerticesBuffer[0].X = translatedPosition.vx; |
| | 4006 | VerticesBuffer[0].Y = translatedPosition.vy; |
| | 4007 | VerticesBuffer[0].Z = translatedPosition.vz; |
| | 4008 | } |
| | 4009 | { |
| | 4010 | VECTORCH translatedPosition = decalPtr->Vertices[1]; |
| | 4011 | TranslatePointIntoViewspace(&translatedPosition); |
| | 4012 | VerticesBuffer[1].X = translatedPosition.vx; |
| | 4013 | VerticesBuffer[1].Y = translatedPosition.vy; |
| | 4014 | VerticesBuffer[1].Z = translatedPosition.vz; |
| | 4015 | } |
| | 4016 | { |
| | 4017 | VECTORCH translatedPosition = decalPtr->Vertices[2]; |
| | 4018 | TranslatePointIntoViewspace(&translatedPosition); |
| | 4019 | VerticesBuffer[2].X = translatedPosition.vx; |
| | 4020 | VerticesBuffer[2].Y = translatedPosition.vy; |
| | 4021 | VerticesBuffer[2].Z = translatedPosition.vz; |
| | 4022 | } |
| | 4023 | { |
| | 4024 | VECTORCH translatedPosition = decalPtr->Vertices[3]; |
| | 4025 | TranslatePointIntoViewspace(&translatedPosition); |
| | 4026 | VerticesBuffer[3].X = translatedPosition.vx; |
| | 4027 | VerticesBuffer[3].Y = translatedPosition.vy; |
| | 4028 | VerticesBuffer[3].Z = translatedPosition.vz; |
| | 4029 | } |
| | 4030 | { |
| | 4031 | int outcode = DecalWithinFrustrum(decalPtr); |
| | 4032 | |
| | 4033 | if (outcode) |
| | 4034 | { |
| | 4035 | DecalPolygon_Construct(decalPtr); |
| | 4036 | |
| | 4037 | if (outcode != 2) |
| | 4038 | { |
| | 4039 | TexturedPolygon_ClipWithZ(); |
| | 4040 | |
| | 4041 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4042 | return; |
| | 4043 | |
| | 4044 | TexturedPolygon_ClipWithNegativeX(); |
| | 4045 | |
| | 4046 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4047 | return; |
| | 4048 | |
| | 4049 | TexturedPolygon_ClipWithPositiveY(); |
| | 4050 | |
| | 4051 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4052 | return; |
| | 4053 | |
| | 4054 | TexturedPolygon_ClipWithNegativeY(); |
| | 4055 | |
| | 4056 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4057 | return; |
| | 4058 | |
| | 4059 | TexturedPolygon_ClipWithPositiveX(); |
| | 4060 | |
| | 4061 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4062 | return; |
| | 4063 | |
| | 4064 | Decal_Output(decalPtr, RenderPolygon.Vertices); |
| | 4065 | } |
| | 4066 | else |
| | 4067 | { |
| | 4068 | Decal_Output(decalPtr, VerticesBuffer); |
| | 4069 | } |
| | 4070 | } |
| | 4071 | } |
| | 4072 | |
| | 4073 | #if MIRRORING_ON |
| | 4074 | if (MirroringActive) |
| | 4075 | RenderMirroredDecal(decalPtr); |
| | 4076 | #endif |
| | 4077 | } |
| | 4078 | |
| | 4079 | void RenderFlechetteParticle(PARTICLE *particlePtr) |
| | 4080 | { |
| | 4081 | VECTORCH vertices[5]; |
| | 4082 | MATRIXCH mat; |
| | 4083 | |
| | 4084 | MakeMatrixFromDirection(&particlePtr->Velocity, &mat); |
| | 4085 | |
| | 4086 | mat.mat11 >>= 12; |
| | 4087 | mat.mat12 >>= 12; |
| | 4088 | mat.mat13 >>= 12; |
| | 4089 | mat.mat21 >>= 12; |
| | 4090 | mat.mat22 >>= 12; |
| | 4091 | mat.mat23 >>= 12; |
| | 4092 | mat.mat31 >>= 9; |
| | 4093 | mat.mat32 >>= 9; |
| | 4094 | mat.mat33 >>= 9; |
| | 4095 | |
| | 4096 | vertices[0].vx = particlePtr->Position.vx - mat.mat31 + mat.mat11; |
| | 4097 | vertices[0].vy = particlePtr->Position.vy - mat.mat32 + mat.mat12; |
| | 4098 | vertices[0].vz = particlePtr->Position.vz - mat.mat33 + mat.mat13; |
| | 4099 | |
| | 4100 | vertices[1].vx = particlePtr->Position.vx - mat.mat31 - mat.mat11; |
| | 4101 | vertices[1].vy = particlePtr->Position.vy - mat.mat32 - mat.mat12; |
| | 4102 | vertices[1].vz = particlePtr->Position.vz - mat.mat33 - mat.mat13; |
| | 4103 | |
| | 4104 | vertices[2] = particlePtr->Position; |
| | 4105 | |
| | 4106 | vertices[3].vx = particlePtr->Position.vx - mat.mat31 + mat.mat21; |
| | 4107 | vertices[3].vy = particlePtr->Position.vy - mat.mat32 + mat.mat22; |
| | 4108 | vertices[3].vz = particlePtr->Position.vz - mat.mat33 + mat.mat23; |
| | 4109 | |
| | 4110 | vertices[4].vx = particlePtr->Position.vx - mat.mat31 - mat.mat21; |
| | 4111 | vertices[4].vy = particlePtr->Position.vy - mat.mat32 - mat.mat22; |
| | 4112 | vertices[4].vz = particlePtr->Position.vz - mat.mat33 - mat.mat23; |
| | 4113 | |
| | 4114 | TranslatePointIntoViewspace(&vertices[0]); |
| | 4115 | TranslatePointIntoViewspace(&vertices[1]); |
| | 4116 | TranslatePointIntoViewspace(&vertices[2]); |
| | 4117 | TranslatePointIntoViewspace(&vertices[3]); |
| | 4118 | TranslatePointIntoViewspace(&vertices[4]); |
| | 4119 | |
| | 4120 | { |
| | 4121 | int i = 0; |
| | 4122 | for (; i < 3; i++) |
| | 4123 | { |
| | 4124 | VerticesBuffer[i].X = vertices[i].vx; |
| | 4125 | VerticesBuffer[i].Y = vertices[i].vy; |
| | 4126 | VerticesBuffer[i].Z = vertices[i].vz; |
| | 4127 | |
| | 4128 | VerticesBuffer[i].A = (particlePtr->Colour >> 24) & 255; |
| | 4129 | VerticesBuffer[i].R = (particlePtr->Colour >> 16) & 255; |
| | 4130 | VerticesBuffer[i].G = (particlePtr->Colour >> 8) & 255; |
| | 4131 | VerticesBuffer[i].B = (particlePtr->Colour) & 255; |
| | 4132 | } |
| | 4133 | |
| | 4134 | RenderPolygon.NumberOfVertices = 3; |
| | 4135 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL; |
| | 4136 | } |
| | 4137 | |
| | 4138 | { |
| | 4139 | int outcode = TriangleWithinFrustrum(); |
| | 4140 | POLYHEADER fakeHeader; |
| | 4141 | fakeHeader.PolyFlags = iflag_transparent; |
| | 4142 | do |
| | 4143 | { |
| | 4144 | if (outcode) |
| | 4145 | { |
| | 4146 | if(outcode != 2) |
| | 4147 | { |
| | 4148 | GouraudPolygon_ClipWithZ(); |
| | 4149 | |
| | 4150 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4151 | continue; |
| | 4152 | |
| | 4153 | GouraudPolygon_ClipWithNegativeX(); |
| | 4154 | |
| | 4155 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4156 | continue; |
| | 4157 | |
| | 4158 | GouraudPolygon_ClipWithPositiveY(); |
| | 4159 | |
| | 4160 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4161 | continue; |
| | 4162 | |
| | 4163 | GouraudPolygon_ClipWithNegativeY(); |
| | 4164 | |
| | 4165 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4166 | continue; |
| | 4167 | |
| | 4168 | GouraudPolygon_ClipWithPositiveX(); |
| | 4169 | |
| | 4170 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4171 | continue; |
| | 4172 | |
| | 4173 | ZBufferedGouraudPolygon_Output(&fakeHeader,RenderPolygon.Vertices); |
| | 4174 | } |
| | 4175 | else |
| | 4176 | { |
| | 4177 | ZBufferedGouraudPolygon_Output(&fakeHeader,VerticesBuffer); |
| | 4178 | } |
| | 4179 | } |
| | 4180 | |
| | 4181 | } while (0); |
| | 4182 | |
| | 4183 | } |
| | 4184 | { |
| | 4185 | int i = 0; |
| | 4186 | for (; i < 3; i++) |
| | 4187 | { |
| | 4188 | VerticesBuffer[i].X = vertices[i+2].vx; |
| | 4189 | VerticesBuffer[i].Y = vertices[i+2].vy; |
| | 4190 | VerticesBuffer[i].Z = vertices[i+2].vz; |
| | 4191 | |
| | 4192 | VerticesBuffer[i].A = (particlePtr->Colour >> 24)&255; |
| | 4193 | VerticesBuffer[i].R = (particlePtr->Colour >> 16)&255; |
| | 4194 | VerticesBuffer[i].G = (particlePtr->Colour >> 8)&255; |
| | 4195 | VerticesBuffer[i].B = (particlePtr->Colour) & 255; |
| | 4196 | } |
| | 4197 | |
| | 4198 | RenderPolygon.NumberOfVertices = 3; |
| | 4199 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL; |
| | 4200 | } |
| | 4201 | |
| | 4202 | { |
| | 4203 | int outcode = TriangleWithinFrustrum(); |
| | 4204 | POLYHEADER fakeHeader; |
| | 4205 | fakeHeader.PolyFlags = iflag_transparent; |
| | 4206 | |
| | 4207 | do |
| | 4208 | { |
| | 4209 | if (outcode) |
| | 4210 | { |
| | 4211 | if(outcode != 2) |
| | 4212 | { |
| | 4213 | GouraudPolygon_ClipWithZ(); |
| | 4214 | |
| | 4215 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4216 | continue; |
| | 4217 | |
| | 4218 | GouraudPolygon_ClipWithNegativeX(); |
| | 4219 | |
| | 4220 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4221 | continue; |
| | 4222 | |
| | 4223 | GouraudPolygon_ClipWithPositiveY(); |
| | 4224 | |
| | 4225 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4226 | continue; |
| | 4227 | |
| | 4228 | GouraudPolygon_ClipWithNegativeY(); |
| | 4229 | |
| | 4230 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4231 | continue; |
| | 4232 | |
| | 4233 | GouraudPolygon_ClipWithPositiveX(); |
| | 4234 | |
| | 4235 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4236 | continue; |
| | 4237 | |
| | 4238 | ZBufferedGouraudPolygon_Output(&fakeHeader, RenderPolygon.Vertices); |
| | 4239 | } |
| | 4240 | else |
| | 4241 | { |
| | 4242 | ZBufferedGouraudPolygon_Output(&fakeHeader, VerticesBuffer); |
| | 4243 | } |
| | 4244 | } |
| | 4245 | |
| | 4246 | } while(0); |
| | 4247 | } |
| | 4248 | } |
| | 4249 | |
| | 4250 | void OutputTranslucentPolyList() |
| | 4251 | { |
| | 4252 | int i; |
| | 4253 | for (i = 0; i < CurrentNumberOfTranslucentPolygons; i++) |
| | 4254 | { |
| | 4255 | if(TranslucentPolygons[i].polygon_header.PolyFlags & iflag_glowing) |
| | 4256 | { |
| | 4257 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_GLOWING; |
| | 4258 | TranslucentPolygons[i].polygon.Vertices->A = 250; |
| | 4259 | } |
| | 4260 | else |
| | 4261 | { |
| | 4262 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL; |
| | 4263 | } |
| | 4264 | |
| | 4265 | RenderPolygon.NumberOfVertices = TranslucentPolygons[i].polygon.NumberOfVertices; |
| | 4266 | ZBufferedGouraudTexturedPolygon_Output(&TranslucentPolygons[i].polygon_header, TranslucentPolygons[i].polygon.Vertices); |
| | 4267 | } |
| | 4268 | } |
| | 4269 | |
| | 4270 | static const int CuboidPolyVertexU[][4] = |
| | 4271 | { |
| | 4272 | {1,1,1,1}, |
| | 4273 | |
| | 4274 | {127,127,0,0}, |
| | 4275 | {128,128,255,255}, |
| | 4276 | |
| | 4277 | {127,127,0,0}, |
| | 4278 | {128,128,255,255}, |
| | 4279 | }; |
| | 4280 | |
| | 4281 | static const int CuboidPolyVertexV[][4] = |
| | 4282 | { |
| | 4283 | {1,1,1,1}, |
| | 4284 | |
| | 4285 | {127,0,0,127}, |
| | 4286 | {127,0,0,127}, |
| | 4287 | {128,255,255,128}, |
| | 4288 | {128,255,255,128}, |
| | 4289 | }; |
| | 4290 | |
| | 4291 | void RenderMirrorSurface() |
| | 4292 | { |
| | 4293 | VECTORCH translatedPts[4] = |
| | 4294 | { |
| | 4295 | {-5596,-932,-1872}, |
| | 4296 | {-5596,-932,-702}, |
| | 4297 | {-5596,1212,-702}, |
| | 4298 | {-5596,1212,-1872}, |
| | 4299 | }; |
| | 4300 | |
| | 4301 | int mirrorUV[]= { 0,0, 127<<16,0, 127<<16,127<<16, 0,127<<16}; |
| | 4302 | |
| | 4303 | POLYHEADER fakeHeader; |
| | 4304 | |
| | 4305 | fakeHeader.PolyFlags = iflag_transparent; |
| | 4306 | fakeHeader.PolyColour = CloudyImageNumber; |
| | 4307 | |
| | 4308 | { |
| | 4309 | int i=0; |
| | 4310 | for (; i < 4; i++) |
| | 4311 | { |
| | 4312 | VerticesBuffer[i].A = 128; |
| | 4313 | |
| | 4314 | TranslatePointIntoViewspace(&translatedPts[i]); |
| | 4315 | VerticesBuffer[i].X = translatedPts[i].vx; |
| | 4316 | VerticesBuffer[i].Y = translatedPts[i].vy; |
| | 4317 | VerticesBuffer[i].Z = translatedPts[i].vz; |
| | 4318 | VerticesBuffer[i].U = mirrorUV[i*2]; |
| | 4319 | VerticesBuffer[i].V = mirrorUV[i*2+1]; |
| | 4320 | |
| | 4321 | VerticesBuffer[i].R = 255; |
| | 4322 | VerticesBuffer[i].G = 255; |
| | 4323 | VerticesBuffer[i].B = 255; |
| | 4324 | VerticesBuffer[i].SpecularR = 0; |
| | 4325 | VerticesBuffer[i].SpecularG = 0; |
| | 4326 | VerticesBuffer[i].SpecularB = 0; |
| | 4327 | } |
| | 4328 | |
| | 4329 | RenderPolygon.NumberOfVertices = 4; |
| | 4330 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_COLOUR; |
| | 4331 | } |
| | 4332 | |
| | 4333 | GouraudTexturedPolygon_ClipWithZ(); |
| | 4334 | |
| | 4335 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4336 | return; |
| | 4337 | |
| | 4338 | GouraudTexturedPolygon_ClipWithNegativeX(); |
| | 4339 | |
| | 4340 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4341 | return; |
| | 4342 | |
| | 4343 | GouraudTexturedPolygon_ClipWithPositiveY(); |
| | 4344 | |
| | 4345 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4346 | return; |
| | 4347 | |
| | 4348 | GouraudTexturedPolygon_ClipWithNegativeY(); |
| | 4349 | |
| | 4350 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4351 | return; |
| | 4352 | |
| | 4353 | GouraudTexturedPolygon_ClipWithPositiveX(); |
| | 4354 | |
| | 4355 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4356 | return; |
| | 4357 | |
| | 4358 | ZBufferedGouraudTexturedPolygon_Output(&fakeHeader, RenderPolygon.Vertices); |
| | 4359 | } |
| | 4360 | |
| | 4361 | void RenderMirrorSurface2() |
| | 4362 | { |
| | 4363 | VECTORCH translatedPts[4] = |
| | 4364 | { |
| | 4365 | {-5596,-592,562}, |
| | 4366 | {-5596,-592,1344}, |
| | 4367 | {-5596,140,1344}, |
| | 4368 | {-5596,140,562}, |
| | 4369 | |
| | 4370 | }; |
| | 4371 | |
| | 4372 | int mirrorUV[]= { 0,0, 127<<16,0, 127<<16,127<<16, 0,127<<16}; |
| | 4373 | |
| | 4374 | POLYHEADER fakeHeader; |
| | 4375 | |
| | 4376 | fakeHeader.PolyFlags = iflag_transparent; |
| | 4377 | fakeHeader.PolyColour = CloudyImageNumber; |
| | 4378 | |
| | 4379 | { |
| | 4380 | int i=0; |
| | 4381 | for (; i < 4; i++) |
| | 4382 | { |
| | 4383 | VerticesBuffer[i].A = 128; |
| | 4384 | |
| | 4385 | TranslatePointIntoViewspace(&translatedPts[i]); |
| | 4386 | VerticesBuffer[i].X = translatedPts[i].vx; |
| | 4387 | VerticesBuffer[i].Y = translatedPts[i].vy; |
| | 4388 | VerticesBuffer[i].Z = translatedPts[i].vz; |
| | 4389 | VerticesBuffer[i].U = mirrorUV[i*2]; |
| | 4390 | VerticesBuffer[i].V = mirrorUV[i*2+1]; |
| | 4391 | |
| | 4392 | VerticesBuffer[i].R = 255; |
| | 4393 | VerticesBuffer[i].G = 255; |
| | 4394 | VerticesBuffer[i].B = 255; |
| | 4395 | VerticesBuffer[i].SpecularR = 0; |
| | 4396 | VerticesBuffer[i].SpecularG = 0; |
| | 4397 | VerticesBuffer[i].SpecularB = 0; |
| | 4398 | } |
| | 4399 | |
| | 4400 | RenderPolygon.NumberOfVertices = 4; |
| | 4401 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_COLOUR; |
| | 4402 | } |
| | 4403 | |
| | 4404 | GouraudTexturedPolygon_ClipWithZ(); |
| | 4405 | |
| | 4406 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4407 | return; |
| | 4408 | |
| | 4409 | GouraudTexturedPolygon_ClipWithNegativeX(); |
| | 4410 | |
| | 4411 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4412 | return; |
| | 4413 | |
| | 4414 | GouraudTexturedPolygon_ClipWithPositiveY(); |
| | 4415 | |
| | 4416 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4417 | return; |
| | 4418 | |
| | 4419 | GouraudTexturedPolygon_ClipWithNegativeY(); |
| | 4420 | |
| | 4421 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4422 | return; |
| | 4423 | |
| | 4424 | GouraudTexturedPolygon_ClipWithPositiveX(); |
| | 4425 | |
| | 4426 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4427 | return; |
| | 4428 | |
| | 4429 | ZBufferedGouraudTexturedPolygon_Output(&fakeHeader, RenderPolygon.Vertices); |
| | 4430 | } |
| | 4431 | |
| | 4432 | #define OCTAVES 3 |
| | 4433 | int u[OCTAVES]; |
| | 4434 | int v[OCTAVES]; |
| | 4435 | int du[OCTAVES]; |
| | 4436 | int dv[OCTAVES]; |
| | 4437 | |
| | 4438 | int SkyColour_R = 200; |
| | 4439 | int SkyColour_G = 200; |
| | 4440 | int SkyColour_B = 200; |
| | 4441 | |
| | 4442 | void init_sky() |
| | 4443 | { |
| | 4444 | int i = 0; |
| | 4445 | for(; i < OCTAVES; i++) |
| | 4446 | { |
| | 4447 | u[i] = (FastRandom() & 65535)*128; |
| | 4448 | v[i] = (FastRandom() & 65535)*128; |
| | 4449 | du[i] = ( ((FastRandom() & 65535)-32768) * (i+1) )*8; |
| | 4450 | dv[i] = ( ((FastRandom() & 65535)-32768) * (i+1) )*8; |
| | 4451 | } |
| | 4452 | } |
| | 4453 | |
| | 4454 | void RenderSky() |
| | 4455 | { |
| | 4456 | int x = -10; |
| | 4457 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_GLOWING; |
| | 4458 | |
| | 4459 | { |
| | 4460 | int i=0; |
| | 4461 | for (; i < OCTAVES; i++) |
| | 4462 | { |
| | 4463 | u[i] += MUL_FIXED(du[i], NormalFrameTime); |
| | 4464 | v[i] += MUL_FIXED(dv[i], NormalFrameTime); |
| | 4465 | } |
| | 4466 | } |
| | 4467 | |
| | 4468 | for(; x <= 10; x++) |
| | 4469 | { |
| | 4470 | int z = -10; |
| | 4471 | for(; z <= 10; z++) |
| | 4472 | { |
| | 4473 | int t = 255; |
| | 4474 | int size = 65536*128; |
| | 4475 | int o = 0; |
| | 4476 | |
| | 4477 | for (o=0; o < OCTAVES; o++) |
| | 4478 | { |
| | 4479 | { |
| | 4480 | VECTORCH translatedPts[4] = |
| | 4481 | { |
| | 4482 | {-1024,-1000,-1024}, |
| | 4483 | {-1024,-1000, 1024}, |
| | 4484 | { 1024,-1000, 1024}, |
| | 4485 | { 1024,-1000,-1024}, |
| | 4486 | |
| | 4487 | }; |
| | 4488 | |
| | 4489 | int i = 0; |
| | 4490 | for (; i < 4; i++) |
| | 4491 | { |
| | 4492 | VerticesBuffer[i].A = t; |
| | 4493 | translatedPts[i].vx += 2048*x;//+(Global_VDB.VDB_World.vx*7)/8; |
| | 4494 | translatedPts[i].vz += 2048*z;//+(Global_VDB.VDB_World.vz*7)/8; |
| | 4495 | |
| | 4496 | // RotateVector(&translatedPts[i],&(Global_VDB.VDB_Mat)); |
| | 4497 | |
| | 4498 | // translatedPts[i].vy = MUL_FIXED(translatedPts[i].vy,87381); |
| | 4499 | translatedPts[i].vx += Global_VDB.VDB_World.vx; |
| | 4500 | translatedPts[i].vy += Global_VDB.VDB_World.vy; |
| | 4501 | translatedPts[i].vz += Global_VDB.VDB_World.vz; |
| | 4502 | TranslatePointIntoViewspace(&translatedPts[i]); |
| | 4503 | |
| | 4504 | VerticesBuffer[i].X = translatedPts[i].vx; |
| | 4505 | VerticesBuffer[i].Y = translatedPts[i].vy; |
| | 4506 | VerticesBuffer[i].Z = translatedPts[i].vz; |
| | 4507 | |
| | 4508 | switch (PlayerStatus.VisionMode) |
| | 4509 | { |
| | 4510 | default: |
| | 4511 | case VISION_MODE_NORMAL: |
| | 4512 | { |
| | 4513 | VerticesBuffer[i].R = SkyColour_R; |
| | 4514 | VerticesBuffer[i].G = SkyColour_G; |
| | 4515 | VerticesBuffer[i].B = SkyColour_B; |
| | 4516 | break; |
| | 4517 | } |
| | 4518 | case VISION_MODE_IMAGEINTENSIFIER: |
| | 4519 | { |
| | 4520 | VerticesBuffer[i].R = 0; |
| | 4521 | VerticesBuffer[i].G = 255; |
| | 4522 | VerticesBuffer[i].B = 0; |
| | 4523 | break; |
| | 4524 | } |
| | 4525 | case VISION_MODE_PRED_THERMAL: |
| | 4526 | case VISION_MODE_PRED_SEEALIENS: |
| | 4527 | case VISION_MODE_PRED_SEEPREDTECH: |
| | 4528 | { |
| | 4529 | VerticesBuffer[i].R = 0; |
| | 4530 | VerticesBuffer[i].G = 0; |
| | 4531 | VerticesBuffer[i].B = 255; |
| | 4532 | break; |
| | 4533 | } |
| | 4534 | } |
| | 4535 | } |
| | 4536 | |
| | 4537 | VerticesBuffer[0].U = (u[o]+size*x); |
| | 4538 | VerticesBuffer[0].V = (v[o]+size*z); |
| | 4539 | VerticesBuffer[1].U = (u[o]+size*x); |
| | 4540 | VerticesBuffer[1].V = (v[o]+size*(z+1)); |
| | 4541 | VerticesBuffer[2].U = (u[o]+size*(x+1)); |
| | 4542 | VerticesBuffer[2].V = (v[o]+size*(z+1)); |
| | 4543 | VerticesBuffer[3].U = (u[o]+size*(x+1)); |
| | 4544 | VerticesBuffer[3].V = (v[o]+size*z); |
| | 4545 | |
| | 4546 | RenderPolygon.NumberOfVertices = 4; |
| | 4547 | } |
| | 4548 | |
| | 4549 | GouraudTexturedPolygon_ClipWithZ(); |
| | 4550 | |
| | 4551 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 4552 | { |
| | 4553 | GouraudTexturedPolygon_ClipWithNegativeX(); |
| | 4554 | |
| | 4555 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 4556 | { |
| | 4557 | GouraudTexturedPolygon_ClipWithPositiveY(); |
| | 4558 | |
| | 4559 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 4560 | { |
| | 4561 | GouraudTexturedPolygon_ClipWithNegativeY(); |
| | 4562 | |
| | 4563 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 4564 | { |
| | 4565 | GouraudTexturedPolygon_ClipWithPositiveX(); |
| | 4566 | |
| | 4567 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 4568 | SkyPolygon_Output(RenderPolygon.Vertices); |
| | 4569 | } |
| | 4570 | } |
| | 4571 | } |
| | 4572 | } |
| | 4573 | t /= 2; |
| | 4574 | size *= 2; |
| | 4575 | } |
| | 4576 | } |
| | 4577 | } |
| | 4578 | } |
| | 4579 | |
| | 4580 | void DrawWaterFallPoly(VECTORCH *v) |
| | 4581 | { |
| | 4582 | POLYHEADER fakeHeader; |
| | 4583 | |
| | 4584 | fakeHeader.PolyFlags = iflag_transparent; |
| | 4585 | fakeHeader.PolyColour = CloudyImageNumber; |
| | 4586 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL; |
| | 4587 | |
| | 4588 | { |
| | 4589 | static int wv = 0; |
| | 4590 | unsigned int a = 0; |
| | 4591 | |
| | 4592 | for (; a < 4; a++) |
| | 4593 | { |
| | 4594 | VerticesBuffer[a].A = 128; |
| | 4595 | VerticesBuffer[a].U = (v[a].vz)<<11; |
| | 4596 | VerticesBuffer[a].V = (v[a].vy<<10)-wv; |
| | 4597 | |
| | 4598 | TranslatePointIntoViewspace(&v[a]); |
| | 4599 | VerticesBuffer[a].X = v[a].vx; |
| | 4600 | VerticesBuffer[a].Y = v[a].vy; |
| | 4601 | VerticesBuffer[a].Z = v[a].vz; |
| | 4602 | VerticesBuffer[a].R = 200; |
| | 4603 | VerticesBuffer[a].G = 200; |
| | 4604 | VerticesBuffer[a].B = 255; |
| | 4605 | VerticesBuffer[a].SpecularR = 0; |
| | 4606 | VerticesBuffer[a].SpecularG = 0; |
| | 4607 | VerticesBuffer[a].SpecularB = 0; |
| | 4608 | } |
| | 4609 | |
| | 4610 | wv += NormalFrameTime * 2; |
| | 4611 | RenderPolygon.NumberOfVertices = 4; |
| | 4612 | } |
| | 4613 | |
| | 4614 | GouraudTexturedPolygon_ClipWithZ(); |
| | 4615 | |
| | 4616 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 4617 | { |
| | 4618 | GouraudTexturedPolygon_ClipWithNegativeX(); |
| | 4619 | |
| | 4620 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 4621 | { |
| | 4622 | GouraudTexturedPolygon_ClipWithPositiveY(); |
| | 4623 | |
| | 4624 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 4625 | { |
| | 4626 | GouraudTexturedPolygon_ClipWithNegativeY(); |
| | 4627 | |
| | 4628 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 4629 | { |
| | 4630 | GouraudTexturedPolygon_ClipWithPositiveX(); |
| | 4631 | |
| | 4632 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 4633 | ZBufferedGouraudTexturedPolygon_Output(&fakeHeader, RenderPolygon.Vertices); |
| | 4634 | } |
| | 4635 | } |
| | 4636 | } |
| | 4637 | } |
| | 4638 | } |
| | 4639 | |
| | 4640 | void RenderWaterFall(int xOrigin, int yOrigin, int zOrigin) |
| | 4641 | { |
| | 4642 | int i,z; |
| | 4643 | VECTORCH v[4]; |
| | 4644 | |
| | 4645 | { |
| | 4646 | int waterfallX[9]; |
| | 4647 | int waterfallY[9]; |
| | 4648 | int waterfallZ[9]; |
| | 4649 | int waterfallZScale[9]; |
| | 4650 | |
| | 4651 | for (i=0; i < 9; i++) |
| | 4652 | { |
| | 4653 | int u = (i*65536)/8; |
| | 4654 | |
| | 4655 | int b = MUL_FIXED(2*u,(65536-u)); |
| | 4656 | int c = MUL_FIXED(u,u); |
| | 4657 | int y3 = (4742-yOrigin); |
| | 4658 | int x3 = 2000; |
| | 4659 | int y2 = 2000; |
| | 4660 | int x2 = 1500; |
| | 4661 | |
| | 4662 | waterfallX[i] = MUL_FIXED(b,x2)+MUL_FIXED(c,x3); |
| | 4663 | waterfallY[i] = yOrigin+MUL_FIXED(b,y2)+MUL_FIXED(c,y3); |
| | 4664 | waterfallZ[i] = zOrigin+MUL_FIXED((66572-zOrigin),u); |
| | 4665 | waterfallZScale[i] = ONE_FIXED+b/2-c; |
| | 4666 | |
| | 4667 | if (i != 8) |
| | 4668 | { |
| | 4669 | waterfallZScale[i]+=(FastRandom()&8191); |
| | 4670 | waterfallY[i]-=(FastRandom()&127); |
| | 4671 | } |
| | 4672 | } |
| | 4673 | |
| | 4674 | for (z=0; z<8; z++) |
| | 4675 | for (i=0; i<8; i++) |
| | 4676 | { |
| | 4677 | v[0].vx = xOrigin+MUL_FIXED(waterfallX[i],waterfallZScale[z]); |
| | 4678 | v[1].vx = xOrigin+MUL_FIXED(waterfallX[i],waterfallZScale[z+1]); |
| | 4679 | v[2].vx = xOrigin+MUL_FIXED(waterfallX[i+1],waterfallZScale[z+1]); |
| | 4680 | v[3].vx = xOrigin+MUL_FIXED(waterfallX[i+1],waterfallZScale[z]); |
| | 4681 | v[0].vy = waterfallY[i]; |
| | 4682 | v[1].vy = waterfallY[i]; |
| | 4683 | v[2].vy = waterfallY[i+1]; |
| | 4684 | v[3].vy = waterfallY[i+1]; |
| | 4685 | |
| | 4686 | v[0].vz = waterfallZ[z]; |
| | 4687 | v[1].vz = waterfallZ[z+1]; |
| | 4688 | v[2].vz = v[1].vz; |
| | 4689 | v[3].vz = v[0].vz; |
| | 4690 | |
| | 4691 | DrawWaterFallPoly(v); |
| | 4692 | } |
| | 4693 | |
| | 4694 | for (z=0; z<3; z++) |
| | 4695 | { |
| | 4696 | v[0].vx = xOrigin+MUL_FIXED(waterfallX[8],waterfallZScale[z+1]); |
| | 4697 | v[1].vx = xOrigin+MUL_FIXED(waterfallX[8],waterfallZScale[z]); |
| | 4698 | v[2].vx = 179450; |
| | 4699 | v[3].vx = 179450; |
| | 4700 | |
| | 4701 | v[0].vy = 4742; |
| | 4702 | v[1].vy = 4742; |
| | 4703 | v[2].vy = 4742; |
| | 4704 | v[3].vy = 4742; |
| | 4705 | |
| | 4706 | v[0].vz = waterfallZ[z]; |
| | 4707 | v[1].vz = waterfallZ[z+1]; |
| | 4708 | v[2].vz = v[1].vz; |
| | 4709 | v[3].vz = v[0].vz; |
| | 4710 | |
| | 4711 | DrawWaterFallPoly(v); |
| | 4712 | } |
| | 4713 | |
| | 4714 | for (z=0; z<8; z++) |
| | 4715 | for (i=0; i<16; i++) |
| | 4716 | { |
| | 4717 | int xOffset,xOffset2; |
| | 4718 | |
| | 4719 | if (z < 3) |
| | 4720 | xOffset = 179450; |
| | 4721 | else |
| | 4722 | xOffset = xOrigin+MUL_FIXED(waterfallX[8],waterfallZScale[z]); |
| | 4723 | |
| | 4724 | if (z < 2) |
| | 4725 | xOffset2 = 179450; |
| | 4726 | else |
| | 4727 | xOffset2 = xOrigin+MUL_FIXED(waterfallX[8],waterfallZScale[z+1]); |
| | 4728 | |
| | 4729 | v[0].vx = xOffset; |
| | 4730 | v[1].vx = xOffset2; |
| | 4731 | v[2].vx = xOffset2; |
| | 4732 | v[3].vx = xOffset; |
| | 4733 | |
| | 4734 | v[0].vy = 4742+i*4096; |
| | 4735 | v[1].vy = 4742+i*4096; |
| | 4736 | v[2].vy = 4742+(i+1)*4096; |
| | 4737 | v[3].vy = 4742+(i+1)*4096; |
| | 4738 | |
| | 4739 | v[0].vz = waterfallZ[z]; |
| | 4740 | v[1].vz = waterfallZ[z+1]; |
| | 4741 | v[2].vz = v[1].vz; |
| | 4742 | v[3].vz = v[0].vz; |
| | 4743 | |
| | 4744 | DrawWaterFallPoly(v); |
| | 4745 | } |
| | 4746 | } |
| | 4747 | } |
| | 4748 | |
| | 4749 | void RenderPredatorTargetingSegment(int theta, int scale, int drawInRed) |
| | 4750 | { |
| | 4751 | VECTOR2D offset[4]; |
| | 4752 | POLYHEADER fakeHeader; |
| | 4753 | int centreX,centreY; |
| | 4754 | int z = ONE_FIXED - scale; |
| | 4755 | z = MUL_FIXED(MUL_FIXED(z, z), 2048); |
| | 4756 | |
| | 4757 | { |
| | 4758 | extern int SmartTargetSightX, SmartTargetSightY; |
| | 4759 | centreY = MUL_FIXED( (SmartTargetSightY-(ScreenDescriptorBlock.SDB_Height<<15)) / Global_VDB.VDB_ProjY,z); |
| | 4760 | |
| | 4761 | centreX = (CHEATMODE_MIRROR == UserProfile.active_bonus) ? |
| | 4762 | MUL_FIXED((-(SmartTargetSightX-(ScreenDescriptorBlock.SDB_Width<<15))) / Global_VDB.VDB_ProjX,z) : |
| | 4763 | MUL_FIXED(( SmartTargetSightX-(ScreenDescriptorBlock.SDB_Width<<15)) / Global_VDB.VDB_ProjX,z); |
| | 4764 | } |
| | 4765 | |
| | 4766 | z = (float)z * CameraZoomScale; |
| | 4767 | |
| | 4768 | { |
| | 4769 | int a = 160; |
| | 4770 | int b = 40; |
| | 4771 | |
| | 4772 | /* tan(30) = 1/sqrt(3), & 65536/(sqrt(3)) = 37837 */ |
| | 4773 | |
| | 4774 | int y = MUL_FIXED(37837,a+20); |
| | 4775 | |
| | 4776 | offset[0].vx = -a+MUL_FIXED(113512,b); |
| | 4777 | offset[0].vy = y-b; |
| | 4778 | |
| | 4779 | offset[1].vx = -offset[0].vx; |
| | 4780 | offset[1].vy = y-b; |
| | 4781 | |
| | 4782 | offset[2].vx = a; |
| | 4783 | offset[2].vy = y; |
| | 4784 | |
| | 4785 | offset[3].vx = -a; |
| | 4786 | offset[3].vy = y; |
| | 4787 | |
| | 4788 | if (theta) |
| | 4789 | { |
| | 4790 | RotateVertex(&offset[0],theta); |
| | 4791 | RotateVertex(&offset[1],theta); |
| | 4792 | RotateVertex(&offset[2],theta); |
| | 4793 | RotateVertex(&offset[3],theta); |
| | 4794 | } |
| | 4795 | |
| | 4796 | if (CHEATMODE_MIRROR == UserProfile.active_bonus) |
| | 4797 | { |
| | 4798 | offset[0].vx = -offset[0].vx; |
| | 4799 | offset[1].vx = -offset[1].vx; |
| | 4800 | offset[2].vx = -offset[2].vx; |
| | 4801 | offset[3].vx = -offset[3].vx; |
| | 4802 | } |
| | 4803 | |
| | 4804 | VerticesBuffer[0].X = offset[0].vx+centreX; |
| | 4805 | VerticesBuffer[0].Y = MUL_FIXED(offset[0].vy,87381)+centreY; |
| | 4806 | |
| | 4807 | VerticesBuffer[1].X = offset[1].vx+centreX; |
| | 4808 | VerticesBuffer[1].Y = MUL_FIXED(offset[1].vy,87381)+centreY; |
| | 4809 | |
| | 4810 | VerticesBuffer[2].X = offset[2].vx+centreX; |
| | 4811 | VerticesBuffer[2].Y = MUL_FIXED(offset[2].vy,87381)+centreY; |
| | 4812 | |
| | 4813 | VerticesBuffer[3].X = offset[3].vx+centreX; |
| | 4814 | VerticesBuffer[3].Y = MUL_FIXED(offset[3].vy,87381)+centreY; |
| | 4815 | } |
| | 4816 | |
| | 4817 | fakeHeader.PolyFlags = iflag_transparent; |
| | 4818 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_GLOWING; |
| | 4819 | |
| | 4820 | { |
| | 4821 | int i=0; |
| | 4822 | for (; i < 4; i++) |
| | 4823 | { |
| | 4824 | VerticesBuffer[i].A = 128; |
| | 4825 | VerticesBuffer[i].Z = z; |
| | 4826 | VerticesBuffer[i].R = 255; |
| | 4827 | VerticesBuffer[i].G = VerticesBuffer[i].B = drawInRed ? 0 : 255; |
| | 4828 | } |
| | 4829 | |
| | 4830 | RenderPolygon.NumberOfVertices = 4; |
| | 4831 | } |
| | 4832 | |
| | 4833 | GouraudPolygon_ClipWithZ(); |
| | 4834 | |
| | 4835 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4836 | return; |
| | 4837 | |
| | 4838 | GouraudPolygon_ClipWithNegativeX(); |
| | 4839 | |
| | 4840 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4841 | return; |
| | 4842 | |
| | 4843 | GouraudPolygon_ClipWithPositiveY(); |
| | 4844 | |
| | 4845 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4846 | return; |
| | 4847 | |
| | 4848 | GouraudPolygon_ClipWithNegativeY(); |
| | 4849 | |
| | 4850 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4851 | return; |
| | 4852 | |
| | 4853 | GouraudPolygon_ClipWithPositiveX(); |
| | 4854 | |
| | 4855 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4856 | return; |
| | 4857 | |
| | 4858 | ZBufferedGouraudPolygon_Output(&fakeHeader, RenderPolygon.Vertices); |
| | 4859 | |
| | 4860 | if (drawInRed) |
| | 4861 | { |
| | 4862 | VerticesBuffer[0].X = MUL_FIXED(offset[3].vx,scale*8)+centreX; |
| | 4863 | VerticesBuffer[0].Y = MUL_FIXED(MUL_FIXED(offset[3].vy,scale*8),87381)+centreY; |
| | 4864 | |
| | 4865 | VerticesBuffer[1].X = MUL_FIXED(offset[2].vx,scale*8)+centreX; |
| | 4866 | VerticesBuffer[1].Y = MUL_FIXED(MUL_FIXED(offset[2].vy,scale*8),87381)+centreY; |
| | 4867 | |
| | 4868 | VerticesBuffer[2].X = offset[2].vx+centreX; |
| | 4869 | VerticesBuffer[2].Y = MUL_FIXED(offset[2].vy,87381)+centreY; |
| | 4870 | |
| | 4871 | VerticesBuffer[3].X = offset[3].vx+centreX; |
| | 4872 | VerticesBuffer[3].Y = MUL_FIXED(offset[3].vy,87381)+centreY; |
| | 4873 | |
| | 4874 | { |
| | 4875 | int i=0; |
| | 4876 | for (; i < 2; i++) |
| | 4877 | { |
| | 4878 | VerticesBuffer[i].A = 0; |
| | 4879 | VerticesBuffer[i].Z = z; |
| | 4880 | VerticesBuffer[i].R = 255; |
| | 4881 | VerticesBuffer[i].G = 0; |
| | 4882 | VerticesBuffer[i].B = 0; |
| | 4883 | } |
| | 4884 | |
| | 4885 | for (i=2; i < 4; i++) |
| | 4886 | { |
| | 4887 | VerticesBuffer[i].A = 128; |
| | 4888 | VerticesBuffer[i].Z = z; |
| | 4889 | VerticesBuffer[i].R = 255; |
| | 4890 | VerticesBuffer[i].G = 0; |
| | 4891 | VerticesBuffer[i].B = 0; |
| | 4892 | } |
| | 4893 | |
| | 4894 | RenderPolygon.NumberOfVertices = 4; |
| | 4895 | } |
| | 4896 | |
| | 4897 | GouraudPolygon_ClipWithZ(); |
| | 4898 | |
| | 4899 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4900 | return; |
| | 4901 | |
| | 4902 | GouraudPolygon_ClipWithNegativeX(); |
| | 4903 | |
| | 4904 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4905 | return; |
| | 4906 | |
| | 4907 | GouraudPolygon_ClipWithPositiveY(); |
| | 4908 | |
| | 4909 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4910 | return; |
| | 4911 | |
| | 4912 | GouraudPolygon_ClipWithNegativeY(); |
| | 4913 | |
| | 4914 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4915 | return; |
| | 4916 | |
| | 4917 | GouraudPolygon_ClipWithPositiveX(); |
| | 4918 | |
| | 4919 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4920 | return; |
| | 4921 | |
| | 4922 | ZBufferedGouraudPolygon_Output(&fakeHeader,RenderPolygon.Vertices); |
| | 4923 | } |
| | 4924 | } |
| | 4925 | |
| | 4926 | void RenderPredatorPlasmaCasterCharge(int value, VECTORCH *worldOffsetPtr, MATRIXCH *orientationPtr) |
| | 4927 | { |
| | 4928 | POLYHEADER fakeHeader; |
| | 4929 | VECTORCH translatedPts[4]; |
| | 4930 | int halfWidth = 100; |
| | 4931 | int halfHeight = 4; |
| | 4932 | int z = -1; |
| | 4933 | |
| | 4934 | translatedPts[0].vx = -halfWidth; |
| | 4935 | translatedPts[0].vy = z; |
| | 4936 | translatedPts[0].vz = -halfHeight-4; |
| | 4937 | |
| | 4938 | translatedPts[1].vx = -halfWidth+MUL_FIXED(value,2*halfWidth-10); |
| | 4939 | translatedPts[1].vy = z; |
| | 4940 | translatedPts[1].vz = -halfHeight-4; |
| | 4941 | |
| | 4942 | translatedPts[2].vx = -halfWidth+MUL_FIXED(value,2*halfWidth-10); |
| | 4943 | translatedPts[2].vy = z; |
| | 4944 | translatedPts[2].vz = halfHeight-4; |
| | 4945 | |
| | 4946 | translatedPts[3].vx = -halfWidth; |
| | 4947 | translatedPts[3].vy = z; |
| | 4948 | translatedPts[3].vz = halfHeight-4; |
| | 4949 | |
| | 4950 | fakeHeader.PolyFlags = iflag_transparent; |
| | 4951 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_GLOWING; |
| | 4952 | |
| | 4953 | { |
| | 4954 | int i=0; |
| | 4955 | for (; i < 4; i++) |
| | 4956 | { |
| | 4957 | VerticesBuffer[i].A = 255; |
| | 4958 | |
| | 4959 | RotateVector(&(translatedPts[i]),orientationPtr); |
| | 4960 | translatedPts[i].vx += worldOffsetPtr->vx; |
| | 4961 | translatedPts[i].vy += worldOffsetPtr->vy; |
| | 4962 | translatedPts[i].vz += worldOffsetPtr->vz; |
| | 4963 | TranslatePointIntoViewspace(&translatedPts[i]); |
| | 4964 | |
| | 4965 | VerticesBuffer[i].X = translatedPts[i].vx; |
| | 4966 | VerticesBuffer[i].Y = translatedPts[i].vy; |
| | 4967 | VerticesBuffer[i].Z = translatedPts[i].vz; |
| | 4968 | |
| | 4969 | VerticesBuffer[i].R = 32; |
| | 4970 | VerticesBuffer[i].G = 0; |
| | 4971 | VerticesBuffer[i].B = 0; |
| | 4972 | } |
| | 4973 | |
| | 4974 | RenderPolygon.NumberOfVertices = 4; |
| | 4975 | } |
| | 4976 | |
| | 4977 | { |
| | 4978 | int outcode = QuadWithinFrustrum(); |
| | 4979 | |
| | 4980 | if (outcode) |
| | 4981 | { |
| | 4982 | if (outcode != 2) |
| | 4983 | { |
| | 4984 | GouraudPolygon_ClipWithZ(); |
| | 4985 | |
| | 4986 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4987 | return; |
| | 4988 | |
| | 4989 | GouraudPolygon_ClipWithNegativeX(); |
| | 4990 | |
| | 4991 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4992 | return; |
| | 4993 | |
| | 4994 | GouraudPolygon_ClipWithPositiveY(); |
| | 4995 | |
| | 4996 | if(RenderPolygon.NumberOfVertices < 3) |
| | 4997 | return; |
| | 4998 | |
| | 4999 | GouraudPolygon_ClipWithNegativeY(); |
| | 5000 | |
| | 5001 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5002 | return; |
| | 5003 | |
| | 5004 | GouraudPolygon_ClipWithPositiveX(); |
| | 5005 | |
| | 5006 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5007 | return; |
| | 5008 | |
| | 5009 | ZBufferedGouraudPolygon_Output(&fakeHeader,RenderPolygon.Vertices); |
| | 5010 | } |
| | 5011 | else |
| | 5012 | { |
| | 5013 | ZBufferedGouraudPolygon_Output(&fakeHeader,VerticesBuffer); |
| | 5014 | } |
| | 5015 | } |
| | 5016 | } |
| | 5017 | } |
| | 5018 | |
| | 5019 | void RenderLightFlare(VECTORCH *positionPtr, unsigned int colour) |
| | 5020 | { |
| | 5021 | PARTICLE particle; |
| | 5022 | VECTORCH point = *positionPtr; |
| | 5023 | |
| | 5024 | TranslatePointIntoViewspace(&point); |
| | 5025 | |
| | 5026 | if(point.vz < 64) |
| | 5027 | return; |
| | 5028 | |
| | 5029 | particle.ParticleID = PARTICLE_LIGHTFLARE; |
| | 5030 | particle.Colour = colour; |
| | 5031 | //printf("render fn %d %d %d\n", positionPtr->vx, positionPtr->vy, positionPtr->vz); |
| | 5032 | |
| | 5033 | { |
| | 5034 | int centreX = DIV_FIXED(point.vx, point.vz); |
| | 5035 | int centreY = DIV_FIXED(point.vy, point.vz); |
| | 5036 | int sizeX = (ScreenDescriptorBlock.SDB_Width << 13) / Global_VDB.VDB_ProjX; |
| | 5037 | int sizeY = MUL_FIXED(ScreenDescriptorBlock.SDB_Height << 13, 87381) / Global_VDB.VDB_ProjY; |
| | 5038 | int z = ONE_FIXED; |
| | 5039 | |
| | 5040 | VerticesBuffer[0].X = centreX - sizeX; |
| | 5041 | VerticesBuffer[0].Y = centreY - sizeY; |
| | 5042 | VerticesBuffer[0].Z = z; |
| | 5043 | VerticesBuffer[1].X = centreX + sizeX; |
| | 5044 | VerticesBuffer[1].Y = centreY - sizeY; |
| | 5045 | VerticesBuffer[1].Z = z; |
| | 5046 | VerticesBuffer[2].X = centreX + sizeX; |
| | 5047 | VerticesBuffer[2].Y = centreY + sizeY; |
| | 5048 | VerticesBuffer[2].Z = z; |
| | 5049 | VerticesBuffer[3].X = centreX - sizeX; |
| | 5050 | VerticesBuffer[3].Y = centreY + sizeY; |
| | 5051 | VerticesBuffer[3].Z = z; |
| | 5052 | } |
| | 5053 | |
| | 5054 | { |
| | 5055 | int outcode = QuadWithinFrustrum(); |
| | 5056 | |
| | 5057 | if (outcode) |
| | 5058 | { |
| | 5059 | RenderPolygon.NumberOfVertices = 4; |
| | 5060 | |
| | 5061 | //printf("On Screen!\n"); |
| | 5062 | VerticesBuffer[0].U = 192 << 16; |
| | 5063 | VerticesBuffer[0].V = 0; |
| | 5064 | |
| | 5065 | VerticesBuffer[1].U = 255 << 16; |
| | 5066 | VerticesBuffer[1].V = 0; |
| | 5067 | |
| | 5068 | VerticesBuffer[2].U = 255 << 16; |
| | 5069 | VerticesBuffer[2].V = 63 << 16; |
| | 5070 | |
| | 5071 | VerticesBuffer[3].U = 192 << 16; |
| | 5072 | VerticesBuffer[3].V = 63 << 16; |
| | 5073 | |
| | 5074 | if (outcode != 2) |
| | 5075 | { |
| | 5076 | TexturedPolygon_ClipWithZ(); |
| | 5077 | |
| | 5078 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5079 | return; |
| | 5080 | |
| | 5081 | TexturedPolygon_ClipWithNegativeX(); |
| | 5082 | |
| | 5083 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5084 | return; |
| | 5085 | |
| | 5086 | TexturedPolygon_ClipWithPositiveY(); |
| | 5087 | |
| | 5088 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5089 | return; |
| | 5090 | |
| | 5091 | TexturedPolygon_ClipWithNegativeY(); |
| | 5092 | |
| | 5093 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5094 | return; |
| | 5095 | |
| | 5096 | TexturedPolygon_ClipWithPositiveX(); |
| | 5097 | |
| | 5098 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5099 | return; |
| | 5100 | |
| | 5101 | Particle_Output(&particle, RenderPolygon.Vertices); |
| | 5102 | } |
| | 5103 | else |
| | 5104 | { |
| | 5105 | Particle_Output(&particle, VerticesBuffer); |
| | 5106 | } |
| | 5107 | } |
| | 5108 | } |
| | 5109 | } |
| | 5110 | |
| | 5111 | void RenderExplosionSurface(struct VOLUMETRIC_EXPLOSION *explosionPtr) |
| | 5112 | { |
| | 5113 | extern int BurningImageNumber; |
| | 5114 | int red,green,blue; |
| | 5115 | |
| | 5116 | switch (PlayerStatus.VisionMode) |
| | 5117 | { |
| | 5118 | case VISION_MODE_NORMAL: |
| | 5119 | default: |
| | 5120 | red = green = blue = 255; |
| | 5121 | break; |
| | 5122 | case VISION_MODE_IMAGEINTENSIFIER: |
| | 5123 | red = blue = 0; |
| | 5124 | green = 255; |
| | 5125 | break; |
| | 5126 | case VISION_MODE_PRED_THERMAL: |
| | 5127 | case VISION_MODE_PRED_SEEALIENS: |
| | 5128 | case VISION_MODE_PRED_SEEPREDTECH: |
| | 5129 | red = blue = 255; |
| | 5130 | green = 0; |
| | 5131 | } |
| | 5132 | |
| | 5133 | { |
| | 5134 | POLYHEADER fakeHeader; |
| | 5135 | VECTORCH *vSphere = SphereRotatedVertex; |
| | 5136 | int f; |
| | 5137 | fakeHeader.PolyFlags = iflag_transparent; |
| | 5138 | fakeHeader.PolyColour = BurningImageNumber; |
| | 5139 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_NORMAL; |
| | 5140 | |
| | 5141 | for (f=0; f < SPHERE_VERTICES; f++) |
| | 5142 | { |
| | 5143 | *vSphere = explosionPtr->Position[f]; |
| | 5144 | TranslatePointIntoViewspace(vSphere); |
| | 5145 | vSphere++; |
| | 5146 | } |
| | 5147 | |
| | 5148 | for (f=0; f < SPHERE_FACES; f++) |
| | 5149 | { |
| | 5150 | { |
| | 5151 | int i; |
| | 5152 | VECTORCH vertex[3]; |
| | 5153 | |
| | 5154 | for (i=0; i < 3; i++) |
| | 5155 | { |
| | 5156 | int n = SphereFace[f].v[i]; |
| | 5157 | vertex[i] = SphereRotatedVertex[n]; |
| | 5158 | } |
| | 5159 | |
| | 5160 | for (i=0; i < 3; i++) |
| | 5161 | { |
| | 5162 | int n = SphereFace[f].v[i]; |
| | 5163 | |
| | 5164 | VerticesBuffer[i].X = vertex[i].vx; |
| | 5165 | VerticesBuffer[i].Y = vertex[i].vy; |
| | 5166 | VerticesBuffer[i].Z = vertex[i].vz; |
| | 5167 | |
| | 5168 | { |
| | 5169 | int u = -(ONE_FIXED - explosionPtr->LifeTime) * 128 * 2; |
| | 5170 | VerticesBuffer[i].U = SphereAtmosU[n]; |
| | 5171 | VerticesBuffer[i].V = SphereAtmosV[n] + u; |
| | 5172 | } |
| | 5173 | |
| | 5174 | { |
| | 5175 | int d1 = VerticesBuffer[0].U - VerticesBuffer[1].U; |
| | 5176 | int d2 = VerticesBuffer[0].U - VerticesBuffer[2].U; |
| | 5177 | int d3 = VerticesBuffer[1].U - VerticesBuffer[2].U; |
| | 5178 | |
| | 5179 | int ad1 = (d1 < 0) ? -d1 : d1, ad2 = (d2 < 0) ? -d2 : d2, ad3 = (d3 < 0) ? -d3 : d3; |
| | 5180 | int i1=0, i2=0, i3=0; |
| | 5181 | |
| | 5182 | if (ad1 > (128*(SPHERE_TEXTURE_WRAP-1)+64)*65536) |
| | 5183 | { |
| | 5184 | if (d1 > 0) |
| | 5185 | i2 = 1; |
| | 5186 | else |
| | 5187 | i1 = 1; |
| | 5188 | } |
| | 5189 | |
| | 5190 | if (ad2 > (128*(SPHERE_TEXTURE_WRAP-1)+64)*65536) |
| | 5191 | { |
| | 5192 | if (d2 > 0) |
| | 5193 | i3 = 1; |
| | 5194 | else |
| | 5195 | i1 = 1; |
| | 5196 | } |
| | 5197 | |
| | 5198 | if (ad3 > (128*(SPHERE_TEXTURE_WRAP-1)+64)*65536) |
| | 5199 | { |
| | 5200 | if (d3 > 0) |
| | 5201 | i3 = 1; |
| | 5202 | else |
| | 5203 | i2 = 1; |
| | 5204 | } |
| | 5205 | |
| | 5206 | if(i1) |
| | 5207 | VerticesBuffer[0].U+=128*65536*SPHERE_TEXTURE_WRAP; |
| | 5208 | |
| | 5209 | if(i2) |
| | 5210 | VerticesBuffer[1].U+=128*65536*SPHERE_TEXTURE_WRAP; |
| | 5211 | |
| | 5212 | if(i3) |
| | 5213 | VerticesBuffer[2].U+=128*65536*SPHERE_TEXTURE_WRAP; |
| | 5214 | } |
| | 5215 | |
| | 5216 | VerticesBuffer[i].A = explosionPtr->LifeTime / 256; |
| | 5217 | VerticesBuffer[i].R = red; |
| | 5218 | VerticesBuffer[i].G = green; |
| | 5219 | VerticesBuffer[i].B = blue; |
| | 5220 | VerticesBuffer[i].SpecularR = VerticesBuffer[i].SpecularG = VerticesBuffer[i].SpecularB = 0; |
| | 5221 | } |
| | 5222 | |
| | 5223 | RenderPolygon.NumberOfVertices = 3; |
| | 5224 | } |
| | 5225 | |
| | 5226 | GouraudTexturedPolygon_ClipWithZ(); |
| | 5227 | |
| | 5228 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 5229 | { |
| | 5230 | GouraudTexturedPolygon_ClipWithNegativeX(); |
| | 5231 | |
| | 5232 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 5233 | { |
| | 5234 | GouraudTexturedPolygon_ClipWithPositiveY(); |
| | 5235 | |
| | 5236 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 5237 | { |
| | 5238 | GouraudTexturedPolygon_ClipWithNegativeY(); |
| | 5239 | |
| | 5240 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 5241 | { |
| | 5242 | GouraudTexturedPolygon_ClipWithPositiveX(); |
| | 5243 | |
| | 5244 | if(RenderPolygon.NumberOfVertices >= 3) |
| | 5245 | ZBufferedGouraudTexturedPolygon_Output(&fakeHeader, RenderPolygon.Vertices); |
| | 5246 | } |
| | 5247 | } |
| | 5248 | } |
| | 5249 | } |
| | 5250 | } |
| | 5251 | } |
| | 5252 | } |
| | 5253 | |
| | 5254 | void RenderInsideAlienTongue(int offset) |
| | 5255 | { |
| | 5256 | #define TONGUE_SCALE 1024 |
| | 5257 | int TonguePolyVertexList[4][4] = |
| | 5258 | { |
| | 5259 | {0,3,7,4}, //+ve y |
| | 5260 | {1,2,3,0}, //+ve x |
| | 5261 | {5,6,7,4}, //-ve x |
| | 5262 | {1,2,6,5}, //-ve y |
| | 5263 | }; |
| | 5264 | |
| | 5265 | VECTORCH vertices[8]= |
| | 5266 | { |
| | 5267 | {+TONGUE_SCALE,-TONGUE_SCALE,0}, |
| | 5268 | {+TONGUE_SCALE,+TONGUE_SCALE,0}, |
| | 5269 | {+TONGUE_SCALE,+TONGUE_SCALE,+TONGUE_SCALE*4}, |
| | 5270 | {+TONGUE_SCALE,-TONGUE_SCALE,+TONGUE_SCALE*4}, |
| | 5271 | |
| | 5272 | {-TONGUE_SCALE,-TONGUE_SCALE,0}, |
| | 5273 | {-TONGUE_SCALE,+TONGUE_SCALE,0}, |
| | 5274 | {-TONGUE_SCALE,+TONGUE_SCALE,+TONGUE_SCALE*4}, |
| | 5275 | {-TONGUE_SCALE,-TONGUE_SCALE,+TONGUE_SCALE*4}, |
| | 5276 | }; |
| | 5277 | |
| | 5278 | VECTORCH translatedPts[8]; |
| | 5279 | |
| | 5280 | POLYHEADER fakeHeader; |
| | 5281 | int polyNumber = 0; |
| | 5282 | |
| | 5283 | #if 1 |
| | 5284 | { |
| | 5285 | int i = 7; |
| | 5286 | do |
| | 5287 | { |
| | 5288 | translatedPts[i] = vertices[i]; |
| | 5289 | translatedPts[i].vz -= (ONE_FIXED-offset)/16; |
| | 5290 | // TranslatePointIntoViewspace(&translatedPts[i]); |
| | 5291 | |
| | 5292 | } while(i--); |
| | 5293 | } |
| | 5294 | #endif |
| | 5295 | { |
| | 5296 | extern int AlienTongueImageNumber; |
| | 5297 | fakeHeader.PolyFlags = 0; |
| | 5298 | fakeHeader.PolyColour = AlienTongueImageNumber; |
| | 5299 | RenderPolygon.TranslucencyMode = TRANSLUCENCY_GLOWING; |
| | 5300 | } |
| | 5301 | |
| | 5302 | for(; polyNumber < 4; polyNumber++) |
| | 5303 | { |
| | 5304 | { |
| | 5305 | int i=0; |
| | 5306 | for (; i < 4; i++) |
| | 5307 | { |
| | 5308 | int v = TonguePolyVertexList[polyNumber][i]; |
| | 5309 | VerticesBuffer[i].A = 255; |
| | 5310 | VerticesBuffer[i].X = translatedPts[v].vx; |
| | 5311 | VerticesBuffer[i].Y = translatedPts[v].vy; |
| | 5312 | VerticesBuffer[i].Z = translatedPts[v].vz; |
| | 5313 | VerticesBuffer[i].U = CuboidPolyVertexU[3][i]<<16; |
| | 5314 | VerticesBuffer[i].V = CuboidPolyVertexV[3][i]<<16; |
| | 5315 | |
| | 5316 | VerticesBuffer[i].R = VerticesBuffer[i].G = VerticesBuffer[i].B = offset/2048; |
| | 5317 | VerticesBuffer[i].SpecularR = VerticesBuffer[i].SpecularG = VerticesBuffer[i].SpecularB = 0; |
| | 5318 | } |
| | 5319 | |
| | 5320 | RenderPolygon.NumberOfVertices = 4; |
| | 5321 | } |
| | 5322 | |
| | 5323 | { |
| | 5324 | GouraudTexturedPolygon_ClipWithZ(); |
| | 5325 | |
| | 5326 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5327 | continue; |
| | 5328 | |
| | 5329 | GouraudTexturedPolygon_ClipWithNegativeX(); |
| | 5330 | |
| | 5331 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5332 | continue; |
| | 5333 | |
| | 5334 | GouraudTexturedPolygon_ClipWithPositiveY(); |
| | 5335 | |
| | 5336 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5337 | continue; |
| | 5338 | |
| | 5339 | GouraudTexturedPolygon_ClipWithNegativeY(); |
| | 5340 | |
| | 5341 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5342 | continue; |
| | 5343 | |
| | 5344 | GouraudTexturedPolygon_ClipWithPositiveX(); |
| | 5345 | |
| | 5346 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5347 | continue; |
| | 5348 | |
| | 5349 | ZBufferedGouraudTexturedPolygon_Output(&fakeHeader, RenderPolygon.Vertices); |
| | 5350 | } |
| | 5351 | } |
| | 5352 | } |
| | 5353 | |
| | 5354 | #define NO_OF_STARS 700 |
| | 5355 | struct |
| | 5356 | { |
| | 5357 | VECTORCH Position; |
| | 5358 | int Colour; |
| | 5359 | int Frequency; |
| | 5360 | int Phase; |
| | 5361 | |
| | 5362 | } StarArray[NO_OF_STARS]; |
| | 5363 | |
| | 5364 | void CreateStarArray() |
| | 5365 | { |
| | 5366 | int i=0; |
| | 5367 | for (; i < NO_OF_STARS; i++) |
| | 5368 | { |
| | 5369 | int phi = random() & 4095; |
| | 5370 | |
| | 5371 | StarArray[i].Position.vy = ONE_FIXED-(random()&131071); |
| | 5372 | |
| | 5373 | { |
| | 5374 | float y = ((float)StarArray[i].Position.vy)/65536.0; |
| | 5375 | y = sqrt(1-y*y); |
| | 5376 | |
| | 5377 | StarArray[i].Position.vx = ((float)GetCos(phi)*y); |
| | 5378 | StarArray[i].Position.vz = ((float)GetSin(phi)*y); |
| | 5379 | } |
| | 5380 | |
| | 5381 | StarArray[i].Colour = 0xff000000 + (random()&0x7f7f7f)+0x7f7f7f; |
| | 5382 | StarArray[i].Frequency = random() & 4095; |
| | 5383 | StarArray[i].Phase = random() & 4095; |
| | 5384 | } |
| | 5385 | } |
| | 5386 | |
| | 5387 | void RenderStarfield() |
| | 5388 | { |
| | 5389 | int i = 0; |
| | 5390 | int sizeX = 256; |
| | 5391 | int sizeY = MUL_FIXED(sizeX,87381); |
| | 5392 | |
| | 5393 | for (; i < NO_OF_STARS; i++) |
| | 5394 | { |
| | 5395 | VECTORCH position = StarArray[i].Position; |
| | 5396 | PARTICLE particle; |
| | 5397 | particle.ParticleID = PARTICLE_STAR; |
| | 5398 | particle.Colour = StarArray[i].Colour; |
| | 5399 | #if 1 |
| | 5400 | position.vx += Global_VDB.VDB_World.vx; |
| | 5401 | position.vy += Global_VDB.VDB_World.vy; |
| | 5402 | position.vz += Global_VDB.VDB_World.vz; |
| | 5403 | |
| | 5404 | TranslatePointIntoViewspace(&position); |
| | 5405 | #endif |
| | 5406 | // RotateVector(&position,&(Global_VDB.VDB_Mat)); |
| | 5407 | |
| | 5408 | VerticesBuffer[0].X = position.vx - sizeX; |
| | 5409 | VerticesBuffer[0].Y = position.vy - sizeY; |
| | 5410 | VerticesBuffer[0].Z = position.vz; |
| | 5411 | VerticesBuffer[1].X = position.vx + sizeX; |
| | 5412 | VerticesBuffer[1].Y = position.vy - sizeY; |
| | 5413 | VerticesBuffer[1].Z = position.vz; |
| | 5414 | VerticesBuffer[2].X = position.vx + sizeX; |
| | 5415 | VerticesBuffer[2].Y = position.vy + sizeY; |
| | 5416 | VerticesBuffer[2].Z = position.vz; |
| | 5417 | VerticesBuffer[3].X = position.vx - sizeX; |
| | 5418 | VerticesBuffer[3].Y = position.vy + sizeY; |
| | 5419 | VerticesBuffer[3].Z = position.vz; |
| | 5420 | |
| | 5421 | { |
| | 5422 | int outcode = QuadWithinFrustrum(); |
| | 5423 | |
| | 5424 | if (outcode) |
| | 5425 | { |
| | 5426 | RenderPolygon.NumberOfVertices = 4; |
| | 5427 | |
| | 5428 | // printf("On Screen!\n"); |
| | 5429 | VerticesBuffer[0].U = 192<<16; |
| | 5430 | VerticesBuffer[0].V = 0; |
| | 5431 | |
| | 5432 | VerticesBuffer[1].U = 255<<16; |
| | 5433 | VerticesBuffer[1].V = 0; |
| | 5434 | |
| | 5435 | VerticesBuffer[2].U = 255<<16; |
| | 5436 | VerticesBuffer[2].V = 63<<16; |
| | 5437 | |
| | 5438 | VerticesBuffer[3].U = 192<<16; |
| | 5439 | VerticesBuffer[3].V = 63<<16; |
| | 5440 | |
| | 5441 | if (outcode != 2) |
| | 5442 | { |
| | 5443 | TexturedPolygon_ClipWithZ(); |
| | 5444 | |
| | 5445 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5446 | return; |
| | 5447 | |
| | 5448 | TexturedPolygon_ClipWithNegativeX(); |
| | 5449 | |
| | 5450 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5451 | return; |
| | 5452 | |
| | 5453 | TexturedPolygon_ClipWithPositiveY(); |
| | 5454 | |
| | 5455 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5456 | return; |
| | 5457 | |
| | 5458 | TexturedPolygon_ClipWithNegativeY(); |
| | 5459 | |
| | 5460 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5461 | return; |
| | 5462 | |
| | 5463 | TexturedPolygon_ClipWithPositiveX(); |
| | 5464 | |
| | 5465 | if(RenderPolygon.NumberOfVertices < 3) |
| | 5466 | return; |
| | 5467 | |
| | 5468 | Particle_Output(&particle, RenderPolygon.Vertices); |
| | 5469 | } |
| | 5470 | else |
| | 5471 | { |
| | 5472 | Particle_Output(&particle, VerticesBuffer); |
| | 5473 | } |
| | 5474 | } |
| | 5475 | } |
| | 5476 | } |
| | 5477 | } |
| | 5478 | |
| | 5479 | void ChooseLightingModel() |
| | 5480 | { |
| | 5481 | switch(UserProfile.active_bonus) |
| | 5482 | { |
| | 5483 | case CHEATMODE_NONACTIVE: |
| | 5484 | default: |
| | 5485 | { |
| | 5486 | switch (PlayerStatus.VisionMode) |
| | 5487 | { |
| | 5488 | default: |
| | 5489 | case VISION_MODE_NORMAL: |
| | 5490 | VertexIntensity = VertexIntensity_Standard_Opt; |
| | 5491 | break; |
| | 5492 | case VISION_MODE_IMAGEINTENSIFIER: |
| | 5493 | VertexIntensity = VertexIntensity_ImageIntensifier; |
| | 5494 | break; |
| | 5495 | case VISION_MODE_ALIEN_SENSE: |
| | 5496 | VertexIntensity = VertexIntensity_Alien_Sense; |
| | 5497 | break; |
| | 5498 | case VISION_MODE_PRED_THERMAL: |
| | 5499 | VertexIntensity = VertexIntensity_Pred_Thermal; |
| | 5500 | break; |
| | 5501 | case VISION_MODE_PRED_SEEALIENS: |
| | 5502 | VertexIntensity = VertexIntensity_Pred_SeeAliens; |
| | 5503 | break; |
| | 5504 | case VISION_MODE_PRED_SEEPREDTECH: |
| | 5505 | VertexIntensity = VertexIntensity_Pred_SeePredatorTech; |
| | 5506 | } |
| | 5507 | } |
| | 5508 | break; |
| | 5509 | case CHEATMODE_DRAWFULLBRIGHT: |
| | 5510 | VertexIntensity = VertexIntensity_FullBright; |
| | 5511 | break; |
| | 5512 | case CHEATMODE_DISCOINFERNO: |
| | 5513 | case CHEATMODE_TRIPTASTIC: |
| | 5514 | VertexIntensity = VertexIntensity_DiscoInferno; |
| | 5515 | break; |
| | 5516 | case CHEATMODE_UNDERWATER: |
| | 5517 | VertexIntensity = VertexIntensity_Underwater; |
| | 5518 | } |
| | 5519 | } |