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