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