1 /*KJL*************************
2 * los.c - Line of sight code *
3 *************************KJL*/
4 #include "3dc.h"
5 #include "module.h"
6 #include "inline.h"
7 #include "stratdef.h"
8 #include "gamedef.h"
9 #include "dynblock.h"
10 #include "dynamics.h"
11 
12 #include "bh_types.h"
13 #include "comp_shp.h"
14 #include "avpview.h"
15 #define UseLocalAssert Yes
16 #include "ourasert.h"
17 #include "dxlog.h"
18 #include "showcmds.h"
19 #include "targeting.h"
20 #include "los.h"
21 
22 /*KJL****************************************************************************************
23 *                                    P R O T O T Y P E S	                                *
24 ****************************************************************************************KJL*/
25 int IsThisObjectVisibleFromThisPosition(DISPLAYBLOCK *dPtr,VECTORCH *positionPtr,int maxRange);
26 void CheckForVectorIntersectionWithHierarchicalObject(DISPLAYBLOCK *dPtr, VECTORCH *viewVectorAlphaPtr, VECTORCH *viewVectorBetaPtr);
27 void CheckForRayIntersectionWithHierarchy(DISPLAYBLOCK *objectPtr, SECTION_DATA *sectionDataPtr);
28 void CheckForRayIntersectionWithObject(DISPLAYBLOCK *dPtr);
29 /*KJL****************************************************************************************
30 * 										D E F I N E S 										*
31 ****************************************************************************************KJL*/
32 #define POLY_REJECT_RANGE 500
33 
34 extern MORPHDISPLAY MorphDisplay;
35 extern VECTORCH MorphedPts[];
36 extern VECTORCH *ShapePointsPtr;
37 extern int *ShapeNormalsPtr;
38 extern int *Shape2NormalsPtr;
39 extern char ShapeIsMorphed;
40 extern int **ItemArrayPtr;
41 extern POLYHEADER *PolyheaderPtr;
42 
43 #define AccessNextPolygon()\
44 {\
45 	int *itemPtr = *(ItemArrayPtr++);\
46 	PolyheaderPtr = (POLYHEADER *) itemPtr;\
47 }
48 
49 #define GetPolygonVertices(polyPtr)\
50 {\
51 	int *vertexNumberPtr = &PolyheaderPtr->Poly1stPt;\
52 \
53   	(polyPtr)->PolyPoint[0] = *(ShapePointsPtr + *vertexNumberPtr++);\
54     (polyPtr)->PolyPoint[1] = *(ShapePointsPtr + *vertexNumberPtr++);\
55     (polyPtr)->PolyPoint[2] = *(ShapePointsPtr + *vertexNumberPtr++);\
56     \
57 	if (*vertexNumberPtr != Term)\
58 	{\
59 	    (polyPtr)->PolyPoint[3] = *(ShapePointsPtr + *vertexNumberPtr);\
60 	   	(polyPtr)->NumberOfVertices=4; \
61 	}\
62 	else\
63 	{\
64 	   	(polyPtr)->NumberOfVertices=3; \
65 	}\
66 }
67 #define GetPolygonNormal(polyPtr)\
68 {	  \
69 	if (ShapeIsMorphed)\
70 	{\
71 		VECTORCH n1Ptr = *(VECTORCH*)(ShapeNormalsPtr + PolyheaderPtr->PolyNormalIndex);\
72 		VECTORCH n2Ptr = *(VECTORCH*)(Shape2NormalsPtr + PolyheaderPtr->PolyNormalIndex);\
73         \
74 		if( ((n1Ptr.vx == n2Ptr.vx)\
75 		  && (n1Ptr.vy == n2Ptr.vy)\
76 		  && (n1Ptr.vz == n2Ptr.vz))\
77 		  || (MorphDisplay.md_lerp == 0) )\
78 		{\
79 			(polyPtr)->PolyNormal = n1Ptr;\
80 		}\
81 		else if(MorphDisplay.md_lerp == 0xffff)\
82 		{\
83 			(polyPtr)->PolyNormal = n2Ptr;\
84 		}\
85 		else\
86 		{\
87 			VECTORCH *pointPtr[3];\
88  			int *vertexNumPtr = &PolyheaderPtr->Poly1stPt;\
89 \
90 			pointPtr[0] = (ShapePointsPtr + *vertexNumPtr++);\
91 			pointPtr[1] = (ShapePointsPtr + *vertexNumPtr++);\
92 			pointPtr[2] = (ShapePointsPtr + *vertexNumPtr);\
93 \
94 			MakeNormal\
95 			(\
96 				pointPtr[0],\
97 				pointPtr[1],\
98 				pointPtr[2],\
99 				&(polyPtr)->PolyNormal\
100 			);\
101 		}\
102 	}\
103     else /* not morphed */\
104     {\
105      	(polyPtr)->PolyNormal = *(VECTORCH*)(ShapeNormalsPtr + PolyheaderPtr->PolyNormalIndex);\
106     }\
107 }
108 
109 /*KJL****************************************************************************************
110 *  										G L O B A L S 	            					    *
111 ****************************************************************************************KJL*/
112 extern DISPLAYBLOCK *Player;
113 
114 /* unnormalised vector in the direction	which the gun's muzzle is pointing, IN VIEW SPACE */
115 /* very useful when considering sprites, which lie in a Z-plane in view space */
116 extern VECTORCH GunMuzzleDirectionInVS;
117 /* dir gun is pointing, normalised and IN WORLD SPACE */
118 extern VECTORCH GunMuzzleDirectionInWS;
119 
120 extern DISPLAYBLOCK PlayersWeapon;
121 
122 
123 extern int NumOnScreenBlocks;
124 extern DISPLAYBLOCK *OnScreenBlockList[];
125 extern int NumActiveBlocks;
126 extern DISPLAYBLOCK *ActiveBlockList[];
127 
128 
129 static VECTORCH *ViewpointDirectionPtr;
130 static VECTORCH *ViewpointPositionPtr;
131 
132 
133 /*KJL****************************************************************************************
134 *                                     CODE STARTS HERE!                                     *
135 ****************************************************************************************KJL*/
CameraCanSeeThisPosition_WithIgnore(DISPLAYBLOCK * ignoredObjectPtr,VECTORCH * positionPtr)136 int CameraCanSeeThisPosition_WithIgnore(DISPLAYBLOCK *ignoredObjectPtr,VECTORCH *positionPtr)
137 {
138 	VECTORCH viewVector;  /* direction of view-line */
139 
140 	GLOBALASSERT(ignoredObjectPtr);
141 
142 	/* try to look at the centre of the camera */
143 	viewVector = Global_VDB_Ptr->VDB_World;
144 
145    	viewVector.vx -= positionPtr->vx;
146 	viewVector.vy -= positionPtr->vy;
147 	viewVector.vz -= positionPtr->vz;
148 	Normalise(&viewVector);
149 
150 	FindPolygonInLineOfSight(&viewVector, positionPtr, 0,ignoredObjectPtr);
151 
152 
153 	if (LOS_ObjectHitPtr == Player) return 1;
154 	else return 0;
155 }
156 
IsThisObjectVisibleFromThisPosition_WithIgnore(DISPLAYBLOCK * objectPtr,DISPLAYBLOCK * ignoredObjectPtr,VECTORCH * positionPtr,int maxRange)157 int IsThisObjectVisibleFromThisPosition_WithIgnore(DISPLAYBLOCK *objectPtr,DISPLAYBLOCK *ignoredObjectPtr,VECTORCH *positionPtr,int maxRange)
158 {
159 	VECTORCH viewVector;  /* direction of view-line */
160 
161 	GLOBALASSERT(objectPtr);
162 
163 	/* try to look at the centre of the object */
164 	GetTargetingPointOfObject(objectPtr, &viewVector);
165 
166    	viewVector.vx -= positionPtr->vx;
167 	viewVector.vy -= positionPtr->vy;
168 	viewVector.vz -= positionPtr->vz;
169 	Normalise(&viewVector);
170 
171 	FindPolygonInLineOfSight(&viewVector, positionPtr, 0,ignoredObjectPtr);
172 
173 
174 	if (LOS_ObjectHitPtr == objectPtr) return 1;
175 	else return 0;
176 }
177 
IsThisObjectVisibleFromThisPosition(DISPLAYBLOCK * objectPtr,VECTORCH * positionPtr,int maxRange)178 int IsThisObjectVisibleFromThisPosition(DISPLAYBLOCK *objectPtr,VECTORCH *positionPtr,int maxRange)
179 {
180 	VECTORCH viewVector;  /* direction of view-line */
181 
182 	GLOBALASSERT(objectPtr);
183 
184 	/* try to look at the centre of the object */
185 	GetTargetingPointOfObject(objectPtr, &viewVector);
186 
187    	viewVector.vx -= positionPtr->vx;
188 	viewVector.vy -= positionPtr->vy;
189 	viewVector.vz -= positionPtr->vz;
190 	Normalise(&viewVector);
191 
192 	FindPolygonInLineOfSight(&viewVector, positionPtr, 0,0);
193 
194 
195 	if (LOS_ObjectHitPtr == objectPtr) return 1;
196 	else return 0;
197 }
198 
199 
CheckForVectorIntersectionWith3dObject(DISPLAYBLOCK * objectPtr,VECTORCH * viewVectorAlphaPtr,VECTORCH * viewVectorBetaPtr,int rigorous)200 void CheckForVectorIntersectionWith3dObject(DISPLAYBLOCK *objectPtr, VECTORCH *viewVectorAlphaPtr, VECTORCH *viewVectorBetaPtr, int rigorous)
201 {
202 	ViewpointPositionPtr = viewVectorAlphaPtr;
203 	ViewpointDirectionPtr = viewVectorBetaPtr;
204 
205 	if (objectPtr->HModelControlBlock)
206 	{
207 		SECTION_DATA *firstSectionPtr;
208 	  	firstSectionPtr=objectPtr->HModelControlBlock->section_data;
209 	  	LOCALASSERT(firstSectionPtr);
210 		if ( !(
211 			(objectPtr->ObWorld.vx<1000000 && objectPtr->ObWorld.vx>-1000000)
212 		 &&	(objectPtr->ObWorld.vy<1000000 && objectPtr->ObWorld.vy>-1000000)
213 		 &&	(objectPtr->ObWorld.vz<1000000 && objectPtr->ObWorld.vz>-1000000)
214 		 ) )
215 		{
216 			return;
217 		}
218 	  	LOCALASSERT(objectPtr->ObWorld.vx<1000000 && objectPtr->ObWorld.vx>-1000000);
219 	  	LOCALASSERT(objectPtr->ObWorld.vy<1000000 && objectPtr->ObWorld.vy>-1000000);
220 	  	LOCALASSERT(objectPtr->ObWorld.vz<1000000 && objectPtr->ObWorld.vz>-1000000);
221 	  	CheckForRayIntersectionWithHierarchy(objectPtr,firstSectionPtr);
222 	}
223 	else
224 	{
225 		CheckForRayIntersectionWithObject(objectPtr);
226 	}
227 }
228 
229 
230 
231 
232 
233 
234 
235 
236 
237 /* KJL 15:26:08 14/05/98 - FindPolygonInLineOfSight
238 
239 	Using either the Active or OnScreen Block list, find which polygon you would hit first
240 	if a ray of light was cast out from a given point in world space (viewpointPositionPtr)
241 	in a given direction (viewpointDirectionPtr).
242 
243 	The following are set:
244 
245 	LOS_ObjectHitPtr	- dispPtr of hit object (NULL if none found)
246 
247 	LOS_Lambda			- distance to hit polygon (or max if no hit)
248 	LOS_Point			- world space coords of intersection of ray & hit poly
249 	LOS_ObjectNormal	- normal of the hit polygon
250 	LOS_HModel_Section	- hierarchical section that was hit (or NULL if not hmodel)
251 
252 */
FindPolygonInLineOfSight(VECTORCH * viewpointDirectionPtr,VECTORCH * viewpointPositionPtr,int useOnScreenBlockList,DISPLAYBLOCK * objectToIgnorePtr)253 void FindPolygonInLineOfSight(VECTORCH *viewpointDirectionPtr, VECTORCH *viewpointPositionPtr, int useOnScreenBlockList, DISPLAYBLOCK *objectToIgnorePtr) {
254 
255 	/* Shell function. */
256 	FindPolygonInLineOfSight_TwoIgnores(viewpointDirectionPtr,viewpointPositionPtr,useOnScreenBlockList,objectToIgnorePtr,NULL);
257 	/* No, it's not recursive! */
258 }
259 
260 
FindPolygonInLineOfSight_TwoIgnores(VECTORCH * viewpointDirectionPtr,VECTORCH * viewpointPositionPtr,int useOnScreenBlockList,DISPLAYBLOCK * objectToIgnorePtr,DISPLAYBLOCK * next_objectToIgnorePtr)261 void FindPolygonInLineOfSight_TwoIgnores(VECTORCH *viewpointDirectionPtr, VECTORCH *viewpointPositionPtr, int useOnScreenBlockList, DISPLAYBLOCK *objectToIgnorePtr,DISPLAYBLOCK *next_objectToIgnorePtr)
262 {
263 	DISPLAYBLOCK **displayBlockList;
264    	int numberOfObjects;
265 
266    	if (useOnScreenBlockList)
267    	{
268 		numberOfObjects = NumOnScreenBlocks;
269 		displayBlockList = OnScreenBlockList;
270 	}
271 	else
272    	{
273    		numberOfObjects = NumActiveBlocks;
274 		displayBlockList = ActiveBlockList;
275 	}
276 
277 	/* initialise the LoS data */
278 
279   	LOS_Lambda=10000000;
280 	LOS_ObjectHitPtr = 0;
281 	LOS_HModel_Section= 0;
282 	ViewpointPositionPtr = viewpointPositionPtr;
283 	ViewpointDirectionPtr = viewpointDirectionPtr;
284 
285 
286    	/* scan throught each object */
287    	while (numberOfObjects--)
288 	{
289 		DISPLAYBLOCK* objectPtr = displayBlockList[numberOfObjects];
290 
291 		if ((objectPtr == objectToIgnorePtr)||(objectPtr == next_objectToIgnorePtr)) continue;
292 
293 		/* if hierarchical model, consider each object in the model separately */
294 		if (objectPtr->HModelControlBlock)
295 		{
296 			SECTION_DATA *firstSectionPtr;
297 		  	firstSectionPtr=objectPtr->HModelControlBlock->section_data;
298 
299 		  	LOCALASSERT(firstSectionPtr);
300 			if ( !(
301 				(objectPtr->ObWorld.vx<1000000 && objectPtr->ObWorld.vx>-1000000)
302 			 &&	(objectPtr->ObWorld.vy<1000000 && objectPtr->ObWorld.vy>-1000000)
303 			 &&	(objectPtr->ObWorld.vz<1000000 && objectPtr->ObWorld.vz>-1000000)
304 			 ) )
305 			 {
306 				continue;
307 
308 				LOGDXFMT(("Pre assertions check for having processed the section...\n"));
309 				LOGDXFMT(("State of initialised flag: %d\n",(firstSectionPtr->flags&section_data_initialised)));
310 				LOGDXFMT(("Name of section: %s\n",firstSectionPtr->sempai->Section_Name));
311 				LOGDXFMT(("It was playing sequence: %d,%d\n",firstSectionPtr->my_controller->Sequence_Type,
312 					firstSectionPtr->my_controller->Sub_Sequence));
313 				LOGDXFMT(("ObWorld %d,%d,%d\n",objectPtr->ObWorld.vx,objectPtr->ObWorld.vy,objectPtr->ObWorld.vz));
314 
315 				{
316 					DYNAMICSBLOCK *dynPtr=objectPtr->ObStrategyBlock->DynPtr;
317 					LOCALASSERT(dynPtr);
318 					LOGDXFMT(("DynPtr->Position %d,%d,%d\n",dynPtr->Position.vx,dynPtr->Position.vy,dynPtr->Position.vz));
319 				}
320 
321 				LOCALASSERT(firstSectionPtr->flags&section_data_initialised);
322 				LOCALASSERT(objectPtr->ObWorld.vx<1000000 && objectPtr->ObWorld.vx>-1000000);
323 				LOCALASSERT(objectPtr->ObWorld.vy<1000000 && objectPtr->ObWorld.vy>-1000000);
324 				LOCALASSERT(objectPtr->ObWorld.vz<1000000 && objectPtr->ObWorld.vz>-1000000);
325 
326 			}
327 		  	CheckForRayIntersectionWithHierarchy(objectPtr,firstSectionPtr);
328 		}
329 		else
330 		{
331 			CheckForRayIntersectionWithObject(objectPtr);
332 		}
333 	}
334 }
335 
CheckForRayIntersectionWithHierarchy(DISPLAYBLOCK * objectPtr,SECTION_DATA * sectionDataPtr)336 void CheckForRayIntersectionWithHierarchy(DISPLAYBLOCK *objectPtr, SECTION_DATA *sectionDataPtr)
337 {
338 	SECTION *sectionPtr;
339 
340 	/* LOS check. */
341 
342 	sectionPtr=sectionDataPtr->sempai;
343 
344 	/* Unreal things can't be hit... */
345 
346 	if (!(sectionDataPtr->flags&section_data_notreal) && (sectionPtr->Shape!=NULL))
347 	{
348 		DISPLAYBLOCK dummy_displayblock;
349 
350 		dummy_displayblock.ObShape=sectionPtr->ShapeNum;
351 		dummy_displayblock.ObShapeData=sectionPtr->Shape;
352 		dummy_displayblock.ObWorld=sectionDataPtr->World_Offset;
353 		dummy_displayblock.ObMat=sectionDataPtr->SecMat;
354 
355 		dummy_displayblock.ObRadius=0;
356 		dummy_displayblock.ObMaxX=0;
357 		dummy_displayblock.ObMinX=0;
358 		dummy_displayblock.ObMaxY=0;
359 		dummy_displayblock.ObMinY=0;
360 		dummy_displayblock.ObMaxZ=0;
361 		dummy_displayblock.ObMinZ=0;
362 
363 		dummy_displayblock.ObTxAnimCtrlBlks=NULL;
364 		dummy_displayblock.ObEIDPtr=NULL;
365 		dummy_displayblock.ObMorphCtrl=NULL;
366 		dummy_displayblock.ObStrategyBlock=objectPtr->ObStrategyBlock;
367 		dummy_displayblock.ShapeAnimControlBlock=sectionDataPtr->sac_ptr;
368 		dummy_displayblock.HModelControlBlock=NULL; /* Don't even want to think about that. */
369 		dummy_displayblock.ObMyModule=NULL;
370 
371 		/* KJL 21:12:11 12/11/98 - arg! ObFlags wasn't set */
372 		dummy_displayblock.ObFlags = 0;
373 
374 		if ( !(
375 			(dummy_displayblock.ObWorld.vx<1000000 && dummy_displayblock.ObWorld.vx>-1000000)
376 		 &&	(dummy_displayblock.ObWorld.vy<1000000 && dummy_displayblock.ObWorld.vy>-1000000)
377 		 &&	(dummy_displayblock.ObWorld.vz<1000000 && dummy_displayblock.ObWorld.vz>-1000000)
378 		 ) ) {
379 
380 			LOGDXFMT(("Pre assertions check for having processed the section...\n"));
381 			LOGDXFMT(("State of initialised flag: %x\n",(sectionDataPtr->flags&section_data_initialised)));
382 			LOGDXFMT(("Name of section: %s\n",sectionDataPtr->sempai->Section_Name));
383 			LOGDXFMT(("It was playing sequence: %d,%d\n",sectionDataPtr->my_controller->Sequence_Type,
384 				sectionDataPtr->my_controller->Sub_Sequence));
385 			LOGDXFMT(("ObWorld %d,%d,%d\n",dummy_displayblock.ObWorld.vx,dummy_displayblock.ObWorld.vy,dummy_displayblock.ObWorld.vz));
386 
387 			{
388 				DYNAMICSBLOCK *dynPtr=objectPtr->ObStrategyBlock->DynPtr;
389 				LOCALASSERT(dynPtr);
390 				LOGDXFMT(("DynPtr->Position %d,%d,%d\n",dynPtr->Position.vx,dynPtr->Position.vy,dynPtr->Position.vz));
391 			}
392 
393 			LOCALASSERT(sectionDataPtr->flags&section_data_initialised);
394 			LOCALASSERT(dummy_displayblock.ObWorld.vx<1000000 && dummy_displayblock.ObWorld.vx>-1000000);
395 			LOCALASSERT(dummy_displayblock.ObWorld.vy<1000000 && dummy_displayblock.ObWorld.vy>-1000000);
396 			LOCALASSERT(dummy_displayblock.ObWorld.vz<1000000 && dummy_displayblock.ObWorld.vz>-1000000);
397 
398 		}
399 
400 		CheckForRayIntersectionWithObject(&dummy_displayblock);
401 
402 		if (LOS_ObjectHitPtr == &dummy_displayblock)
403 		{
404 			/* ah, we've hit this object */
405 			LOS_ObjectHitPtr = objectPtr;
406 			LOS_HModel_Section = sectionDataPtr;
407 		}
408 	}
409 
410 	/* Now call recursion... */
411 	if (sectionDataPtr->First_Child!=NULL)
412 	{
413 		SECTION_DATA *childrenListPtr = sectionDataPtr->First_Child;
414 
415 		while (childrenListPtr!=NULL)
416 		{
417 			CheckForRayIntersectionWithHierarchy(objectPtr,childrenListPtr);
418 			childrenListPtr=childrenListPtr->Next_Sibling;
419 		}
420 	}
421 
422 }
423 
424 
425 
426 
CheckForRayIntersectionWithObject(DISPLAYBLOCK * dPtr)427 void CheckForRayIntersectionWithObject(DISPLAYBLOCK *dPtr)
428 {
429 	int numberOfItems;
430 	VECTORCH viewVectorAlpha = *ViewpointPositionPtr;
431 	VECTORCH viewVectorBeta = *ViewpointDirectionPtr;
432 	VECTORCH position;
433 	int needToRotate;
434 
435 	/* check for a valid object */
436 	{
437 		STRATEGYBLOCK* sbPtr;
438 		GLOBALASSERT(dPtr);
439 
440 		/* can it be seen? */
441 		if((dPtr->ObFlags&ObFlag_NotVis)&&(dPtr!=Player)) return;
442 		/* KJL 21:18:44 23/05/98 - ugh. Currently the player's bounding box is notvis; I need a rethink */
443 
444 		/* any hierarchical models should have been split up by now */
445 		LOCALASSERT(dPtr->HModelControlBlock==NULL);
446 
447 		/* no shape? */
448 		if (!dPtr->ObShape && dPtr->SfxPtr) return;
449 
450 		sbPtr = dPtr->ObStrategyBlock;
451 
452 		/* test for objects we're not interested in */
453    		if (sbPtr)
454 		{
455 			if (sbPtr->DynPtr)
456 			{
457 				/* ignore it if it's a non-collideable object, eg. debris */
458 				if(sbPtr->DynPtr->DynamicsType == DYN_TYPE_NO_COLLISIONS)
459 					return;
460 			}
461 		}
462 	}
463 
464 	/* check objects position is sensible */
465 	#if 0
466 	LOCALASSERT(dPtr->ObWorld.vx<1000000 && dPtr->ObWorld.vx>-1000000);
467 	LOCALASSERT(dPtr->ObWorld.vy<1000000 && dPtr->ObWorld.vy>-1000000);
468 	LOCALASSERT(dPtr->ObWorld.vz<1000000 && dPtr->ObWorld.vz>-1000000);
469 	#else
470 	if(dPtr->ObWorld.vx>1000000 || dPtr->ObWorld.vx<-1000000) return;
471 	if(dPtr->ObWorld.vy>1000000 || dPtr->ObWorld.vy<-1000000) return;
472 	if(dPtr->ObWorld.vz>1000000 || dPtr->ObWorld.vz<-1000000) return;
473 	#endif
474 	if (dPtr==Player)
475 	{
476 		position = dPtr->ObStrategyBlock->DynPtr->Position;
477 	}
478 	else
479 	{
480 		position = dPtr->ObWorld;
481 	}
482 	/* transform view line into shape space */
483 	viewVectorAlpha.vx -= position.vx;
484 	viewVectorAlpha.vy -= position.vy;
485 	viewVectorAlpha.vz -= position.vz;
486 
487 	#if 1
488 	if (dPtr!=Player)
489 	{
490 		if (MagnitudeOfCrossProduct(&viewVectorAlpha,&viewVectorBeta)>dPtr->ObShapeData->shaperadius)
491 			return;
492 	}
493 	#endif
494 
495 	/* if we're not dealing with a module, it's probably rotated */
496 	if(!dPtr->ObMyModule&&dPtr!=Player)
497 	{
498 		needToRotate = 1;
499 	}
500 	else
501 	{
502 		needToRotate = 0;
503 	}
504 
505 	if (needToRotate)
506 	{
507 		MATRIXCH matrix = dPtr->ObMat;
508 		TransposeMatrixCH(&matrix);
509 		RotateVector(&viewVectorBeta,&matrix);
510 		RotateVector(&viewVectorAlpha,&matrix);
511 	}
512 
513 	numberOfItems = SetupPolygonAccess(dPtr);
514 	if (!dPtr->ObShape)
515 	{
516 //		PrintDebuggingText("polys %d\n",numberOfItems);
517 	}
518 
519   	while(numberOfItems--)
520 	{
521 		extern POLYHEADER *PolyheaderPtr;
522 		VECTORCH polyNormal;
523 		struct ColPolyTag polyData;
524 		VECTORCH pointOnPlane;
525 		int lambda;
526 		int axis1;
527 		int axis2;
528 
529 		/* scanning through polys */
530 		AccessNextPolygon();
531 
532 		if( (PolyheaderPtr->PolyFlags & iflag_notvis) && !(PolyheaderPtr->PolyFlags & iflag_mirror)) continue;
533 
534 
535 		{
536 			int normDotBeta;
537 
538 			GetPolygonNormal(&polyData);
539 			polyNormal = polyData.PolyNormal;
540 
541 			normDotBeta	= DotProduct(&(polyNormal),&viewVectorBeta);
542 			{
543 				/* if the polygon is flagged as double-sided, and it's pointing
544 				the wrong way, consider it to be flipped round */
545 				//if((PolyheaderPtr->PolyFlags) & iflag_no_bfc)
546 				/* KJL 16:06:11 10/07/98 - treat all polys as no bfc */
547 				{
548 					if (normDotBeta>0)
549 					{
550 						normDotBeta=-normDotBeta;
551 						polyNormal.vx = -polyNormal.vx;
552 						polyNormal.vy = -polyNormal.vy;
553 						polyNormal.vz = -polyNormal.vz;
554 					}
555 				}
556 			}
557 
558 			/* trivial rejection of poly if it is not facing LOS */
559 	   		if (normDotBeta>-POLY_REJECT_RANGE)
560 	   		{
561 	   			continue;
562 			}
563 
564             GetPolygonVertices(&polyData);
565 			/* calculate coords of plane-line intersection */
566 			{
567 				int d;
568 				{
569 					/* get a pt in the poly */
570 					VECTORCH pop=polyData.PolyPoint[0];
571 					pop.vx -= viewVectorAlpha.vx;
572 					pop.vy -= viewVectorAlpha.vy;
573 					pop.vz -= viewVectorAlpha.vz;
574 
575 				  	d = DotProduct(&(polyNormal),&pop);
576 				}
577 
578 				if (d>0) continue;
579 
580 			  	lambda = DIV_FIXED(d,normDotBeta);
581 
582 				if (lambda>=LOS_Lambda)
583 				{
584 					continue;
585 				}
586 		   		pointOnPlane.vx	= viewVectorAlpha.vx + MUL_FIXED(lambda,viewVectorBeta.vx);
587  		   		pointOnPlane.vy	= viewVectorAlpha.vy + MUL_FIXED(lambda,viewVectorBeta.vy);
588 		   		pointOnPlane.vz	= viewVectorAlpha.vz + MUL_FIXED(lambda,viewVectorBeta.vz);
589 
590 	  		}
591 
592 			/* decide which 2d plane to project onto */
593 
594 			{
595 				VECTORCH absNormal = (polyNormal);
596 				if (absNormal.vx<0) absNormal.vx=-absNormal.vx;
597 				if (absNormal.vy<0) absNormal.vy=-absNormal.vy;
598 				if (absNormal.vz<0) absNormal.vz=-absNormal.vz;
599 
600 				if (absNormal.vx > absNormal.vy)
601 				{
602 					if (absNormal.vx > absNormal.vz)
603 					{
604 						axis1=iy;
605 						axis2=iz;
606 					}
607 					else
608 					{
609 						axis1=ix;
610 						axis2=iy;
611 					}
612 				}
613 				else
614 				{
615 					if (absNormal.vy > absNormal.vz)
616 					{
617 						axis1=ix;
618 						axis2=iz;
619 					}
620 					else
621 					{
622 						axis1=ix;
623 						axis2=iy;
624 					}
625 				}
626 			}
627 
628 		}
629 
630 		{
631 			int projectedPolyVertex[20];
632 			int projectedPointOnPlane[2];
633 			int *popPtr = &pointOnPlane.vx;
634 
635 			projectedPointOnPlane[0]=*(popPtr+axis1);
636 		 	projectedPointOnPlane[1]=*(popPtr+axis2);
637 
638 		 	{
639 		 		VECTORCH *vertexPtr = &polyData.PolyPoint[0];
640 		 		int *projectedVertexPtr= &projectedPolyVertex[0];
641 				int noOfVertices = polyData.NumberOfVertices;
642 
643 				do
644 				{
645 		 			*projectedVertexPtr++ = *((int*)vertexPtr + axis1);
646 		 			*projectedVertexPtr++ = *((int*)vertexPtr + axis2);
647 
648 	 	 		   	vertexPtr++;
649 		 			noOfVertices--;
650 		 		}
651                 while(noOfVertices);
652 
653 		 	}
654 
655 
656 			if (PointInPolygon(&projectedPointOnPlane[0],&projectedPolyVertex[0],polyData.NumberOfVertices,2))
657 			{
658 				/* rotate vector back into World Space if it's not a module */
659 				LOS_ObjectNormal = polyNormal;
660 				if (needToRotate)
661 				{
662 					MATRIXCH matrix = dPtr->ObMat;
663 					RotateVector(&pointOnPlane,&matrix);
664 
665 					RotateVector(&LOS_ObjectNormal,&matrix);
666 				}
667 
668 				/* and translate origin */
669 				pointOnPlane.vx += position.vx;
670 				pointOnPlane.vy += position.vy;
671 				pointOnPlane.vz += position.vz;
672 
673 				LOS_Point=pointOnPlane;
674 				LOS_ObjectHitPtr = dPtr;
675 				LOS_Lambda=lambda;
676 				LOS_HModel_Section = 0;
677 			}
678 		}
679 	}
680     return;
681 }
682 
683 /* KJL 15:35:58 14/05/98 - IsObjectVisibleFromThisPoint
684 
685 	Returns a non-zero value if an object can be seen from a given point in world space
686 	(viewpointPositionPtr), with a given field of view (fieldOfView) about a given
687 	direction (viewpointDirectionPtr).
688 */
IsObjectVisibleFromThisPoint(DISPLAYBLOCK * dispPtr,VECTORCH * viewpointDirectionPtr,VECTORCH * viewpointPositionPtr,int fieldOfView)689 int IsObjectVisibleFromThisPoint(DISPLAYBLOCK *dispPtr, VECTORCH *viewpointDirectionPtr, VECTORCH *viewpointPositionPtr, int fieldOfView)
690 {
691 
692 	return 0;
693 }
694 
695 
696 
697 
698 
699 
700 
701