| | 1 | #include "system.h" |
| | 2 | #include "stratdef.h" |
| | 3 | #include "kshape.h" |
| | 4 | #include "userprofile.h" |
| | 5 | #include "bh_types.h" |
| | 6 | #include "frustum.h" |
| | 7 | |
| | 8 | #define MAX_NUMBER_OF_VISIBLE_MODULES 400 |
| | 9 | |
| | 10 | extern int DrawingAReflection; |
| | 11 | extern int NumActiveBlocks; |
| | 12 | extern DISPLAYBLOCK *ActiveBlockList[]; |
| | 13 | extern void RenderBoundingbox(VECTORCH objectVertices[4], DISPLAYBLOCK *objectPtr); |
| | 14 | |
| | 15 | static int SortKObject(const void * void_a, const void *void_b) |
| | 16 | { |
| | 17 | const struct KObject * a = void_a; |
| | 18 | const struct KObject * b = void_b; |
| | 19 | |
| | 20 | return (a->SortKey < b->SortKey) ? -1 : (a->SortKey > b->SortKey); |
| | 21 | } |
| | 22 | |
| | 23 | void ReflectObject(DISPLAYBLOCK *dPtr) |
| | 24 | { |
| | 25 | dPtr->ObWorld.vx = MirroringAxis - dPtr->ObWorld.vx; |
| | 26 | dPtr->ObMat.mat11 = -dPtr->ObMat.mat11; |
| | 27 | dPtr->ObMat.mat21 = -dPtr->ObMat.mat21; |
| | 28 | dPtr->ObMat.mat31 = -dPtr->ObMat.mat31; |
| | 29 | } |
| | 30 | |
| | 31 | struct KObject VisibleModules[MAX_NUMBER_OF_VISIBLE_MODULES]; |
| | 32 | struct KObject VisibleObjects[maxobjects]; |
| | 33 | |
| | 34 | struct viewdescriptorblock Global_VDB; |
| | 35 | |
| | 36 | int numVisMods = 0; |
| | 37 | int numVisObjs = 0; |
| | 38 | |
| | 39 | static void draw_boundingbox(VECTORCH objectVertices[8], DISPLAYBLOCK *objectPtr) |
| | 40 | { |
| | 41 | VECTORCH test[4]; |
| | 42 | |
| | 43 | //if(0) |
| | 44 | { |
| | 45 | test[0].vx = objectVertices[0].vx; |
| | 46 | test[0].vy = objectVertices[0].vy; |
| | 47 | test[0].vz = objectVertices[0].vz; |
| | 48 | |
| | 49 | test[1].vx = objectVertices[1].vx; |
| | 50 | test[1].vy = objectVertices[1].vy; |
| | 51 | test[1].vz = objectVertices[1].vz; |
| | 52 | |
| | 53 | test[2].vx = objectVertices[3].vx; |
| | 54 | test[2].vy = objectVertices[3].vy; |
| | 55 | test[2].vz = objectVertices[3].vz; |
| | 56 | |
| | 57 | test[3].vx = objectVertices[2].vx; |
| | 58 | test[3].vy = objectVertices[2].vy; |
| | 59 | test[3].vz = objectVertices[2].vz; |
| | 60 | //RenderBoundingbox(&test[0]); |
| | 61 | RenderBoundingbox(&test[0], objectPtr); |
| | 62 | } |
| | 63 | |
| | 64 | //if(0) |
| | 65 | { |
| | 66 | test[0].vx = objectVertices[0].vx; |
| | 67 | test[0].vy = objectVertices[0].vy; |
| | 68 | test[0].vz = objectVertices[0].vz; |
| | 69 | |
| | 70 | test[1].vx = objectVertices[4].vx; |
| | 71 | test[1].vy = objectVertices[4].vy; |
| | 72 | test[1].vz = objectVertices[4].vz; |
| | 73 | |
| | 74 | test[2].vx = objectVertices[6].vx; |
| | 75 | test[2].vy = objectVertices[6].vy; |
| | 76 | test[2].vz = objectVertices[6].vz; |
| | 77 | |
| | 78 | test[3].vx = objectVertices[2].vx; |
| | 79 | test[3].vy = objectVertices[2].vy; |
| | 80 | test[3].vz = objectVertices[2].vz; |
| | 81 | //RenderBoundingbox(&test[0]); |
| | 82 | RenderBoundingbox(&test[0], objectPtr); |
| | 83 | } |
| | 84 | |
| | 85 | //if(0) |
| | 86 | { |
| | 87 | test[0].vx = objectVertices[4].vx; |
| | 88 | test[0].vy = objectVertices[4].vy; |
| | 89 | test[0].vz = objectVertices[4].vz; |
| | 90 | |
| | 91 | test[1].vx = objectVertices[5].vx; |
| | 92 | test[1].vy = objectVertices[5].vy; |
| | 93 | test[1].vz = objectVertices[5].vz; |
| | 94 | |
| | 95 | test[2].vx = objectVertices[7].vx; |
| | 96 | test[2].vy = objectVertices[7].vy; |
| | 97 | test[2].vz = objectVertices[7].vz; |
| | 98 | |
| | 99 | test[3].vx = objectVertices[6].vx; |
| | 100 | test[3].vy = objectVertices[6].vy; |
| | 101 | test[3].vz = objectVertices[6].vz; |
| | 102 | //RenderBoundingbox(&test[0]); |
| | 103 | RenderBoundingbox(&test[0], objectPtr); |
| | 104 | } |
| | 105 | |
| | 106 | //if(0) |
| | 107 | { |
| | 108 | test[0].vx = objectVertices[5].vx; |
| | 109 | test[0].vy = objectVertices[5].vy; |
| | 110 | test[0].vz = objectVertices[5].vz; |
| | 111 | |
| | 112 | test[1].vx = objectVertices[1].vx; |
| | 113 | test[1].vy = objectVertices[1].vy; |
| | 114 | test[1].vz = objectVertices[1].vz; |
| | 115 | |
| | 116 | test[2].vx = objectVertices[3].vx; |
| | 117 | test[2].vy = objectVertices[3].vy; |
| | 118 | test[2].vz = objectVertices[3].vz; |
| | 119 | |
| | 120 | test[3].vx = objectVertices[7].vx; |
| | 121 | test[3].vy = objectVertices[7].vy; |
| | 122 | test[3].vz = objectVertices[7].vz; |
| | 123 | //RenderBoundingbox(&test[0]); |
| | 124 | RenderBoundingbox(&test[0], objectPtr); |
| | 125 | } |
| | 126 | |
| | 127 | if(0) // bottom |
| | 128 | { |
| | 129 | test[0].vx = objectVertices[0].vx; |
| | 130 | test[0].vy = objectVertices[0].vy; |
| | 131 | test[0].vz = objectVertices[0].vz; |
| | 132 | |
| | 133 | test[1].vx = objectVertices[1].vx; |
| | 134 | test[1].vy = objectVertices[1].vy; |
| | 135 | test[1].vz = objectVertices[1].vz; |
| | 136 | |
| | 137 | test[2].vx = objectVertices[5].vx; |
| | 138 | test[2].vy = objectVertices[5].vy; |
| | 139 | test[2].vz = objectVertices[5].vz; |
| | 140 | |
| | 141 | test[3].vx = objectVertices[4].vx; |
| | 142 | test[3].vy = objectVertices[4].vy; |
| | 143 | test[3].vz = objectVertices[4].vz; |
| | 144 | //RenderBoundingbox(&test[0]); |
| | 145 | } |
| | 146 | |
| | 147 | if(0) // top |
| | 148 | { |
| | 149 | test[0].vx = objectVertices[2].vx; |
| | 150 | test[0].vy = objectVertices[2].vy; |
| | 151 | test[0].vz = objectVertices[2].vz; |
| | 152 | |
| | 153 | test[1].vx = objectVertices[3].vx; |
| | 154 | test[1].vy = objectVertices[3].vy; |
| | 155 | test[1].vz = objectVertices[3].vz; |
| | 156 | |
| | 157 | test[2].vx = objectVertices[7].vx; |
| | 158 | test[2].vy = objectVertices[7].vy; |
| | 159 | test[2].vz = objectVertices[7].vz; |
| | 160 | |
| | 161 | test[3].vx = objectVertices[6].vx; |
| | 162 | test[3].vy = objectVertices[6].vy; |
| | 163 | test[3].vz = objectVertices[6].vz; |
| | 164 | //RenderBoundingbox(&test[0]); |
| | 165 | } |
| | 166 | } |
| | 167 | |
| | 168 | void AddShapes() |
| | 169 | { |
| | 170 | DISPLAYBLOCK *OnScreenBlockList[maxobjects]; |
| | 171 | int i, NumOnScreenBlocks = 0; |
| | 172 | numVisMods = 0; |
| | 173 | numVisObjs = 0; |
| | 174 | |
| | 175 | //static void AVPGetInViewVolumeList() |
| | 176 | //{ |
| | 177 | if(!PlayerStatus.FirstPersonView) |
| | 178 | OnScreenBlockList[NumOnScreenBlocks++] = PlayerStatus.DisplayBlock; |
| | 179 | |
| | 180 | for (i=1; i < NumActiveBlocks; i++) |
| | 181 | { |
| | 182 | DISPLAYBLOCK *dptr = ActiveBlockList[i]; |
| | 183 | |
| | 184 | if(dptr->Module) |
| | 185 | { |
| | 186 | if(ModuleCurrVisArray[dptr->Module->m_index] > 1) |
| | 187 | OnScreenBlockList[NumOnScreenBlocks++] = dptr; |
| | 188 | } |
| | 189 | else if (!(dptr->ObFlags & ObFlag_NotVis)) |
| | 190 | { |
| | 191 | dptr->ObView.vx = dptr->ObWorld.vx - Global_VDB.VDB_World.vx; |
| | 192 | dptr->ObView.vy = dptr->ObWorld.vy - Global_VDB.VDB_World.vy; |
| | 193 | dptr->ObView.vz = dptr->ObWorld.vz - Global_VDB.VDB_World.vz; |
| | 194 | |
| | 195 | RotateVector(&dptr->ObView, &Global_VDB.VDB_Mat); |
| | 196 | |
| | 197 | if (dptr->HModelControlBlock || ObjectWithinFrustrum(dptr)) |
| | 198 | { |
| | 199 | OnScreenBlockList[NumOnScreenBlocks++] = dptr; |
| | 200 | } |
| | 201 | } |
| | 202 | } |
| | 203 | //} |
| | 204 | for (i=0; i < NumOnScreenBlocks; i++) |
| | 205 | { |
| | 206 | DISPLAYBLOCK *objectPtr = OnScreenBlockList[i]; |
| | 207 | MODULE *modulePtr = objectPtr->Module; |
| | 208 | |
| | 209 | /* if it's a module, which isn't inside another module */ |
| | 210 | if (modulePtr && !(modulePtr->m_flags & m_flag_slipped_inside)) |
| | 211 | { |
| | 212 | if(modulePtr == PlayerStatus.sbptr->containingModule) |
| | 213 | { |
| | 214 | VisibleModules[numVisMods].SortKey = 0; |
| | 215 | //printf("fog is %d in player's module\n", modulePtr->m_flags & MODULEFLAG_FOG); |
| | 216 | } |
| | 217 | else |
| | 218 | { |
| | 219 | VECTORCH position; |
| | 220 | VECTORCH dist; |
| | 221 | int min, max; |
| | 222 | |
| | 223 | position.vx = modulePtr->m_world.vx - PlayerStatus.DisplayBlock->ObWorld.vx; |
| | 224 | position.vy = modulePtr->m_world.vy - PlayerStatus.DisplayBlock->ObWorld.vy; |
| | 225 | position.vz = modulePtr->m_world.vz - PlayerStatus.DisplayBlock->ObWorld.vz; |
| | 226 | |
| | 227 | min = modulePtr->m_minx + position.vx; |
| | 228 | max = modulePtr->m_maxx + position.vx; |
| | 229 | |
| | 230 | if (max < 0) /* outside maxX side */ |
| | 231 | { |
| | 232 | dist.vx = max; |
| | 233 | } |
| | 234 | else if (min > 0) /* outside minX faces */ |
| | 235 | { |
| | 236 | dist.vx = min; |
| | 237 | } |
| | 238 | else /* between faces */ |
| | 239 | { |
| | 240 | dist.vx = 0; |
| | 241 | } |
| | 242 | |
| | 243 | min = modulePtr->m_miny + position.vy; |
| | 244 | max = modulePtr->m_maxy + position.vy; |
| | 245 | |
| | 246 | if (max < 0) /* outside maxY side */ |
| | 247 | { |
| | 248 | dist.vy = max; |
| | 249 | } |
| | 250 | else if (min > 0) /* outside minY faces */ |
| | 251 | { |
| | 252 | dist.vy = min; |
| | 253 | } |
| | 254 | else /* between faces */ |
| | 255 | { |
| | 256 | dist.vy = 0; |
| | 257 | } |
| | 258 | |
| | 259 | min = modulePtr->m_minz + position.vz; |
| | 260 | max = modulePtr->m_maxz + position.vz; |
| | 261 | |
| | 262 | if (max < 0) /* outside maxZ side */ |
| | 263 | { |
| | 264 | dist.vz = max; |
| | 265 | } |
| | 266 | else if (min > 0) /* outside minZ faces */ |
| | 267 | { |
| | 268 | dist.vz = min; |
| | 269 | } |
| | 270 | else /* between faces */ |
| | 271 | { |
| | 272 | dist.vz = 0; |
| | 273 | } |
| | 274 | |
| | 275 | VisibleModules[numVisMods].SortKey = Magnitude(&dist); |
| | 276 | } |
| | 277 | |
| | 278 | VisibleModules[numVisMods].DispPtr = objectPtr; |
| | 279 | |
| | 280 | if(numVisMods++ > MAX_NUMBER_OF_VISIBLE_MODULES) |
| | 281 | { |
| | 282 | // outside the environment! |
| | 283 | printf("MAX_NUMBER_OF_VISIBLE_MODULES (%d) exceeded!\n", MAX_NUMBER_OF_VISIBLE_MODULES); |
| | 284 | printf("Possibly outside the environment!\n"); |
| | 285 | return; |
| | 286 | } |
| | 287 | } |
| | 288 | else //if(!objectPtr->SfxPtr) |
| | 289 | { |
| | 290 | VisibleObjects[numVisObjs].DispPtr = objectPtr; |
| | 291 | /* this sort key defaults to the object not being drawn, ie. a grenade |
| | 292 | behind a closed door (so there is no module behind door) would still be |
| | 293 | in the OnScreenBlockList but need not be drawn. */ |
| | 294 | |
| | 295 | //if(NULL != objectPtr->ObStrategyBlock) |
| | 296 | if(!objectPtr->SfxPtr) |
| | 297 | VisibleObjects[numVisObjs++].SortKey = objectPtr->ObStrategyBlock->type; |
| | 298 | else |
| | 299 | VisibleObjects[numVisObjs++].SortKey = -1; |
| | 300 | } |
| | 301 | } |
| | 302 | |
| | 303 | //printf("numvismods %d\n", numVisMods); |
| | 304 | //printf("numvisobjs %d\n", numVisObjs); |
| | 305 | |
| | 306 | qsort(VisibleModules, numVisMods, sizeof(struct KObject), SortKObject); |
| | 307 | qsort(VisibleObjects, numVisObjs, sizeof(struct KObject), SortKObject); |
| | 308 | |
| | 309 | for(i=0; i< numVisMods; i++) |
| | 310 | { |
| | 311 | AddModuleShape(VisibleModules[i].DispPtr); |
| | 312 | |
| | 313 | if (MirroringActive) |
| | 314 | { |
| | 315 | DISPLAYBLOCK *dptr = VisibleModules[i].DispPtr; |
| | 316 | |
| | 317 | ReflectObject(dptr); |
| | 318 | |
| | 319 | dptr->ObView.vx = dptr->ObWorld.vx - Global_VDB.VDB_World.vx; |
| | 320 | dptr->ObView.vy = dptr->ObWorld.vy - Global_VDB.VDB_World.vy; |
| | 321 | dptr->ObView.vz = dptr->ObWorld.vz - Global_VDB.VDB_World.vz; |
| | 322 | |
| | 323 | RotateVector(&dptr->ObView, &Global_VDB.VDB_Mat); |
| | 324 | |
| | 325 | DrawingAReflection = 1; |
| | 326 | AddModuleShape(dptr); |
| | 327 | DrawingAReflection = 0; |
| | 328 | ReflectObject(dptr); |
| | 329 | } |
| | 330 | } |
| | 331 | |
| | 332 | int o = numVisObjs; |
| | 333 | |
| | 334 | while(o--) |
| | 335 | { |
| | 336 | DISPLAYBLOCK *objectPtr = VisibleObjects[o].DispPtr; |
| | 337 | |
| | 338 | if(UserProfile.GameOptions.ShowboundingBox) |
| | 339 | { |
| | 340 | STRATEGYBLOCK *sbPtr = objectPtr->ObStrategyBlock; |
| | 341 | |
| | 342 | if(NULL != sbPtr) |
| | 343 | { |
| | 344 | struct dynamicsblock* DynPtr = sbPtr->DynPtr; |
| | 345 | |
| | 346 | if(NULL != DynPtr) |
| | 347 | { |
| | 348 | //if(!DynPtr->CollisionRadius) |
| | 349 | if(DynPtr->DynamicsType != DYN_TYPE_NO_COLLISIONS) |
| | 350 | if(DYN_TYPE_NRBB_COLLISIONS == DynPtr->DynamicsType) |
| | 351 | { |
| | 352 | if(!(PlayerStatus.FirstPersonView && (sbPtr == PlayerStatus.sbptr))) // for now |
| | 353 | draw_boundingbox(DynPtr->ObjectVertices, objectPtr); |
| | 354 | } |
| | 355 | } |
| | 356 | } |
| | 357 | } |
| | 358 | |
| | 359 | if (VisibleObjects[o].DispPtr->HModelControlBlock) |
| | 360 | { |
| | 361 | AddHierarchicalShapes(VisibleObjects[o].DispPtr); |
| | 362 | } |
| | 363 | else if(!VisibleObjects[o].DispPtr->SfxPtr) |
| | 364 | //else |
| | 365 | { |
| | 366 | AddShape(VisibleObjects[o].DispPtr); |
| | 367 | |
| | 368 | if (MirroringActive) |
| | 369 | { |
| | 370 | DISPLAYBLOCK *dptr = VisibleObjects[o].DispPtr; |
| | 371 | |
| | 372 | ReflectObject(dptr); |
| | 373 | |
| | 374 | dptr->ObView.vx = dptr->ObWorld.vx - Global_VDB.VDB_World.vx; |
| | 375 | dptr->ObView.vy = dptr->ObWorld.vy - Global_VDB.VDB_World.vy; |
| | 376 | dptr->ObView.vz = dptr->ObWorld.vz - Global_VDB.VDB_World.vz; |
| | 377 | |
| | 378 | RotateVector(&dptr->ObView, &Global_VDB.VDB_Mat); |
| | 379 | |
| | 380 | DrawingAReflection = 1; |
| | 381 | AddShape(dptr); |
| | 382 | DrawingAReflection = 0; |
| | 383 | ReflectObject(dptr); |
| | 384 | } |
| | 385 | } |
| | 386 | } |
| | 387 | } |
| | 388 | |
| | 389 | void RenderThisHierarchicalDisplayblock(DISPLAYBLOCK *dPtr) |
| | 390 | { |
| | 391 | if(ObjectWithinFrustrum(dPtr)) |
| | 392 | { |
| | 393 | AddHierarchicalShape(dPtr); |
| | 394 | |
| | 395 | if (MirroringActive && dPtr->ObStrategyBlock) |
| | 396 | { |
| | 397 | ReflectObject(dPtr); |
| | 398 | dPtr->ObView.vx = dPtr->ObWorld.vx - Global_VDB.VDB_World.vx; |
| | 399 | dPtr->ObView.vy = dPtr->ObWorld.vy - Global_VDB.VDB_World.vy; |
| | 400 | dPtr->ObView.vz = dPtr->ObWorld.vz - Global_VDB.VDB_World.vz; |
| | 401 | RotateVector(&dPtr->ObView, &Global_VDB.VDB_Mat); |
| | 402 | DrawingAReflection = 1; |
| | 403 | AddHierarchicalShape(dPtr); |
| | 404 | DrawingAReflection = 0; |
| | 405 | ReflectObject(dPtr); |
| | 406 | } |
| | 407 | } |
| | 408 | } |