1 
2 #include "3dc.h"
3 #include "inline.h"
4 
5 
6 
7 /*
8 
9  externs for commonly used global variables and arrays
10 
11 */
12 
13 extern int ScanDrawMode;
14 
15 
16 /*
17 
18  General System Globals
19 
20 */
21 
22 SCENE Global_Scene/* = 0*/;
23 
24 
25 
26 
27 /*
28 
29  Screen Descriptor Block
30 
31 */
32 
33 SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
34 
35 
36 /*
37 
38  View Descriptor Blocks
39 
40 */
41 
42 	int NumFreeVDBs;
43 	VIEWDESCRIPTORBLOCK *FreeVDBList[maxvdbs];
44 	static VIEWDESCRIPTORBLOCK **FreeVDBListPtr = &FreeVDBList[maxvdbs-1];
45 
46 	int NumActiveVDBs;
47 	VIEWDESCRIPTORBLOCK *ActiveVDBList[maxvdbs];
48 	static VIEWDESCRIPTORBLOCK **ActiveVDBListPtr = &ActiveVDBList[0];
49 
50 	static VIEWDESCRIPTORBLOCK FreeVDBData[maxvdbs];
51 
52 
53 /* Clip Plane Block */
54 
55 	static CLIPPLANEPOINTS ClipPlanePoints;
56 
57 
58 
59 extern int GlobalAmbience;
60 
61 /*
62 
63  Support Functions
64 
65 */
66 
67 
68 /*
69 
70  Calculate View Volume Planes from the Clip Boundaries for a VDB
71 
72  Before doing this, check that the requested boundaries are within those of
73  the physical sceen. If any boundary transgresses, truncate it and set the
74  appropriate flag bit.
75 
76 */
77 
VDBClipPlanes(VIEWDESCRIPTORBLOCK * vdb)78 void VDBClipPlanes(VIEWDESCRIPTORBLOCK *vdb)
79 
80 {
81 
82 
83 /* Check Clip Boundaries against the Physical Screen */
84 
85 
86 	/* Check Left Boundary */
87 
88 	if(vdb->VDB_ClipLeft < ScreenDescriptorBlock.SDB_ClipLeft) {
89 
90 		vdb->VDB_ClipLeft = ScreenDescriptorBlock.SDB_ClipLeft;
91 		vdb->VDB_Flags |= ViewDB_Flag_LTrunc;
92 
93 	}
94 
95 	/* Check Right Boundary */
96 
97 	if(vdb->VDB_ClipRight > ScreenDescriptorBlock.SDB_ClipRight) {
98 
99 		vdb->VDB_ClipRight = ScreenDescriptorBlock.SDB_ClipRight;
100 		vdb->VDB_Flags |= ViewDB_Flag_RTrunc;
101 
102 	}
103 
104 	/* Check Up boundary */
105 
106 	if(vdb->VDB_ClipUp < ScreenDescriptorBlock.SDB_ClipUp) {
107 
108 		vdb->VDB_ClipUp = ScreenDescriptorBlock.SDB_ClipUp;
109 		vdb->VDB_Flags |= ViewDB_Flag_UTrunc;
110 
111 	}
112 
113 	/* Check Down boundary */
114 
115 	if(vdb->VDB_ClipDown > ScreenDescriptorBlock.SDB_ClipDown) {
116 
117 		vdb->VDB_ClipDown = ScreenDescriptorBlock.SDB_ClipDown;
118 		vdb->VDB_Flags |= ViewDB_Flag_DTrunc;
119 
120 	}
121 
122 
123 /* Calculate Width and Height */
124 
125 	/* textprint("current wh = %d, %d\n", vdb->VDB_Width, vdb->VDB_Height); */
126 
127 	/* Width */
128 
129 	vdb->VDB_Width = vdb->VDB_ClipRight - vdb->VDB_ClipLeft;
130 
131 	/* Height */
132 
133 	vdb->VDB_Height = vdb->VDB_ClipDown - vdb->VDB_ClipUp;
134 
135 	#if 0
136 	textprint("new wh = %d, %d\n", vdb->VDB_Width, vdb->VDB_Height);
137 	WaitForReturn();
138 	#endif
139 
140 
141 /* Set up the Clip Planes */
142 
143 
144 	/* Clip Left */
145 
146 	ClipPlanePoints.cpp1.vx = vdb->VDB_ClipLeft;
147 	ClipPlanePoints.cpp1.vy = vdb->VDB_ClipUp;
148 	ClipPlanePoints.cpp1.vz = NearZ;
149 
150 	ClipPlanePoints.cpp2.vx = vdb->VDB_ClipLeft;
151 	ClipPlanePoints.cpp2.vy = (vdb->VDB_ClipUp + vdb->VDB_ClipDown) / 2;
152 	ClipPlanePoints.cpp2.vz = FarZ;
153 
154 	ClipPlanePoints.cpp3.vx = vdb->VDB_ClipLeft;
155 	ClipPlanePoints.cpp3.vy = vdb->VDB_ClipDown;
156 	ClipPlanePoints.cpp3.vz = NearZ;
157 
158 	MakeClipPlane(vdb, &vdb->VDB_ClipLeftPlane, &ClipPlanePoints);
159 
160 
161 	/* Clip Right */
162 
163 	ClipPlanePoints.cpp1.vx = vdb->VDB_ClipRight;
164 	ClipPlanePoints.cpp1.vy = vdb->VDB_ClipUp;
165 	ClipPlanePoints.cpp1.vz = NearZ;
166 
167 	ClipPlanePoints.cpp2.vx = vdb->VDB_ClipRight;
168 	ClipPlanePoints.cpp2.vy = vdb->VDB_ClipDown;
169 	ClipPlanePoints.cpp2.vz = NearZ;
170 
171 	ClipPlanePoints.cpp3.vx = vdb->VDB_ClipRight;
172 	ClipPlanePoints.cpp3.vy = (vdb->VDB_ClipUp + vdb->VDB_ClipDown) / 2;
173 	ClipPlanePoints.cpp3.vz = FarZ;
174 
175 	MakeClipPlane(vdb, &vdb->VDB_ClipRightPlane, &ClipPlanePoints);
176 
177 
178 	/* Clip Up */
179 
180 	ClipPlanePoints.cpp1.vx = vdb->VDB_ClipLeft;
181 	ClipPlanePoints.cpp1.vy = vdb->VDB_ClipUp;
182 	ClipPlanePoints.cpp1.vz = NearZ;
183 
184 	ClipPlanePoints.cpp2.vx = vdb->VDB_ClipRight;
185 	ClipPlanePoints.cpp2.vy = vdb->VDB_ClipUp;
186 	ClipPlanePoints.cpp2.vz = NearZ;
187 
188 	ClipPlanePoints.cpp3.vx = (vdb->VDB_ClipLeft + vdb->VDB_ClipRight) / 2;
189 	ClipPlanePoints.cpp3.vy = vdb->VDB_ClipUp;
190 	ClipPlanePoints.cpp3.vz = FarZ;
191 
192 	MakeClipPlane(vdb, &vdb->VDB_ClipUpPlane, &ClipPlanePoints);
193 
194 
195 	/* Clip Down */
196 
197 	ClipPlanePoints.cpp1.vx = vdb->VDB_ClipLeft;
198 	ClipPlanePoints.cpp1.vy = vdb->VDB_ClipDown;
199 	ClipPlanePoints.cpp1.vz = NearZ;
200 
201 	ClipPlanePoints.cpp2.vx = (vdb->VDB_ClipLeft + vdb->VDB_ClipRight) / 2;
202 	ClipPlanePoints.cpp2.vy = vdb->VDB_ClipDown;
203 	ClipPlanePoints.cpp2.vz = FarZ;
204 
205 	ClipPlanePoints.cpp3.vx = vdb->VDB_ClipRight;
206 	ClipPlanePoints.cpp3.vy = vdb->VDB_ClipDown;
207 	ClipPlanePoints.cpp3.vz = NearZ;
208 
209 	MakeClipPlane(vdb, &vdb->VDB_ClipDownPlane, &ClipPlanePoints);
210 
211 
212 /* Clip Z */
213 
214 	vdb->VDB_ClipZPlane.CPB_Normal.vx = 0;
215 	vdb->VDB_ClipZPlane.CPB_Normal.vy = 0;
216 	vdb->VDB_ClipZPlane.CPB_Normal.vz = -ONE_FIXED;
217 
218 	vdb->VDB_ClipZPlane.CPB_POP.vx = 0;
219 	vdb->VDB_ClipZPlane.CPB_POP.vy = 0;
220 	vdb->VDB_ClipZPlane.CPB_POP.vz = vdb->VDB_ClipZ;
221 
222 }
223 
224 
225 /*
226 
227  Make a Clip Plane.
228 
229  Reverse Project the three Clip Points (overwrite their struct).
230 
231  Use the first Clip Point as the POP, writing this to the CPB.
232 
233  Pass the three Clip Points to MakeNormal() specifying the CPB Normal as
234  the destination.
235 
236  NOTES
237 
238  The vdb is passed for the reverse projection.
239 
240 */
241 
MakeClipPlane(VIEWDESCRIPTORBLOCK * vdb,CLIPPLANEBLOCK * cpb,CLIPPLANEPOINTS * cpp)242 void MakeClipPlane(
243 
244 VIEWDESCRIPTORBLOCK *vdb,
245 CLIPPLANEBLOCK *cpb,
246 CLIPPLANEPOINTS *cpp)
247 
248 {
249 
250 	int x, y;
251 
252 /* Reverse Project the Clip Points */
253 
254 
255 /* cpp1 */
256 
257 /* x */
258 
259 	x=cpp->cpp1.vx;
260 	x-=vdb->VDB_CentreX;
261 	x*=cpp->cpp1.vz;
262 	x/=vdb->VDB_ProjX;
263 	cpp->cpp1.vx=x;
264 
265 /* y */
266 
267 	y=cpp->cpp1.vy;
268 	y-=vdb->VDB_CentreY;
269 	y*=cpp->cpp1.vz;
270 	y/=vdb->VDB_ProjY;
271 	cpp->cpp1.vy=y;
272 
273 
274 /* cpp2 */
275 
276 /* x */
277 
278 	x=cpp->cpp2.vx;
279 	x-=vdb->VDB_CentreX;
280 	x*=cpp->cpp2.vz;
281 	x/=vdb->VDB_ProjX;
282 	cpp->cpp2.vx=x;
283 
284 /* y */
285 
286 	y=cpp->cpp2.vy;
287 	y-=vdb->VDB_CentreY;
288 	y*=cpp->cpp2.vz;
289 	y/=vdb->VDB_ProjY;
290 	cpp->cpp2.vy=y;
291 
292 
293 /* cpp3 */
294 
295 /* x */
296 
297 	x=cpp->cpp3.vx;
298 	x-=vdb->VDB_CentreX;
299 	x*=cpp->cpp3.vz;
300 	x/=vdb->VDB_ProjX;
301 	cpp->cpp3.vx=x;
302 
303 /* y */
304 
305 	y=cpp->cpp3.vy;
306 	y-=vdb->VDB_CentreY;
307 	y*=cpp->cpp3.vz;
308 	y/=vdb->VDB_ProjY;
309 	cpp->cpp3.vy=y;
310 
311 /* The 1st Clip Point can be the POP */
312 
313 	cpb->CPB_POP.vx=cpp->cpp1.vx;
314 	cpb->CPB_POP.vy=cpp->cpp1.vy;
315 	cpb->CPB_POP.vz=cpp->cpp1.vz;
316 
317 /* Make CPB_Normal */
318 
319 	MakeNormal(&cpp->cpp1, &cpp->cpp2, &cpp->cpp3, &cpb->CPB_Normal);
320 
321 }
322 
323 
324 #if pc_backdrops
325 
326 /*
327 
328  Create the projector array used for cylindrically projected backdrops
329 
330  The array looks like this
331 
332 	unsigned short VDB_ProjectorXOffsets[MaxScreenWidth];
333 
334  For each centre relative x there is a projector. Using just the x and z
335  components of the projector an angular offset from the centre (0) can be
336  calculated using ArcTan().
337 
338  To calculate a projector one must reverse project each x value at a given
339  z value. Rather than go on to create the normalised projector vector we can
340  go straight to the ArcTan() to find the angular offset.
341 
342 */
343 
CreateProjectorArray(VIEWDESCRIPTORBLOCK * vdb)344 static void CreateProjectorArray(VIEWDESCRIPTORBLOCK *vdb)
345 
346 {
347 
348 	int sx, x, vx, vz, i, ao;
349 
350 
351 	vz = ONE_FIXED;
352 
353 	sx = vdb->VDB_ClipLeft;
354 
355 	i = 0;
356 
357 	while(sx < vdb->VDB_ClipRight) {
358 
359 		x = sx - vdb->VDB_CentreX;
360 
361 		vx = (x * vz) / vdb->VDB_ProjX;
362 
363 		ao = ArcTan(vx, vz);
364 
365 		vdb->VDB_ProjectorXOffsets[i] = ao;
366 
367 		#if 0
368 		textprint("Pr. Offset %d = %u\n", i, vdb->VDB_ProjectorXOffsets[i]);
369 		WaitForReturn();
370 		#endif
371 
372 		sx++; i++;
373 
374 	}
375 
376 }
377 
378 #endif
379 
380 
381 
382 
383 
384 
385 /*
386 
387  SetVDB requires a VIEWDESCRIPTORBLOCK
388 
389 */
390 
SetVDB(VIEWDESCRIPTORBLOCK * vdb,int fl,int ty,int d,int cx,int cy,int prx,int pry,int mxp,int cl,int cr,int cu,int cd,int h1,int h2,int hc,int amb)391 void SetVDB(VIEWDESCRIPTORBLOCK *vdb, int fl, int ty, int d, int cx, int cy,
392     int prx, int pry, int mxp, int cl, int cr, int cu, int cd,
393     int h1, int h2, int hc, int amb)
394 {
395 
396 
397 
398 	/* Initial setup */
399 
400 	vdb->VDB_Flags			= fl;
401 	vdb->VDB_ViewType		= ty;
402 
403 
404 	/* Ambience */
405 
406 	vdb->VDB_Ambience = amb;
407 	/* KJL 14:30:57 05/14/97 - set globalAmbience here as well */
408 	GlobalAmbience = amb;
409 
410 	/* Width and Height are set by the Clip Boundaries */
411 
412 	if(vdb->VDB_Flags & ViewDB_Flag_FullSize) {
413 
414 		vdb->VDB_Depth			= ScreenDescriptorBlock.SDB_Depth;
415 
416 		vdb->VDB_ScreenDepth    = ScreenDescriptorBlock.SDB_ScreenDepth;
417 
418 		vdb->VDB_CentreX		= ScreenDescriptorBlock.SDB_CentreX;
419 		vdb->VDB_CentreY		= ScreenDescriptorBlock.SDB_CentreY;
420 
421 		vdb->VDB_ProjX			= ScreenDescriptorBlock.SDB_ProjX;
422 		vdb->VDB_ProjY			= ScreenDescriptorBlock.SDB_ProjY;
423 		vdb->VDB_MaxProj		= ScreenDescriptorBlock.SDB_MaxProj;
424 
425 		vdb->VDB_ClipLeft		= ScreenDescriptorBlock.SDB_ClipLeft;
426 		vdb->VDB_ClipRight	= ScreenDescriptorBlock.SDB_ClipRight;
427 		vdb->VDB_ClipUp		= ScreenDescriptorBlock.SDB_ClipUp;
428 		vdb->VDB_ClipDown		= ScreenDescriptorBlock.SDB_ClipDown;
429 
430 	}
431 
432 	else {
433 
434 		 if (ScanDrawMode == ScanDrawDirectDraw)
435 		   vdb->VDB_Depth			= d;
436 		 else
437 		   vdb->VDB_Depth = VideoModeType_24;
438 
439 		vdb->VDB_ScreenDepth    = ScreenDescriptorBlock.SDB_ScreenDepth;
440 
441 		vdb->VDB_CentreX		= cx;
442 		vdb->VDB_CentreY		= cy;
443 
444 		vdb->VDB_ProjX			= prx;
445 		vdb->VDB_ProjY			= pry;
446 		vdb->VDB_MaxProj		= mxp;
447 
448 		vdb->VDB_ClipLeft		= cl;
449 		vdb->VDB_ClipRight	= cr;
450 		vdb->VDB_ClipUp		= cu;
451 		vdb->VDB_ClipDown		= cd;
452 
453 		if(vdb->VDB_Flags & ViewDB_Flag_AdjustScale) {
454 
455 			vdb->VDB_CentreX =
456 				WideMulNarrowDiv(
457 					vdb->VDB_CentreX,
458 					ScreenDescriptorBlock.SDB_Width,
459 					320);
460 
461 			vdb->VDB_CentreY =
462 				WideMulNarrowDiv(
463 					vdb->VDB_CentreY,
464 					ScreenDescriptorBlock.SDB_Height,
465 					200);
466 
467 
468 			vdb->VDB_ProjX =
469 				WideMulNarrowDiv(
470 					vdb->VDB_ProjX,
471 					ScreenDescriptorBlock.SDB_Width,
472 					320);
473 
474 			vdb->VDB_ProjY =
475 				WideMulNarrowDiv(
476 					vdb->VDB_ProjY,
477 					ScreenDescriptorBlock.SDB_Height,
478 					200);
479 
480 			vdb->VDB_MaxProj =
481 				WideMulNarrowDiv(
482 					vdb->VDB_MaxProj,
483 					ScreenDescriptorBlock.SDB_Width,
484 					320);
485 
486 
487 			vdb->VDB_ClipLeft =
488 				WideMulNarrowDiv(
489 					vdb->VDB_ClipLeft,
490 					ScreenDescriptorBlock.SDB_Width,
491 					320);
492 
493 			vdb->VDB_ClipRight =
494 				WideMulNarrowDiv(
495 					vdb->VDB_ClipRight,
496 					ScreenDescriptorBlock.SDB_Width,
497 					320);
498 
499 			vdb->VDB_ClipUp =
500 				WideMulNarrowDiv(
501 					vdb->VDB_ClipUp,
502 					ScreenDescriptorBlock.SDB_Height,
503 					200);
504 
505 			vdb->VDB_ClipDown =
506 				WideMulNarrowDiv(
507 					vdb->VDB_ClipDown,
508 					ScreenDescriptorBlock.SDB_Height,
509 					200);
510 
511 		}
512 
513 	}
514 
515 
516 	/* Create the clip planes */
517 
518 	/* KJL 10:41:13 04/09/97 - set to constant so the same for all screen sizes! */
519 	vdb->VDB_ClipZ = 64;//vdb->VDB_MaxProj;	/* Safe */
520 
521 	VDBClipPlanes(vdb);
522 
523 	#if 0
524 	/* View Angle */
525 
526 	if(vdb->VDB_CentreX > vdb->VDB_CentreY) s = vdb->VDB_CentreX;
527 	else s = vdb->VDB_CentreY;
528 
529 	z = vdb->VDB_MaxProj * 100;
530 
531 	x = (s * z) / vdb->VDB_MaxProj;
532 
533 	vdb->VDB_ViewAngle = ArcTan(x, z);
534 
535 	vdb->VDB_ViewAngleCos = GetCos(vdb->VDB_ViewAngle);
536 
537 
538 	#if 0
539 	textprint("View Angle = %d\n", vdb->VDB_ViewAngle);
540 	WaitForReturn();
541 	#endif
542 
543 
544 	#if pc_backdrops
545 
546 	/* Projector Array */
547 
548 	CreateProjectorArray(vdb);
549 
550 	#endif
551 
552 
553 	/* Hazing & Background Colour */
554 
555 	vdb->VDB_H1				= h1;
556 	vdb->VDB_H2				= h2;
557 	vdb->VDB_HInterval	= h2 - h1;
558 	vdb->VDB_HColour		= hc;
559 	#endif
560 }
561 
562 
563 
564 
565 /*
566 
567  Initialise the Free VDB List
568 
569 */
570 
InitialiseVDBs(void)571 void InitialiseVDBs(void)
572 
573 {
574 
575 	VIEWDESCRIPTORBLOCK *FreeVDBPtr = &FreeVDBData[0];
576 
577 	NumActiveVDBs = 0;
578 
579 	for(NumFreeVDBs = 0; NumFreeVDBs < maxvdbs; NumFreeVDBs++) {
580 
581 		FreeVDBList[NumFreeVDBs] = FreeVDBPtr;
582 
583 		FreeVDBPtr++;
584 
585 	}
586 
587 	FreeVDBListPtr   = &FreeVDBList[maxvdbs-1];
588 	ActiveVDBListPtr = &ActiveVDBList[0];
589 
590 }
591 
592 
593 /*
594 
595  Get a VDB from the Free VDB list
596 
597 */
598 
AllocateVDB(void)599 VIEWDESCRIPTORBLOCK* AllocateVDB(void)
600 
601 {
602 
603 	VIEWDESCRIPTORBLOCK *FreeVDBPtr = 0;	/* Default to null ptr */
604 	int *i_src;
605 	int i;
606 
607 
608 	if(NumFreeVDBs) {
609 
610 		FreeVDBPtr = *FreeVDBListPtr--;
611 
612 		NumFreeVDBs -= 1;							/* One less free block */
613 
614 		/* Clear the block */
615 
616 		i_src = (int *) FreeVDBPtr;
617 		for(i = sizeof(VIEWDESCRIPTORBLOCK)/4; i!=0; i--)
618 			*i_src++ = 0;
619 
620 	}
621 
622 	return(FreeVDBPtr);
623 
624 }
625 
626 
627 /*
628 
629  Return a VDB to the Free VDB list
630 
631 */
632 
DeallocateVDB(VIEWDESCRIPTORBLOCK * vdb)633 void DeallocateVDB(VIEWDESCRIPTORBLOCK *vdb)
634 
635 {
636 
637 	FreeVDBListPtr++;
638 	*FreeVDBListPtr = vdb;
639 
640 	NumFreeVDBs++;							/* One more free block */
641 
642 }
643 
644 
645 /*
646 
647  Allocate a VDB and make it active
648 
649 */
650 
CreateActiveVDB(void)651 VIEWDESCRIPTORBLOCK* CreateActiveVDB(void)
652 
653 {
654 
655 	VIEWDESCRIPTORBLOCK *vdb;
656 	VIEWDESCRIPTORBLOCK *vdb_tmp;
657 	VIEWDESCRIPTORBLOCK **v_src;
658 
659 	int v;
660 	int p = -1;
661 
662 
663 	vdb = AllocateVDB();
664 
665 	if(vdb) {
666 
667 		/* Find the next "VDB_Priority" */
668 
669 		if(NumActiveVDBs) {
670 
671 			v_src = &ActiveVDBList[0];
672 
673 			for(v = NumActiveVDBs; v!=0; v--) {
674 
675 				vdb_tmp = *v_src++;
676 
677 				if(vdb_tmp->VDB_Priority > p) p = vdb_tmp->VDB_Priority;
678 
679 			}
680 
681 		}
682 
683 		/* Set the VDB priority */
684 
685 		vdb->VDB_Priority = (p + 1);
686 
687 		/* Update the active VDB list */
688 
689 		*ActiveVDBListPtr++ = vdb;
690 
691 		NumActiveVDBs++;
692 
693 	}
694 
695 	return vdb;
696 
697 }
698 
699 
700 /*
701 
702  Deallocate an active VDB
703 
704 */
705 
DestroyActiveVDB(VIEWDESCRIPTORBLOCK * dblockptr)706 int DestroyActiveVDB(VIEWDESCRIPTORBLOCK *dblockptr)
707 {
708 
709 	int j = -1;
710 	int i;
711 
712 
713 	/* If the VDB ptr is OK, search the Active VDB List */
714 
715 	if(dblockptr) {
716 
717 		for(i = 0; i < NumActiveVDBs && j!=0; i++) {
718 
719 			if(ActiveVDBList[i] == dblockptr) {
720 
721 				#if ProjectSpecificVDBs
722 				ProjectSpecificVDBDestroy(dblockptr);
723 				#endif
724 
725 				ActiveVDBList[i] = ActiveVDBList[NumActiveVDBs - 1];
726 				NumActiveVDBs--;
727 				ActiveVDBListPtr--;
728 				DeallocateVDB(dblockptr);		/* Return VDB to Free List */
729 				j = 0;								/* Flag OK */
730 
731 			}
732 		}
733 	}
734 
735 	return(j);
736 
737 }
738