1 #include "3dc.h"
2 #include "inline.h"
3 #include "module.h"
4
5 #include "stratdef.h"
6 #include "gamedef.h"
7
8 #include "kzsort.h"
9 #include "kshape.h"
10 #include "pldnet.h"
11 #include "avpview.h"
12
13 #include "d3d_render.h"
14 #define UseLocalAssert Yes
15 #include "ourasert.h"
16 #include "avp_userprofile.h"
17
18 #define PENTIUM_PROFILING_ON 0
19 #if PENTIUM_PROFILING_ON
20 #include "pentime.h"
21 #else
22 #define ProfileStart();
23 #define ProfileStop(x);
24 #endif
25 #define MultipleExecuteBuffers Yes
26
27 extern int *ItemPointers[maxpolyptrs];
28 extern int ItemCount;
29
30 extern int ScanDrawMode;
31 extern int ZBufferMode;
32 extern int NumVertices;
33 extern int WireFrameMode;
34 extern int DrawingAReflection;
35
36 struct KItem KItemList[maxpolyptrs];
37 #if 0
38 static struct KItem KItemList2[maxpolyptrs];
39 #endif
40
41 static struct KObject VisibleModules[MAX_NUMBER_OF_VISIBLE_MODULES];
42 static struct KObject VisibleModules2[MAX_NUMBER_OF_VISIBLE_MODULES];
43 static struct KObject *SortedModules;
44 static struct KObject VisibleObjects[maxobjects];
45
46 static int PointIsInModule(VECTORCH *pointPtr,MODULE *modulePtr);
47
48 /*KJL*****************************
49 * externs for new shape function *
50 *****************************KJL*/
51 int *MorphedObjectPointsPtr=0;
52
53 #if 0
54 static void MergeItems(struct KItem *src1, int n1, struct KItem *src2, int n2, struct KItem *dest)
55 {
56 /* merge the 2 sorted lists: at src1, length n1, and at src2, length n2, into dest */
57
58 while (n1>0 && n2>0) /* until one list is exhausted */
59 {
60 if (src1->SortKey < src2->SortKey)
61 {
62 /* src1 is nearer */
63 *dest++ = *src1++;
64 n1--;
65 }
66 else
67 {
68 /* src2 is nearer */
69 *dest++ = *src2++;
70 n2--;
71 }
72 }
73
74 if (n1==0)
75 {
76 /* remainder in srce2 goes into dest */
77 while (n2>0)
78 {
79 *dest++ = *src2++;
80 n2--;
81 }
82 }
83 else
84 {
85 /* remainder in srce1 goes into dest */
86 while (n1>0)
87 {
88 *dest++ = *src1++;
89 n1--;
90 }
91 }
92 }
93 #endif
94
MergeObjects(struct KObject * src1,int n1,struct KObject * src2,int n2,struct KObject * dest)95 static void MergeObjects(struct KObject *src1, int n1, struct KObject *src2, int n2, struct KObject *dest)
96 {
97 /* merge the 2 sorted lists: at src1, length n1, and at src2, length n2, into dest */
98
99 while (n1>0 && n2>0) /* until one list is exhausted */
100 {
101 if (src1->SortKey < src2->SortKey)
102 {
103 /* src1 is nearer */
104 *dest++ = *src1++;
105 n1--;
106 }
107 else
108 {
109 /* src2 is nearer */
110 *dest++ = *src2++;
111 n2--;
112 }
113 }
114
115 if (n1==0)
116 {
117 /* remainder in srce2 goes into dest */
118 while (n2>0)
119 {
120 *dest++ = *src2++;
121 n2--;
122 }
123 }
124 else
125 {
126 /* remainder in srce1 goes into dest */
127 while (n1>0)
128 {
129 *dest++ = *src1++;
130 n1--;
131 }
132 }
133 }
134 #if 0
135 static void ZSortItems(void)
136 {
137 unsigned int partitionSize;
138 unsigned int noOfPasses = 0;
139 unsigned int noOfItems = ItemCount;
140 struct KItem *mergeFrom = &KItemList[0];
141 struct KItem *mergeTo = &KItemList2[0];
142 struct KItem *mergeTemp;
143 unsigned int offSet;
144
145 for (partitionSize=1;partitionSize<noOfItems;partitionSize*=2)
146 {
147 /* for each partition size...
148 loop through partition pairs and merge */
149
150 /* initialise partition and destination offsets */
151 offSet = 0;
152
153 /* do merges for this partition size,
154 omitting the last merge if the second partition is incomplete */
155 while((offSet+(partitionSize*2)) <= noOfItems)
156 {
157 MergeItems(
158 (mergeFrom+offSet),
159 partitionSize,
160 (mergeFrom+offSet+partitionSize),
161 partitionSize,
162 (mergeTo+offSet) );
163
164 offSet += partitionSize*2;
165 }
166
167 /* At this stage, there's less than 2 whole partitions
168 left in the array. If there's no data left at all, then
169 there's nothing left to do. However, if there's any data
170 left at the end of the array, we need to do something with it:
171
172 If there's more than a full partition, merge it against the remaining
173 partial partition. If there's less than a full partition, just copy
174 it across (via the MergeItems fn): it will be merged in again during a
175 later pass.
176
177 */
178
179 if((offSet+partitionSize) < noOfItems)
180 {
181 /* merge full partition against a partial partition */
182 MergeItems(
183 (mergeFrom+offSet),
184 partitionSize,
185 (mergeFrom+offSet+partitionSize),
186 (noOfItems - (offSet+partitionSize)),
187 (mergeTo+offSet) );
188 }
189 else if(offSet < noOfItems)
190 {
191 /* pass the incomplete partition thro' the merge fn
192 to copy it across */
193 MergeItems(
194 (mergeFrom+offSet),
195 (noOfItems-offSet),
196 (mergeFrom+offSet), /* this is a dummy parameter ... */
197 0,
198 (mergeTo+offSet) );
199 }
200
201 /* count number of passes */
202 noOfPasses++;
203 /* swap source and destination */
204 mergeTemp = mergeFrom;
205 mergeFrom = mergeTo;
206 mergeTo = mergeTemp;
207 }
208
209 /* check where the final list is, and move if neccesary */
210 if (noOfPasses%2 == 1)
211 {
212 unsigned int i;
213 /* final list is in the auxiliary buffer, so move it back */
214 for(i=0;i<noOfItems;i++)
215 {
216 KItemList[i] = KItemList2[i];
217 }
218 }
219 }
220 #endif
SortModules(unsigned int noOfItems)221 void SortModules(unsigned int noOfItems)
222 {
223 unsigned int partitionSize;
224 unsigned int noOfPasses = 0;
225
226 struct KObject *mergeFrom = &VisibleModules[0];
227 struct KObject *mergeTo = &VisibleModules2[0];
228 struct KObject *mergeTemp;
229
230 unsigned int offSet;
231
232 for (partitionSize=1;partitionSize<noOfItems;partitionSize*=2)
233 {
234 /* for each partition size...
235 loop through partition pairs and merge */
236
237 /* initialise partition and destination offsets */
238 offSet = 0;
239
240 /* do merges for this partition size,
241 omitting the last merge if the second partition is incomplete */
242 while((offSet+(partitionSize*2)) <= noOfItems)
243 {
244 MergeObjects(
245 (mergeFrom+offSet),
246 partitionSize,
247 (mergeFrom+offSet+partitionSize),
248 partitionSize,
249 (mergeTo+offSet) );
250
251 offSet += partitionSize*2;
252 }
253
254 /* At this stage, there's less than 2 whole partitions
255 left in the array. If there's no data left at all, then
256 there's nothing left to do. However, if there's any data
257 left at the end of the array, we need to do something with it:
258
259 If there's more than a full partition, merge it against the remaining
260 partial partition. If there's less than a full partition, just copy
261 it across (via the MergeObjects fn): it will be merged in again during a
262 later pass.
263
264 */
265
266 if((offSet+partitionSize) < noOfItems)
267 {
268 /* merge full partition against a partial partition */
269 MergeObjects(
270 (mergeFrom+offSet),
271 partitionSize,
272 (mergeFrom+offSet+partitionSize),
273 (noOfItems - (offSet+partitionSize)),
274 (mergeTo+offSet) );
275 }
276 else if(offSet < noOfItems)
277 {
278 /* pass the incomplete partition thro' the merge fn
279 to copy it across */
280 MergeObjects(
281 (mergeFrom+offSet),
282 (noOfItems-offSet),
283 (mergeFrom+offSet), /* this is a dummy parameter ... */
284 0,
285 (mergeTo+offSet) );
286 }
287
288 /* count number of passes */
289 noOfPasses++;
290 /* swap source and destination */
291 mergeTemp = mergeFrom;
292 mergeFrom = mergeTo;
293 mergeTo = mergeTemp;
294 }
295
296 /* check where the final list is, and move if neccesary */
297 if (noOfPasses%2 == 1)
298 {
299 /* final list is in the auxiliary buffer */
300 SortedModules = VisibleModules2;
301 }
302 else
303 {
304 SortedModules = VisibleModules;
305 }
306 }
307
308
309
310
311
312
313 /* KJL 12:21:51 02/11/97 - This routine is too big and ugly. Split & clean up required! */
KRenderItems(VIEWDESCRIPTORBLOCK * VDBPtr)314 void KRenderItems(VIEWDESCRIPTORBLOCK *VDBPtr)
315 {
316 extern int NumOnScreenBlocks;
317 extern DISPLAYBLOCK *OnScreenBlockList[];
318 int numOfObjects = NumOnScreenBlocks;
319 int numVisMods=0;
320 int numVisObjs=0;
321 ProfileStart();
322 while(numOfObjects)
323 {
324 extern DISPLAYBLOCK *Player;
325
326 DISPLAYBLOCK *objectPtr = OnScreenBlockList[--numOfObjects];
327 MODULE *modulePtr = objectPtr->ObMyModule;
328
329 /* if it's a module, which isn't inside another module */
330 if (modulePtr && !(modulePtr->m_flags & m_flag_slipped_inside))
331 {
332 #if 1
333 if(PointIsInModule(&(VDBPtr->VDB_World),modulePtr))
334 {
335 VisibleModules[numVisMods].DispPtr = objectPtr;
336 VisibleModules[numVisMods].SortKey = smallint;
337 // textprint("fog is %d in player's module\n",modulePtr->m_flags & MODULEFLAG_FOG);
338 }
339 #else
340 // these tests should really be done using the camera (VDB) position
341 extern MODULE *playerPherModule;
342 if (playerPherModule == modulePtr)
343 {
344 VisibleModules[numVisMods].DispPtr = objectPtr;
345 VisibleModules[numVisMods].SortKey = smallint;
346 }
347 #endif
348 else
349 {
350 VECTORCH position;
351 VECTORCH dist;
352
353 position.vx = modulePtr->m_world.vx - Player->ObWorld.vx;
354 position.vy = modulePtr->m_world.vy - Player->ObWorld.vy;
355 position.vz = modulePtr->m_world.vz - Player->ObWorld.vz;
356
357 {
358 int minX = modulePtr->m_minx + position.vx;
359 int maxX = modulePtr->m_maxx + position.vx;
360
361 if (maxX<0) /* outside maxX side */
362 {
363 dist.vx = maxX;
364 }
365 else if (minX>0) /* outside minX faces */
366 {
367 dist.vx = minX;
368 }
369 else /* between faces */
370 {
371 dist.vx = 0;
372 }
373 }
374 {
375 int minY = modulePtr->m_miny + position.vy;
376 int maxY = modulePtr->m_maxy + position.vy;
377
378 if (maxY<0) /* outside maxY side */
379 {
380 dist.vy = maxY;
381 }
382 else if (minY>0) /* outside minY faces */
383 {
384 dist.vy = minY;
385 }
386 else /* between faces */
387 {
388 dist.vy = 0;
389 }
390 }
391 {
392 int minZ = modulePtr->m_minz + position.vz;
393 int maxZ = modulePtr->m_maxz + position.vz;
394
395 if (maxZ<0) /* outside maxZ side */
396 {
397 dist.vz = maxZ;
398 }
399 else if (minZ>0) /* outside minZ faces */
400 {
401 dist.vz = minZ;
402 }
403 else /* between faces */
404 {
405 dist.vz = 0;
406 }
407 }
408
409 VisibleModules[numVisMods].DispPtr = objectPtr;
410 #if 1
411 VisibleModules[numVisMods].SortKey = Magnitude(&dist);
412 #else
413 VisibleModules[numVisMods].SortKey = MUL_FIXED(dist.vx,dist.vx)
414 + MUL_FIXED(dist.vy,dist.vy)
415 + MUL_FIXED(dist.vz,dist.vz);
416 #endif
417 }
418
419 if(numVisMods>MAX_NUMBER_OF_VISIBLE_MODULES)
420 {
421 /* outside the environment! */
422 textprint("MAX_NUMBER_OF_VISIBLE_MODULES (%d) exceeded!\n",MAX_NUMBER_OF_VISIBLE_MODULES);
423 textprint("Possibly outside the environment!\n");
424 // LOCALASSERT(0);
425 return;
426 }
427
428 numVisMods++;
429 }
430 else /* it's just an object */
431 {
432 VisibleObjects[numVisObjs].DispPtr = objectPtr;
433 /* this sort key defaults to the object not being drawn, ie. a grenade
434 behind a closed door (so there is no module behind door) would still be
435 in the OnScreenBlockList but need not be drawn. */
436 VisibleObjects[numVisObjs].SortKey = 0X7FFFFFFF;
437 numVisObjs++;
438 }
439 }
440 ProfileStop("SORTSETUP");
441 textprint("numvismods %d\n",numVisMods);
442 textprint("numvisobjs %d\n",numVisObjs);
443
444 ProfileStart();
445 #if 1
446 {
447 int numMods = numVisMods;
448
449 while(numMods)
450 {
451 int n = numMods;
452
453 int furthestModule=0;
454 int furthestDistance=0;
455
456 while(n)
457 {
458 n--;
459 if (furthestDistance < VisibleModules[n].SortKey)
460 {
461 furthestDistance = VisibleModules[n].SortKey;
462 furthestModule = n;
463 }
464 }
465
466 numMods--;
467
468 VisibleModules2[numMods] = VisibleModules[furthestModule];
469 VisibleModules[furthestModule] = VisibleModules[numMods];
470 SortedModules = VisibleModules2;
471 }
472 }
473 #else
474 SortModules(numVisMods);
475 #endif
476 ProfileStop("MODULESORT");
477
478 ProfileStart();
479 {
480 #if FOG_ON
481 int fogDistance = 0x7f000000;
482 #endif
483
484 int o = numVisObjs;
485 while(o--)
486 {
487 DISPLAYBLOCK *objectPtr = VisibleObjects[o].DispPtr;
488 int maxX = objectPtr->ObWorld.vx + objectPtr->ObRadius;
489 int minX = objectPtr->ObWorld.vx - objectPtr->ObRadius;
490 int maxZ = objectPtr->ObWorld.vz + objectPtr->ObRadius;
491 int minZ = objectPtr->ObWorld.vz - objectPtr->ObRadius;
492 int maxY = objectPtr->ObWorld.vy + objectPtr->ObRadius;
493 int minY = objectPtr->ObWorld.vy - objectPtr->ObRadius;
494
495 int numMods = 0;
496 while(numMods<numVisMods)
497 {
498 MODULE *modulePtr = SortedModules[numMods].DispPtr->ObMyModule;
499
500 if (maxX >= modulePtr->m_minx+modulePtr->m_world.vx)
501 if (minX <= modulePtr->m_maxx+modulePtr->m_world.vx)
502 if (maxZ >= modulePtr->m_minz+modulePtr->m_world.vz)
503 if (minZ <= modulePtr->m_maxz+modulePtr->m_world.vz)
504 if (maxY >= modulePtr->m_miny+modulePtr->m_world.vy)
505 if (minY <= modulePtr->m_maxy+modulePtr->m_world.vy)
506 {
507 VisibleObjects[o].SortKey=numMods;
508 break;
509 }
510 numMods++;
511 }
512 #if 0
513 /* find nearest module which is fogged */
514 if(modulePtr->m_flags & MODULEFLAG_FOG)
515 {
516 if (fogDistance>SortedModules[numMods].SortKey)
517 fogDistance = SortedModules[numMods].SortKey;
518 }
519 #endif
520 if (CurrentVisionMode == VISION_MODE_PRED_SEEALIENS && objectPtr->ObStrategyBlock)
521 {
522 if (objectPtr->ObStrategyBlock->I_SBtype == I_BehaviourAlien)
523 VisibleObjects[o].DrawBeforeEnvironment = 0;//1;
524 }
525 else
526 {
527 VisibleObjects[o].DrawBeforeEnvironment = 0;
528 }
529 }
530 #if FOG_ON
531 if (fogDistance<0) fogDistance=0;
532 SetFogDistance(fogDistance);
533 #endif
534 }
535 ProfileStop("OBJS IN MOD TESTS");
536 DrawingAReflection=0;
537 {
538 int numMods = numVisMods;
539 #if 1
540 {
541 int o = numVisObjs;
542 CheckWireFrameMode(WireFrameMode&2);
543 while(o)
544 {
545 o--;
546
547 if(VisibleObjects[o].DrawBeforeEnvironment)
548 {
549 DISPLAYBLOCK *dptr = VisibleObjects[o].DispPtr;
550 AddShape(VisibleObjects[o].DispPtr,VDBPtr);
551 #if MIRRORING_ON
552 if (MirroringActive && !dptr->HModelControlBlock)
553 {
554 ReflectObject(dptr);
555
556 MakeVector(&dptr->ObWorld, &VDBPtr->VDB_World, &dptr->ObView);
557 RotateVector(&dptr->ObView, &VDBPtr->VDB_Mat);
558
559 DrawingAReflection=1;
560 AddShape(dptr,VDBPtr);
561 DrawingAReflection=0;
562 ReflectObject(dptr);
563 }
564 #endif
565 }
566 }
567 }
568
569 ClearTranslucentPolyList();
570
571 if (MOTIONBLUR_CHEATMODE)
572 {
573 for (numMods=0; numMods<numVisMods; numMods++)
574 {
575 MODULE *modulePtr = SortedModules[numMods].DispPtr->ObMyModule;
576
577 CheckWireFrameMode(WireFrameMode&1);
578 AddShape(SortedModules[numMods].DispPtr,VDBPtr);
579 #if MIRRORING_ON
580 if (MirroringActive)
581 {
582 DISPLAYBLOCK *dptr = SortedModules[numMods].DispPtr;
583 {
584 ReflectObject(dptr);
585
586 MakeVector(&dptr->ObWorld, &VDBPtr->VDB_World, &dptr->ObView);
587 RotateVector(&dptr->ObView, &VDBPtr->VDB_Mat);
588
589 DrawingAReflection=1;
590 AddShape(dptr,VDBPtr);
591 DrawingAReflection=0;
592 ReflectObject(dptr);
593 }
594 }
595 #endif
596 CheckWireFrameMode(WireFrameMode&2);
597 {
598 int o = numVisObjs;
599 while(o)
600 {
601 o--;
602
603 if(VisibleObjects[o].SortKey == numMods && !VisibleObjects[o].DrawBeforeEnvironment)
604 {
605 DISPLAYBLOCK *dptr = VisibleObjects[o].DispPtr;
606 AddShape(VisibleObjects[o].DispPtr,VDBPtr);
607 #if MIRRORING_ON
608 if (MirroringActive && !dptr->HModelControlBlock)
609 {
610 ReflectObject(dptr);
611
612 MakeVector(&dptr->ObWorld, &VDBPtr->VDB_World, &dptr->ObView);
613 RotateVector(&dptr->ObView, &VDBPtr->VDB_Mat);
614
615 DrawingAReflection=1;
616 AddShape(dptr,VDBPtr);
617 DrawingAReflection=0;
618 ReflectObject(dptr);
619 }
620 #endif
621 }
622 }
623 }
624
625
626 {
627 D3D_DrawWaterTest(modulePtr);
628 }
629 }
630 }
631 else
632 {
633 while(numMods--)
634 {
635 MODULE *modulePtr = SortedModules[numMods].DispPtr->ObMyModule;
636
637 CheckWireFrameMode(WireFrameMode&1);
638 AddShape(SortedModules[numMods].DispPtr,VDBPtr);
639 #if MIRRORING_ON
640 if (MirroringActive)
641 {
642 DISPLAYBLOCK *dptr = SortedModules[numMods].DispPtr;
643 {
644 ReflectObject(dptr);
645
646 MakeVector(&dptr->ObWorld, &VDBPtr->VDB_World, &dptr->ObView);
647 RotateVector(&dptr->ObView, &VDBPtr->VDB_Mat);
648
649 DrawingAReflection=1;
650 AddShape(dptr,VDBPtr);
651 DrawingAReflection=0;
652 ReflectObject(dptr);
653 }
654 }
655 #endif
656 CheckWireFrameMode(WireFrameMode&2);
657 {
658 int o = numVisObjs;
659 while(o)
660 {
661 o--;
662
663 if(VisibleObjects[o].SortKey == numMods && !VisibleObjects[o].DrawBeforeEnvironment)
664 {
665 DISPLAYBLOCK *dptr = VisibleObjects[o].DispPtr;
666 AddShape(VisibleObjects[o].DispPtr,VDBPtr);
667 #if MIRRORING_ON
668 if (MirroringActive && !dptr->HModelControlBlock)
669 {
670 ReflectObject(dptr);
671
672 MakeVector(&dptr->ObWorld, &VDBPtr->VDB_World, &dptr->ObView);
673 RotateVector(&dptr->ObView, &VDBPtr->VDB_Mat);
674
675 DrawingAReflection=1;
676 AddShape(dptr,VDBPtr);
677 DrawingAReflection=0;
678 ReflectObject(dptr);
679 }
680 #endif
681 }
682 }
683 }
684
685
686 {
687 D3D_DrawWaterTest(modulePtr);
688 }
689 }
690 }
691 // OutputTranslucentPolyList();
692 #endif
693 #if 0
694 {
695 int numMods = numVisMods;
696 while(numMods--)
697 AddShape(SortedModules[numMods].DispPtr,VDBPtr);
698 }
699 #endif
700 /* KJL 12:51:00 13/08/98 - scan for hierarchical objects which aren't going to be drawn,
701 and update their timers */
702 {
703 int o = numVisObjs;
704 while(o)
705 {
706 o--;
707
708 if(VisibleObjects[o].SortKey == 0x7fffffff)
709 {
710 if(VisibleObjects[o].DispPtr->HModelControlBlock)
711 {
712 DoHModelTimer(VisibleObjects[o].DispPtr->HModelControlBlock);
713 }
714 }
715 }
716 }
717
718 #if MIRRORING_ON
719 if (MirroringActive)
720 {
721 DrawingAReflection=1;
722 RenderPlayersImageInMirror();
723 DrawingAReflection=0;
724 }
725
726 #endif
727
728 #if 0
729 if (ScanDrawMode != ScanDrawDirectDraw)
730 {
731 WriteEndCodeToExecuteBuffer();
732 UnlockExecuteBufferAndPrepareForUse();
733 ExecuteBuffer();
734 EndD3DScene();
735 }
736 #endif
737
738 if (ScanDrawMode == ScanDrawDirectDraw)
739 {
740 UnlockSurface();
741 }
742
743 }
744 }
745
746 #if 0
747 static int ObjectIsInModule(DISPLAYBLOCK *objectPtr,MODULE *modulePtr)
748 {
749 int objectSize = objectPtr->ObRadius;
750 VECTORCH position = objectPtr->ObWorld;
751
752 position.vx -= modulePtr->m_world.vx;
753 position.vy -= modulePtr->m_world.vy;
754 position.vz -= modulePtr->m_world.vz;
755
756 if (position.vx + objectSize >= modulePtr->m_minx)
757 if (position.vx - objectSize <= modulePtr->m_maxx)
758 if (position.vz + objectSize >= modulePtr->m_minz)
759 if (position.vz - objectSize <= modulePtr->m_maxz)
760 if (position.vy + objectSize >= modulePtr->m_miny)
761 if (position.vy - objectSize <= modulePtr->m_maxy)
762 return 1;
763
764 return 0;
765
766 }
767 #endif
768
PointIsInModule(VECTORCH * pointPtr,MODULE * modulePtr)769 static int PointIsInModule(VECTORCH *pointPtr,MODULE *modulePtr)
770 {
771 VECTORCH position = *pointPtr;
772 position.vx -= modulePtr->m_world.vx;
773 position.vy -= modulePtr->m_world.vy;
774 position.vz -= modulePtr->m_world.vz;
775
776 if (position.vx >= modulePtr->m_minx)
777 if (position.vx <= modulePtr->m_maxx)
778 if (position.vz >= modulePtr->m_minz)
779 if (position.vz <= modulePtr->m_maxz)
780 if (position.vy >= modulePtr->m_miny)
781 if (position.vy <= modulePtr->m_maxy)
782 return 1;
783 return 0;
784
785 }
786
787
788
RenderThisDisplayblock(DISPLAYBLOCK * dbPtr)789 void RenderThisDisplayblock(DISPLAYBLOCK *dbPtr)
790 {
791 extern VIEWDESCRIPTORBLOCK *ActiveVDBList[];
792 VIEWDESCRIPTORBLOCK *VDBPtr = ActiveVDBList[0];
793
794 AddShape(dbPtr,VDBPtr);
795 }
796
RenderThisHierarchicalDisplayblock(DISPLAYBLOCK * dbPtr)797 void RenderThisHierarchicalDisplayblock(DISPLAYBLOCK *dbPtr)
798 {
799 extern VIEWDESCRIPTORBLOCK *ActiveVDBList[];
800 VIEWDESCRIPTORBLOCK *VDBPtr = ActiveVDBList[0];
801
802 AddHierarchicalShape(dbPtr,VDBPtr);
803 #if MIRRORING_ON
804 if (MirroringActive && dbPtr->ObStrategyBlock)
805 {
806 ReflectObject(dbPtr);
807
808 MakeVector(&dbPtr->ObWorld, &VDBPtr->VDB_World, &dbPtr->ObView);
809 RotateVector(&dbPtr->ObView, &VDBPtr->VDB_Mat);
810
811 AddHierarchicalShape(dbPtr,VDBPtr);
812 ReflectObject(dbPtr);
813 }
814 #endif
815 }
816
817
818
819
820
821 /* KJL 10:33:03 7/9/97 - this code no longer used */
822
823 #if 0
824 void OutputKItem(int *shapeitemptr)
825 {
826 /* Allocate space in the Item Data array */
827 if (IPtsArrSize)
828 {
829 int *itemDataPtr = AllocateItemData(IHdrSize + IPtsArrSize + ITrmSize);
830
831 if(itemDataPtr)
832 {
833 POLYHEADER *mypolyheader = (POLYHEADER*) itemDataPtr;
834 struct KItem * const currentItemPtr = &KItemList[ItemCount];
835
836 currentItemPtr->PolyPtr = mypolyheader;
837
838 {
839 POLYHEADER* polyheader = (POLYHEADER *)shapeitemptr;
840 int *offsetPtr = (int*) &polyheader->Poly1stPt;
841
842 int maxZ = smallint;
843 int minZ = bigint;
844
845 if (MorphedObjectPointsPtr)
846 {
847 while(*offsetPtr != Term)
848 {
849 VECTORCH v = *(VECTORCH*)((int *)MorphedObjectPointsPtr + *offsetPtr);
850 int z;
851
852 z = MUL_FIXED(LToVMat.mat13, v.vx);
853 z += MUL_FIXED(LToVMat.mat23, v.vy);
854 z += MUL_FIXED(LToVMat.mat33, v.vz);
855 z += Global_ODB_Ptr->ObView.vz;
856
857 if(z > maxZ) maxZ = z;
858 else if(z < minZ) minZ = z;
859
860 offsetPtr++;
861 }
862 }
863 else
864 {
865 while(*offsetPtr != Term)
866 {
867 int z = *((int *)RotatedPts + *offsetPtr + iz);
868
869 if(z > maxZ) maxZ = z;
870 else if(z < minZ) minZ = z;
871
872 offsetPtr++;
873 }
874 }
875
876 if (polyheader->PolyFlags & iflag_sortnearz) currentItemPtr->SortKey = minZ;
877 else if (polyheader->PolyFlags & iflag_sortfarz) currentItemPtr->SortKey = maxZ +10;
878 else currentItemPtr->SortKey = maxZ;
879 }
880
881 ItemCount++;
882
883 /* Write out the Item Header */
884
885 mypolyheader->PolyItemType = *shapeitemptr++;
886 mypolyheader->PolyNormalIndex = *shapeitemptr++;
887 mypolyheader->PolyFlags = *shapeitemptr++;
888 mypolyheader->PolyColour = ItemColour;
889
890 /* Write out the Item Points Array */
891 {
892 int *ptsArrayPtr = &PointsArray[0];
893 int i = IPtsArrSize;
894
895 itemDataPtr = &mypolyheader->Poly1stPt;
896
897 do
898 {
899 *itemDataPtr++ = *ptsArrayPtr++;
900 }
901 while(--i);
902 }
903
904 /* Write out the Item Terminator */
905 *itemDataPtr = Term;
906 }
907 }
908 }
909
910 void KShapeItemsInstr(SHAPEINSTR *shapeinstrptr)
911 {
912 int numitems= shapeinstrptr->sh_numitems;
913 int **shapeitemarrayptr = shapeinstrptr->sh_instr_data;
914
915 while(numitems)
916 {
917 int clip_output;
918 int *shapeitemptr = *shapeitemarrayptr;
919 POLYHEADER *pheaderPtr = (POLYHEADER*) shapeitemptr;
920
921 GLOBALASSERT(*shapeitemptr < I_Last);
922
923
924 if((Global_ODB_Ptr->ObFlags & ObFlag_BFCRO)
925 ||(Global_ODB_Ptr->ObFlags & ObFlag_ParrallelBFC))
926 {
927 if((pheaderPtr->PolyFlags & iflag_viewdotpos) == 0)
928 {
929 ItemOCSBlock.ocs_flags |= ocs_flag_outcoded;
930 }
931 else
932 {
933 ItemOCSBlock.ocs_flags = ocs_flag_nobfc;
934 OutcodeItem[*shapeitemptr](shapeitemptr, &ItemOCSBlock);
935 }
936 }
937 else
938 {
939 ItemOCSBlock.ocs_flags = 0;
940 OutcodeItem[*shapeitemptr](shapeitemptr, &ItemOCSBlock);
941 }
942
943
944 if((ItemOCSBlock.ocs_flags & ocs_flag_outcoded) == 0)
945 {
946 #if support3dtextures
947 if((pheaderPtr->PolyFlags & iflag_tx2dor3d)
948 && pheaderPtr->PolyItemType == I_2dTexturedPolygon)
949 pheaderPtr->PolyItemType = I_3dTexturedPolygon;
950 #if SupportZBuffering
951 if((pheaderPtr->PolyFlags & iflag_tx2dor3d)
952 && pheaderPtr->PolyItemType == I_ZB_2dTexturedPolygon)
953 pheaderPtr->PolyItemType = I_ZB_3dTexturedPolygon;
954 #endif
955 #endif
956
957 #if SupportGouraud3dTextures
958 if((pheaderPtr->PolyFlags & iflag_tx2dor3d)
959 && pheaderPtr->PolyItemType == I_Gouraud2dTexturedPolygon)
960 pheaderPtr->PolyItemType = I_Gouraud3dTexturedPolygon;
961 #if SupportZBuffering
962 if((pheaderPtr->PolyFlags & iflag_tx2dor3d)
963 && pheaderPtr->PolyItemType == I_ZB_Gouraud2dTexturedPolygon)
964 pheaderPtr->PolyItemType = I_ZB_Gouraud3dTexturedPolygon;
965 #endif
966 #endif
967
968 /* KJL 14:08:52 04/26/97 - hack to draw everything as a certain poly type */
969 #if 0
970 pheaderPtr->PolyItemType = I_2dTexturedPolygon;
971 #endif
972
973 /* KJL 17:15:46 06/07/97 - I'm not sure that we need 3dTexturedPolys */
974 if(pheaderPtr->PolyItemType == I_3dTexturedPolygon)
975 pheaderPtr->PolyItemType = I_2dTexturedPolygon;
976
977 if(ItemOCSBlock.ocs_clipstate == ocs_cs_totally_on)
978 {
979 CreateItemPtsArray[*shapeitemptr](shapeitemptr, &PointsArray[0]);
980
981 if(Global_ShapeNormals)
982 ItemColour = ItemLightingModel[*shapeitemptr](shapeitemptr);
983 else
984 ItemColour = pheaderPtr->PolyColour;
985
986 OutputKItem(shapeitemptr);
987 }
988 else
989 {
990 #if 0
991 /* Because in d3d polygons are rendered as triangles
992 the splits made to turn n-gons into triangles must
993 be invariant with the clipping performed on the poly,
994 otherwise artefacts will occur as polygons are clipped
995 to fit into screen space, such as the apparent intensity
996 changing on a clipper-created vertex.
997 This is difficult to achieve; the best way, which seems
998 to work well is to split the quads into triangles before
999 clipping - splitting them across the same diagonal as the
1000 renderer does. */
1001 int num_verts = 0;
1002 if (ScanDrawDirectDraw != ScanDrawMode)
1003 {
1004 /* count the number of verts - see if its a quad */
1005 int * ptsptr = &((POLYHEADER *)shapeitemptr)->Poly1stPt;
1006 while (Term != *ptsptr++)
1007 ++num_verts;
1008 /* shouldn't have pentagons etc. at this stage */
1009 GLOBALASSERT(num_verts<=4);
1010 }
1011 /* FIXME:
1012 I am not doing this quad splitting on textures with iflag_txanim set
1013 This is rather more complicated than I care to imagine - the uv
1014 co-ords which also need splitting are generated in a function
1015 called CreateTxAnimUVArray which also seems to do a lot more than
1016 just that. Bloody Chris Humphries.
1017 Anyway, I think the lighting artefact will be less noticeable if the texture is animating */
1018 if (4==num_verts && !(((POLYHEADER *)shapeitemptr)->PolyFlags & iflag_txanim))
1019 /* need to split quads in d3d mode -
1020 note that num_verts will be 0 in scandraw mode
1021 so this condition will always be false */
1022 {
1023 /* get pointers to the output items - we may need to adjust the sort key */
1024 struct KItem * triangle1 = 0;
1025 struct KItem * triangle2 = 0;
1026 /* For a quad we create the triangles (0,1,3) and (1,2,3) */
1027 /* (see item.c - PrepareTriangleArray_4 functions) */
1028 /* copy the header data for the quad into this buffer */
1029 int item_array_buf[sizeof(POLYHEADER)+sizeof(int)*4]; /* 4 verts + polyheader & term */
1030 /* save the previous uv data in this buffer and modify the actual uv data */
1031 int uv_array_store[8]; /* 4 verts, U and V foreach vert */
1032 /* this points to the uv data we are going to save and modify */
1033 int * uv_array_ptr = NULL; /* will set this non-null if we have a textured item type */
1034 if (
1035 I_2dTexturedPolygon == *shapeitemptr ||
1036 I_Gouraud2dTexturedPolygon == *shapeitemptr ||
1037 I_3dTexturedPolygon == *shapeitemptr ||
1038 I_UnscaledSprite == *shapeitemptr ||
1039 I_ScaledSprite == *shapeitemptr ||
1040 I_ZB_2dTexturedPolygon == *shapeitemptr ||
1041 I_ZB_Gouraud2dTexturedPolygon == *shapeitemptr ||
1042 I_ZB_3dTexturedPolygon == *shapeitemptr ||
1043 I_Gouraud3dTexturedPolygon == *shapeitemptr ||
1044 I_ZB_Gouraud3dTexturedPolygon == *shapeitemptr
1045 ) /* textured item type - has uv coords */
1046 uv_array_ptr = Global_ShapeTextures[((POLYHEADER *)shapeitemptr)->PolyColour >> TxDefn];
1047 /* copy the header data for the quad into the buffer */
1048 /* ...and the first two verts since these are the same for the first triangle as for the quad */
1049 memcpy(item_array_buf,shapeitemptr,sizeof(POLYHEADER)-sizeof(int)+2*sizeof(int));
1050 /* save the uv data */
1051 if (uv_array_ptr) memcpy(uv_array_store,uv_array_ptr,sizeof uv_array_store);
1052 /* select vertices for the first triangle */
1053 #define PFP_OFFSET (sizeof(POLYHEADER)/sizeof(int)-1) /* normally 4 but what if polyheader changes */
1054 LOCALASSERT(item_array_buf[PFP_OFFSET+0] == shapeitemptr[PFP_OFFSET+0]);
1055 LOCALASSERT(item_array_buf[PFP_OFFSET+1] == shapeitemptr[PFP_OFFSET+1]);
1056 item_array_buf[PFP_OFFSET+2] = shapeitemptr[PFP_OFFSET+3];
1057 item_array_buf[PFP_OFFSET+3] = Term;
1058 if (uv_array_ptr)
1059 {
1060 /* select the uv coords for the first triangle */
1061 LOCALASSERT(uv_array_ptr[0] == uv_array_store[0]); /* U */
1062 LOCALASSERT(uv_array_ptr[1] == uv_array_store[1]); /* V */
1063 LOCALASSERT(uv_array_ptr[2] == uv_array_store[2]); /* U */
1064 LOCALASSERT(uv_array_ptr[3] == uv_array_store[3]); /* V */
1065 uv_array_ptr[4] = uv_array_store[6]; /* U */
1066 uv_array_ptr[5] = uv_array_store[7]; /* V */
1067 }
1068 /* output it in the usual way */
1069 if(ItemOCSBlock.ocs_ptsoutstate == ocs_pout_2d)
1070 {
1071 CreateItemPtsArray[*item_array_buf](item_array_buf, &ClipPointsArray0[0]);
1072 clip_output = Clip2d[*item_array_buf](item_array_buf);
1073 }
1074 else
1075 {
1076 /* also ensure both polygons are rendered in 3d */
1077 ((POLYHEADER *)item_array_buf)->PolyFlags &= ~iflag_tx2dor3d;
1078 CreateItemPtsArray_Clip3d[*item_array_buf](item_array_buf, &ClipPointsArray0[0]);
1079 clip_output = Clip3d[*item_array_buf](item_array_buf);
1080 }
1081 if(clip_output)
1082 {
1083
1084 if(Global_ShapeNormals)
1085 ItemColour = ItemLightingModel[*item_array_buf](item_array_buf);
1086 else
1087 ItemColour = pheaderPtr->PolyColour;
1088
1089 triangle1 = OutputKItem(item_array_buf);
1090 }
1091 /* copy the header data for the quad into the buffer again
1092 because the outcode function fuck around with it,,, */
1093 memcpy(item_array_buf,shapeitemptr,sizeof(POLYHEADER)-sizeof(int));
1094 /* select vertices for the second triangle */
1095 item_array_buf[PFP_OFFSET+0] = shapeitemptr[PFP_OFFSET+1];
1096 item_array_buf[PFP_OFFSET+1] = shapeitemptr[PFP_OFFSET+2];
1097 LOCALASSERT(item_array_buf[PFP_OFFSET+2] == shapeitemptr[PFP_OFFSET+3]);
1098 LOCALASSERT(item_array_buf[PFP_OFFSET+3] == Term);
1099 if (uv_array_ptr)
1100 {
1101 /* select the uv coords for the first triangle */
1102 uv_array_ptr[0] = uv_array_store[2]; /* U */
1103 uv_array_ptr[1] = uv_array_store[3]; /* V */
1104 uv_array_ptr[2] = uv_array_store[4]; /* U */
1105 uv_array_ptr[3] = uv_array_store[5]; /* V */
1106 LOCALASSERT(uv_array_ptr[4] == uv_array_store[6]); /* U */
1107 LOCALASSERT(uv_array_ptr[5] == uv_array_store[7]); /* V */
1108 }
1109 /* output it in the usual way */
1110 if(ItemOCSBlock.ocs_ptsoutstate == ocs_pout_2d)
1111 {
1112 CreateItemPtsArray[*item_array_buf](item_array_buf, &ClipPointsArray0[0]);
1113 clip_output = Clip2d[*item_array_buf](item_array_buf);
1114 }
1115 else
1116 {
1117 /* also ensure both polygons are rendered in 3d */
1118 ((POLYHEADER *)item_array_buf)->PolyFlags &= ~iflag_tx2dor3d;
1119 CreateItemPtsArray_Clip3d[*item_array_buf](item_array_buf, &ClipPointsArray0[0]);
1120 clip_output = Clip3d[*item_array_buf](item_array_buf);
1121 }
1122 if(clip_output)
1123 {
1124
1125 if(Global_ShapeNormals)
1126 ItemColour = ItemLightingModel[*item_array_buf](item_array_buf);
1127 else
1128 ItemColour = pheaderPtr->PolyColour;
1129
1130 triangle2 = OutputKItem(item_array_buf);
1131 }
1132 /* restore the uv data */
1133 if (uv_array_ptr) memcpy(uv_array_ptr,uv_array_store,sizeof uv_array_store);
1134 /* if both triangles have been output,
1135 we may need to change the sort keys on one or both,
1136 so that far z and near z values will hopefully be
1137 the same as if it was output as a quad */
1138 if (triangle1 && triangle2)
1139 {
1140 if (((POLYHEADER *)shapeitemptr)->PolyFlags & iflag_sortnearz)
1141 {
1142 /* take minimum sort keys */
1143 if (triangle1->SortKey < triangle2->SortKey)
1144 triangle2->SortKey = triangle1->SortKey;
1145 else
1146 triangle1->SortKey = triangle2->SortKey;
1147 }
1148 else
1149 {
1150 /* since sortfarz and no sort flag both take the largest z value
1151 take maximum sort keys */
1152 if (triangle1->SortKey > triangle2->SortKey)
1153 triangle2->SortKey = triangle1->SortKey;
1154 else
1155 triangle1->SortKey = triangle2->SortKey;
1156 }
1157 }
1158 }
1159 else
1160 #endif
1161 {
1162 if(ItemOCSBlock.ocs_ptsoutstate == ocs_pout_2d)
1163 {
1164 CreateItemPtsArray[*shapeitemptr](shapeitemptr, &ClipPointsArray0[0]);
1165 clip_output = Clip2d[*shapeitemptr](shapeitemptr);
1166 }
1167 else
1168 {
1169 CreateItemPtsArray_Clip3d[*shapeitemptr](shapeitemptr, &ClipPointsArray0[0]);
1170 clip_output = Clip3d[*shapeitemptr](shapeitemptr);
1171 }
1172 if(clip_output)
1173 {
1174
1175 if(Global_ShapeNormals)
1176 ItemColour = ItemLightingModel[*shapeitemptr](shapeitemptr);
1177 else
1178 ItemColour = pheaderPtr->PolyColour;
1179
1180 OutputKItem(shapeitemptr);
1181 }
1182 }
1183 }
1184 }
1185
1186 shapeitemarrayptr++; /* next polygon etc. */
1187 numitems--;
1188 }
1189 }
1190 #endif
1191
1192
1193