1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the AUTHORS
5 * file distributed with this source distribution.
6 *
7 * Additional copyright for this file:
8 * Copyright (C) 1999-2000 Revolution Software Ltd.
9 * This code is based on source code created by Revolution Software,
10 * used with permission.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 */
27
28 #include "engines/icb/common/px_common.h"
29 #include "engines/icb/gfx/psx_pcdefines.h"
30 #include "engines/icb/gfx/psx_pcdefines.h"
31 #include "engines/icb/gfx/psx_scrn.h"
32 #include "engines/icb/common/px_capri_maths.h"
33 #include "engines/icb/gfx/psx_poly.h"
34 #include "engines/icb/global_objects_psx.h"
35 #include "engines/icb/light_pc.h"
36
37 namespace ICB {
38
39 #if _PSX_ON_PC == 1
40
41 extern uint32 selFace;
42 extern CVECTOR unlitPoly;
43 extern CVECTOR deadObjectColour;
44 extern uint32 deadObject;
45
46 extern uint32 _drawBface;
47
48 extern uint8 selWRed;
49 extern uint8 selWGreen;
50 extern uint8 selWBlue;
51
52 extern uint8 selPRed;
53 extern uint8 selPGreen;
54 extern uint8 selPBlue;
55 extern uint8 selPAlpha;
56
57 #else // #if _PSX_ON_PC == 1
58
59 uint32 selFace = 65537;
60 CVECTOR unlitPoly = {255, 255, 255, 0};
61 CVECTOR deadObjectColour = {0, 0, 0, 0};
62 uint32 deadObject = 0;
63
64 uint32 _drawBface = 0;
65
66 uint8 selWRed = 0;
67 uint8 selWGreen = 255;
68 uint8 selWBlue = 255;
69
70 uint8 selPRed = 255;
71 uint8 selPGreen = 255;
72 uint8 selPBlue = 0;
73 uint8 selPAlpha = 0;
74
75 #endif // #if _PSX_ON_PC == 1
76
77 // Specialist lighting routines for polygons
78 // support for bounce & width
LightPolygon(SVECTOR * n0,CVECTOR * rgbIn,CVECTOR * rgb0)79 inline void LightPolygon(SVECTOR *n0, CVECTOR *rgbIn, CVECTOR *rgb0) {
80 SVECTORPC lightEffect;
81 // Normal line vector(local) -> light source effect
82 ApplyMatrixSV_pc(gtelight_pc, n0, &lightEffect);
83
84 if (useLampWidth) {
85 lightEffect.vx = (int16)(lightEffect.vx + lampWidth[0]);
86 lightEffect.vy = (int16)(lightEffect.vy + lampWidth[1]);
87 lightEffect.vz = (int16)(lightEffect.vy + lampWidth[2]);
88 }
89 if (useLampBounce) {
90 if (lightEffect.vx < 0) {
91 lightEffect.vx = (int16)-lightEffect.vx;
92 if (lightEffect.vx > lampBounce[0])
93 lightEffect.vx = (int16)lampBounce[0];
94 }
95 if (lightEffect.vy < 0) {
96 lightEffect.vy = (int16)-lightEffect.vy;
97 if (lightEffect.vy > lampBounce[1])
98 lightEffect.vy = (int16)lampBounce[1];
99 }
100 if (lightEffect.vz < 0) {
101 lightEffect.vz = (int16)-lightEffect.vz;
102 if (lightEffect.vz > lampBounce[2])
103 lightEffect.vz = (int16)lampBounce[2];
104 }
105 } else {
106 if (lightEffect.vx < 0)
107 lightEffect.vx = 0;
108 if (lightEffect.vy < 0)
109 lightEffect.vy = 0;
110 if (lightEffect.vz < 0)
111 lightEffect.vz = 0;
112 }
113
114 // Light source effect -> Colour effect(local colour matrix+back colour)
115 SVECTORPC colourEffect;
116 ApplyMatrixSV_pc(gtecolour_pc, &lightEffect, &colourEffect);
117 if (colourEffect.vx < 0)
118 colourEffect.vx = 0;
119 if (colourEffect.vy < 0)
120 colourEffect.vy = 0;
121 if (colourEffect.vz < 0)
122 colourEffect.vz = 0;
123
124 // colourEffect is 0-4095 (2^12)
125 // gteback is 0-255 (2^8)
126 colourEffect.vx = (int16)((colourEffect.vx >> 4) + gteback_pc[0]);
127 colourEffect.vy = (int16)((colourEffect.vy >> 4) + gteback_pc[1]);
128 colourEffect.vz = (int16)((colourEffect.vz >> 4) + gteback_pc[2]);
129
130 // 256 = 1.0 in colourEffect
131 // 128 = 1.0 in in0
132 int32 red = (rgbIn->r * colourEffect.vx);
133 int32 green = (rgbIn->g * colourEffect.vy);
134 int32 blue = (rgbIn->b * colourEffect.vz);
135
136 red = red >> 8;
137 green = green >> 8;
138 blue = blue >> 8;
139
140 if (red > 255)
141 red = 255;
142 if (green > 255)
143 green = 255;
144 if (blue > 255)
145 blue = 255;
146
147 rgb0->r = (uint8)(red);
148 rgb0->g = (uint8)(green);
149 rgb0->b = (uint8)(blue);
150 }
151
152 // Specialist lighting routines for polygons
153 // support for bounce & width
LightPolygon3(SVECTOR * n0,SVECTOR * n1,SVECTOR * n2,CVECTOR * rgbIn,CVECTOR * rgb0,CVECTOR * rgb1,CVECTOR * rgb2)154 inline void LightPolygon3(SVECTOR *n0, SVECTOR *n1, SVECTOR *n2, CVECTOR *rgbIn, CVECTOR *rgb0, CVECTOR *rgb1, CVECTOR *rgb2) {
155 LightPolygon(n0, rgbIn, rgb0);
156 LightPolygon(n1, rgbIn, rgb1);
157 LightPolygon(n2, rgbIn, rgb2);
158 }
159
160 #define LIGHTPOLYGON(n0, rgbIn, rgb0) \
161 { \
162 if (useLampWidth || useLampBounce) \
163 LightPolygon(n0, rgbIn, rgb0); \
164 else \
165 gte_NormalColorCol_pc(n0, rgbIn, rgb0); \
166 }
167
168 #define LIGHTPOLYGON3(n0, n1, n2, rgbIn, rgb0, rgb1, rgb2) \
169 { \
170 if (useLampWidth || useLampBounce) \
171 LightPolygon3(n0, n1, n2, rgbIn, rgb0, rgb1, rgb2); \
172 else \
173 gte_NormalColorCol3_pc(n0, n1, n2, rgbIn, rgb0, rgb1, rgb2); \
174 }
175
176 //----------------------------------------------------------------
177
178 /*
179 gte_ll();
180 gte_llv0();
181 gte_llv1();
182 gte_llv2();
183 gte_llir();
184 gte_llv0tr();
185 gte_llv1tr();
186 gte_llv2tr();
187 gte_llirtr();
188 gte_llv0bk();
189 gte_llv1bk();
190 gte_llv2bk();
191 gte_llirbk();
192 gte_lc();
193 gte_lcv0();
194 gte_lcv1();
195 gte_lcv2();
196 gte_lcir();
197 gte_lcv0tr();
198 gte_lcv1tr();
199 gte_lcv2tr();
200 gte_lcirtr();
201 gte_lcv0bk();
202 gte_lcv1bk();
203 gte_lcv2bk();
204 gte_lcirbk();
205 */
206
207 //------------------------------------------------------------------------
208
209 #if CD_MODE == 0
210
211 //------------------------------------------------------------------------
212
213 // Flat, Un-Textured, Self-Luminous, triangles
drawFUS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)214 void drawFUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
215 SVECTORPC *v0;
216 SVECTORPC *v1;
217 SVECTORPC *v2;
218
219 // uint32 num = min( n, 10 ); // do a maximum of 10 polygons
220 uint32 num = n;
221 int32 p, flag;
222 uint32 i;
223 uint32 *pPoly;
224 int32 z0, z1, z2;
225 SVECTORPC sxy0, sxy1, sxy2, stemp;
226 CVECTOR *rgbIn;
227 uint32 tmp;
228
229 pPoly = polyStart;
230 // Loop over each polygon
231 for (i = 0; i < num; i++) {
232 // Structure is :
233 // 0x20 | B | G | R
234 // v1 | v0
235 // pad | v2
236 rgbIn = (CVECTOR *)pPoly++;
237
238 if (deadObject) {
239 rgbIn = &deadObjectColour;
240 }
241
242 tmp = *pPoly++;
243 v0 = pVertex + (tmp & 0xFFFF);
244 v1 = pVertex + (tmp >> 16);
245
246 tmp = *pPoly++;
247 v2 = pVertex + (tmp & 0xFFFF);
248
249 // Now do RotTransPers3 on the vectors
250 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
251 gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
252 z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
253
254 // test the return value of flag
255 if (flag & 0x80000000)
256 continue;
257
258 gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
259 z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
260 // test the return value of flag
261 if (flag & 0x80000000)
262 continue;
263
264 gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
265 z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
266 // test the return value of flag
267 if (flag & 0x80000000)
268 continue;
269
270 // Give the GTE some time to recover
271 int32 avgz;
272 gte_AverageZ3_pc(z0, z1, z2, &avgz);
273
274 // Do we want to do back face removal ?
275 if (_removeBackface) {
276 // use winding order of the polygons
277 // e.g. NormalClip which is cross product of screen vectors
278 if (_useWindingOrder) {
279 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
280 // Drawing back facings polys requires making them have
281 // clockwise winding order as by definition they have
282 // anti-clockwise winding order
283 if (flag < 0) {
284 if (_drawBface) {
285 stemp = sxy1;
286 sxy1 = sxy2;
287 sxy2 = stemp;
288 } else {
289 // Skip this polygon
290 continue;
291 }
292 } else if (flag == 0)
293 continue; // ignore zero-area polygons
294 }
295
296 // TODO
297 // dot product of viewing direction and polygon normal
298 // will require generation of polygon normal from vertex normals
299 // and transformation of the normal to world space
300 }
301
302 // Put wireframe triangles in list before textured ones
303 // so should be in front of textured ones
304 if ((_drawWfrm) || (selFace == i)) {
305 LINE_F4 *line = (LINE_F4 *)drawpacket;
306 setLineF4(line);
307 // set XY's in the GPU packet 0-1-2-3
308 line->x0 = sxy0.vx;
309 line->y0 = sxy0.vy;
310 line->x1 = sxy1.vx;
311 line->y1 = sxy1.vy;
312 line->x2 = sxy2.vx;
313 line->y2 = sxy2.vy;
314 line->x3 = sxy0.vx;
315 line->y3 = sxy0.vy;
316 if (selFace == i)
317 setRGB0(line, selWRed, selWGreen, selWBlue);
318 else
319 setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
320 // Put it into the global ot at the correct place
321 myAddPrimClip(avgz, drawpacket);
322 // advance the global packet pointer by correct amount
323 myAddPacket(sizeof(LINE_F4));
324 }
325
326 // Draw polygon version behind the wireframe
327 if ((_drawPolys) || (selFace == i)) {
328 // Draw untextured polygons
329 POLY_F3 *poly = (POLY_F3 *)drawpacket;
330 setPolyF3(poly);
331 // set XY's in the GPU packet 0-1-2
332 poly->x0 = sxy0.vx;
333 poly->y0 = sxy0.vy;
334 poly->x1 = sxy1.vx;
335 poly->y1 = sxy1.vy;
336 poly->x2 = sxy2.vx;
337 poly->y2 = sxy2.vy;
338
339 // Set the RGB colours
340 // No light source calculation
341 // So just set base colour
342 if (selFace == i)
343 setRGB0(poly, selPRed, selPGreen, selPBlue);
344 else
345 setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
346 // Put it into the global ot at the correct place
347 myAddPrimClip(avgz, drawpacket);
348 // advance the global packet pointer by correct amount
349 myAddPacket(sizeof(POLY_F3));
350 }
351 }
352 }
353
354 //------------------------------------------------------------------------
355
356 // Gouraud, Un-Textured, Self-Luminous, triangles
drawGUS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)357 void drawGUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
358 SVECTORPC *v0;
359 SVECTORPC *v1;
360 SVECTORPC *v2;
361
362 // uint32 num = min( n, 10 ); // do a maximum of 10 polygons
363 uint32 num = n;
364 uint32 tmp;
365 int32 p, flag;
366 uint32 i;
367 uint32 *pPoly;
368 int32 z0, z1, z2;
369 SVECTORPC sxy0, sxy1, sxy2, stemp;
370
371 // Base colour for gouraud shading computation
372 CVECTOR *rgb0;
373 CVECTOR *rgb1;
374 CVECTOR *rgb2;
375 CVECTOR *rgbTemp;
376
377 pPoly = polyStart;
378 // Loop over each polygon
379 for (i = 0; i < num; i++) {
380 // Structure is :
381 // 8-bits | 8-bits | 8-bits | 8-bits
382 // 0x30 | Blue0 | Green0 | Red0
383 // 0x30 | Blue1 | Green1 | Red1
384 // 0x30 | Blue2 | Green2 | Red2
385 // 16-bits | 8-bits | 8-bits
386 // --------------------------
387 // v1 | v0
388 // pad | v2
389 rgb0 = (CVECTOR *)pPoly++;
390 rgb1 = (CVECTOR *)pPoly++;
391 rgb2 = (CVECTOR *)pPoly++;
392
393 if (deadObject) {
394 rgb0 = &deadObjectColour;
395 rgb1 = &deadObjectColour;
396 rgb2 = &deadObjectColour;
397 }
398
399 tmp = *pPoly++;
400 v0 = pVertex + (tmp & 0xFFFF);
401 v1 = pVertex + (tmp >> 16);
402
403 tmp = *pPoly++;
404 v2 = pVertex + (tmp & 0xFFFF);
405
406 // Now do RotTransPers3 on the vectors
407 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
408 gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
409 z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
410
411 // test the return value of flag
412 if (flag & 0x80000000)
413 continue;
414
415 gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
416 z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
417 // test the return value of flag
418 if (flag & 0x80000000)
419 continue;
420
421 gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
422 z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
423 // test the return value of flag
424 if (flag & 0x80000000)
425 continue;
426
427 // Give the GTE some time to recover
428 int32 avgz;
429 gte_AverageZ3_pc(z0, z1, z2, &avgz);
430
431 // Do we want to do back face removal ?
432 if (_removeBackface) {
433 // use winding order of the polygons
434 // e.g. NormalClip which is cross product of screen vectors
435 if (_useWindingOrder) {
436 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
437 // Drawing back facings polys requires making them have
438 // clockwise winding order as by definition they have
439 // anti-clockwise winding order
440 if (flag < 0) {
441 if (_drawBface) {
442 stemp = sxy1;
443 sxy1 = sxy2;
444 sxy2 = stemp;
445 rgbTemp = rgb1;
446 rgb1 = rgb2;
447 rgb2 = rgbTemp;
448 } else {
449 // Skip this polygon
450 continue;
451 }
452 } else if (flag == 0)
453 continue; // ignore zero-area polygons
454 }
455
456 // TODO
457 // dot product of viewing direction and polygon normal
458 // will require generation of polygon normal from vertex normals
459 // and transformation of the normal to world space
460 }
461
462 // Put wireframe triangles in list before textured ones
463 // so should be in front of textured ones
464 if ((_drawWfrm) || (selFace == i)) {
465 LINE_F4 *line = (LINE_F4 *)drawpacket;
466 setLineF4(line);
467 if (selFace == i)
468 setRGB0(line, selWRed, selWGreen, selWBlue);
469 else
470 setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
471 // set XY's in the GPU packet 0-1-2-3
472 line->x0 = sxy0.vx;
473 line->y0 = sxy0.vy;
474 line->x1 = sxy1.vx;
475 line->y1 = sxy1.vy;
476 line->x2 = sxy2.vx;
477 line->y2 = sxy2.vy;
478 line->x3 = sxy0.vx;
479 line->y3 = sxy0.vy;
480 // Put it into the global ot at the correct place
481 myAddPrimClip(avgz, drawpacket);
482 // advance the global packet pointer by correct amount
483 myAddPacket(sizeof(LINE_F4));
484 }
485
486 // Draw textured version behind the wireframe
487 if ((_drawPolys) || (selFace == i)) {
488 POLY_G3 *poly = (POLY_G3 *)drawpacket;
489 // Draw untextured polygons
490 setPolyG3(poly);
491 // set XY's in the GPU packet 0-1-2
492 poly->x0 = sxy0.vx;
493 poly->y0 = sxy0.vy;
494 poly->x1 = sxy1.vx;
495 poly->y1 = sxy1.vy;
496 poly->x2 = sxy2.vx;
497 poly->y2 = sxy2.vy;
498
499 // No light source calculation
500 // So just set base colour
501 if (selFace == i) {
502 setRGB0(poly, selPRed, selPGreen, selPBlue);
503 setRGB1(poly, selPRed, selPGreen, selPBlue);
504 setRGB2(poly, selPRed, selPGreen, selPBlue);
505 } else {
506 setRGB0(poly, rgb0->r, rgb0->g, rgb0->b);
507 setRGB1(poly, rgb1->r, rgb1->g, rgb1->b);
508 setRGB2(poly, rgb2->r, rgb2->g, rgb2->b);
509 }
510 // Put it into the global ot at the correct place
511 myAddPrimClip(avgz, drawpacket);
512 // advance the global packet pointer by correct amount
513 myAddPacket(sizeof(POLY_G3));
514 }
515 }
516 }
517
518 // Flat, Textured, Self-Luminous Triangles
drawFTS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)519 void drawFTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
520 SVECTORPC *v0;
521 SVECTORPC *v1;
522 SVECTORPC *v2;
523
524 // uint32 num = min( n, 10 ); // do a maximum of 10 polygons
525 uint32 num = n;
526 uint16 uu0, uu1, uu2;
527 uint16 vv0, vv1, vv2;
528 uint32 tmp;
529 int32 p, flag;
530 uint32 i;
531 uint32 *pPoly;
532 int32 z0, z1, z2;
533 SVECTORPC sxy0, sxy1, sxy2, stemp;
534 uint32 uv0, uv1, uv2;
535
536 // Base colour for shading computation
537 // Could easily be specified per polygon
538 CVECTOR *rgbIn;
539
540 pPoly = polyStart;
541 // Loop over each polygon
542 for (i = 0; i < num; i++) {
543 // Structure is :
544 // Bit 31 ----> Bit 0
545 //
546 // 8-bits | 8-bits | 8-bits | 8-bits
547 // 0x24 | Blue | Green | Red
548 // 16-bits | 16-bits
549 // --------------------------
550 // v0 | u0
551 // v1 | u1
552 // v2 | u2
553 // --------------------------
554 // pad | v0
555 // v2 | v1
556 rgbIn = (CVECTOR *)pPoly++;
557
558 if (deadObject) {
559 rgbIn = &deadObjectColour;
560 }
561
562 uv0 = *pPoly++;
563 vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
564 uu0 = (uint16)(uv0 & 0xFFFF);
565
566 uv1 = *pPoly++;
567 vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
568 uu1 = (uint16)(uv1 & 0xFFFF);
569
570 uv2 = *pPoly++;
571 vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
572 uu2 = (uint16)(uv2 & 0xFFFF);
573
574 tmp = *pPoly++;
575 v0 = pVertex + (tmp & 0xFFFF);
576
577 tmp = *pPoly++;
578 v1 = pVertex + (uint)(tmp & 0xFFFF);
579 v2 = pVertex + (uint)(tmp >> 16);
580
581 // Now do RotTransPers3 on the vectors
582 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
583 gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
584 z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
585
586 // test the return value of flag
587 if (flag & 0x80000000)
588 continue;
589
590 gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
591 z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
592 // test the return value of flag
593 if (flag & 0x80000000)
594 continue;
595
596 gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
597 z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
598 // test the return value of flag
599 if (flag & 0x80000000)
600 continue;
601
602 // Give the GTE some time to recover
603 int32 avgz;
604 gte_AverageZ3_pc(z0, z1, z2, &avgz);
605
606 // Do we want to do back face removal ?
607 if (_removeBackface) {
608 // use winding order of the polygons
609 // e.g. NormalClip which is cross product of screen vectors
610 if (_useWindingOrder) {
611 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
612 // Drawing back facings polys requires making them have
613 // clockwise winding order as by definition they have
614 // anti-clockwise winding order
615 if (flag < 0) {
616 if (_drawBface) {
617 stemp = sxy1;
618 sxy1 = sxy2;
619 sxy2 = stemp;
620 flag = uv1;
621 uv1 = uv2;
622 uv2 = flag;
623 } else {
624 // Skip this polygon
625 continue;
626 }
627 } else if (flag == 0)
628 continue; // ignore zero-area polygons
629 }
630
631 // TODO
632 // dot product of viewing direction and polygon normal
633 // will require generation of polygon normal from vertex normals
634 // and transformation of the normal to world space
635 }
636
637 // Put wireframe triangles in list before textured ones
638 // so should be in front of textured ones
639 if ((_drawWfrm) || (selFace == i)) {
640 LINE_F4 *line = (LINE_F4 *)drawpacket;
641 setLineF4(line);
642 if (selFace == i)
643 setRGB0(line, selWRed, selWGreen, selWBlue);
644 else
645 setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
646 // set XY's in the GPU packet 0-1-2-3
647 line->x0 = sxy0.vx;
648 line->y0 = sxy0.vy;
649 line->x1 = sxy1.vx;
650 line->y1 = sxy1.vy;
651 line->x2 = sxy2.vx;
652 line->y2 = sxy2.vy;
653 line->x3 = sxy0.vx;
654 line->y3 = sxy0.vy;
655 // Put it into the global ot at the correct place
656 myAddPrimClip(avgz, drawpacket);
657 // advance the global packet pointer by correct amount
658 myAddPacket(sizeof(LINE_F4));
659 }
660
661 // Draw textured version behind the wireframe
662 if ((_drawPolys) || (selFace == i)) {
663 if (_drawTxture) {
664 POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
665 setPolyFT3(poly);
666 // set XY's in the GPU packet 0-1-2
667 poly->x0 = sxy0.vx;
668 poly->y0 = sxy0.vy;
669 poly->x1 = sxy1.vx;
670 poly->y1 = sxy1.vy;
671 poly->x2 = sxy2.vx;
672 poly->y2 = sxy2.vy;
673
674 setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
675
676 // No light source calculation
677 // So just set base colour
678 if (selFace == i)
679 setRGB0(poly, selPRed, selPGreen, selPBlue);
680 else
681 setRGB0(poly, rgbIn->r, rgbIn->b, rgbIn->b);
682
683 // Put it into the global ot at the correct place
684 myAddPrimClip(avgz, drawpacket);
685 // advance the global packet pointer by correct amount
686 myAddPacket(sizeof(POLY_FT3));
687 } else {
688 // Set the RGB colours
689 POLY_F3 *poly = (POLY_F3 *)drawpacket;
690 // Draw untextured polygons
691 setPolyF3(poly);
692 // set XY's in the GPU packet 0-1-2
693 poly->x0 = sxy0.vx;
694 poly->y0 = sxy0.vy;
695 poly->x1 = sxy1.vx;
696 poly->y1 = sxy1.vy;
697 poly->x2 = sxy2.vx;
698 poly->y2 = sxy2.vy;
699
700 // No light source calculation
701 // So just set base colour
702 if (selFace == i)
703 setRGB0(poly, selPRed, selPGreen, selPBlue);
704 else
705 setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
706 // Put it into the global ot at the correct place
707 myAddPrimClip(avgz, drawpacket);
708 // advance the global packet pointer by correct amount
709 myAddPacket(sizeof(POLY_F3));
710 }
711 }
712 }
713 }
714
715 // Gouraud, Textured, Self-Luminous Triangles
drawGTS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)716 void drawGTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
717 SVECTORPC *v0;
718 SVECTORPC *v1;
719 SVECTORPC *v2;
720
721 // uint32 num = min( n, 10 ); // do a maximum of 10 polygons
722 uint32 num = n;
723 uint16 uu0, uu1, uu2;
724 uint16 vv0, vv1, vv2;
725 uint32 tmp;
726 int32 p, flag;
727 uint32 i;
728 uint32 *pPoly;
729 int32 z0, z1, z2;
730 SVECTORPC sxy0, sxy1, sxy2, stemp;
731 uint32 uv0, uv1, uv2;
732
733 // gouraud colours
734 CVECTOR *rgb0;
735 CVECTOR *rgb1;
736 CVECTOR *rgb2;
737 CVECTOR *rgbTemp;
738
739 pPoly = polyStart;
740 // Loop over each polygon
741 for (i = 0; i < num; i++) {
742 // Structure is :
743 // 8-bits | 8-bits | 8-bits | 8-bits
744 // 0x34 | Blue0 | Green0 | Red0
745 // 0x34 | Blue1 | Green1 | Red1
746 // 0x34 | Blue2 | Green2 | Red2
747 // 16-bits | 16-bits
748 // --------------------------
749 // v0 | u0
750 // v1 | u1
751 // v2 | u2
752 // --------------------------
753 // pad | v0
754 // v2 | v1
755 rgb0 = (CVECTOR *)pPoly++;
756 rgb1 = (CVECTOR *)pPoly++;
757 rgb2 = (CVECTOR *)pPoly++;
758
759 if (deadObject) {
760 rgb0 = &deadObjectColour;
761 rgb1 = &deadObjectColour;
762 rgb2 = &deadObjectColour;
763 }
764
765 uv0 = *pPoly++;
766 vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
767 uu0 = (uint16)(uv0 & 0xFFFF);
768
769 uv1 = *pPoly++;
770 vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
771 uu1 = (uint16)(uv1 & 0xFFFF);
772
773 uv2 = *pPoly++;
774 vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
775 uu2 = (uint16)(uv2 & 0xFFFF);
776
777 tmp = *pPoly++;
778 v0 = pVertex + (tmp & 0xFFFF);
779
780 tmp = *pPoly++;
781 v1 = pVertex + (tmp & 0xFFFF);
782 v2 = pVertex + (tmp >> 16);
783
784 // Now do RotTransPers3 on the vectors
785 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
786 gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
787 z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
788
789 // test the return value of flag
790 if (flag & 0x80000000)
791 continue;
792
793 gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
794 z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
795 // test the return value of flag
796 if (flag & 0x80000000)
797 continue;
798
799 gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
800 z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
801 // test the return value of flag
802 if (flag & 0x80000000)
803 continue;
804
805 // Give the GTE some time to recover
806 int32 avgz;
807 gte_AverageZ3_pc(z0, z1, z2, &avgz);
808
809 // Do we want to do back face removal ?
810 if (_removeBackface) {
811 // use winding order of the polygons
812 // e.g. NormalClip which is cross product of screen vectors
813 if (_useWindingOrder) {
814 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
815 // Drawing back facings polys requires making them have
816 // clockwise winding order as by definition they have
817 // anti-clockwise winding order
818 if (flag < 0) {
819 if (_drawBface) {
820 stemp = sxy1;
821 sxy1 = sxy2;
822 sxy2 = stemp;
823 rgbTemp = rgb1;
824 rgb1 = rgb2;
825 rgb2 = rgbTemp;
826 flag = uv1;
827 uv1 = uv2;
828 uv2 = flag;
829 } else {
830 // Skip this polygon
831 continue;
832 }
833 } else if (flag == 0)
834 continue; // ignore zero-area polygons
835 }
836
837 // TODO
838 // dot product of viewing direction and polygon normal
839 // will require generation of polygon normal from vertex normals
840 // and transformation of the normal to world space
841 }
842
843 // Put wireframe triangles in list before textured ones
844 // so should be in front of textured ones
845 if ((_drawWfrm) || (selFace == i)) {
846 LINE_F4 *line = (LINE_F4 *)drawpacket;
847 setLineF4(line);
848 if (selFace == i)
849 setRGB0(line, selWRed, selWGreen, selWBlue);
850 else
851 setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
852 // set XY's in the GPU packet 0-1-2-3
853 line->x0 = sxy0.vx;
854 line->y0 = sxy0.vy;
855 line->x1 = sxy1.vx;
856 line->y1 = sxy1.vy;
857 line->x2 = sxy2.vx;
858 line->y2 = sxy2.vy;
859 line->x3 = sxy0.vx;
860 line->y3 = sxy0.vy;
861
862 // Put it into the global ot at the correct place
863 myAddPrimClip(avgz, drawpacket);
864 // advance the global packet pointer by correct amount
865 myAddPacket(sizeof(LINE_F4));
866 }
867
868 // Draw textured version behind the wireframe
869 if ((_drawPolys) || (selFace == i)) {
870 if (_drawTxture) {
871 // Set the RGB colours
872 POLY_GT3 *poly = (POLY_GT3 *)drawpacket;
873 setPolyGT3(poly);
874 // set XY's in the GPU packet 0-1-2
875 poly->x0 = sxy0.vx;
876 poly->y0 = sxy0.vy;
877 poly->x1 = sxy1.vx;
878 poly->y1 = sxy1.vy;
879 poly->x2 = sxy2.vx;
880 poly->y2 = sxy2.vy;
881
882 setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
883
884 // No light source calculation
885 // So just set base colour
886 if (selFace == i) {
887 setRGB0(poly, selPRed, selPGreen, selPBlue);
888 setRGB1(poly, selPRed, selPGreen, selPBlue);
889 setRGB2(poly, selPRed, selPGreen, selPBlue);
890 } else {
891 setRGB0(poly, rgb0->r, rgb0->b, rgb0->b);
892 setRGB1(poly, rgb1->r, rgb1->b, rgb1->b);
893 setRGB2(poly, rgb2->r, rgb2->b, rgb2->b);
894 }
895
896 // Put it into the global ot at the correct place
897 myAddPrimClip(avgz, drawpacket);
898 // advance the global packet pointer by correct amount
899 myAddPacket(sizeof(POLY_GT3));
900 } else {
901 // Set the RGB colours
902 POLY_G3 *poly = (POLY_G3 *)drawpacket;
903 // Draw untextured polygons
904 setPolyG3(poly);
905 // set XY's in the GPU packet 0-1-2
906 poly->x0 = sxy0.vx;
907 poly->y0 = sxy0.vy;
908 poly->x1 = sxy1.vx;
909 poly->y1 = sxy1.vy;
910 poly->x2 = sxy2.vx;
911 poly->y2 = sxy2.vy;
912
913 // No light source calculation
914 // So just set base colour
915 if (selFace == i) {
916 setRGB0(poly, selPRed, selPGreen, selPBlue);
917 setRGB1(poly, selPRed, selPGreen, selPBlue);
918 setRGB2(poly, selPRed, selPGreen, selPBlue);
919 } else {
920 setRGB0(poly, rgb0->r, rgb0->b, rgb0->b);
921 setRGB1(poly, rgb1->r, rgb1->b, rgb1->b);
922 setRGB2(poly, rgb2->r, rgb2->b, rgb2->b);
923 }
924
925 // Put it into the global ot at the correct place
926 myAddPrimClip(avgz, drawpacket);
927 // advance the global packet pointer by correct amount
928 myAddPacket(sizeof(POLY_G3));
929 }
930 }
931 }
932 }
933
934 // Flat, Un-Textured, Lit, triangles
drawFUL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)935 void drawFUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
936 SVECTOR *n0;
937 SVECTORPC *v0;
938 SVECTORPC *v1;
939 SVECTORPC *v2;
940
941 // uint32 num = min( n, 10 ); // do a maximum of 10 polygons
942 uint32 num = n;
943 int32 p, flag;
944 uint32 i;
945 uint32 *pPoly;
946 int32 z0, z1, z2;
947 SVECTORPC sxy0, sxy1, sxy2, stemp;
948 SVECTORPC sxyn0;
949 SVECTORPC sn0;
950 CVECTOR *rgbIn;
951 CVECTOR rgb0 = {0, 0, 0, 0};
952 uint32 tmp;
953 uint8 ctmp;
954
955 pPoly = polyStart;
956 // Loop over each polygon
957 for (i = 0; i < num; i++) {
958 // Structure is :
959 // 0x20 | B | G | R
960 // v0 | n0
961 // v2 | v1
962 rgbIn = (CVECTOR *)pPoly++;
963
964 tmp = *pPoly++;
965 v0 = pVertex + (tmp >> 16);
966 n0 = pNormal + (tmp & 0xFFFF);
967
968 tmp = *pPoly++;
969 v2 = pVertex + (tmp >> 16);
970 v1 = pVertex + (tmp & 0xFFFF);
971
972 // Now do RotTransPers3 on the vectors
973 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
974 gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
975 z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
976
977 // test the return value of flag
978 if (flag & 0x80000000)
979 continue;
980
981 gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
982 z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
983 // test the return value of flag
984 if (flag & 0x80000000)
985 continue;
986
987 gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
988 z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
989 // test the return value of flag
990 if (flag & 0x80000000)
991 continue;
992
993 // Give the GTE some time to recover
994 int32 avgz;
995 gte_AverageZ3_pc(z0, z1, z2, &avgz);
996
997 // Do we want to do back face removal ?
998 if (_removeBackface) {
999 // use winding order of the polygons
1000 // e.g. NormalClip which is cross product of screen vectors
1001 if (_useWindingOrder) {
1002 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
1003 // Drawing back facings polys requires making them have
1004 // clockwise winding order as by definition they have
1005 // anti-clockwise winding order
1006 if (flag < 0) {
1007 if (_drawBface) {
1008 stemp = sxy1;
1009 sxy1 = sxy2;
1010 sxy2 = stemp;
1011 } else {
1012 // Skip this polygon
1013 continue;
1014 }
1015 } else if (flag == 0)
1016 continue; // ignore zero-area polygons
1017 }
1018
1019 // TODO
1020 // dot product of viewing direction and polygon normal
1021 // will require generation of polygon normal from vertex normals
1022 // and transformation of the normal to world space
1023 }
1024
1025 // Set the RGB colours
1026 if (_drawLit) {
1027 // Do the flat lighting computation
1028 LIGHTPOLYGON(n0, rgbIn, &rgb0);
1029 }
1030
1031 // Put normal lines in list before wireframe
1032 // so should be drawn in front of wireframe triangles
1033 if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
1034 // Do coord transform on the scaled normal vectors + v0
1035 sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
1036 sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
1037 sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
1038 // z0 = RotTransPers( &sn0, &sxyn0, &p, &flag );
1039 gte_RotTransPers_pc(&sn0, &sxyn0, &p, &flag, &z0);
1040 // Normal 0 : scale the normal and add to vertex scrn pos
1041 LINE_G2 *line = (LINE_G2 *)drawpacket;
1042 setLineG2(line);
1043 line->x0 = sxy0.vx;
1044 line->y0 = sxy0.vy;
1045 line->x1 = sxyn0.vx;
1046 line->y1 = sxyn0.vy;
1047 if (selFace == i) {
1048 // from bright red
1049 setRGB0(line, 255, 0, 0);
1050 // to bright white
1051 setRGB1(line, 255, 255, 255);
1052 } else {
1053 // from bright blue
1054 setRGB0(line, 0, 0, 255);
1055 // to bright white
1056 setRGB1(line, 255, 255, 255);
1057 }
1058 // Put it into the global ot at the correct place
1059 myAddPrimClip(avgz, drawpacket);
1060 // advance the global packet pointer by correct amount
1061 myAddPacket(sizeof(LINE_G2));
1062 }
1063
1064 // Put wireframe triangles in list before textured ones
1065 // so should be in front of textured ones
1066 if ((_drawWfrm) || (selFace == i)) {
1067 LINE_F4 *line = (LINE_F4 *)drawpacket;
1068 setLineF4(line);
1069 // set XY's in the GPU packet 0-1-2-3
1070 line->x0 = sxy0.vx;
1071 line->y0 = sxy0.vy;
1072 line->x1 = sxy1.vx;
1073 line->y1 = sxy1.vy;
1074 line->x2 = sxy2.vx;
1075 line->y2 = sxy2.vy;
1076 line->x3 = sxy0.vx;
1077 line->y3 = sxy0.vy;
1078 // Draw a wireframe that responds to lighting
1079 if (_drawLit) {
1080 int32 cval;
1081 // Compute the colour scaling and clip it
1082 // Flat shading so give the same colour to each vertex
1083 if (rgbIn->r != 0) {
1084 cval = ((wfrmRed * rgb0.r) / rgbIn->r);
1085 if (cval > 255)
1086 cval = 255;
1087 ctmp = (uint8)cval;
1088 } else
1089 ctmp = 0;
1090 line->r0 = ctmp;
1091
1092 if (rgbIn->g != 0) {
1093 cval = ((wfrmGreen * rgb0.g) / rgbIn->g);
1094 if (cval > 255)
1095 cval = 255;
1096 ctmp = (uint8)cval;
1097 } else
1098 ctmp = 0;
1099 line->g0 = ctmp;
1100
1101 if (rgbIn->b != 0) {
1102 cval = ((wfrmBlue * rgb0.b) / rgbIn->b);
1103 if (cval > 255)
1104 cval = 255;
1105 ctmp = (uint8)cval;
1106 } else
1107 ctmp = 0;
1108 line->b0 = ctmp;
1109 } else {
1110 setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
1111 }
1112 if (selFace == i)
1113 setRGB0(line, selWRed, selWGreen, selWBlue);
1114
1115 // Put it into the global ot at the correct place
1116 myAddPrimClip(avgz, drawpacket);
1117 // advance the global packet pointer by correct amount
1118 myAddPacket(sizeof(LINE_F4));
1119 }
1120
1121 // Draw polygon version behind the wireframe
1122 if ((_drawPolys) || (selFace == i)) {
1123 // Draw untextured polygons
1124 POLY_F3 *poly = (POLY_F3 *)drawpacket;
1125 setPolyF3(poly);
1126 // set XY's in the GPU packet 0-1-2
1127 poly->x0 = sxy0.vx;
1128 poly->y0 = sxy0.vy;
1129 poly->x1 = sxy1.vx;
1130 poly->y1 = sxy1.vy;
1131 poly->x2 = sxy2.vx;
1132 poly->y2 = sxy2.vy;
1133
1134 // Set the RGB colours
1135 if (_drawLit) {
1136 // Flat shaded so give each vertex the same colour
1137 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
1138 } else {
1139 // No light source calculation
1140 // So just set base colour
1141 setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
1142 }
1143 if (selFace == i) {
1144 setRGB0(poly, selPRed, selPGreen, selPBlue);
1145 }
1146 // Put it into the global ot at the correct place
1147 myAddPrimClip(avgz, drawpacket);
1148 // advance the global packet pointer by correct amount
1149 myAddPacket(sizeof(POLY_F3));
1150 }
1151 }
1152 }
1153
1154 // Gouraud, Un-Textured, Lit, triangles
drawGUL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)1155 void drawGUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
1156 SVECTOR *n0;
1157 SVECTOR *n1;
1158 SVECTOR *n2;
1159 SVECTORPC *v0;
1160 SVECTORPC *v1;
1161 SVECTORPC *v2;
1162 SVECTOR *ntemp;
1163
1164 // uint32 num = min( n, 10 ); // do a maximum of 10 polygons
1165 uint32 num = n;
1166 uint32 tmp;
1167 uint8 ctmp;
1168 int32 p, flag;
1169 uint32 i;
1170 uint32 *pPoly;
1171 int32 z0, z1, z2;
1172 SVECTORPC sxy0, sxy1, sxy2, stemp;
1173 SVECTORPC sxyn0, sxyn1, sxyn2;
1174 SVECTORPC sn0, sn1, sn2;
1175
1176 // Base colour for gouraud shading computation
1177 // Could easily be specified per polygon
1178 CVECTOR rgbIn;
1179 CVECTOR rgb0 = {0, 0, 0, 0};
1180 CVECTOR rgb1 = {0, 0, 0, 0};
1181 CVECTOR rgb2 = {0, 0, 0, 0};
1182
1183 pPoly = polyStart;
1184 // Loop over each polygon
1185 for (i = 0; i < num; i++) {
1186 // Structure is :
1187 // 8-bits | 8-bits | 8-bits | 8-bits
1188 // 0x20 | Blue | Green | Red
1189 // 16-bits | 8-bits | 8-bits
1190 // --------------------------
1191 // v0 | n0
1192 // v1 | n1
1193 // v2 | n2
1194 tmp = *pPoly++;
1195 // code0 = tmp >> 24;
1196 rgbIn.r = (uint8)(tmp & 0xFF);
1197 rgbIn.g = (uint8)((tmp >> 8) & 0xFF);
1198 rgbIn.b = (uint8)((tmp >> 16) & 0xFF);
1199
1200 tmp = *pPoly++;
1201 v0 = pVertex + (tmp >> 16);
1202 n0 = pNormal + (tmp & 0xFFFF);
1203
1204 tmp = *pPoly++;
1205 v1 = pVertex + (tmp >> 16);
1206 n1 = pNormal + (tmp & 0xFFFF);
1207
1208 tmp = *pPoly++;
1209 v2 = pVertex + (tmp >> 16);
1210 n2 = pNormal + (tmp & 0xFFFF);
1211
1212 // Now do RotTransPers3 on the vectors
1213 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
1214 gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
1215 z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1216
1217 // test the return value of flag
1218 if (flag & 0x80000000)
1219 continue;
1220
1221 gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
1222 z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1223 // test the return value of flag
1224 if (flag & 0x80000000)
1225 continue;
1226
1227 gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
1228 z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1229 // test the return value of flag
1230 if (flag & 0x80000000)
1231 continue;
1232
1233 // Give the GTE some time to recover
1234 int32 avgz;
1235 gte_AverageZ3_pc(z0, z1, z2, &avgz);
1236
1237 // Do we want to do back face removal ?
1238 if (_removeBackface) {
1239 // use winding order of the polygons
1240 // e.g. NormalClip which is cross product of screen vectors
1241 if (_useWindingOrder) {
1242 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
1243 // Drawing back facings polys requires making them have
1244 // clockwise winding order as by definition they have
1245 // anti-clockwise winding order
1246 if (flag < 0) {
1247 if (_drawBface) {
1248 stemp = sxy1;
1249 sxy1 = sxy2;
1250 sxy2 = stemp;
1251 ntemp = n1;
1252 n1 = n2;
1253 n2 = ntemp;
1254 } else {
1255 // Skip this polygon
1256 continue;
1257 }
1258 } else if (flag == 0)
1259 continue; // ignore zero-area polygons
1260 }
1261
1262 // TODO
1263 // dot product of viewing direction and polygon normal
1264 // will require generation of polygon normal from vertex normals
1265 // and transformation of the normal to world space
1266 }
1267
1268 // Set the RGB colours
1269 if (_drawLit) {
1270 // Do the full gouraud computation
1271 // NormalColorCol3( n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2 );
1272 LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
1273
1274 int32 cval;
1275
1276 if (!_drawGouraud) {
1277 // For flat shading mode take the average RGB for the face
1278 // Could/should use something like AVSZ3
1279 // but hell whats a divide by 3 between friends (~30 cycles?)
1280 cval = ((rgb0.r + rgb1.r + rgb2.r) / 3);
1281 if (cval > 255)
1282 cval = 255;
1283 rgb0.r = (uint8)cval;
1284
1285 cval = ((rgb0.g + rgb1.g + rgb2.g) / 3);
1286 if (cval > 255)
1287 cval = 255;
1288 rgb0.g = (uint8)cval;
1289
1290 cval = ((rgb0.b + rgb1.b + rgb2.b) / 3);
1291 if (cval > 255)
1292 cval = 255;
1293 rgb0.b = (uint8)cval;
1294 }
1295 } else {
1296 rgbIn.r = unlitPoly.r;
1297 rgbIn.g = unlitPoly.g;
1298 rgbIn.b = unlitPoly.b;
1299 }
1300
1301 // Put normal lines in list before wireframe
1302 // so should be drawn in front of wireframe triangles
1303 if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
1304 // Do coord transform on the scaled normal vectors + v0
1305 sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
1306 sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
1307 sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
1308 sn1.vx = (int16)(v1->vx + (-n1->vx >> _normalScale));
1309 sn1.vy = (int16)(v1->vy + (-n1->vy >> _normalScale));
1310 sn1.vz = (int16)(v1->vz + (-n1->vz >> _normalScale));
1311 sn2.vx = (int16)(v2->vx + (-n2->vx >> _normalScale));
1312 sn2.vy = (int16)(v2->vy + (-n2->vy >> _normalScale));
1313 sn2.vz = (int16)(v2->vz + (-n2->vz >> _normalScale));
1314
1315 // z0 = RotTransPers3( &sn0, &sn1, &sn2,
1316 // &sxyn0, &sxyn1, &sxyn2, &p, &flag );
1317 gte_RotTransPers3_pc(&sn0, &sn1, &sn2, &sxyn0, &sxyn1, &sxyn2, &p, &flag, &z0);
1318 // Normal 0
1319 LINE_G2 *line = (LINE_G2 *)drawpacket;
1320 setLineG2(line);
1321 line->x0 = sxy0.vx;
1322 line->y0 = sxy0.vy;
1323 line->x1 = sxy1.vx;
1324 line->y1 = sxy1.vy;
1325 if (selFace == i) {
1326 // Bright red
1327 setRGB0(line, 255, 0, 0);
1328 // Bright white
1329 setRGB1(line, 255, 255, 255);
1330 } else {
1331 // Bright blue
1332 setRGB0(line, 0, 0, 255);
1333 // Bright white
1334 setRGB1(line, 255, 255, 255);
1335 }
1336 // Put it into the global ot at the correct place
1337 myAddPrimClip(avgz, drawpacket);
1338 // advance the global packet pointer by correct amount
1339 myAddPacket(sizeof(LINE_G2));
1340
1341 // Normal 1
1342 line = (LINE_G2 *)drawpacket;
1343 setLineG2(line);
1344 line->x0 = sxy0.vx;
1345 line->y0 = sxy0.vy;
1346 line->x1 = sxyn1.vx;
1347 line->y1 = sxyn1.vy;
1348 if (selFace == i) {
1349 // Bright red
1350 setRGB0(line, 255, 0, 0);
1351 // Bright white
1352 setRGB1(line, 255, 255, 255);
1353 } else {
1354 // Bright blue
1355 setRGB0(line, 0, 0, 255);
1356 // Bright white
1357 setRGB1(line, 255, 255, 255);
1358 }
1359 // Put it into the global ot at the correct place
1360 myAddPrimClip(avgz, drawpacket);
1361 // advance the global packet pointer by correct amount
1362 myAddPacket(sizeof(LINE_G2));
1363
1364 // Normal 2
1365 line = (LINE_G2 *)drawpacket;
1366 setLineG2(line);
1367 line->x0 = sxy0.vx;
1368 line->y0 = sxy0.vy;
1369 line->x1 = sxyn2.vx;
1370 line->y1 = sxyn2.vy;
1371 if (selFace == i) {
1372 // Bright red
1373 setRGB0(line, 255, 0, 0);
1374 // Bright white
1375 setRGB1(line, 255, 255, 255);
1376 } else {
1377 // Bright blue
1378 setRGB0(line, 0, 0, 255);
1379 // Bright white
1380 setRGB1(line, 255, 255, 255);
1381 }
1382 // Put it into the global ot at the correct place
1383 myAddPrimClip(avgz, drawpacket);
1384 // advance the global packet pointer by correct amount
1385 myAddPacket(sizeof(LINE_G2));
1386 }
1387
1388 // Put wireframe triangles in list before textured ones
1389 // so should be in front of textured ones
1390 if ((_drawWfrm) || (selFace == i)) {
1391 // Draw a wireframe that responds to lighting
1392 if (_drawLit) {
1393 LINE_G4 *line = (LINE_G4 *)drawpacket;
1394 setLineG4(line);
1395 int32 cval;
1396 if (_drawGouraud) {
1397 // Give each vertex a seperate colour
1398 // Compute the colour scaling and clip it
1399 if (rgbIn.r != 0) {
1400 cval = ((wfrmRed * rgb0.r) / rgbIn.r);
1401 if (cval > 255)
1402 cval = 255;
1403 ctmp = (uint8)cval;
1404 line->r0 = ctmp;
1405 line->r3 = ctmp;
1406
1407 cval = ((wfrmRed * rgb1.r) / rgbIn.r);
1408 if (cval > 255)
1409 cval = 255;
1410 ctmp = (uint8)cval;
1411 line->r1 = ctmp;
1412
1413 cval = ((wfrmRed * rgb2.r) / rgbIn.r);
1414 if (cval > 255)
1415 cval = 255;
1416 ctmp = (uint8)cval;
1417 line->r2 = ctmp;
1418 } else {
1419 line->r0 = 0;
1420 line->r3 = 0;
1421 line->r1 = 0;
1422 line->r2 = 0;
1423 }
1424
1425 if (rgbIn.g != 0) {
1426 cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
1427 if (cval > 255)
1428 cval = 255;
1429 ctmp = (uint8)cval;
1430 line->g0 = ctmp;
1431 line->g3 = ctmp;
1432
1433 cval = ((wfrmGreen * rgb1.g) / rgbIn.g);
1434 if (cval > 255)
1435 cval = 255;
1436 ctmp = (uint8)cval;
1437 line->g1 = ctmp;
1438
1439 cval = ((wfrmGreen * rgb2.g) / rgbIn.g);
1440 if (cval > 255)
1441 cval = 255;
1442 ctmp = (uint8)cval;
1443 line->g2 = ctmp;
1444 } else {
1445 line->g0 = 0;
1446 line->g3 = 0;
1447 line->g1 = 0;
1448 line->g2 = 0;
1449 }
1450 if (rgbIn.b != 0) {
1451 cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
1452 if (cval > 255)
1453 cval = 255;
1454 ctmp = (uint8)cval;
1455 line->b0 = ctmp;
1456 line->b3 = ctmp;
1457
1458 cval = ((wfrmBlue * rgb1.b) / rgbIn.b);
1459 if (cval > 255)
1460 cval = 255;
1461 ctmp = (uint8)cval;
1462 line->b1 = ctmp;
1463
1464 cval = ((wfrmBlue * rgb2.b) / rgbIn.b);
1465 if (cval > 255)
1466 cval = 255;
1467 ctmp = (uint8)cval;
1468 line->b2 = ctmp;
1469 } else {
1470 line->b0 = 0;
1471 line->b3 = 0;
1472 line->b1 = 0;
1473 line->b2 = 0;
1474 }
1475 } else {
1476 // Compute the colour scaling and clip it
1477 // Flat shading so give the same colour to each vertex
1478 if (rgbIn.r != 0) {
1479 cval = ((wfrmRed * rgb0.r) / rgbIn.r);
1480 if (cval > 255)
1481 cval = 255;
1482 ctmp = (uint8)cval;
1483 } else
1484 ctmp = 0;
1485 line->r0 = ctmp;
1486 line->r1 = ctmp;
1487 line->r2 = ctmp;
1488 line->r3 = ctmp;
1489
1490 if (rgbIn.g != 0) {
1491 cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
1492 if (cval > 255)
1493 cval = 255;
1494 ctmp = (uint8)cval;
1495 } else
1496 ctmp = 0;
1497 line->g0 = ctmp;
1498 line->g1 = ctmp;
1499 line->g2 = ctmp;
1500 line->g3 = ctmp;
1501
1502 if (rgbIn.b != 0) {
1503 cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
1504 if (cval > 255)
1505 cval = 255;
1506 ctmp = (uint8)cval;
1507 } else
1508 ctmp = 0;
1509
1510 line->b0 = ctmp;
1511 line->b1 = ctmp;
1512 line->b2 = ctmp;
1513 line->b3 = ctmp;
1514 }
1515 if (selFace == i) {
1516 setRGB0(line, selWRed, selWGreen, selWBlue);
1517 setRGB1(line, selWRed, selWGreen, selWBlue);
1518 setRGB2(line, selWRed, selWGreen, selWBlue);
1519 setRGB3(line, selWRed, selWGreen, selWBlue);
1520 }
1521
1522 // set XY's in the GPU packet 0-1-2-3
1523 line->x0 = sxy0.vx;
1524 line->y0 = sxy0.vy;
1525 line->x1 = sxy1.vx;
1526 line->y1 = sxy1.vy;
1527 line->x2 = sxy2.vx;
1528 line->y2 = sxy2.vy;
1529 line->x3 = sxy0.vx;
1530 line->y3 = sxy0.vy;
1531 // Put it into the global ot at the correct place
1532 myAddPrimClip(avgz, drawpacket);
1533 // advance the global packet pointer by correct amount
1534 myAddPacket(sizeof(LINE_G4));
1535 } else {
1536 LINE_F4 *line = (LINE_F4 *)drawpacket;
1537 setLineF4(line);
1538 if (selFace == i)
1539 setRGB0(line, selWRed, selWGreen, selWBlue);
1540 else
1541 setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
1542 // set XY's in the GPU packet 0-1-2-3
1543 line->x0 = sxy0.vx;
1544 line->y0 = sxy0.vy;
1545 line->x1 = sxy1.vx;
1546 line->y1 = sxy1.vy;
1547 line->x2 = sxy2.vx;
1548 line->y2 = sxy2.vy;
1549 line->x3 = sxy0.vx;
1550 line->y3 = sxy0.vy;
1551 // Put it into the global ot at the correct place
1552 myAddPrimClip(avgz, drawpacket);
1553 // advance the global packet pointer by correct amount
1554 myAddPacket(sizeof(LINE_F4));
1555 }
1556 }
1557
1558 // Draw textured version behind the wireframe
1559 if ((_drawPolys) || (selFace == i)) {
1560 // Set the RGB colours
1561 if (_drawLit) {
1562 if (_drawGouraud) {
1563 POLY_G3 *poly = (POLY_G3 *)drawpacket;
1564 // Draw untextured polygons
1565 setPolyG3(poly);
1566 // set XY's in the GPU packet 0-1-2
1567 poly->x0 = sxy0.vx;
1568 poly->y0 = sxy0.vy;
1569 poly->x1 = sxy1.vx;
1570 poly->y1 = sxy1.vy;
1571 poly->x2 = sxy2.vx;
1572 poly->y2 = sxy2.vy;
1573
1574 if (selFace == i) {
1575 setRGB0(poly, selPRed, selPGreen, selPBlue);
1576 setRGB1(poly, selPRed, selPGreen, selPBlue);
1577 setRGB2(poly, selPRed, selPGreen, selPBlue);
1578 } else {
1579 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
1580 setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
1581 setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
1582 }
1583
1584 // Put it into the global ot at the correct place
1585 myAddPrimClip(avgz, drawpacket);
1586 // advance the global packet pointer by correct amount
1587 myAddPacket(sizeof(POLY_G3));
1588 } else {
1589 POLY_F3 *poly = (POLY_F3 *)drawpacket;
1590 // Draw untextured polygons
1591 setPolyF3(poly);
1592 // set XY's in the GPU packet 0-1-2
1593 poly->x0 = sxy0.vx;
1594 poly->y0 = sxy0.vy;
1595 poly->x1 = sxy1.vx;
1596 poly->y1 = sxy1.vy;
1597 poly->x2 = sxy2.vx;
1598 poly->y2 = sxy2.vy;
1599
1600 // Flat shaded so give each vertex the same colour
1601 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
1602
1603 // Put it into the global ot at the correct place
1604 myAddPrimClip(avgz, drawpacket);
1605 // advance the global packet pointer by correct amount
1606 myAddPacket(sizeof(POLY_F3));
1607 }
1608 } else {
1609 POLY_F3 *poly = (POLY_F3 *)drawpacket;
1610 // Draw untextured polygons
1611 setPolyF3(poly);
1612 // set XY's in the GPU packet 0-1-2
1613 poly->x0 = sxy0.vx;
1614 poly->y0 = sxy0.vy;
1615 poly->x1 = sxy1.vx;
1616 poly->y1 = sxy1.vy;
1617 poly->x2 = sxy2.vx;
1618 poly->y2 = sxy2.vy;
1619
1620 // No light source calculation
1621 // So just set base colour
1622 setRGB0(poly, rgbIn.r, rgbIn.g, rgbIn.b);
1623 // Put it into the global ot at the correct place
1624 myAddPrimClip(avgz, drawpacket);
1625 // advance the global packet pointer by correct amount
1626 myAddPacket(sizeof(POLY_F3));
1627 }
1628 }
1629 }
1630 }
1631
1632 // Flat, Textured, Lit Triangles
drawFTL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)1633 void drawFTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
1634 SVECTOR *n0;
1635 SVECTORPC *v0;
1636 SVECTORPC *v1;
1637 SVECTORPC *v2;
1638
1639 // uint32 num = min( n, 10 ); // do a maximum of 10 polygons
1640 uint32 num = n;
1641 uint16 uu0, uu1, uu2;
1642 uint16 vv0, vv1, vv2;
1643 uint32 tmp;
1644 uint8 ctmp;
1645 int32 p, flag;
1646 uint32 i;
1647 uint32 *pPoly;
1648 int32 z0, z1, z2;
1649 SVECTORPC sxy0, sxy1, sxy2, stemp;
1650 SVECTORPC sxyn0;
1651 SVECTORPC sn0;
1652 uint32 uv0, uv1, uv2;
1653
1654 // Base colour for shading computation
1655 // Could easily be specified per polygon
1656 CVECTOR rgbIn = {128, 128, 128, 0};
1657 CVECTOR rgb0 = {0, 0, 0, 0};
1658
1659 pPoly = polyStart;
1660 // Loop over each polygon
1661 for (i = 0; i < num; i++) {
1662 // Structure is :
1663 // Bit 31 ----> Bit 0
1664 //
1665 // 16-bits | 16-bits
1666 // --------------------------
1667 // v0 | u0
1668 // v1 | u1
1669 // v2 | u2
1670 // --------------------------
1671 // v0 | n0
1672 // v2 | v1
1673 uv0 = *pPoly++;
1674 vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
1675 uu0 = (uint16)(uv0 & 0xFFFF);
1676
1677 uv1 = *pPoly++;
1678 vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
1679 uu1 = (uint16)(uv1 & 0xFFFF);
1680
1681 uv2 = *pPoly++;
1682 vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
1683 uu2 = (uint16)(uv2 & 0xFFFF);
1684
1685 tmp = *pPoly++;
1686 v0 = pVertex + (tmp >> 16);
1687 n0 = pNormal + (tmp & 0xFFFF);
1688
1689 tmp = *pPoly++;
1690 v1 = pVertex + (tmp & 0xFFFF);
1691 v2 = pVertex + (tmp >> 16);
1692
1693 // Now do RotTransPers3 on the vectors
1694 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
1695 gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
1696 z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1697
1698 // test the return value of flag
1699 if (flag & 0x80000000)
1700 continue;
1701
1702 gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
1703 z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1704 // test the return value of flag
1705 if (flag & 0x80000000)
1706 continue;
1707
1708 gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
1709 z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
1710 // test the return value of flag
1711 if (flag & 0x80000000)
1712 continue;
1713
1714 // Give the GTE some time to recover
1715 int32 avgz;
1716 gte_AverageZ3_pc(z0, z1, z2, &avgz);
1717
1718 // Do we want to do back face removal ?
1719 if (_removeBackface) {
1720 // use winding order of the polygons
1721 // e.g. NormalClip which is cross product of screen vectors
1722 if (_useWindingOrder) {
1723 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
1724 // Drawing back facings polys requires making them have
1725 // clockwise winding order as by definition they have
1726 // anti-clockwise winding order
1727 if (flag < 0) {
1728 if (_drawBface) {
1729 stemp = sxy1;
1730 sxy1 = sxy2;
1731 sxy2 = stemp;
1732 flag = uv1;
1733 uv1 = uv2;
1734 uv2 = flag;
1735 } else {
1736 // Skip this polygon
1737 continue;
1738 }
1739 } else if (flag == 0)
1740 continue; // ignore zero-area polygons
1741 }
1742
1743 // TODO
1744 // dot product of viewing direction and polygon normal
1745 // will require generation of polygon normal from vertex normals
1746 // and transformation of the normal to world space
1747 }
1748
1749 // Set the RGB colours
1750 if (_drawLit) {
1751 // Do the full gouraud computation
1752 // NormalColorCol( n0, &rgbIn, &rgb0 );
1753 LIGHTPOLYGON(n0, &rgbIn, &rgb0);
1754 }
1755
1756 // Put normal lines in list before wireframe
1757 // so should be drawn in front of wireframe triangles
1758 if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
1759 // Do coord transform on the scaled normal vectors + v0
1760 sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
1761 sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
1762 sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
1763 // z0 = RotTransPers( &sn0, &sxyn0, &p, &flag );
1764 gte_RotTransPers_pc(&sn0, &sxyn0, &p, &flag, &z0);
1765 // Normal 0
1766 LINE_G2 *line = (LINE_G2 *)drawpacket;
1767 setLineG2(line);
1768 line->x0 = sxy0.vx;
1769 line->y0 = sxy0.vy;
1770 line->x1 = sxyn0.vx;
1771 line->y1 = sxyn0.vy;
1772 if (selFace == i) {
1773 // Bright red
1774 setRGB0(line, 255, 0, 0);
1775 // Bright white
1776 setRGB1(line, 255, 255, 255);
1777 } else {
1778 // Bright blue
1779 setRGB0(line, 0, 0, 255);
1780 // Bright white
1781 setRGB1(line, 255, 255, 255);
1782 }
1783 // Put it into the global ot at the correct place
1784 myAddPrimClip(avgz, drawpacket);
1785 // advance the global packet pointer by correct amount
1786 myAddPacket(sizeof(LINE_G2));
1787 }
1788
1789 // Put wireframe triangles in list before textured ones
1790 // so should be in front of textured ones
1791 if ((_drawWfrm) || (selFace == i)) {
1792 // Draw a wireframe that responds to lighting
1793 if (_drawLit) {
1794 int32 cval;
1795 LINE_G4 *line = (LINE_G4 *)drawpacket;
1796 setLineG4(line);
1797 // Compute the colour scaling and clip it
1798 // Flat shading so give the same colour to each vertex
1799 cval = ((wfrmRed * rgb0.r) / rgbIn.r);
1800 if (cval > 255)
1801 cval = 255;
1802 ctmp = (uint8)cval;
1803 line->r0 = ctmp;
1804 line->r1 = ctmp;
1805 line->r2 = ctmp;
1806 line->r3 = ctmp;
1807 cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
1808 if (cval > 255)
1809 cval = 255;
1810 ctmp = (uint8)cval;
1811 line->g0 = ctmp;
1812 line->g1 = ctmp;
1813 line->g2 = ctmp;
1814 line->g3 = ctmp;
1815 cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
1816 if (cval > 255)
1817 cval = 255;
1818 ctmp = (uint8)cval;
1819 line->b0 = ctmp;
1820 line->b1 = ctmp;
1821 line->b2 = ctmp;
1822 line->b3 = ctmp;
1823
1824 if (selFace == i) {
1825 setRGB0(line, selWRed, selWGreen, selWBlue);
1826 setRGB1(line, selWRed, selWGreen, selWBlue);
1827 setRGB2(line, selWRed, selWGreen, selWBlue);
1828 setRGB3(line, selWRed, selWGreen, selWBlue);
1829 }
1830 // set XY's in the GPU packet 0-1-2-3
1831 line->x0 = sxy0.vx;
1832 line->y0 = sxy0.vy;
1833 line->x1 = sxy1.vx;
1834 line->y1 = sxy1.vy;
1835 line->x2 = sxy2.vx;
1836 line->y2 = sxy2.vy;
1837 line->x3 = sxy0.vx;
1838 line->y3 = sxy0.vy;
1839 // Put it into the global ot at the correct place
1840 myAddPrimClip(avgz, drawpacket);
1841 // advance the global packet pointer by correct amount
1842 myAddPacket(sizeof(LINE_G4));
1843 } else {
1844 LINE_F4 *line = (LINE_F4 *)drawpacket;
1845 setLineF4(line);
1846 if (selFace == i)
1847 setRGB0(line, selWRed, selWGreen, selWBlue);
1848 else
1849 setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
1850 // set XY's in the GPU packet 0-1-2-3
1851 line->x0 = sxy0.vx;
1852 line->y0 = sxy0.vy;
1853 line->x1 = sxy1.vx;
1854 line->y1 = sxy1.vy;
1855 line->x2 = sxy2.vx;
1856 line->y2 = sxy2.vy;
1857 line->x3 = sxy0.vx;
1858 line->y3 = sxy0.vy;
1859 // Put it into the global ot at the correct place
1860 myAddPrimClip(avgz, drawpacket);
1861 // advance the global packet pointer by correct amount
1862 myAddPacket(sizeof(LINE_F4));
1863 }
1864 }
1865
1866 // Draw textured version behind the wireframe
1867 if ((_drawPolys) || (selFace == i)) {
1868 if (_drawTxture) {
1869 POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
1870 setPolyFT3(poly);
1871 // set XY's in the GPU packet 0-1-2
1872 poly->x0 = sxy0.vx;
1873 poly->y0 = sxy0.vy;
1874 poly->x1 = sxy1.vx;
1875 poly->y1 = sxy1.vy;
1876 poly->x2 = sxy2.vx;
1877 poly->y2 = sxy2.vy;
1878
1879 setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
1880
1881 if (_drawLit) {
1882 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
1883 } else {
1884 // No light source calculation
1885 // So just set base colour
1886 setRGB0(poly, rgbIn.r, rgbIn.b, rgbIn.b);
1887 }
1888 if (selFace == i) {
1889 setRGB0(poly, selPRed, selPGreen, selPBlue);
1890 }
1891
1892 // Put it into the global ot at the correct place
1893 myAddPrimClip(avgz, drawpacket);
1894 // advance the global packet pointer by correct amount
1895 myAddPacket(sizeof(POLY_FT3));
1896 } else {
1897 // Set the RGB colours
1898 if (_drawLit) {
1899 POLY_F3 *poly = (POLY_F3 *)drawpacket;
1900 // Draw untextured polygons
1901 setPolyF3(poly);
1902 // set XY's in the GPU packet 0-1-2
1903 poly->x0 = sxy0.vx;
1904 poly->y0 = sxy0.vy;
1905 poly->x1 = sxy1.vx;
1906 poly->y1 = sxy1.vy;
1907 poly->x2 = sxy2.vx;
1908 poly->y2 = sxy2.vy;
1909
1910 // Flat shaded so give each vertex the same colour
1911 if (selFace == i) {
1912 setRGB0(poly, selPRed, selPGreen, selPBlue);
1913 } else {
1914 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
1915 }
1916
1917 // Put it into the global ot at the correct place
1918 myAddPrimClip(avgz, drawpacket);
1919 // advance the global packet pointer by correct amount
1920 myAddPacket(sizeof(POLY_F3));
1921 } else {
1922 POLY_F3 *poly = (POLY_F3 *)drawpacket;
1923 // Draw untextured polygons
1924 setPolyF3(poly);
1925 // set XY's in the GPU packet 0-1-2
1926 poly->x0 = sxy0.vx;
1927 poly->y0 = sxy0.vy;
1928 poly->x1 = sxy1.vx;
1929 poly->y1 = sxy1.vy;
1930 poly->x2 = sxy2.vx;
1931 poly->y2 = sxy2.vy;
1932
1933 // No light source calculation
1934 // So just set base colour
1935 setRGB0(poly, rgbIn.r, rgbIn.g, rgbIn.b);
1936 // Put it into the global ot at the correct place
1937 myAddPrimClip(avgz, drawpacket);
1938 // advance the global packet pointer by correct amount
1939 myAddPacket(sizeof(POLY_F3));
1940 }
1941 }
1942 }
1943 }
1944 }
1945
1946 // Gouraud, Textured, Lit Triangles
drawGTL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)1947 void drawGTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
1948 SVECTOR *n0;
1949 SVECTOR *n1;
1950 SVECTOR *n2;
1951 SVECTORPC *v0;
1952 SVECTORPC *v1;
1953 SVECTORPC *v2;
1954 SVECTOR *ntemp;
1955
1956 // uint32 num = min( n, 10 ); // do a maximum of 10 polygons
1957 uint32 num = n;
1958 uint16 uu0, uu1, uu2;
1959 uint16 vv0, vv1, vv2;
1960 uint32 tmp;
1961 uint8 ctmp;
1962 int32 p, flag;
1963 uint32 i;
1964 uint32 *pPoly;
1965 int32 z0, z1, z2;
1966 SVECTORPC sxy0, sxy1, sxy2, stemp;
1967 SVECTORPC sxyn0, sxyn1, sxyn2;
1968 SVECTORPC sn0, sn1, sn2;
1969 uint32 uv0, uv1, uv2;
1970
1971 // Base colour for gouraud shading computation
1972 // Could easily be specified per polygon
1973 CVECTOR rgbIn = {128, 128, 128, 0};
1974 CVECTOR rgb0 = {0, 0, 0, 0};
1975 CVECTOR rgb1 = {0, 0, 0, 0};
1976 CVECTOR rgb2 = {0, 0, 0, 0};
1977
1978 pPoly = polyStart;
1979 // Loop over each polygon
1980 for (i = 0; i < num; i++) {
1981 // Structure is :
1982 // v0, u0
1983 // v1, u1
1984 // v2, u2
1985 // v0 | n0
1986 // v1 | n1
1987 // v2 | n2
1988 uv0 = *pPoly++;
1989 vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
1990 uu0 = (uint16)(uv0 & 0xFFFF);
1991
1992 uv1 = *pPoly++;
1993 vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
1994 uu1 = (uint16)(uv1 & 0xFFFF);
1995
1996 uv2 = *pPoly++;
1997 vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
1998 uu2 = (uint16)(uv2 & 0xFFFF);
1999
2000 tmp = *pPoly++;
2001 v0 = pVertex + (tmp >> 16);
2002 n0 = pNormal + (tmp & 0xFFFF);
2003
2004 tmp = *pPoly++;
2005 v1 = pVertex + (tmp >> 16);
2006 n1 = pNormal + (tmp & 0xFFFF);
2007
2008 tmp = *pPoly++;
2009 v2 = pVertex + (tmp >> 16);
2010 n2 = pNormal + (tmp & 0xFFFF);
2011
2012 // Now do RotTransPers3 on the vectors
2013 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2014 gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
2015 z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2016
2017 // test the return value of flag
2018 if (flag & 0x80000000)
2019 continue;
2020
2021 gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
2022 z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2023 // test the return value of flag
2024 if (flag & 0x80000000)
2025 continue;
2026
2027 gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
2028 z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2029 // test the return value of flag
2030 if (flag & 0x80000000)
2031 continue;
2032
2033 // Give the GTE some time to recover
2034 int32 avgz;
2035 gte_AverageZ3_pc(z0, z1, z2, &avgz);
2036
2037 // Do we want to do back face removal ?
2038 if (_removeBackface) {
2039 // use winding order of the polygons
2040 // e.g. NormalClip which is cross product of screen vectors
2041 if (_useWindingOrder) {
2042 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
2043 // Drawing back facings polys requires making them have
2044 // clockwise winding order as by definition they have
2045 // anti-clockwise winding order
2046 if (flag < 0) {
2047 if (_drawBface) {
2048 stemp = sxy1;
2049 sxy1 = sxy2;
2050 sxy2 = stemp;
2051 ntemp = n1;
2052 n1 = n2;
2053 n2 = ntemp;
2054 flag = uv1;
2055 uv1 = uv2;
2056 uv2 = flag;
2057 } else {
2058 // Skip this polygon
2059 continue;
2060 }
2061 } else if (flag == 0)
2062 continue; // ignore zero-area polygons
2063 }
2064
2065 // TODO
2066 // dot product of viewing direction and polygon normal
2067 // will require generation of polygon normal from vertex normals
2068 // and transformation of the normal to world space
2069 }
2070
2071 // Set the RGB colours
2072 if (_drawLit) {
2073 // Do the full gouraud computation
2074 // NormalColorCol3( n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2 );
2075 LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
2076 int32 cval;
2077
2078 if (!_drawGouraud) {
2079 // For flat shading mode take the average RGB for the face
2080 // Could/should use something like AVSZ3
2081 // but hell whats a divide by 3 between friends (~30 cycles?)
2082 cval = ((rgb0.r + rgb1.r + rgb2.r) / 3);
2083 if (cval > 255)
2084 cval = 255;
2085 rgb0.r = (uint8)cval;
2086
2087 cval = ((rgb0.g + rgb1.g + rgb2.g) / 3);
2088 if (cval > 255)
2089 cval = 255;
2090 rgb0.g = (uint8)cval;
2091
2092 cval = ((rgb0.b + rgb1.b + rgb2.b) / 3);
2093 if (cval > 255)
2094 cval = 255;
2095 rgb0.b = (uint8)cval;
2096 }
2097 }
2098
2099 // Put normal lines in list before wireframe
2100 // so should be drawn in front of wireframe triangles
2101 if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
2102 // Do coord transform on the scaled normal vectors + v0
2103 sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
2104 sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
2105 sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
2106 sn1.vx = (int16)(v1->vx + (-n1->vx >> _normalScale));
2107 sn1.vy = (int16)(v1->vy + (-n1->vy >> _normalScale));
2108 sn1.vz = (int16)(v1->vz + (-n1->vz >> _normalScale));
2109 sn2.vx = (int16)(v2->vx + (-n2->vx >> _normalScale));
2110 sn2.vy = (int16)(v2->vy + (-n2->vy >> _normalScale));
2111 sn2.vz = (int16)(v2->vz + (-n2->vz >> _normalScale));
2112 // z0 = RotTransPers3( &sn0, &sn1, &sn2,
2113 // &sxyn0, &sxyn1, &sxyn2, &p, &flag );
2114 gte_RotTransPers3_pc(&sn0, &sn1, &sn2, &sxyn0, &sxyn1, &sxyn2, &p, &flag, &z0);
2115 // Normal 0
2116 LINE_G2 *line = (LINE_G2 *)drawpacket;
2117 setLineG2(line);
2118 line->x0 = sxy0.vx;
2119 line->y0 = sxy0.vy;
2120 line->x1 = sxyn0.vx;
2121 line->y1 = sxyn0.vy;
2122 if (selFace == i) {
2123 // Bright red
2124 setRGB0(line, 255, 0, 0);
2125 // Bright white
2126 setRGB1(line, 255, 255, 255);
2127 } else {
2128 // Bright blue
2129 setRGB0(line, 0, 0, 255);
2130 // Bright white
2131 setRGB1(line, 255, 255, 255);
2132 }
2133 // Put it into the global ot at the correct place
2134 myAddPrimClip(avgz, drawpacket);
2135 // advance the global packet pointer by correct amount
2136 myAddPacket(sizeof(LINE_G2));
2137
2138 // Normal 1
2139 line = (LINE_G2 *)drawpacket;
2140 setLineG2(line);
2141 line->x0 = sxy0.vx;
2142 line->y0 = sxy0.vy;
2143 line->x1 = sxyn1.vx;
2144 line->y1 = sxyn1.vy;
2145 if (selFace == i) {
2146 // Bright red
2147 setRGB0(line, 255, 0, 0);
2148 // Bright white
2149 setRGB1(line, 255, 255, 255);
2150 } else {
2151 // Bright blue
2152 setRGB0(line, 0, 0, 255);
2153 // Bright white
2154 setRGB1(line, 255, 255, 255);
2155 }
2156 // Put it into the global ot at the correct place
2157 myAddPrimClip(avgz, drawpacket);
2158 // advance the global packet pointer by correct amount
2159 myAddPacket(sizeof(LINE_G2));
2160
2161 // Normal 2
2162 line = (LINE_G2 *)drawpacket;
2163 setLineG2(line);
2164 line->x0 = sxy0.vx;
2165 line->y0 = sxy0.vy;
2166 line->x1 = sxyn2.vx;
2167 line->y1 = sxyn2.vy;
2168 if (selFace == i) {
2169 // Bright red
2170 setRGB0(line, 255, 0, 0);
2171 // Bright white
2172 setRGB1(line, 255, 255, 255);
2173 } else {
2174 // Bright blue
2175 setRGB0(line, 0, 0, 255);
2176 // Bright white
2177 setRGB1(line, 255, 255, 255);
2178 }
2179 // Put it into the global ot at the correct place
2180 myAddPrimClip(avgz, drawpacket);
2181 // advance the global packet pointer by correct amount
2182 myAddPacket(sizeof(LINE_G2));
2183 }
2184
2185 // Put wireframe triangles in list before textured ones
2186 // so should be in front of textured ones
2187 if ((_drawWfrm) || (selFace == i)) {
2188 // Draw a wireframe that responds to lighting
2189 if (_drawLit) {
2190 LINE_G4 *line = (LINE_G4 *)drawpacket;
2191 setLineG4(line);
2192 int32 cval;
2193 if (_drawGouraud) {
2194 // Give each vertex a seperate colour
2195 // Compute the colour scaling and clip it
2196 if (rgbIn.r != 0) {
2197 cval = ((wfrmRed * rgb0.r) / rgbIn.r);
2198 if (cval > 255)
2199 cval = 255;
2200 ctmp = (uint8)cval;
2201 line->r0 = ctmp;
2202 line->r3 = ctmp;
2203
2204 cval = ((wfrmRed * rgb1.r) / rgbIn.r);
2205 if (cval > 255)
2206 cval = 255;
2207 ctmp = (uint8)cval;
2208 line->r1 = ctmp;
2209
2210 cval = ((wfrmRed * rgb2.r) / rgbIn.r);
2211 if (cval > 255)
2212 cval = 255;
2213 ctmp = (uint8)cval;
2214 line->r2 = ctmp;
2215 } else {
2216 line->r0 = 0;
2217 line->r3 = 0;
2218 line->r1 = 0;
2219 line->r2 = 0;
2220 }
2221
2222 if (rgbIn.g != 0) {
2223 cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
2224 if (cval > 255)
2225 cval = 255;
2226 ctmp = (uint8)cval;
2227 line->g0 = ctmp;
2228 line->g3 = ctmp;
2229 cval = ((wfrmGreen * rgb1.g) / rgbIn.g);
2230 if (cval > 255)
2231 cval = 255;
2232 ctmp = (uint8)cval;
2233 line->g1 = ctmp;
2234 cval = ((wfrmGreen * rgb2.g) / rgbIn.g);
2235 if (cval > 255)
2236 cval = 255;
2237 ctmp = (uint8)cval;
2238 line->g2 = ctmp;
2239 } else {
2240 line->g0 = 0;
2241 line->g3 = 0;
2242 line->g1 = 0;
2243 line->g2 = 0;
2244 }
2245 if (rgbIn.b != 0) {
2246 cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
2247 if (cval > 255)
2248 cval = 255;
2249 ctmp = (uint8)cval;
2250 line->b0 = ctmp;
2251 line->b3 = ctmp;
2252 cval = ((wfrmBlue * rgb1.b) / rgbIn.b);
2253 if (cval > 255)
2254 cval = 255;
2255 ctmp = (uint8)cval;
2256 line->b1 = ctmp;
2257 cval = ((wfrmBlue * rgb2.b) / rgbIn.b);
2258 if (cval > 255)
2259 cval = 255;
2260 ctmp = (uint8)cval;
2261 line->b2 = ctmp;
2262 } else {
2263 line->b0 = 0;
2264 line->b3 = 0;
2265 line->b1 = 0;
2266 line->b2 = 0;
2267 }
2268 } else {
2269 // Compute the colour scaling and clip it
2270 // Flat shading so give the same colour to each vertex
2271 if (rgbIn.r != 0) {
2272 cval = ((wfrmRed * rgb0.r) / rgbIn.r);
2273 if (cval > 255)
2274 cval = 255;
2275 ctmp = (uint8)cval;
2276 } else
2277 ctmp = 0;
2278 line->r0 = ctmp;
2279 line->r1 = ctmp;
2280 line->r2 = ctmp;
2281 line->r3 = ctmp;
2282
2283 if (rgbIn.g != 0) {
2284 cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
2285 if (cval > 255)
2286 cval = 255;
2287 ctmp = (uint8)cval;
2288 } else
2289 ctmp = 0;
2290 line->g0 = ctmp;
2291 line->g1 = ctmp;
2292 line->g2 = ctmp;
2293 line->g3 = ctmp;
2294
2295 if (rgbIn.b != 0) {
2296 cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
2297 if (cval > 255)
2298 cval = 255;
2299 ctmp = (uint8)cval;
2300 } else
2301 ctmp = 0;
2302
2303 line->b0 = ctmp;
2304 line->b1 = ctmp;
2305 line->b2 = ctmp;
2306 line->b3 = ctmp;
2307 }
2308
2309 if (selFace == i) {
2310 setRGB0(line, selWRed, selWGreen, selWBlue);
2311 setRGB1(line, selWRed, selWGreen, selWBlue);
2312 setRGB2(line, selWRed, selWGreen, selWBlue);
2313 setRGB3(line, selWRed, selWGreen, selWBlue);
2314 }
2315 // set XY's in the GPU packet 0-1-2-3
2316 line->x0 = sxy0.vx;
2317 line->y0 = sxy0.vy;
2318 line->x1 = sxy1.vx;
2319 line->y1 = sxy1.vy;
2320 line->x2 = sxy2.vx;
2321 line->y2 = sxy2.vy;
2322 line->x3 = sxy0.vx;
2323 line->y3 = sxy0.vy;
2324 // Put it into the global ot at the correct place
2325 myAddPrimClip(avgz, drawpacket);
2326 // advance the global packet pointer by correct amount
2327 myAddPacket(sizeof(LINE_G4));
2328 } else {
2329 LINE_F4 *line = (LINE_F4 *)drawpacket;
2330 setLineF4(line);
2331 if (selFace == i)
2332 setRGB0(line, selWRed, selWGreen, selWBlue);
2333 else
2334 setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
2335 // set XY's in the GPU packet 0-1-2-3
2336 line->x0 = sxy0.vx;
2337 line->y0 = sxy0.vy;
2338 line->x1 = sxy1.vx;
2339 line->y1 = sxy1.vy;
2340 line->x2 = sxy2.vx;
2341 line->y2 = sxy2.vy;
2342 line->x3 = sxy0.vx;
2343 line->y3 = sxy0.vy;
2344 // Put it into the global ot at the correct place
2345 myAddPrimClip(avgz, drawpacket);
2346 // advance the global packet pointer by correct amount
2347 myAddPacket(sizeof(LINE_F4));
2348 }
2349 }
2350
2351 // Draw textured version behind the wireframe
2352 if ((_drawPolys) || (selFace == i)) {
2353 if (_drawTxture) {
2354 // Set the RGB colours
2355 if ((_drawLit) && (_drawGouraud)) {
2356 POLY_GT3 *poly = (POLY_GT3 *)drawpacket;
2357 setPolyGT3(poly);
2358 // set XY's in the GPU packet 0-1-2
2359 poly->x0 = sxy0.vx;
2360 poly->y0 = sxy0.vy;
2361 poly->x1 = sxy1.vx;
2362 poly->y1 = sxy1.vy;
2363 poly->x2 = sxy2.vx;
2364 poly->y2 = sxy2.vy;
2365
2366 setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
2367 if (selFace == i) {
2368 setRGB0(poly, selPRed, selPGreen, selPBlue);
2369 setRGB1(poly, selPRed, selPGreen, selPBlue);
2370 setRGB2(poly, selPRed, selPGreen, selPBlue);
2371 } else {
2372 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
2373 setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
2374 setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
2375 }
2376
2377 // Put it into the global ot at the correct place
2378 myAddPrimClip(avgz, drawpacket);
2379 // advance the global packet pointer by correct amount
2380 myAddPacket(sizeof(POLY_GT3));
2381 } else {
2382 POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
2383 setPolyFT3(poly);
2384 // set XY's in the GPU packet 0-1-2
2385 poly->x0 = sxy0.vx;
2386 poly->y0 = sxy0.vy;
2387 poly->x1 = sxy1.vx;
2388 poly->y1 = sxy1.vy;
2389 poly->x2 = sxy2.vx;
2390 poly->y2 = sxy2.vy;
2391
2392 setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
2393
2394 if (_drawLit) {
2395 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
2396 } else {
2397 // No light source calculation
2398 // So just set base colour
2399 setRGB0(poly, rgbIn.r, rgbIn.g, rgbIn.b);
2400 }
2401 if (selFace == i) {
2402 setRGB0(poly, selPRed, selPGreen, selPBlue);
2403 }
2404
2405 // Put it into the global ot at the correct place
2406 myAddPrimClip(avgz, drawpacket);
2407 // advance the global packet pointer by correct amount
2408 myAddPacket(sizeof(POLY_FT3));
2409 }
2410 } else {
2411 // Set the RGB colours
2412 if (_drawLit) {
2413 if (_drawGouraud) {
2414 POLY_G3 *poly = (POLY_G3 *)drawpacket;
2415 // Draw untextured polygons
2416 setPolyG3(poly);
2417 // set XY's in the GPU packet 0-1-2
2418 poly->x0 = sxy0.vx;
2419 poly->y0 = sxy0.vy;
2420 poly->x1 = sxy1.vx;
2421 poly->y1 = sxy1.vy;
2422 poly->x2 = sxy2.vx;
2423 poly->y2 = sxy2.vy;
2424
2425 if (selFace == i) {
2426 setRGB0(poly, selPRed, selPGreen, selPBlue);
2427 setRGB1(poly, selPRed, selPGreen, selPBlue);
2428 setRGB2(poly, selPRed, selPGreen, selPBlue);
2429 } else {
2430 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
2431 setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
2432 setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
2433 }
2434
2435 // Put it into the global ot at the correct place
2436 myAddPrimClip(avgz, drawpacket);
2437 // advance the global packet pointer by correct amount
2438 myAddPacket(sizeof(POLY_G3));
2439 } else {
2440 POLY_F3 *poly = (POLY_F3 *)drawpacket;
2441 // Draw untextured polygons
2442 setPolyF3(poly);
2443 // set XY's in the GPU packet 0-1-2
2444 poly->x0 = sxy0.vx;
2445 poly->y0 = sxy0.vy;
2446 poly->x1 = sxy1.vx;
2447 poly->y1 = sxy1.vy;
2448 poly->x2 = sxy2.vx;
2449 poly->y2 = sxy2.vy;
2450
2451 // Flat shaded so give each vertex the same colour
2452 if (selFace == i) {
2453 setRGB0(poly, selPRed, selPGreen, selPBlue);
2454 } else {
2455 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
2456 }
2457
2458 // Put it into the global ot at the correct place
2459 myAddPrimClip(avgz, drawpacket);
2460 // advance the global packet pointer by correct amount
2461 myAddPacket(sizeof(POLY_F3));
2462 }
2463 } else {
2464 POLY_F3 *poly = (POLY_F3 *)drawpacket;
2465 // Draw untextured polygons
2466 setPolyF3(poly);
2467 // set XY's in the GPU packet 0-1-2
2468 poly->x0 = sxy0.vx;
2469 poly->y0 = sxy0.vy;
2470 poly->x1 = sxy1.vx;
2471 poly->y1 = sxy1.vy;
2472 poly->x2 = sxy2.vx;
2473 poly->y2 = sxy2.vy;
2474
2475 // No light source calculation
2476 // So just set base colour
2477 if (selFace == i) {
2478 setRGB0(poly, selPRed, selPGreen, selPBlue);
2479 } else {
2480 setRGB0(poly, unlitPoly.r, unlitPoly.g, unlitPoly.b);
2481 poly->code = unlitPoly.cd;
2482 }
2483 // Put it into the global ot at the correct place
2484 myAddPrimClip(avgz, drawpacket);
2485 // advance the global packet pointer by correct amount
2486 myAddPacket(sizeof(POLY_F3));
2487 }
2488 }
2489 }
2490 }
2491 }
2492
2493 // Simple flat untextured triangles
2494 // draw backfacing triangles as well
2495 // the colour is set by a global variable
2496
drawTRI3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)2497 void drawTRI3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
2498 SVECTORPC *v0;
2499 SVECTORPC *v1;
2500 SVECTORPC *v2;
2501
2502 // uint32 num = min( n, 10 ); // do a maximum of 10 polygons
2503 uint32 num = n;
2504 int32 p, flag;
2505 uint32 i;
2506 uint32 *pPoly;
2507 int32 z0, z1, z2;
2508 SVECTORPC sxy0, sxy1, sxy2, stemp;
2509 uint32 tmp;
2510
2511 pPoly = polyStart;
2512 // Loop over each polygon
2513 for (i = 0; i < num; i++) {
2514 // Each polygon is 2 32-bit WORDS
2515 // Bit 31 ----> Bit 0
2516 //
2517 // 16-bits | 16-bits
2518 // --------------------------
2519 // v1 | v0
2520 // pad | v2
2521
2522 tmp = *pPoly++;
2523 v0 = pVertex + (tmp & 0xFFFF);
2524 v1 = pVertex + (tmp >> 16);
2525
2526 tmp = *pPoly++;
2527 v2 = pVertex + (tmp & 0xFFFF);
2528
2529 // Now do RotTransPers3 on the vectors
2530 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2531 gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
2532 z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2533
2534 // test the return value of flag
2535 if (flag & 0x80000000)
2536 continue;
2537
2538 gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
2539 z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2540 // test the return value of flag
2541 if (flag & 0x80000000)
2542 continue;
2543
2544 gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
2545 z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
2546 // test the return value of flag
2547 if (flag & 0x80000000)
2548 continue;
2549
2550 // Give the GTE some time to recover
2551 int32 avgz;
2552 gte_AverageZ3_pc(z0, z1, z2, &avgz);
2553
2554 // See what winding order this polygon is ?
2555 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
2556
2557 // Drawing back facing polys requires making them have
2558 // clockwise winding order as by definition they have
2559 // anti-clockwise winding order
2560 if (flag < 0) {
2561 stemp = sxy1;
2562 sxy1 = sxy2;
2563 sxy2 = stemp;
2564 }
2565
2566 // Put wireframe triangles in list before textured ones
2567 // so should be in front of textured ones
2568 if ((_drawWfrm) || (selFace == i)) {
2569 LINE_F4 *line = (LINE_F4 *)drawpacket;
2570 setLineF4(line);
2571 // set XY's in the GPU packet 0-1-2-3
2572 line->x0 = sxy0.vx;
2573 line->y0 = sxy0.vy;
2574 line->x1 = sxy1.vx;
2575 line->y1 = sxy1.vy;
2576 line->x2 = sxy2.vx;
2577 line->y2 = sxy2.vy;
2578 line->x3 = sxy0.vx;
2579 line->y3 = sxy0.vy;
2580 if (selFace == i)
2581 setRGB0(line, selWRed, selWGreen, selWBlue);
2582 else
2583 setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
2584 // Put it into the global ot at the correct place
2585 myAddPrimClip(avgz, drawpacket);
2586 // advance the global packet pointer by correct amount
2587 myAddPacket(sizeof(LINE_F4));
2588 }
2589
2590 // Draw polygon version behind the wireframe
2591 if ((_drawPolys) || (selFace == i)) {
2592 // Draw untextured polygons
2593 TPOLY_F3 *poly = (TPOLY_F3 *)drawpacket;
2594 setTPolyF3(poly);
2595 setTABRMode(poly, 2); // 2 = back - front
2596 setTSemiTrans(poly, 1); // 1 = enable semi-transparency
2597
2598 // set XY's in the GPU packet 0-1-2
2599 poly->x0 = sxy0.vx;
2600 poly->y0 = sxy0.vy;
2601 poly->x1 = sxy1.vx;
2602 poly->y1 = sxy1.vy;
2603 poly->x2 = sxy2.vx;
2604 poly->y2 = sxy2.vy;
2605
2606 // Set the RGB colours
2607 // No light source calculation
2608 // So just set base colour
2609 if (selFace == i) {
2610 setRGB0(poly, selPRed, selPGreen, selPBlue);
2611 poly->code = selPAlpha;
2612 } else {
2613 setRGB0(poly, unlitPoly.r, unlitPoly.g, unlitPoly.b);
2614 poly->code = unlitPoly.cd;
2615 }
2616
2617 // Put it into the global ot at the correct place
2618 myAddPrimClip(avgz, drawpacket);
2619 // advance the global packet pointer by correct amount
2620 myAddPacket(sizeof(TPOLY_F3));
2621 }
2622 }
2623 }
2624
2625 #endif // #if CD_MODE == 0
2626
2627 // Flat, Un-Textured, Self-Luminous, triangles
fastDrawFUS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)2628 void fastDrawFUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
2629 SVECTORPC *v0;
2630 SVECTORPC *v1;
2631 SVECTORPC *v2;
2632
2633 int32 flag;
2634 uint32 i;
2635 uint32 *pPoly;
2636 int32 z0;
2637 SVECTORPC sxy0, sxy1, sxy2;
2638 CVECTOR *rgbIn;
2639 uint32 tmp;
2640
2641 pPoly = polyStart;
2642 // Loop over each polygon
2643 for (i = 0; i < n; i++) {
2644 // Structure is :
2645 // 0x20 | B | G | R
2646 // v1 | v0
2647 // pad | v2
2648 rgbIn = (CVECTOR *)pPoly++;
2649
2650 if (deadObject) {
2651 rgbIn = &deadObjectColour;
2652 }
2653
2654 tmp = *pPoly++;
2655 v0 = pVertex + (tmp & 0xFFFF);
2656 v1 = pVertex + (tmp >> 16);
2657
2658 tmp = *pPoly++;
2659 v2 = pVertex + (tmp & 0xFFFF);
2660
2661 // Now do RotTransPers3 on the vectors
2662 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2663 // gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
2664
2665 // test the return value of flag
2666 // The vertices have been pre-transformed into screen space and stored in the vertex pool
2667 // The flag value is set to 0x8000 or 0 in the pad structure
2668 if (v0->pad != 0)
2669 continue;
2670 if (v1->pad != 0)
2671 continue;
2672 if (v2->pad != 0)
2673 continue;
2674
2675 // use winding order of the polygons
2676 // e.g. NormalClip which is cross product of screen vectors
2677 sxy0.vx = v0->vx;
2678 sxy0.vy = v0->vy;
2679 sxy1.vx = v1->vx;
2680 sxy1.vy = v1->vy;
2681 sxy2.vx = v2->vx;
2682 sxy2.vy = v2->vy;
2683
2684 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
2685 if (flag <= 0)
2686 continue;
2687
2688 // Draw untextured polygons
2689 POLY_F3 *poly = (POLY_F3 *)drawpacket;
2690 setPolyF3(poly);
2691 // set XY's in the GPU packet 0-1-2
2692 poly->x0 = sxy0.vx;
2693 poly->y0 = sxy0.vy;
2694 poly->x1 = sxy1.vx;
2695 poly->y1 = sxy1.vy;
2696 poly->x2 = sxy2.vx;
2697 poly->y2 = sxy2.vy;
2698
2699 // Set the RGB colours
2700 // No light source calculation
2701 // So just set base colour
2702 setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
2703
2704 // Give the GTE some time to recover
2705 gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
2706
2707 // Put it into the global ot at the correct place
2708 myAddPrimClip(z0, drawpacket);
2709 // advance the global packet pointer by correct amount
2710 myAddPacket(sizeof(POLY_F3));
2711 }
2712 }
2713
2714 // Fast: no options, Gouraud, Un-Textured, Self-Luminous, triangles
fastDrawGUS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)2715 void fastDrawGUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
2716 SVECTORPC *v0;
2717 SVECTORPC *v1;
2718 SVECTORPC *v2;
2719
2720 uint32 tmp;
2721 int32 flag;
2722 uint32 i;
2723 uint32 *pPoly;
2724 int32 z0;
2725 SVECTORPC sxy0, sxy1, sxy2;
2726
2727 // Base colour for gouraud shading computation
2728 // Could easily be specified per polygon
2729 CVECTOR *rgb0;
2730 CVECTOR *rgb1;
2731 CVECTOR *rgb2;
2732
2733 pPoly = polyStart;
2734 // Loop over each polygon
2735 for (i = 0; i < n; i++) {
2736 // Structure is :
2737 // 8-bits | 8-bits | 8-bits | 8-bits
2738 // 0x30 | Blue0 | Green0 | Red0
2739 // 0x30 | Blue1 | Green1 | Red1
2740 // 0x30 | Blue2 | Green2 | Red2
2741 // 16-bits | 8-bits | 8-bits
2742 // --------------------------
2743 // v1 | v0
2744 // pad | v2
2745 rgb0 = (CVECTOR *)pPoly++;
2746 rgb1 = (CVECTOR *)pPoly++;
2747 rgb2 = (CVECTOR *)pPoly++;
2748
2749 if (deadObject) {
2750 rgb0 = &deadObjectColour;
2751 rgb1 = &deadObjectColour;
2752 rgb2 = &deadObjectColour;
2753 }
2754
2755 tmp = *pPoly++;
2756 v0 = pVertex + (tmp & 0xFFFF);
2757 v1 = pVertex + (tmp >> 16);
2758
2759 tmp = *pPoly++;
2760 v2 = pVertex + (tmp & 0xFFFF);
2761
2762 // Now do RotTransPers3 on the vectors
2763 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2764 // gte_RotTransPers3(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
2765
2766 // test the return value of flag
2767 // The vertices have been pre-transformed into screen space and stored in the vertex pool
2768 // The flag value is set to 0x8000 or 0 in the pad structure
2769 if (v0->pad != 0)
2770 continue;
2771 if (v1->pad != 0)
2772 continue;
2773 if (v2->pad != 0)
2774 continue;
2775
2776 // use winding order of the polygons
2777 // e.g. NormalClip which is cross product of screen vectors
2778 sxy0.vx = v0->vx;
2779 sxy0.vy = v0->vy;
2780 sxy1.vx = v1->vx;
2781 sxy1.vy = v1->vy;
2782 sxy2.vx = v2->vx;
2783 sxy2.vy = v2->vy;
2784
2785 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
2786 if (flag <= 0)
2787 continue;
2788
2789 POLY_G3 *poly = (POLY_G3 *)drawpacket;
2790 // Draw untextured polygons
2791 setPolyG3(poly);
2792 // set XY's in the GPU packet 0-1-2
2793 poly->x0 = sxy0.vx;
2794 poly->y0 = sxy0.vy;
2795 poly->x1 = sxy1.vx;
2796 poly->y1 = sxy1.vy;
2797 poly->x2 = sxy2.vx;
2798 poly->y2 = sxy2.vy;
2799
2800 setRGB0(poly, rgb0->r, rgb0->g, rgb0->b);
2801 setRGB1(poly, rgb1->r, rgb1->g, rgb1->b);
2802 setRGB2(poly, rgb2->r, rgb2->g, rgb2->b);
2803
2804 // Give the GTE some time to recover
2805 gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
2806
2807 // Put it into the global ot at the correct place
2808 myAddPrimClip(z0, drawpacket);
2809 // advance the global packet pointer by correct amount
2810 myAddPacket(sizeof(POLY_G3));
2811 }
2812 }
2813
2814 // Fast: no options, Flat, Textured, Self-Luminous Triangles
fastDrawFTS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)2815 void fastDrawFTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
2816 SVECTORPC *v0;
2817 SVECTORPC *v1;
2818 SVECTORPC *v2;
2819
2820 uint16 uu0, uu1, uu2;
2821 uint16 vv0, vv1, vv2;
2822 uint32 tmp;
2823 int32 flag;
2824 uint32 i;
2825 uint32 *pPoly;
2826 int32 z0;
2827 SVECTORPC sxy0, sxy1, sxy2;
2828 uint32 uv0, uv1, uv2;
2829
2830 // Base colour for shading computation
2831 // Could easily be specified per polygon
2832 CVECTOR *rgbIn;
2833
2834 pPoly = polyStart;
2835 // Loop over each polygon
2836 for (i = 0; i < n; i++) {
2837 // Structure is :
2838 // Bit 31 ----> Bit 0
2839 //
2840 // 8-bits | 8-bits | 8-bits | 8-bits
2841 // 0x24 | Blue | Green | Red
2842 // 16-bits | 16-bits
2843 // --------------------------
2844 // v0 | u0
2845 // v1 | u1
2846 // v2 | u2
2847 // --------------------------
2848 // pad | v0
2849 // v2 | v1
2850 rgbIn = (CVECTOR *)pPoly++;
2851
2852 if (deadObject == 1) {
2853 rgbIn = &deadObjectColour;
2854 }
2855
2856 uv0 = *pPoly++;
2857 vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
2858 uu0 = (uint16)(uv0 & 0xFFFF);
2859
2860 uv1 = *pPoly++;
2861 vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
2862 uu1 = (uint16)(uv1 & 0xFFFF);
2863
2864 uv2 = *pPoly++;
2865 vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
2866 uu2 = (uint16)(uv2 & 0xFFFF);
2867
2868 tmp = *pPoly++;
2869 v0 = pVertex + (tmp & 0xFFFF);
2870
2871 tmp = *pPoly++;
2872 v1 = pVertex + (uint)(tmp & 0xFFFF);
2873 v2 = pVertex + (uint)(tmp >> 16);
2874
2875 // Now do RotTransPers3 on the vectors
2876 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2877 // gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
2878
2879 // test the return value of flag
2880 // The vertices have been pre-transformed into screen space and stored in the vertex pool
2881 // The flag value is set to 0x8000 or 0 in the pad structure
2882 if (v0->pad != 0)
2883 continue;
2884 if (v1->pad != 0)
2885 continue;
2886 if (v2->pad != 0)
2887 continue;
2888
2889 // use winding order of the polygons
2890 // e.g. NormalClip which is cross product of screen vectors
2891 sxy0.vx = v0->vx;
2892 sxy0.vy = v0->vy;
2893 sxy1.vx = v1->vx;
2894 sxy1.vy = v1->vy;
2895 sxy2.vx = v2->vx;
2896 sxy2.vy = v2->vy;
2897
2898 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
2899 if (flag <= 0)
2900 continue;
2901
2902 POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
2903 setPolyFT3(poly);
2904 // set XY's in the GPU packet 0-1-2
2905 poly->x0 = sxy0.vx;
2906 poly->y0 = sxy0.vy;
2907 poly->x1 = sxy1.vx;
2908 poly->y1 = sxy1.vy;
2909 poly->x2 = sxy2.vx;
2910 poly->y2 = sxy2.vy;
2911
2912 setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
2913
2914 // No light source calculation so just set base colour
2915 setRGB0(poly, rgbIn->r, rgbIn->b, rgbIn->b);
2916
2917 // Give the GTE some time to recover
2918 gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
2919
2920 // Put it into the global ot at the correct place
2921 myAddPrimClip(z0, drawpacket);
2922 // advance the global packet pointer by correct amount
2923 myAddPacket(sizeof(POLY_FT3));
2924 }
2925 }
2926
2927 // Fast: no options, Gouraud, Textured, Self-Luminous Triangles
fastDrawGTS3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)2928 void fastDrawGTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
2929 SVECTORPC *v0;
2930 SVECTORPC *v1;
2931 SVECTORPC *v2;
2932
2933 uint16 uu0, uu1, uu2;
2934 uint16 vv0, vv1, vv2;
2935 uint32 tmp;
2936 int32 flag;
2937 uint32 i;
2938 uint32 *pPoly;
2939 int32 z0;
2940 SVECTORPC sxy0, sxy1, sxy2;
2941 uint32 uv0, uv1, uv2;
2942
2943 // gouraud colours
2944 CVECTOR *rgb0;
2945 CVECTOR *rgb1;
2946 CVECTOR *rgb2;
2947
2948 pPoly = polyStart;
2949 // Loop over each polygon
2950 for (i = 0; i < n; i++) {
2951 // Structure is :
2952 // 8-bits | 8-bits | 8-bits | 8-bits
2953 // 0x34 | Blue0 | Green0 | Red0
2954 // 0x34 | Blue1 | Green1 | Red1
2955 // 0x34 | Blue2 | Green2 | Red2
2956 // 16-bits | 16-bits
2957 // --------------------------
2958 // v0 | u0
2959 // v1 | u1
2960 // v2 | u2
2961 // --------------------------
2962 // pad | v0
2963 // v2 | v1
2964 rgb0 = (CVECTOR *)pPoly++;
2965 rgb1 = (CVECTOR *)pPoly++;
2966 rgb2 = (CVECTOR *)pPoly++;
2967
2968 if (deadObject) {
2969 rgb0 = &deadObjectColour;
2970 rgb1 = &deadObjectColour;
2971 rgb2 = &deadObjectColour;
2972 }
2973
2974 uv0 = *pPoly++;
2975 vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
2976 uu0 = (uint16)(uv0 & 0xFFFF);
2977
2978 uv1 = *pPoly++;
2979 vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
2980 uu1 = (uint16)(uv1 & 0xFFFF);
2981
2982 uv2 = *pPoly++;
2983 vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
2984 uu2 = (uint16)(uv2 & 0xFFFF);
2985
2986 tmp = *pPoly++;
2987 v0 = pVertex + (tmp & 0xFFFF);
2988
2989 tmp = *pPoly++;
2990 v1 = pVertex + (tmp & 0xFFFF);
2991 v2 = pVertex + (tmp >> 16);
2992
2993 // Now do RotTransPers3 on the vectors
2994 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
2995 // gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
2996
2997 // test the return value of flag
2998 // The vertices have been pre-transformed into screen space and stored in the vertex pool
2999 // The flag value is set to 0x8000 or 0 in the pad structure
3000 if (v0->pad != 0)
3001 continue;
3002 if (v1->pad != 0)
3003 continue;
3004 if (v2->pad != 0)
3005 continue;
3006
3007 // use winding order of the polygons
3008 // e.g. NormalClip which is cross product of screen vectors
3009 sxy0.vx = v0->vx;
3010 sxy0.vy = v0->vy;
3011 sxy1.vx = v1->vx;
3012 sxy1.vy = v1->vy;
3013 sxy2.vx = v2->vx;
3014 sxy2.vy = v2->vy;
3015
3016 // use winding order of the polygons
3017 // e.g. NormalClip which is cross product of screen vectors
3018 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3019 if (flag <= 0)
3020 continue;
3021
3022 // Set the RGB colours
3023 POLY_GT3 *poly = (POLY_GT3 *)drawpacket;
3024 setPolyGT3(poly);
3025 // set XY's in the GPU packet 0-1-2
3026 poly->x0 = sxy0.vx;
3027 poly->y0 = sxy0.vy;
3028 poly->x1 = sxy1.vx;
3029 poly->y1 = sxy1.vy;
3030 poly->x2 = sxy2.vx;
3031 poly->y2 = sxy2.vy;
3032
3033 setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
3034
3035 setRGB0(poly, rgb0->r, rgb0->b, rgb0->b);
3036 setRGB1(poly, rgb1->r, rgb1->b, rgb1->b);
3037 setRGB2(poly, rgb2->r, rgb2->b, rgb2->b);
3038
3039 // Give the GTE some time to recover
3040 gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3041
3042 // Put it into the global ot at the correct place
3043 myAddPrimClip(z0, drawpacket);
3044
3045 // advance the global packet pointer by correct amount
3046 myAddPacket(sizeof(POLY_GT3));
3047 }
3048 }
3049
3050 // Fast: no options, Flat, Un-Textured, Lit, triangles
fastDrawFUL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)3051 void fastDrawFUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
3052 SVECTOR *n0;
3053 SVECTORPC *v0;
3054 SVECTORPC *v1;
3055 SVECTORPC *v2;
3056
3057 int32 flag;
3058 uint32 i;
3059 uint32 *pPoly;
3060 int32 z0;
3061 SVECTORPC sxy0, sxy1, sxy2;
3062 CVECTOR *rgbIn;
3063 CVECTOR rgb0;
3064 uint32 tmp;
3065
3066 pPoly = polyStart;
3067 // Loop over each polygon
3068 for (i = 0; i < n; i++) {
3069 // Structure is :
3070 // 0x20 | B | G | R
3071 // v0 | n0
3072 // v2 | v1
3073 rgbIn = (CVECTOR *)pPoly++;
3074
3075 tmp = *pPoly++;
3076 v0 = pVertex + (tmp >> 16);
3077 n0 = pNormal + (tmp & 0xFFFF);
3078
3079 tmp = *pPoly++;
3080 v2 = pVertex + (tmp >> 16);
3081 v1 = pVertex + (tmp & 0xFFFF);
3082
3083 // Now do RotTransPers3 on the vectors
3084 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
3085 // gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
3086
3087 // test the return value of flag
3088 // The vertices have been pre-transformed into screen space and stored in the vertex pool
3089 // The flag value is set to 0x8000 or 0 in the pad structure
3090 if (v0->pad != 0)
3091 continue;
3092 if (v1->pad != 0)
3093 continue;
3094 if (v2->pad != 0)
3095 continue;
3096
3097 // use winding order of the polygons
3098 // e.g. NormalClip which is cross product of screen vectors
3099 sxy0.vx = v0->vx;
3100 sxy0.vy = v0->vy;
3101 sxy1.vx = v1->vx;
3102 sxy1.vy = v1->vy;
3103 sxy2.vx = v2->vx;
3104 sxy2.vy = v2->vy;
3105
3106 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3107 if (flag <= 0)
3108 continue;
3109
3110 // Do the flat lighting computation
3111 LIGHTPOLYGON(n0, rgbIn, &rgb0);
3112
3113 // Draw untextured polygons
3114 POLY_F3 *poly = (POLY_F3 *)drawpacket;
3115 setPolyF3(poly);
3116
3117 // set XY's in the GPU packet 0-1-2
3118 poly->x0 = sxy0.vx;
3119 poly->y0 = sxy0.vy;
3120 poly->x1 = sxy1.vx;
3121 poly->y1 = sxy1.vy;
3122 poly->x2 = sxy2.vx;
3123 poly->y2 = sxy2.vy;
3124
3125 // Set the RGB colours
3126 // Flat shaded so give each vertex the same colour
3127 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
3128
3129 // Give the GTE some time to recover
3130 gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3131
3132 // Put it into the global ot at the correct place
3133 myAddPrimClip(z0, drawpacket);
3134
3135 // advance the global packet pointer by correct amount
3136 myAddPacket(sizeof(POLY_F3));
3137 }
3138 }
3139
3140 // Fast: no options, Gouraud, Un-Textured, Lit, triangles
fastDrawGUL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)3141 void fastDrawGUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
3142 SVECTOR *n0;
3143 SVECTOR *n1;
3144 SVECTOR *n2;
3145 SVECTORPC *v0;
3146 SVECTORPC *v1;
3147 SVECTORPC *v2;
3148
3149 uint32 tmp;
3150 int32 flag;
3151 uint32 i;
3152 uint32 *pPoly;
3153 int32 z0;
3154 SVECTORPC sxy0, sxy1, sxy2;
3155
3156 // Base colour for gouraud shading computation
3157 // Could easily be specified per polygon
3158 CVECTOR rgbIn = {128, 128, 128, 0};
3159 CVECTOR rgb0, rgb1, rgb2;
3160
3161 pPoly = polyStart;
3162 // Loop over each polygon
3163 for (i = 0; i < n; i++) {
3164 // Structure is :
3165 // 8-bits | 8-bits | 8-bits | 8-bits
3166 // 0x20 | Blue | Green | Red
3167 // 16-bits | 8-bits | 8-bits
3168 // --------------------------
3169 // v0 | n0
3170 // v1 | n1
3171 // v2 | n2
3172 tmp = *pPoly++;
3173 // code0 = tmp >> 24;
3174 rgbIn.r = (uint8)(tmp & 0xFF);
3175 rgbIn.g = (uint8)((tmp >> 8) & 0xFF);
3176 rgbIn.b = (uint8)((tmp >> 16) & 0xFF);
3177
3178 tmp = *pPoly++;
3179 v0 = pVertex + (tmp >> 16);
3180 n0 = pNormal + (tmp & 0xFFFF);
3181
3182 tmp = *pPoly++;
3183 v1 = pVertex + (tmp >> 16);
3184 n1 = pNormal + (tmp & 0xFFFF);
3185
3186 tmp = *pPoly++;
3187 v2 = pVertex + (tmp >> 16);
3188 n2 = pNormal + (tmp & 0xFFFF);
3189
3190 // Now do RotTransPers3 on the vectors
3191 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
3192 // gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
3193
3194 // test the return value of flag
3195 // The vertices have been pre-transformed into screen space and stored in the vertex pool
3196 // The flag value is set to 0x8000 or 0 in the pad structure
3197 if (v0->pad != 0)
3198 continue;
3199 if (v1->pad != 0)
3200 continue;
3201 if (v2->pad != 0)
3202 continue;
3203
3204 // use winding order of the polygons
3205 // e.g. NormalClip which is cross product of screen vectors
3206 sxy0.vx = v0->vx;
3207 sxy0.vy = v0->vy;
3208 sxy1.vx = v1->vx;
3209 sxy1.vy = v1->vy;
3210 sxy2.vx = v2->vx;
3211 sxy2.vy = v2->vy;
3212
3213 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3214 if (flag <= 0)
3215 continue;
3216
3217 // Do the full gouraud computation
3218 // NormalColorCol3( n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2 );
3219 LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
3220
3221 POLY_G3 *poly = (POLY_G3 *)drawpacket;
3222 // Draw untextured polygons
3223 setPolyG3(poly);
3224 // set XY's in the GPU packet 0-1-2
3225 poly->x0 = sxy0.vx;
3226 poly->y0 = sxy0.vy;
3227 poly->x1 = sxy1.vx;
3228 poly->y1 = sxy1.vy;
3229 poly->x2 = sxy2.vx;
3230 poly->y2 = sxy2.vy;
3231
3232 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
3233 setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
3234 setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
3235
3236 // Give the GTE some time to recover
3237 gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3238
3239 // Put it into the global ot at the correct place
3240 myAddPrimClip(z0, drawpacket);
3241 // advance the global packet pointer by correct amount
3242 myAddPacket(sizeof(POLY_G3));
3243 }
3244 }
3245
3246 //------------------------------------------------------------------------
3247
3248 // Fast: no options, Flat, Textured, Lit Triangles
fastDrawFTL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)3249 void fastDrawFTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
3250 SVECTOR *n0;
3251 SVECTORPC *v0;
3252 SVECTORPC *v1;
3253 SVECTORPC *v2;
3254
3255 uint16 uu0, uu1, uu2;
3256 uint16 vv0, vv1, vv2;
3257 uint32 tmp;
3258 int32 flag;
3259 uint32 i;
3260 uint32 *pPoly;
3261 int32 z0;
3262 SVECTORPC sxy0, sxy1, sxy2;
3263 uint32 uv0, uv1, uv2;
3264
3265 // Base colour for shading computation
3266 // Could easily be specified per polygon
3267 CVECTOR rgbIn = {128, 128, 128, 0};
3268 CVECTOR rgb0;
3269
3270 pPoly = polyStart;
3271 // Loop over each polygon
3272 for (i = 0; i < n; i++) {
3273 // Structure is :
3274 // Bit 31 ----> Bit 0
3275 //
3276 // 16-bits | 16-bits
3277 // --------------------------
3278 // v0 | u0
3279 // v1 | u1
3280 // v2 | u2
3281 // --------------------------
3282 // v0 | n0
3283 // v2 | v1
3284 uv0 = *pPoly++;
3285 vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
3286 uu0 = (uint16)(uv0 & 0xFFFF);
3287
3288 uv1 = *pPoly++;
3289 vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
3290 uu1 = (uint16)(uv1 & 0xFFFF);
3291
3292 uv2 = *pPoly++;
3293 vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
3294 uu2 = (uint16)(uv2 & 0xFFFF);
3295
3296 tmp = *pPoly++;
3297 v0 = pVertex + (tmp >> 16);
3298 n0 = pNormal + (tmp & 0xFFFF);
3299
3300 tmp = *pPoly++;
3301 v1 = pVertex + (tmp & 0xFFFF);
3302 v2 = pVertex + (tmp >> 16);
3303
3304 // Now do RotTransPers3 on the vectors
3305 // z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
3306 // gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
3307
3308 // test the return value of flag
3309 // The vertices have been pre-transformed into screen space and stored in the vertex pool
3310 // The flag value is set to 0x8000 or 0 in the pad structure
3311 if (v0->pad != 0)
3312 continue;
3313 if (v1->pad != 0)
3314 continue;
3315 if (v2->pad != 0)
3316 continue;
3317
3318 // use winding order of the polygons
3319 // e.g. NormalClip which is cross product of screen vectors
3320 sxy0.vx = v0->vx;
3321 sxy0.vy = v0->vy;
3322 sxy1.vx = v1->vx;
3323 sxy1.vy = v1->vy;
3324 sxy2.vx = v2->vx;
3325 sxy2.vy = v2->vy;
3326
3327 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3328 if (flag <= 0)
3329 continue;
3330
3331 // Do the full gouraud computation
3332 // NormalColorCol( n0, &rgbIn, &rgb0 );
3333 LIGHTPOLYGON(n0, &rgbIn, &rgb0);
3334
3335 POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
3336 setPolyFT3(poly);
3337 // set XY's in the GPU packet 0-1-2
3338 poly->x0 = sxy0.vx;
3339 poly->y0 = sxy0.vy;
3340 poly->x1 = sxy1.vx;
3341 poly->y1 = sxy1.vy;
3342 poly->x2 = sxy2.vx;
3343 poly->y2 = sxy2.vy;
3344
3345 setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
3346 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
3347
3348 // Give the GTE some time to recover
3349 gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3350
3351 // Put it into the global ot at the correct place
3352 myAddPrimClip(z0, drawpacket);
3353 // advance the global packet pointer by correct amount
3354 myAddPacket(sizeof(POLY_FT3));
3355 }
3356 }
3357
3358 // Fast : no options : Gouraud, Textured, Lit Triangles
fastDrawGTL3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex,SVECTOR * pNormal)3359 void fastDrawGTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
3360 SVECTOR *n0;
3361 SVECTOR *n1;
3362 SVECTOR *n2;
3363 SVECTORPC *v0;
3364 SVECTORPC *v1;
3365 SVECTORPC *v2;
3366
3367 uint16 uu0;
3368 uint16 uu1;
3369 uint16 uu2;
3370 uint16 vv0;
3371 uint16 vv1;
3372 uint16 vv2;
3373 int32 flag;
3374 uint32 i;
3375 int32 z0;
3376 uint32 uv0;
3377 uint32 uv1;
3378 uint32 uv2;
3379 uint32 vt0;
3380 uint32 vt1;
3381 uint32 vt2;
3382 SVECTORPC sxy0;
3383 SVECTORPC sxy1;
3384 SVECTORPC sxy2;
3385 int32 pad0;
3386 int32 pad1;
3387 int32 pad2;
3388
3389 // Base colour for gouraud shading computation
3390 // Could easily be specified per polygon
3391 CVECTOR rgbIn = {128, 128, 128, 0};
3392 CVECTOR rgb0, rgb1, rgb2;
3393
3394 POLY_GT3 *poly;
3395 uint32 *pPoly;
3396
3397 pPoly = polyStart;
3398 // Loop over each polygon
3399 for (i = 0; i < n; i++) {
3400 // Structure is :
3401 // v0, u0
3402 // v1, u1
3403 // v2, u2
3404 // v0 | n0
3405 // v1 | n1
3406 // v2 | n2
3407
3408 uv0 = *(pPoly++);
3409 vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
3410 uu0 = (uint16)(uv0 & 0xFFFF);
3411
3412 uv1 = *(pPoly++);
3413 vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
3414 uu1 = (uint16)(uv1 & 0xFFFF);
3415
3416 uv2 = *(pPoly++);
3417 vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
3418 uu2 = (uint16)(uv2 & 0xFFFF);
3419
3420 vt0 = *(pPoly++);
3421 v0 = (pVertex + (vt0 >> 16));
3422 n0 = (pNormal + (vt0 & 0xFFFF));
3423
3424 vt1 = *(pPoly++);
3425 v1 = (pVertex + (vt1 >> 16));
3426 n1 = (pNormal + (vt1 & 0xFFFF));
3427
3428 vt2 = *(pPoly++);
3429 v2 = (pVertex + (vt2 >> 16));
3430 n2 = (pNormal + (vt2 & 0xFFFF));
3431
3432 // The vertices have been pre-transformed into screen space and stored in the vertex pool
3433 // The flag value is set to 0x8000 or 0 in the pad structure
3434 pad0 = v0->pad;
3435 pad1 = v1->pad;
3436 pad2 = v2->pad;
3437 flag = pad0 | pad1 | pad2;
3438
3439 if (flag != 0)
3440 continue;
3441
3442 // use winding order of the polygons
3443 // e.g. NormalClip which is cross product of screen vectors
3444 sxy0.vx = v0->vx;
3445 sxy0.vy = v0->vy;
3446 sxy1.vx = v1->vx;
3447 sxy1.vy = v1->vy;
3448 sxy2.vx = v2->vx;
3449 sxy2.vy = v2->vy;
3450
3451 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3452
3453 // Give the GTE some time to recover
3454
3455 // Ignore polygons which are too small
3456 if (flag <= 0)
3457 continue;
3458
3459 // Do the full gouraud computation
3460 LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
3461
3462 // Try to overlap this with the LIGHTPOLYGON3 !
3463 poly = (POLY_GT3 *)drawpacket;
3464 setPolyGT3(poly);
3465 // set XY's in the GPU packet 0-1-2
3466 poly->x0 = sxy0.vx;
3467 poly->y0 = sxy0.vy;
3468 poly->x1 = sxy1.vx;
3469 poly->y1 = sxy1.vy;
3470 poly->x2 = sxy2.vx;
3471 poly->y2 = sxy2.vy;
3472
3473 // Give the GTE some time to recover
3474 gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3475
3476 setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
3477
3478 setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
3479 setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
3480 setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
3481
3482 // Put it into the global ot at the correct place
3483 myAddPrimClip(z0, drawpacket);
3484
3485 // advance the global packet pointer by correct amount
3486 myAddPacket(sizeof(POLY_GT3));
3487 }
3488 }
3489
3490 // For mucking about with lighting
3491 // Draw a solid bounding box around the actor (and so obscuring him)
3492 // but then have the box respond to the lights e.g. give it normals
3493 // and do flat & goraud shading
3494 // Assume the GTE lighting registers to be pre-prepared
3495
3496 #if CD_MODE == 0
3497
drawSolidBboxPC(SVECTOR * scrn,CVECTOR * rgbIn)3498 void drawSolidBboxPC(SVECTOR *scrn, CVECTOR *rgbIn) {
3499 // 6 POLY_F4's i.e. 6 faces
3500 // The 8 verticies are:
3501 // 0 { xmin, ymin, zmin },
3502 // 1 { xmin, ymin, zmax },
3503 // 2 { xmax, ymin, zmin },
3504 // 3 { xmax, ymin, zmax },
3505 // 4 { xmax, ymax, zmin },
3506 // 5 { xmax, ymax, zmax },
3507 // 6 { xmin, ymax, zmin },
3508 // 7 { xmin, ymax, zmax }
3509
3510 // The 6 faces are the following vertex links:
3511 // ymin face : 0->1->3->2
3512 // xmax face : 2->3->5->4
3513 // zmin face : 0->2->4->6
3514 // xmin face : 0->6->7->1
3515 // zmax face : 1->7->5->3
3516 // ymax face : 6->4->5->7
3517
3518 // The 6 face normals are (normal points into front side of face on PSX)
3519 // ymin face : 0,+4096,0 +ve y
3520 // xmax face : -4096,0,0 -ve x
3521 // zmin face : 0,0,+4096 +ve z
3522 // xmin face : +4096,0,0 +ve x
3523 // zmax face : 0,0,-4096 -ve z
3524 // ymax face : 0,-4096,0 -ve y
3525
3526 int32 z0, flag;
3527 SVECTOR normal;
3528 CVECTOR rgb;
3529 POLY_F4 *face = NULL;
3530
3531 gte_NormalClip_pc(&(scrn[0]), &(scrn[1]), &(scrn[2]), &flag);
3532 if (flag > 0) {
3533 face = (POLY_F4 *)drawpacket;
3534 setPolyF4(face);
3535 // ymin face normal : 0,+4096,0 +ve y
3536 normal.vx = 0;
3537 normal.vy = 4096;
3538 normal.vz = 0;
3539 if (_drawLit) {
3540 LIGHTPOLYGON(&normal, rgbIn, &rgb);
3541 setRGB0(face, rgb.r, rgb.g, rgb.b);
3542 } else {
3543 setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3544 }
3545 // ymin face : 0->1->3->2 : note PSX is 0-1-3-2 for a quad
3546 setXY4(face, scrn[0].vx, scrn[0].vy, scrn[1].vx, scrn[1].vy, scrn[2].vx, scrn[2].vy, scrn[3].vx, scrn[3].vy);
3547
3548 z0 = (scrn[0].vz + scrn[1].vz + scrn[2].vz + scrn[3].vz) / 4;
3549 z0 = myAddPrimClip(z0, drawpacket);
3550 myAddPacket(sizeof(POLY_F4));
3551 }
3552
3553 gte_NormalClip_pc(&(scrn[2]), &(scrn[3]), &(scrn[4]), &flag);
3554 if (flag > 0) {
3555 // xmax face : 2->3->5->4 : note PSX is 0-1-3-2 for a quad
3556 face = (POLY_F4 *)drawpacket;
3557 setPolyF4(face);
3558 // xmax face : -4096,0,0 -ve x
3559 normal.vx = -4096;
3560 normal.vy = 0;
3561 normal.vz = 0;
3562 if (_drawLit) {
3563 LIGHTPOLYGON(&normal, rgbIn, &rgb);
3564 setRGB0(face, rgb.r, rgb.g, rgb.b);
3565 } else {
3566 setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3567 }
3568 setXY4(face, scrn[2].vx, scrn[2].vy, scrn[3].vx, scrn[3].vy, scrn[4].vx, scrn[4].vy, scrn[5].vx, scrn[5].vy);
3569 z0 = (scrn[2].vz + scrn[3].vz + scrn[4].vz + scrn[5].vz) / 4;
3570 z0 = myAddPrimClip(z0, drawpacket);
3571 myAddPacket(sizeof(POLY_F4));
3572 }
3573
3574 gte_NormalClip_pc(&(scrn[0]), &(scrn[2]), &(scrn[4]), &flag);
3575 if (flag > 0) {
3576 // zmin face : 0->2->4->6 : note PSX is 0-1-3-2 for a quad
3577 face = (POLY_F4 *)drawpacket;
3578 setPolyF4(face);
3579 // zmin face : 0,0,+4096 +ve z
3580 normal.vx = 0;
3581 normal.vy = 0;
3582 normal.vz = 4096;
3583 if (_drawLit) {
3584 LIGHTPOLYGON(&normal, rgbIn, &rgb);
3585 setRGB0(face, rgb.r, rgb.g, rgb.b);
3586 } else {
3587 setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3588 }
3589 setXY4(face, scrn[0].vx, scrn[0].vy, scrn[2].vx, scrn[2].vy, scrn[6].vx, scrn[6].vy, scrn[4].vx, scrn[4].vy);
3590 z0 = (scrn[0].vz + scrn[2].vz + scrn[4].vz + scrn[6].vz) / 4;
3591 z0 = myAddPrimClip(z0, drawpacket);
3592 myAddPacket(sizeof(POLY_F4));
3593 }
3594
3595 gte_NormalClip_pc(&(scrn[0]), &(scrn[6]), &(scrn[7]), &flag);
3596 if (flag > 0) {
3597 // xmin face : 0->6->7->1 : note PSX is 0-1-3-2 for a quad
3598 face = (POLY_F4 *)drawpacket;
3599 setPolyF4(face);
3600 // xmin face : +4096,0,0 +ve x
3601 normal.vx = 0;
3602 normal.vy = 0;
3603 normal.vz = 4096;
3604 if (_drawLit) {
3605 LIGHTPOLYGON(&normal, rgbIn, &rgb);
3606 setRGB0(face, rgb.r, rgb.g, rgb.b);
3607 } else {
3608 setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3609 }
3610 setXY4(face, scrn[0].vx, scrn[0].vy, scrn[6].vx, scrn[6].vy, scrn[1].vx, scrn[1].vy, scrn[7].vx, scrn[7].vy);
3611 z0 = myAddPrimClip(scrn[7].vz, drawpacket);
3612 myAddPacket(sizeof(POLY_F4));
3613 }
3614
3615 gte_NormalClip_pc(&(scrn[1]), &(scrn[7]), &(scrn[5]), &flag);
3616 if (flag > 0) {
3617 // zmax face : 1->7->5->3 : note PSX is 0-1-3-2 for a quad
3618 face = (POLY_F4 *)drawpacket;
3619 setPolyF4(face);
3620 // zmax face : 0,0,-4096 -ve z
3621 normal.vx = 0;
3622 normal.vy = 0;
3623 normal.vz = -4096;
3624 if (_drawLit) {
3625 LIGHTPOLYGON(&normal, rgbIn, &rgb);
3626 setRGB0(face, rgb.r, rgb.g, rgb.b);
3627 } else {
3628 setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3629 }
3630 setXY4(face, scrn[1].vx, scrn[1].vy, scrn[7].vx, scrn[7].vy, scrn[3].vx, scrn[3].vy, scrn[5].vx, scrn[5].vy);
3631 z0 = (scrn[1].vz + scrn[3].vz + scrn[5].vz + scrn[7].vz) / 4;
3632 z0 = myAddPrimClip(z0, drawpacket);
3633 myAddPacket(sizeof(POLY_F4));
3634 }
3635
3636 gte_NormalClip_pc(&(scrn[6]), &(scrn[4]), &(scrn[5]), &flag);
3637 if (flag > 0) {
3638 // ymax face : 6->4->5->7 : note PSX is 0-1-3-2 for a quad
3639 face = (POLY_F4 *)drawpacket;
3640 setPolyF4(face);
3641 // ymax face : 0,-4096,0 -ve y
3642 normal.vx = 0;
3643 normal.vy = -4096;
3644 normal.vz = 0;
3645 if (_drawLit) {
3646 LIGHTPOLYGON(&normal, rgbIn, &rgb);
3647 setRGB0(face, rgb.r, rgb.g, rgb.b);
3648 } else {
3649 setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
3650 }
3651 setXY4(face, scrn[6].vx, scrn[6].vy, scrn[4].vx, scrn[4].vy, scrn[7].vx, scrn[7].vy, scrn[5].vx, scrn[5].vy);
3652 z0 = (scrn[4].vz + scrn[5].vz + scrn[6].vz + scrn[7].vz) / 4;
3653 z0 = myAddPrimClip(z0, drawpacket);
3654 myAddPacket(sizeof(POLY_F4));
3655 }
3656 }
3657
3658 #endif // #if CD_MODE == 0
3659
3660 // Simple flat untextured triangles
3661 // draw backfacing triangles as well
3662 // the colour is set by a global variable
fastDrawTRI3PC(uint32 * polyStart,const uint32 n,SVECTORPC * pVertex)3663 void fastDrawTRI3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
3664 SVECTORPC *v0;
3665 SVECTORPC *v1;
3666 SVECTORPC *v2;
3667
3668 int32 flag;
3669 uint32 i;
3670 uint32 *pPoly;
3671 int32 z0;
3672 SVECTORPC sxy0, sxy1, sxy2, stemp;
3673 uint32 tmp;
3674
3675 pPoly = polyStart;
3676 // Loop over each polygon
3677 for (i = 0; i < n; i++) {
3678 // Each polygon is 2 32-bit WORDS
3679 // Bit 31 ----> Bit 0
3680 //
3681 // 16-bits | 16-bits
3682 // --------------------------
3683 // v1 | v0
3684 // pad | v2
3685
3686 tmp = *pPoly++;
3687 v0 = pVertex + (tmp & 0xFFFF);
3688 v1 = pVertex + (tmp >> 16);
3689
3690 tmp = *pPoly++;
3691 v2 = pVertex + (tmp & 0xFFFF);
3692
3693 flag = (v0->pad) | (v1->pad) | (v2->pad);
3694 if (flag != 0)
3695 continue;
3696
3697 // use winding order of the polygons
3698 // e.g. NormalClip which is cross product of screen vectors
3699 sxy0.vx = v0->vx;
3700 sxy0.vy = v0->vy;
3701 sxy1.vx = v1->vx;
3702 sxy1.vy = v1->vy;
3703 sxy2.vx = v2->vx;
3704 sxy2.vy = v2->vy;
3705
3706 // See what winding order this polygon is ?
3707 gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
3708
3709 // Drawing back facing polys requires making them have
3710 // clockwise winding order as by definition they have
3711 // anti-clockwise winding order
3712 if (flag < 0) {
3713 stemp = sxy1;
3714 sxy1 = sxy2;
3715 sxy2 = stemp;
3716 }
3717
3718 // Give the GTE some time to recover
3719 gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
3720
3721 // Draw untextured polygons
3722 TPOLY_F3 *poly = (TPOLY_F3 *)drawpacket;
3723 setTPolyF3(poly);
3724 setTABRMode(poly, 2); // 2 = back - front
3725 setTSemiTrans(poly, 1); // 1 = enable semi-transparency
3726
3727 // set XY's in the GPU packet 0-1-2
3728 poly->x0 = sxy0.vx;
3729 poly->y0 = sxy0.vy;
3730 poly->x1 = sxy1.vx;
3731 poly->y1 = sxy1.vy;
3732 poly->x2 = sxy2.vx;
3733 poly->y2 = sxy2.vy;
3734
3735 // Set the RGB colours
3736 // No light source calculation
3737 // So just set base colour
3738 setRGB0(poly, unlitPoly.r, unlitPoly.g, unlitPoly.b);
3739 poly->code = unlitPoly.cd;
3740
3741 myAddPrimClip(z0, drawpacket);
3742
3743 // advance the global packet pointer by correct amount
3744 myAddPacket(sizeof(TPOLY_F3));
3745 }
3746 }
3747
3748 } // End of namespace ICB
3749