Files
scummvm/engines/icb/drawpoly_pc.cpp
T
D G Turner d9ae18ecbe ICB: Remove Macro Test Usage of Undefined CD_MODE Symbol
This symbol was undefined which meant that it defaulted to being equal
to zero. Since this was the value tested for in all cases, then all
cases of this macro test were enabled which was not very clear.

Looking at the code, it appears this is intended to guard a debugging
mode enabling slower, but more readable rendering code and other graphics
information. This should probably be migrated to a boolean flag of the
engine (since debug already exists) or a ScummVM debug level / flag.

This changes also removes a large number of GCC warnings regarding
use of undefined macro symbols.
2022-07-11 00:43:33 +01:00

3736 lines
100 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* Additional copyright for this file:
* Copyright (C) 1999-2000 Revolution Software Ltd.
* This code is based on source code created by Revolution Software,
* used with permission.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "engines/icb/common/px_common.h"
#include "engines/icb/gfx/psx_pcdefines.h"
#include "engines/icb/gfx/psx_pcdefines.h"
#include "engines/icb/gfx/psx_scrn.h"
#include "engines/icb/common/px_capri_maths.h"
#include "engines/icb/gfx/psx_poly.h"
#include "engines/icb/global_objects_psx.h"
#include "engines/icb/light_pc.h"
namespace ICB {
#if _PSX_ON_PC == 1
extern uint32 selFace;
extern CVECTOR unlitPoly;
extern CVECTOR deadObjectColour;
extern uint32 deadObject;
extern uint32 _drawBface;
extern uint8 selWRed;
extern uint8 selWGreen;
extern uint8 selWBlue;
extern uint8 selPRed;
extern uint8 selPGreen;
extern uint8 selPBlue;
extern uint8 selPAlpha;
#else // #if _PSX_ON_PC == 1
uint32 selFace = 65537;
CVECTOR unlitPoly = {255, 255, 255, 0};
CVECTOR deadObjectColour = {0, 0, 0, 0};
uint32 deadObject = 0;
uint32 _drawBface = 0;
uint8 selWRed = 0;
uint8 selWGreen = 255;
uint8 selWBlue = 255;
uint8 selPRed = 255;
uint8 selPGreen = 255;
uint8 selPBlue = 0;
uint8 selPAlpha = 0;
#endif // #if _PSX_ON_PC == 1
// Specialist lighting routines for polygons
// support for bounce & width
inline void LightPolygon(SVECTOR *n0, CVECTOR *rgbIn, CVECTOR *rgb0) {
SVECTORPC lightEffect;
// Normal line vector(local) -> light source effect
ApplyMatrixSV_pc(gtelight_pc, n0, &lightEffect);
if (useLampWidth) {
lightEffect.vx = (int16)(lightEffect.vx + lampWidth[0]);
lightEffect.vy = (int16)(lightEffect.vy + lampWidth[1]);
lightEffect.vz = (int16)(lightEffect.vy + lampWidth[2]);
}
if (useLampBounce) {
if (lightEffect.vx < 0) {
lightEffect.vx = (int16)-lightEffect.vx;
if (lightEffect.vx > lampBounce[0])
lightEffect.vx = (int16)lampBounce[0];
}
if (lightEffect.vy < 0) {
lightEffect.vy = (int16)-lightEffect.vy;
if (lightEffect.vy > lampBounce[1])
lightEffect.vy = (int16)lampBounce[1];
}
if (lightEffect.vz < 0) {
lightEffect.vz = (int16)-lightEffect.vz;
if (lightEffect.vz > lampBounce[2])
lightEffect.vz = (int16)lampBounce[2];
}
} else {
if (lightEffect.vx < 0)
lightEffect.vx = 0;
if (lightEffect.vy < 0)
lightEffect.vy = 0;
if (lightEffect.vz < 0)
lightEffect.vz = 0;
}
// Light source effect -> Colour effect(local colour matrix+back colour)
SVECTORPC colourEffect;
ApplyMatrixSV_pc(gtecolour_pc, &lightEffect, &colourEffect);
if (colourEffect.vx < 0)
colourEffect.vx = 0;
if (colourEffect.vy < 0)
colourEffect.vy = 0;
if (colourEffect.vz < 0)
colourEffect.vz = 0;
// colourEffect is 0-4095 (2^12)
// gteback is 0-255 (2^8)
colourEffect.vx = (int16)((colourEffect.vx >> 4) + gteback_pc[0]);
colourEffect.vy = (int16)((colourEffect.vy >> 4) + gteback_pc[1]);
colourEffect.vz = (int16)((colourEffect.vz >> 4) + gteback_pc[2]);
// 256 = 1.0 in colourEffect
// 128 = 1.0 in in0
int32 red = (rgbIn->r * colourEffect.vx);
int32 green = (rgbIn->g * colourEffect.vy);
int32 blue = (rgbIn->b * colourEffect.vz);
red = red >> 8;
green = green >> 8;
blue = blue >> 8;
if (red > 255)
red = 255;
if (green > 255)
green = 255;
if (blue > 255)
blue = 255;
rgb0->r = (uint8)(red);
rgb0->g = (uint8)(green);
rgb0->b = (uint8)(blue);
}
// Specialist lighting routines for polygons
// support for bounce & width
inline void LightPolygon3(SVECTOR *n0, SVECTOR *n1, SVECTOR *n2, CVECTOR *rgbIn, CVECTOR *rgb0, CVECTOR *rgb1, CVECTOR *rgb2) {
LightPolygon(n0, rgbIn, rgb0);
LightPolygon(n1, rgbIn, rgb1);
LightPolygon(n2, rgbIn, rgb2);
}
#define LIGHTPOLYGON(n0, rgbIn, rgb0) \
{ \
if (useLampWidth || useLampBounce) \
LightPolygon(n0, rgbIn, rgb0); \
else \
gte_NormalColorCol_pc(n0, rgbIn, rgb0); \
}
#define LIGHTPOLYGON3(n0, n1, n2, rgbIn, rgb0, rgb1, rgb2) \
{ \
if (useLampWidth || useLampBounce) \
LightPolygon3(n0, n1, n2, rgbIn, rgb0, rgb1, rgb2); \
else \
gte_NormalColorCol3_pc(n0, n1, n2, rgbIn, rgb0, rgb1, rgb2); \
}
//----------------------------------------------------------------
/*
gte_ll();
gte_llv0();
gte_llv1();
gte_llv2();
gte_llir();
gte_llv0tr();
gte_llv1tr();
gte_llv2tr();
gte_llirtr();
gte_llv0bk();
gte_llv1bk();
gte_llv2bk();
gte_llirbk();
gte_lc();
gte_lcv0();
gte_lcv1();
gte_lcv2();
gte_lcir();
gte_lcv0tr();
gte_lcv1tr();
gte_lcv2tr();
gte_lcirtr();
gte_lcv0bk();
gte_lcv1bk();
gte_lcv2bk();
gte_lcirbk();
*/
//------------------------------------------------------------------------
// Flat, Un-Textured, Self-Luminous, triangles
void drawFUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
uint32 num = n;
int32 p, flag;
uint32 i;
uint32 *pPoly;
int32 z0, z1, z2;
SVECTORPC sxy0, sxy1, sxy2, stemp;
CVECTOR *rgbIn;
uint32 tmp;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < num; i++) {
// Structure is :
// 0x20 | B | G | R
// v1 | v0
// pad | v2
rgbIn = (CVECTOR *)pPoly++;
if (deadObject) {
rgbIn = &deadObjectColour;
}
tmp = *pPoly++;
v0 = pVertex + (tmp & 0xFFFF);
v1 = pVertex + (tmp >> 16);
tmp = *pPoly++;
v2 = pVertex + (tmp & 0xFFFF);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
// Give the GTE some time to recover
int32 avgz;
gte_AverageZ3_pc(z0, z1, z2, &avgz);
// Do we want to do back face removal ?
if (_removeBackface) {
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
if (_useWindingOrder) {
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
// Drawing back facings polys requires making them have
// clockwise winding order as by definition they have
// anti-clockwise winding order
if (flag < 0) {
if (_drawBface) {
stemp = sxy1;
sxy1 = sxy2;
sxy2 = stemp;
} else {
// Skip this polygon
continue;
}
} else if (flag == 0)
continue; // ignore zero-area polygons
}
// TODO
// dot product of viewing direction and polygon normal
// will require generation of polygon normal from vertex normals
// and transformation of the normal to world space
}
// Put wireframe triangles in list before textured ones
// so should be in front of textured ones
if ((_drawWfrm) || (selFace == i)) {
LINE_F4 *line = (LINE_F4 *)drawpacket;
setLineF4(line);
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
if (selFace == i)
setRGB0(line, selWRed, selWGreen, selWBlue);
else
setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_F4));
}
// Draw polygon version behind the wireframe
if ((_drawPolys) || (selFace == i)) {
// Draw untextured polygons
POLY_F3 *poly = (POLY_F3 *)drawpacket;
setPolyF3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// Set the RGB colours
// No light source calculation
// So just set base colour
if (selFace == i)
setRGB0(poly, selPRed, selPGreen, selPBlue);
else
setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_F3));
}
}
}
// Gouraud, Un-Textured, Self-Luminous, triangles
void drawGUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
uint32 num = n;
uint32 tmp;
int32 p, flag;
uint32 i;
uint32 *pPoly;
int32 z0, z1, z2;
SVECTORPC sxy0, sxy1, sxy2, stemp;
// Base colour for gouraud shading computation
CVECTOR *rgb0;
CVECTOR *rgb1;
CVECTOR *rgb2;
CVECTOR *rgbTemp;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < num; i++) {
// Structure is :
// 8-bits | 8-bits | 8-bits | 8-bits
// 0x30 | Blue0 | Green0 | Red0
// 0x30 | Blue1 | Green1 | Red1
// 0x30 | Blue2 | Green2 | Red2
// 16-bits | 8-bits | 8-bits
// --------------------------
// v1 | v0
// pad | v2
rgb0 = (CVECTOR *)pPoly++;
rgb1 = (CVECTOR *)pPoly++;
rgb2 = (CVECTOR *)pPoly++;
if (deadObject) {
rgb0 = &deadObjectColour;
rgb1 = &deadObjectColour;
rgb2 = &deadObjectColour;
}
tmp = *pPoly++;
v0 = pVertex + (tmp & 0xFFFF);
v1 = pVertex + (tmp >> 16);
tmp = *pPoly++;
v2 = pVertex + (tmp & 0xFFFF);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
// Give the GTE some time to recover
int32 avgz;
gte_AverageZ3_pc(z0, z1, z2, &avgz);
// Do we want to do back face removal ?
if (_removeBackface) {
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
if (_useWindingOrder) {
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
// Drawing back facings polys requires making them have
// clockwise winding order as by definition they have
// anti-clockwise winding order
if (flag < 0) {
if (_drawBface) {
stemp = sxy1;
sxy1 = sxy2;
sxy2 = stemp;
rgbTemp = rgb1;
rgb1 = rgb2;
rgb2 = rgbTemp;
} else {
// Skip this polygon
continue;
}
} else if (flag == 0)
continue; // ignore zero-area polygons
}
// TODO
// dot product of viewing direction and polygon normal
// will require generation of polygon normal from vertex normals
// and transformation of the normal to world space
}
// Put wireframe triangles in list before textured ones
// so should be in front of textured ones
if ((_drawWfrm) || (selFace == i)) {
LINE_F4 *line = (LINE_F4 *)drawpacket;
setLineF4(line);
if (selFace == i)
setRGB0(line, selWRed, selWGreen, selWBlue);
else
setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_F4));
}
// Draw textured version behind the wireframe
if ((_drawPolys) || (selFace == i)) {
POLY_G3 *poly = (POLY_G3 *)drawpacket;
// Draw untextured polygons
setPolyG3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// No light source calculation
// So just set base colour
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
setRGB1(poly, selPRed, selPGreen, selPBlue);
setRGB2(poly, selPRed, selPGreen, selPBlue);
} else {
setRGB0(poly, rgb0->r, rgb0->g, rgb0->b);
setRGB1(poly, rgb1->r, rgb1->g, rgb1->b);
setRGB2(poly, rgb2->r, rgb2->g, rgb2->b);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_G3));
}
}
}
// Flat, Textured, Self-Luminous Triangles
void drawFTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
uint32 num = n;
uint16 uu0, uu1, uu2;
uint16 vv0, vv1, vv2;
uint32 tmp;
int32 p, flag;
uint32 i;
uint32 *pPoly;
int32 z0, z1, z2;
SVECTORPC sxy0, sxy1, sxy2, stemp;
uint32 uv0, uv1, uv2;
// Base colour for shading computation
// Could easily be specified per polygon
CVECTOR *rgbIn;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < num; i++) {
// Structure is :
// Bit 31 ----> Bit 0
//
// 8-bits | 8-bits | 8-bits | 8-bits
// 0x24 | Blue | Green | Red
// 16-bits | 16-bits
// --------------------------
// v0 | u0
// v1 | u1
// v2 | u2
// --------------------------
// pad | v0
// v2 | v1
rgbIn = (CVECTOR *)pPoly++;
if (deadObject) {
rgbIn = &deadObjectColour;
}
uv0 = *pPoly++;
vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
uu0 = (uint16)(uv0 & 0xFFFF);
uv1 = *pPoly++;
vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
uu1 = (uint16)(uv1 & 0xFFFF);
uv2 = *pPoly++;
vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
uu2 = (uint16)(uv2 & 0xFFFF);
tmp = *pPoly++;
v0 = pVertex + (tmp & 0xFFFF);
tmp = *pPoly++;
v1 = pVertex + (uint)(tmp & 0xFFFF);
v2 = pVertex + (uint)(tmp >> 16);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
// Give the GTE some time to recover
int32 avgz;
gte_AverageZ3_pc(z0, z1, z2, &avgz);
// Do we want to do back face removal ?
if (_removeBackface) {
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
if (_useWindingOrder) {
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
// Drawing back facings polys requires making them have
// clockwise winding order as by definition they have
// anti-clockwise winding order
if (flag < 0) {
if (_drawBface) {
stemp = sxy1;
sxy1 = sxy2;
sxy2 = stemp;
flag = uv1;
uv1 = uv2;
uv2 = flag;
} else {
// Skip this polygon
continue;
}
} else if (flag == 0)
continue; // ignore zero-area polygons
}
// TODO
// dot product of viewing direction and polygon normal
// will require generation of polygon normal from vertex normals
// and transformation of the normal to world space
}
// Put wireframe triangles in list before textured ones
// so should be in front of textured ones
if ((_drawWfrm) || (selFace == i)) {
LINE_F4 *line = (LINE_F4 *)drawpacket;
setLineF4(line);
if (selFace == i)
setRGB0(line, selWRed, selWGreen, selWBlue);
else
setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_F4));
}
// Draw textured version behind the wireframe
if ((_drawPolys) || (selFace == i)) {
if (_drawTxture) {
POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
setPolyFT3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
// No light source calculation
// So just set base colour
if (selFace == i)
setRGB0(poly, selPRed, selPGreen, selPBlue);
else
setRGB0(poly, rgbIn->r, rgbIn->b, rgbIn->b);
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_FT3));
} else {
// Set the RGB colours
POLY_F3 *poly = (POLY_F3 *)drawpacket;
// Draw untextured polygons
setPolyF3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// No light source calculation
// So just set base colour
if (selFace == i)
setRGB0(poly, selPRed, selPGreen, selPBlue);
else
setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_F3));
}
}
}
}
// Gouraud, Textured, Self-Luminous Triangles
void drawGTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
uint32 num = n;
uint16 uu0, uu1, uu2;
uint16 vv0, vv1, vv2;
uint32 tmp;
int32 p, flag;
uint32 i;
uint32 *pPoly;
int32 z0, z1, z2;
SVECTORPC sxy0, sxy1, sxy2, stemp;
uint32 uv0, uv1, uv2;
// gouraud colours
CVECTOR *rgb0;
CVECTOR *rgb1;
CVECTOR *rgb2;
CVECTOR *rgbTemp;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < num; i++) {
// Structure is :
// 8-bits | 8-bits | 8-bits | 8-bits
// 0x34 | Blue0 | Green0 | Red0
// 0x34 | Blue1 | Green1 | Red1
// 0x34 | Blue2 | Green2 | Red2
// 16-bits | 16-bits
// --------------------------
// v0 | u0
// v1 | u1
// v2 | u2
// --------------------------
// pad | v0
// v2 | v1
rgb0 = (CVECTOR *)pPoly++;
rgb1 = (CVECTOR *)pPoly++;
rgb2 = (CVECTOR *)pPoly++;
if (deadObject) {
rgb0 = &deadObjectColour;
rgb1 = &deadObjectColour;
rgb2 = &deadObjectColour;
}
uv0 = *pPoly++;
vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
uu0 = (uint16)(uv0 & 0xFFFF);
uv1 = *pPoly++;
vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
uu1 = (uint16)(uv1 & 0xFFFF);
uv2 = *pPoly++;
vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
uu2 = (uint16)(uv2 & 0xFFFF);
tmp = *pPoly++;
v0 = pVertex + (tmp & 0xFFFF);
tmp = *pPoly++;
v1 = pVertex + (tmp & 0xFFFF);
v2 = pVertex + (tmp >> 16);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
// Give the GTE some time to recover
int32 avgz;
gte_AverageZ3_pc(z0, z1, z2, &avgz);
// Do we want to do back face removal ?
if (_removeBackface) {
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
if (_useWindingOrder) {
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
// Drawing back facings polys requires making them have
// clockwise winding order as by definition they have
// anti-clockwise winding order
if (flag < 0) {
if (_drawBface) {
stemp = sxy1;
sxy1 = sxy2;
sxy2 = stemp;
rgbTemp = rgb1;
rgb1 = rgb2;
rgb2 = rgbTemp;
flag = uv1;
uv1 = uv2;
uv2 = flag;
} else {
// Skip this polygon
continue;
}
} else if (flag == 0)
continue; // ignore zero-area polygons
}
// TODO
// dot product of viewing direction and polygon normal
// will require generation of polygon normal from vertex normals
// and transformation of the normal to world space
}
// Put wireframe triangles in list before textured ones
// so should be in front of textured ones
if ((_drawWfrm) || (selFace == i)) {
LINE_F4 *line = (LINE_F4 *)drawpacket;
setLineF4(line);
if (selFace == i)
setRGB0(line, selWRed, selWGreen, selWBlue);
else
setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_F4));
}
// Draw textured version behind the wireframe
if ((_drawPolys) || (selFace == i)) {
if (_drawTxture) {
// Set the RGB colours
POLY_GT3 *poly = (POLY_GT3 *)drawpacket;
setPolyGT3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
// No light source calculation
// So just set base colour
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
setRGB1(poly, selPRed, selPGreen, selPBlue);
setRGB2(poly, selPRed, selPGreen, selPBlue);
} else {
setRGB0(poly, rgb0->r, rgb0->b, rgb0->b);
setRGB1(poly, rgb1->r, rgb1->b, rgb1->b);
setRGB2(poly, rgb2->r, rgb2->b, rgb2->b);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_GT3));
} else {
// Set the RGB colours
POLY_G3 *poly = (POLY_G3 *)drawpacket;
// Draw untextured polygons
setPolyG3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// No light source calculation
// So just set base colour
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
setRGB1(poly, selPRed, selPGreen, selPBlue);
setRGB2(poly, selPRed, selPGreen, selPBlue);
} else {
setRGB0(poly, rgb0->r, rgb0->b, rgb0->b);
setRGB1(poly, rgb1->r, rgb1->b, rgb1->b);
setRGB2(poly, rgb2->r, rgb2->b, rgb2->b);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_G3));
}
}
}
}
// Flat, Un-Textured, Lit, triangles
void drawFUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
SVECTOR *n0;
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
uint32 num = n;
int32 p, flag;
uint32 i;
uint32 *pPoly;
int32 z0, z1, z2;
SVECTORPC sxy0, sxy1, sxy2, stemp;
SVECTORPC sxyn0;
SVECTORPC sn0;
CVECTOR *rgbIn;
CVECTOR rgb0 = {0, 0, 0, 0};
uint32 tmp;
uint8 ctmp;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < num; i++) {
// Structure is :
// 0x20 | B | G | R
// v0 | n0
// v2 | v1
rgbIn = (CVECTOR *)pPoly++;
tmp = *pPoly++;
v0 = pVertex + (tmp >> 16);
n0 = pNormal + (tmp & 0xFFFF);
tmp = *pPoly++;
v2 = pVertex + (tmp >> 16);
v1 = pVertex + (tmp & 0xFFFF);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
// Give the GTE some time to recover
int32 avgz;
gte_AverageZ3_pc(z0, z1, z2, &avgz);
// Do we want to do back face removal ?
if (_removeBackface) {
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
if (_useWindingOrder) {
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
// Drawing back facings polys requires making them have
// clockwise winding order as by definition they have
// anti-clockwise winding order
if (flag < 0) {
if (_drawBface) {
stemp = sxy1;
sxy1 = sxy2;
sxy2 = stemp;
} else {
// Skip this polygon
continue;
}
} else if (flag == 0)
continue; // ignore zero-area polygons
}
// TODO
// dot product of viewing direction and polygon normal
// will require generation of polygon normal from vertex normals
// and transformation of the normal to world space
}
// Set the RGB colours
if (_drawLit) {
// Do the flat lighting computation
LIGHTPOLYGON(n0, rgbIn, &rgb0);
}
// Put normal lines in list before wireframe
// so should be drawn in front of wireframe triangles
if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
// Do coord transform on the scaled normal vectors + v0
sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
// z0 = RotTransPers( &sn0, &sxyn0, &p, &flag );
gte_RotTransPers_pc(&sn0, &sxyn0, &p, &flag, &z0);
// Normal 0 : scale the normal and add to vertex scrn pos
LINE_G2 *line = (LINE_G2 *)drawpacket;
setLineG2(line);
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxyn0.vx;
line->y1 = sxyn0.vy;
if (selFace == i) {
// from bright red
setRGB0(line, 255, 0, 0);
// to bright white
setRGB1(line, 255, 255, 255);
} else {
// from bright blue
setRGB0(line, 0, 0, 255);
// to bright white
setRGB1(line, 255, 255, 255);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_G2));
}
// Put wireframe triangles in list before textured ones
// so should be in front of textured ones
if ((_drawWfrm) || (selFace == i)) {
LINE_F4 *line = (LINE_F4 *)drawpacket;
setLineF4(line);
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
// Draw a wireframe that responds to lighting
if (_drawLit) {
int32 cval;
// Compute the colour scaling and clip it
// Flat shading so give the same colour to each vertex
if (rgbIn->r != 0) {
cval = ((wfrmRed * rgb0.r) / rgbIn->r);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
} else
ctmp = 0;
line->r0 = ctmp;
if (rgbIn->g != 0) {
cval = ((wfrmGreen * rgb0.g) / rgbIn->g);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
} else
ctmp = 0;
line->g0 = ctmp;
if (rgbIn->b != 0) {
cval = ((wfrmBlue * rgb0.b) / rgbIn->b);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
} else
ctmp = 0;
line->b0 = ctmp;
} else {
setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
}
if (selFace == i)
setRGB0(line, selWRed, selWGreen, selWBlue);
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_F4));
}
// Draw polygon version behind the wireframe
if ((_drawPolys) || (selFace == i)) {
// Draw untextured polygons
POLY_F3 *poly = (POLY_F3 *)drawpacket;
setPolyF3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// Set the RGB colours
if (_drawLit) {
// Flat shaded so give each vertex the same colour
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
} else {
// No light source calculation
// So just set base colour
setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
}
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_F3));
}
}
}
// Gouraud, Un-Textured, Lit, triangles
void drawGUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
SVECTOR *n0;
SVECTOR *n1;
SVECTOR *n2;
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
SVECTOR *ntemp;
// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
uint32 num = n;
uint32 tmp;
uint8 ctmp;
int32 p, flag;
uint32 i;
uint32 *pPoly;
int32 z0, z1, z2;
SVECTORPC sxy0, sxy1, sxy2, stemp;
SVECTORPC sxyn0, sxyn1, sxyn2;
SVECTORPC sn0, sn1, sn2;
// Base colour for gouraud shading computation
// Could easily be specified per polygon
CVECTOR rgbIn;
CVECTOR rgb0 = {0, 0, 0, 0};
CVECTOR rgb1 = {0, 0, 0, 0};
CVECTOR rgb2 = {0, 0, 0, 0};
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < num; i++) {
// Structure is :
// 8-bits | 8-bits | 8-bits | 8-bits
// 0x20 | Blue | Green | Red
// 16-bits | 8-bits | 8-bits
// --------------------------
// v0 | n0
// v1 | n1
// v2 | n2
tmp = *pPoly++;
// code0 = tmp >> 24;
rgbIn.r = (uint8)(tmp & 0xFF);
rgbIn.g = (uint8)((tmp >> 8) & 0xFF);
rgbIn.b = (uint8)((tmp >> 16) & 0xFF);
tmp = *pPoly++;
v0 = pVertex + (tmp >> 16);
n0 = pNormal + (tmp & 0xFFFF);
tmp = *pPoly++;
v1 = pVertex + (tmp >> 16);
n1 = pNormal + (tmp & 0xFFFF);
tmp = *pPoly++;
v2 = pVertex + (tmp >> 16);
n2 = pNormal + (tmp & 0xFFFF);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
// Give the GTE some time to recover
int32 avgz;
gte_AverageZ3_pc(z0, z1, z2, &avgz);
// Do we want to do back face removal ?
if (_removeBackface) {
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
if (_useWindingOrder) {
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
// Drawing back facings polys requires making them have
// clockwise winding order as by definition they have
// anti-clockwise winding order
if (flag < 0) {
if (_drawBface) {
stemp = sxy1;
sxy1 = sxy2;
sxy2 = stemp;
ntemp = n1;
n1 = n2;
n2 = ntemp;
} else {
// Skip this polygon
continue;
}
} else if (flag == 0)
continue; // ignore zero-area polygons
}
// TODO
// dot product of viewing direction and polygon normal
// will require generation of polygon normal from vertex normals
// and transformation of the normal to world space
}
// Set the RGB colours
if (_drawLit) {
// Do the full gouraud computation
// NormalColorCol3( n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2 );
LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
int32 cval;
if (!_drawGouraud) {
// For flat shading mode take the average RGB for the face
// Could/should use something like AVSZ3
// but hell whats a divide by 3 between friends (~30 cycles?)
cval = ((rgb0.r + rgb1.r + rgb2.r) / 3);
if (cval > 255)
cval = 255;
rgb0.r = (uint8)cval;
cval = ((rgb0.g + rgb1.g + rgb2.g) / 3);
if (cval > 255)
cval = 255;
rgb0.g = (uint8)cval;
cval = ((rgb0.b + rgb1.b + rgb2.b) / 3);
if (cval > 255)
cval = 255;
rgb0.b = (uint8)cval;
}
} else {
rgbIn.r = unlitPoly.r;
rgbIn.g = unlitPoly.g;
rgbIn.b = unlitPoly.b;
}
// Put normal lines in list before wireframe
// so should be drawn in front of wireframe triangles
if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
// Do coord transform on the scaled normal vectors + v0
sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
sn1.vx = (int16)(v1->vx + (-n1->vx >> _normalScale));
sn1.vy = (int16)(v1->vy + (-n1->vy >> _normalScale));
sn1.vz = (int16)(v1->vz + (-n1->vz >> _normalScale));
sn2.vx = (int16)(v2->vx + (-n2->vx >> _normalScale));
sn2.vy = (int16)(v2->vy + (-n2->vy >> _normalScale));
sn2.vz = (int16)(v2->vz + (-n2->vz >> _normalScale));
// z0 = RotTransPers3( &sn0, &sn1, &sn2,
// &sxyn0, &sxyn1, &sxyn2, &p, &flag );
gte_RotTransPers3_pc(&sn0, &sn1, &sn2, &sxyn0, &sxyn1, &sxyn2, &p, &flag, &z0);
// Normal 0
LINE_G2 *line = (LINE_G2 *)drawpacket;
setLineG2(line);
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
if (selFace == i) {
// Bright red
setRGB0(line, 255, 0, 0);
// Bright white
setRGB1(line, 255, 255, 255);
} else {
// Bright blue
setRGB0(line, 0, 0, 255);
// Bright white
setRGB1(line, 255, 255, 255);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_G2));
// Normal 1
line = (LINE_G2 *)drawpacket;
setLineG2(line);
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxyn1.vx;
line->y1 = sxyn1.vy;
if (selFace == i) {
// Bright red
setRGB0(line, 255, 0, 0);
// Bright white
setRGB1(line, 255, 255, 255);
} else {
// Bright blue
setRGB0(line, 0, 0, 255);
// Bright white
setRGB1(line, 255, 255, 255);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_G2));
// Normal 2
line = (LINE_G2 *)drawpacket;
setLineG2(line);
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxyn2.vx;
line->y1 = sxyn2.vy;
if (selFace == i) {
// Bright red
setRGB0(line, 255, 0, 0);
// Bright white
setRGB1(line, 255, 255, 255);
} else {
// Bright blue
setRGB0(line, 0, 0, 255);
// Bright white
setRGB1(line, 255, 255, 255);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_G2));
}
// Put wireframe triangles in list before textured ones
// so should be in front of textured ones
if ((_drawWfrm) || (selFace == i)) {
// Draw a wireframe that responds to lighting
if (_drawLit) {
LINE_G4 *line = (LINE_G4 *)drawpacket;
setLineG4(line);
int32 cval;
if (_drawGouraud) {
// Give each vertex a separate colour
// Compute the colour scaling and clip it
if (rgbIn.r != 0) {
cval = ((wfrmRed * rgb0.r) / rgbIn.r);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->r0 = ctmp;
line->r3 = ctmp;
cval = ((wfrmRed * rgb1.r) / rgbIn.r);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->r1 = ctmp;
cval = ((wfrmRed * rgb2.r) / rgbIn.r);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->r2 = ctmp;
} else {
line->r0 = 0;
line->r3 = 0;
line->r1 = 0;
line->r2 = 0;
}
if (rgbIn.g != 0) {
cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->g0 = ctmp;
line->g3 = ctmp;
cval = ((wfrmGreen * rgb1.g) / rgbIn.g);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->g1 = ctmp;
cval = ((wfrmGreen * rgb2.g) / rgbIn.g);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->g2 = ctmp;
} else {
line->g0 = 0;
line->g3 = 0;
line->g1 = 0;
line->g2 = 0;
}
if (rgbIn.b != 0) {
cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->b0 = ctmp;
line->b3 = ctmp;
cval = ((wfrmBlue * rgb1.b) / rgbIn.b);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->b1 = ctmp;
cval = ((wfrmBlue * rgb2.b) / rgbIn.b);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->b2 = ctmp;
} else {
line->b0 = 0;
line->b3 = 0;
line->b1 = 0;
line->b2 = 0;
}
} else {
// Compute the colour scaling and clip it
// Flat shading so give the same colour to each vertex
if (rgbIn.r != 0) {
cval = ((wfrmRed * rgb0.r) / rgbIn.r);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
} else
ctmp = 0;
line->r0 = ctmp;
line->r1 = ctmp;
line->r2 = ctmp;
line->r3 = ctmp;
if (rgbIn.g != 0) {
cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
} else
ctmp = 0;
line->g0 = ctmp;
line->g1 = ctmp;
line->g2 = ctmp;
line->g3 = ctmp;
if (rgbIn.b != 0) {
cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
} else
ctmp = 0;
line->b0 = ctmp;
line->b1 = ctmp;
line->b2 = ctmp;
line->b3 = ctmp;
}
if (selFace == i) {
setRGB0(line, selWRed, selWGreen, selWBlue);
setRGB1(line, selWRed, selWGreen, selWBlue);
setRGB2(line, selWRed, selWGreen, selWBlue);
setRGB3(line, selWRed, selWGreen, selWBlue);
}
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_G4));
} else {
LINE_F4 *line = (LINE_F4 *)drawpacket;
setLineF4(line);
if (selFace == i)
setRGB0(line, selWRed, selWGreen, selWBlue);
else
setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_F4));
}
}
// Draw textured version behind the wireframe
if ((_drawPolys) || (selFace == i)) {
// Set the RGB colours
if (_drawLit) {
if (_drawGouraud) {
POLY_G3 *poly = (POLY_G3 *)drawpacket;
// Draw untextured polygons
setPolyG3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
setRGB1(poly, selPRed, selPGreen, selPBlue);
setRGB2(poly, selPRed, selPGreen, selPBlue);
} else {
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_G3));
} else {
POLY_F3 *poly = (POLY_F3 *)drawpacket;
// Draw untextured polygons
setPolyF3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// Flat shaded so give each vertex the same colour
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_F3));
}
} else {
POLY_F3 *poly = (POLY_F3 *)drawpacket;
// Draw untextured polygons
setPolyF3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// No light source calculation
// So just set base colour
setRGB0(poly, rgbIn.r, rgbIn.g, rgbIn.b);
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_F3));
}
}
}
}
// Flat, Textured, Lit Triangles
void drawFTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
SVECTOR *n0;
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
uint32 num = n;
uint16 uu0, uu1, uu2;
uint16 vv0, vv1, vv2;
uint32 tmp;
uint8 ctmp;
int32 p, flag;
uint32 i;
uint32 *pPoly;
int32 z0, z1, z2;
SVECTORPC sxy0, sxy1, sxy2, stemp;
SVECTORPC sxyn0;
SVECTORPC sn0;
uint32 uv0, uv1, uv2;
// Base colour for shading computation
// Could easily be specified per polygon
CVECTOR rgbIn = {128, 128, 128, 0};
CVECTOR rgb0 = {0, 0, 0, 0};
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < num; i++) {
// Structure is :
// Bit 31 ----> Bit 0
//
// 16-bits | 16-bits
// --------------------------
// v0 | u0
// v1 | u1
// v2 | u2
// --------------------------
// v0 | n0
// v2 | v1
uv0 = *pPoly++;
vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
uu0 = (uint16)(uv0 & 0xFFFF);
uv1 = *pPoly++;
vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
uu1 = (uint16)(uv1 & 0xFFFF);
uv2 = *pPoly++;
vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
uu2 = (uint16)(uv2 & 0xFFFF);
tmp = *pPoly++;
v0 = pVertex + (tmp >> 16);
n0 = pNormal + (tmp & 0xFFFF);
tmp = *pPoly++;
v1 = pVertex + (tmp & 0xFFFF);
v2 = pVertex + (tmp >> 16);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
// Give the GTE some time to recover
int32 avgz;
gte_AverageZ3_pc(z0, z1, z2, &avgz);
// Do we want to do back face removal ?
if (_removeBackface) {
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
if (_useWindingOrder) {
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
// Drawing back facings polys requires making them have
// clockwise winding order as by definition they have
// anti-clockwise winding order
if (flag < 0) {
if (_drawBface) {
stemp = sxy1;
sxy1 = sxy2;
sxy2 = stemp;
flag = uv1;
uv1 = uv2;
uv2 = flag;
} else {
// Skip this polygon
continue;
}
} else if (flag == 0)
continue; // ignore zero-area polygons
}
// TODO
// dot product of viewing direction and polygon normal
// will require generation of polygon normal from vertex normals
// and transformation of the normal to world space
}
// Set the RGB colours
if (_drawLit) {
// Do the full gouraud computation
// NormalColorCol( n0, &rgbIn, &rgb0 );
LIGHTPOLYGON(n0, &rgbIn, &rgb0);
}
// Put normal lines in list before wireframe
// so should be drawn in front of wireframe triangles
if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
// Do coord transform on the scaled normal vectors + v0
sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
// z0 = RotTransPers( &sn0, &sxyn0, &p, &flag );
gte_RotTransPers_pc(&sn0, &sxyn0, &p, &flag, &z0);
// Normal 0
LINE_G2 *line = (LINE_G2 *)drawpacket;
setLineG2(line);
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxyn0.vx;
line->y1 = sxyn0.vy;
if (selFace == i) {
// Bright red
setRGB0(line, 255, 0, 0);
// Bright white
setRGB1(line, 255, 255, 255);
} else {
// Bright blue
setRGB0(line, 0, 0, 255);
// Bright white
setRGB1(line, 255, 255, 255);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_G2));
}
// Put wireframe triangles in list before textured ones
// so should be in front of textured ones
if ((_drawWfrm) || (selFace == i)) {
// Draw a wireframe that responds to lighting
if (_drawLit) {
int32 cval;
LINE_G4 *line = (LINE_G4 *)drawpacket;
setLineG4(line);
// Compute the colour scaling and clip it
// Flat shading so give the same colour to each vertex
cval = ((wfrmRed * rgb0.r) / rgbIn.r);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->r0 = ctmp;
line->r1 = ctmp;
line->r2 = ctmp;
line->r3 = ctmp;
cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->g0 = ctmp;
line->g1 = ctmp;
line->g2 = ctmp;
line->g3 = ctmp;
cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->b0 = ctmp;
line->b1 = ctmp;
line->b2 = ctmp;
line->b3 = ctmp;
if (selFace == i) {
setRGB0(line, selWRed, selWGreen, selWBlue);
setRGB1(line, selWRed, selWGreen, selWBlue);
setRGB2(line, selWRed, selWGreen, selWBlue);
setRGB3(line, selWRed, selWGreen, selWBlue);
}
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_G4));
} else {
LINE_F4 *line = (LINE_F4 *)drawpacket;
setLineF4(line);
if (selFace == i)
setRGB0(line, selWRed, selWGreen, selWBlue);
else
setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_F4));
}
}
// Draw textured version behind the wireframe
if ((_drawPolys) || (selFace == i)) {
if (_drawTxture) {
POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
setPolyFT3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
if (_drawLit) {
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
} else {
// No light source calculation
// So just set base colour
setRGB0(poly, rgbIn.r, rgbIn.g, rgbIn.b);
}
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_FT3));
} else {
// Set the RGB colours
if (_drawLit) {
POLY_F3 *poly = (POLY_F3 *)drawpacket;
// Draw untextured polygons
setPolyF3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// Flat shaded so give each vertex the same colour
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
} else {
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_F3));
} else {
POLY_F3 *poly = (POLY_F3 *)drawpacket;
// Draw untextured polygons
setPolyF3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// No light source calculation
// So just set base colour
setRGB0(poly, rgbIn.r, rgbIn.g, rgbIn.b);
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_F3));
}
}
}
}
}
// Gouraud, Textured, Lit Triangles
void drawGTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
SVECTOR *n0;
SVECTOR *n1;
SVECTOR *n2;
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
SVECTOR *ntemp;
// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
uint32 num = n;
uint16 uu0, uu1, uu2;
uint16 vv0, vv1, vv2;
uint32 tmp;
uint8 ctmp;
int32 p, flag;
uint32 i;
uint32 *pPoly;
int32 z0, z1, z2;
SVECTORPC sxy0, sxy1, sxy2, stemp;
SVECTORPC sxyn0, sxyn1, sxyn2;
SVECTORPC sn0, sn1, sn2;
uint32 uv0, uv1, uv2;
// Base colour for gouraud shading computation
// Could easily be specified per polygon
CVECTOR rgbIn = {128, 128, 128, 0};
CVECTOR rgb0 = {0, 0, 0, 0};
CVECTOR rgb1 = {0, 0, 0, 0};
CVECTOR rgb2 = {0, 0, 0, 0};
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < num; i++) {
// Structure is :
// v0, u0
// v1, u1
// v2, u2
// v0 | n0
// v1 | n1
// v2 | n2
uv0 = *pPoly++;
vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
uu0 = (uint16)(uv0 & 0xFFFF);
uv1 = *pPoly++;
vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
uu1 = (uint16)(uv1 & 0xFFFF);
uv2 = *pPoly++;
vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
uu2 = (uint16)(uv2 & 0xFFFF);
tmp = *pPoly++;
v0 = pVertex + (tmp >> 16);
n0 = pNormal + (tmp & 0xFFFF);
tmp = *pPoly++;
v1 = pVertex + (tmp >> 16);
n1 = pNormal + (tmp & 0xFFFF);
tmp = *pPoly++;
v2 = pVertex + (tmp >> 16);
n2 = pNormal + (tmp & 0xFFFF);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
// Give the GTE some time to recover
int32 avgz;
gte_AverageZ3_pc(z0, z1, z2, &avgz);
// Do we want to do back face removal ?
if (_removeBackface) {
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
if (_useWindingOrder) {
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
// Drawing back facings polys requires making them have
// clockwise winding order as by definition they have
// anti-clockwise winding order
if (flag < 0) {
if (_drawBface) {
stemp = sxy1;
sxy1 = sxy2;
sxy2 = stemp;
ntemp = n1;
n1 = n2;
n2 = ntemp;
flag = uv1;
uv1 = uv2;
uv2 = flag;
} else {
// Skip this polygon
continue;
}
} else if (flag == 0)
continue; // ignore zero-area polygons
}
// TODO
// dot product of viewing direction and polygon normal
// will require generation of polygon normal from vertex normals
// and transformation of the normal to world space
}
// Set the RGB colours
if (_drawLit) {
// Do the full gouraud computation
// NormalColorCol3( n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2 );
LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
int32 cval;
if (!_drawGouraud) {
// For flat shading mode take the average RGB for the face
// Could/should use something like AVSZ3
// but hell whats a divide by 3 between friends (~30 cycles?)
cval = ((rgb0.r + rgb1.r + rgb2.r) / 3);
if (cval > 255)
cval = 255;
rgb0.r = (uint8)cval;
cval = ((rgb0.g + rgb1.g + rgb2.g) / 3);
if (cval > 255)
cval = 255;
rgb0.g = (uint8)cval;
cval = ((rgb0.b + rgb1.b + rgb2.b) / 3);
if (cval > 255)
cval = 255;
rgb0.b = (uint8)cval;
}
}
// Put normal lines in list before wireframe
// so should be drawn in front of wireframe triangles
if ((_drawNormals) && ((selFace == i) || (selFace > 65536))) {
// Do coord transform on the scaled normal vectors + v0
sn0.vx = (int16)(v0->vx + (-n0->vx >> _normalScale));
sn0.vy = (int16)(v0->vy + (-n0->vy >> _normalScale));
sn0.vz = (int16)(v0->vz + (-n0->vz >> _normalScale));
sn1.vx = (int16)(v1->vx + (-n1->vx >> _normalScale));
sn1.vy = (int16)(v1->vy + (-n1->vy >> _normalScale));
sn1.vz = (int16)(v1->vz + (-n1->vz >> _normalScale));
sn2.vx = (int16)(v2->vx + (-n2->vx >> _normalScale));
sn2.vy = (int16)(v2->vy + (-n2->vy >> _normalScale));
sn2.vz = (int16)(v2->vz + (-n2->vz >> _normalScale));
// z0 = RotTransPers3( &sn0, &sn1, &sn2,
// &sxyn0, &sxyn1, &sxyn2, &p, &flag );
gte_RotTransPers3_pc(&sn0, &sn1, &sn2, &sxyn0, &sxyn1, &sxyn2, &p, &flag, &z0);
// Normal 0
LINE_G2 *line = (LINE_G2 *)drawpacket;
setLineG2(line);
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxyn0.vx;
line->y1 = sxyn0.vy;
if (selFace == i) {
// Bright red
setRGB0(line, 255, 0, 0);
// Bright white
setRGB1(line, 255, 255, 255);
} else {
// Bright blue
setRGB0(line, 0, 0, 255);
// Bright white
setRGB1(line, 255, 255, 255);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_G2));
// Normal 1
line = (LINE_G2 *)drawpacket;
setLineG2(line);
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxyn1.vx;
line->y1 = sxyn1.vy;
if (selFace == i) {
// Bright red
setRGB0(line, 255, 0, 0);
// Bright white
setRGB1(line, 255, 255, 255);
} else {
// Bright blue
setRGB0(line, 0, 0, 255);
// Bright white
setRGB1(line, 255, 255, 255);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_G2));
// Normal 2
line = (LINE_G2 *)drawpacket;
setLineG2(line);
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxyn2.vx;
line->y1 = sxyn2.vy;
if (selFace == i) {
// Bright red
setRGB0(line, 255, 0, 0);
// Bright white
setRGB1(line, 255, 255, 255);
} else {
// Bright blue
setRGB0(line, 0, 0, 255);
// Bright white
setRGB1(line, 255, 255, 255);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_G2));
}
// Put wireframe triangles in list before textured ones
// so should be in front of textured ones
if ((_drawWfrm) || (selFace == i)) {
// Draw a wireframe that responds to lighting
if (_drawLit) {
LINE_G4 *line = (LINE_G4 *)drawpacket;
setLineG4(line);
int32 cval;
if (_drawGouraud) {
// Give each vertex a separate colour
// Compute the colour scaling and clip it
if (rgbIn.r != 0) {
cval = ((wfrmRed * rgb0.r) / rgbIn.r);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->r0 = ctmp;
line->r3 = ctmp;
cval = ((wfrmRed * rgb1.r) / rgbIn.r);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->r1 = ctmp;
cval = ((wfrmRed * rgb2.r) / rgbIn.r);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->r2 = ctmp;
} else {
line->r0 = 0;
line->r3 = 0;
line->r1 = 0;
line->r2 = 0;
}
if (rgbIn.g != 0) {
cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->g0 = ctmp;
line->g3 = ctmp;
cval = ((wfrmGreen * rgb1.g) / rgbIn.g);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->g1 = ctmp;
cval = ((wfrmGreen * rgb2.g) / rgbIn.g);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->g2 = ctmp;
} else {
line->g0 = 0;
line->g3 = 0;
line->g1 = 0;
line->g2 = 0;
}
if (rgbIn.b != 0) {
cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->b0 = ctmp;
line->b3 = ctmp;
cval = ((wfrmBlue * rgb1.b) / rgbIn.b);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->b1 = ctmp;
cval = ((wfrmBlue * rgb2.b) / rgbIn.b);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
line->b2 = ctmp;
} else {
line->b0 = 0;
line->b3 = 0;
line->b1 = 0;
line->b2 = 0;
}
} else {
// Compute the colour scaling and clip it
// Flat shading so give the same colour to each vertex
if (rgbIn.r != 0) {
cval = ((wfrmRed * rgb0.r) / rgbIn.r);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
} else
ctmp = 0;
line->r0 = ctmp;
line->r1 = ctmp;
line->r2 = ctmp;
line->r3 = ctmp;
if (rgbIn.g != 0) {
cval = ((wfrmGreen * rgb0.g) / rgbIn.g);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
} else
ctmp = 0;
line->g0 = ctmp;
line->g1 = ctmp;
line->g2 = ctmp;
line->g3 = ctmp;
if (rgbIn.b != 0) {
cval = ((wfrmBlue * rgb0.b) / rgbIn.b);
if (cval > 255)
cval = 255;
ctmp = (uint8)cval;
} else
ctmp = 0;
line->b0 = ctmp;
line->b1 = ctmp;
line->b2 = ctmp;
line->b3 = ctmp;
}
if (selFace == i) {
setRGB0(line, selWRed, selWGreen, selWBlue);
setRGB1(line, selWRed, selWGreen, selWBlue);
setRGB2(line, selWRed, selWGreen, selWBlue);
setRGB3(line, selWRed, selWGreen, selWBlue);
}
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_G4));
} else {
LINE_F4 *line = (LINE_F4 *)drawpacket;
setLineF4(line);
if (selFace == i)
setRGB0(line, selWRed, selWGreen, selWBlue);
else
setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_F4));
}
}
// Draw textured version behind the wireframe
if ((_drawPolys) || (selFace == i)) {
if (_drawTxture) {
// Set the RGB colours
if ((_drawLit) && (_drawGouraud)) {
POLY_GT3 *poly = (POLY_GT3 *)drawpacket;
setPolyGT3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
setRGB1(poly, selPRed, selPGreen, selPBlue);
setRGB2(poly, selPRed, selPGreen, selPBlue);
} else {
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_GT3));
} else {
POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
setPolyFT3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
if (_drawLit) {
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
} else {
// No light source calculation
// So just set base colour
setRGB0(poly, rgbIn.r, rgbIn.g, rgbIn.b);
}
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_FT3));
}
} else {
// Set the RGB colours
if (_drawLit) {
if (_drawGouraud) {
POLY_G3 *poly = (POLY_G3 *)drawpacket;
// Draw untextured polygons
setPolyG3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
setRGB1(poly, selPRed, selPGreen, selPBlue);
setRGB2(poly, selPRed, selPGreen, selPBlue);
} else {
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_G3));
} else {
POLY_F3 *poly = (POLY_F3 *)drawpacket;
// Draw untextured polygons
setPolyF3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// Flat shaded so give each vertex the same colour
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
} else {
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_F3));
}
} else {
POLY_F3 *poly = (POLY_F3 *)drawpacket;
// Draw untextured polygons
setPolyF3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// No light source calculation
// So just set base colour
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
} else {
setRGB0(poly, unlitPoly.r, unlitPoly.g, unlitPoly.b);
poly->code = unlitPoly.cd;
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_F3));
}
}
}
}
}
// Simple flat untextured triangles
// draw backfacing triangles as well
// the colour is set by a global variable
void drawTRI3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
// uint32 num = min( n, 10 ); // do a maximum of 10 polygons
uint32 num = n;
int32 p, flag;
uint32 i;
uint32 *pPoly;
int32 z0, z1, z2;
SVECTORPC sxy0, sxy1, sxy2, stemp;
uint32 tmp;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < num; i++) {
// Each polygon is 2 32-bit WORDS
// Bit 31 ----> Bit 0
//
// 16-bits | 16-bits
// --------------------------
// v1 | v0
// pad | v2
tmp = *pPoly++;
v0 = pVertex + (tmp & 0xFFFF);
v1 = pVertex + (tmp >> 16);
tmp = *pPoly++;
v2 = pVertex + (tmp & 0xFFFF);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
gte_RotTransPers_pc(v0, &sxy0, &p, &flag, &z0);
z0 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v1, &sxy1, &p, &flag, &z1);
z1 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
gte_RotTransPers_pc(v2, &sxy2, &p, &flag, &z2);
z2 <<= 2; // multiply by 4 to cope with AverageZ later on dividing by 4
// test the return value of flag
if (flag & 0x80000000)
continue;
// Give the GTE some time to recover
int32 avgz;
gte_AverageZ3_pc(z0, z1, z2, &avgz);
// See what winding order this polygon is ?
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
// Drawing back facing polys requires making them have
// clockwise winding order as by definition they have
// anti-clockwise winding order
if (flag < 0) {
stemp = sxy1;
sxy1 = sxy2;
sxy2 = stemp;
}
// Put wireframe triangles in list before textured ones
// so should be in front of textured ones
if ((_drawWfrm) || (selFace == i)) {
LINE_F4 *line = (LINE_F4 *)drawpacket;
setLineF4(line);
// set XY's in the GPU packet 0-1-2-3
line->x0 = sxy0.vx;
line->y0 = sxy0.vy;
line->x1 = sxy1.vx;
line->y1 = sxy1.vy;
line->x2 = sxy2.vx;
line->y2 = sxy2.vy;
line->x3 = sxy0.vx;
line->y3 = sxy0.vy;
if (selFace == i)
setRGB0(line, selWRed, selWGreen, selWBlue);
else
setRGB0(line, (uint8)wfrmRed, (uint8)wfrmGreen, (uint8)wfrmBlue);
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(LINE_F4));
}
// Draw polygon version behind the wireframe
if ((_drawPolys) || (selFace == i)) {
// Draw untextured polygons
TPOLY_F3 *poly = (TPOLY_F3 *)drawpacket;
setTPolyF3(poly);
setTABRMode(poly, 2); // 2 = back - front
setTSemiTrans(poly, 1); // 1 = enable semi-transparency
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// Set the RGB colours
// No light source calculation
// So just set base colour
if (selFace == i) {
setRGB0(poly, selPRed, selPGreen, selPBlue);
poly->code = selPAlpha;
} else {
setRGB0(poly, unlitPoly.r, unlitPoly.g, unlitPoly.b);
poly->code = unlitPoly.cd;
}
// Put it into the global ot at the correct place
myAddPrimClip(avgz, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(TPOLY_F3));
}
}
}
// Flat, Un-Textured, Self-Luminous, triangles
void fastDrawFUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
int32 flag;
uint32 i;
uint32 *pPoly;
int32 z0;
SVECTORPC sxy0, sxy1, sxy2;
CVECTOR *rgbIn;
uint32 tmp;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < n; i++) {
// Structure is :
// 0x20 | B | G | R
// v1 | v0
// pad | v2
rgbIn = (CVECTOR *)pPoly++;
if (deadObject) {
rgbIn = &deadObjectColour;
}
tmp = *pPoly++;
v0 = pVertex + (tmp & 0xFFFF);
v1 = pVertex + (tmp >> 16);
tmp = *pPoly++;
v2 = pVertex + (tmp & 0xFFFF);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
// test the return value of flag
// The vertices have been pre-transformed into screen space and stored in the vertex pool
// The flag value is set to 0x8000 or 0 in the pad structure
if (v0->pad != 0)
continue;
if (v1->pad != 0)
continue;
if (v2->pad != 0)
continue;
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
sxy0.vx = v0->vx;
sxy0.vy = v0->vy;
sxy1.vx = v1->vx;
sxy1.vy = v1->vy;
sxy2.vx = v2->vx;
sxy2.vy = v2->vy;
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
if (flag <= 0)
continue;
// Draw untextured polygons
POLY_F3 *poly = (POLY_F3 *)drawpacket;
setPolyF3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// Set the RGB colours
// No light source calculation
// So just set base colour
setRGB0(poly, rgbIn->r, rgbIn->g, rgbIn->b);
// Give the GTE some time to recover
gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
// Put it into the global ot at the correct place
myAddPrimClip(z0, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_F3));
}
}
// Fast: no options, Gouraud, Un-Textured, Self-Luminous, triangles
void fastDrawGUS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
uint32 tmp;
int32 flag;
uint32 i;
uint32 *pPoly;
int32 z0;
SVECTORPC sxy0, sxy1, sxy2;
// Base colour for gouraud shading computation
// Could easily be specified per polygon
CVECTOR *rgb0;
CVECTOR *rgb1;
CVECTOR *rgb2;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < n; i++) {
// Structure is :
// 8-bits | 8-bits | 8-bits | 8-bits
// 0x30 | Blue0 | Green0 | Red0
// 0x30 | Blue1 | Green1 | Red1
// 0x30 | Blue2 | Green2 | Red2
// 16-bits | 8-bits | 8-bits
// --------------------------
// v1 | v0
// pad | v2
rgb0 = (CVECTOR *)pPoly++;
rgb1 = (CVECTOR *)pPoly++;
rgb2 = (CVECTOR *)pPoly++;
if (deadObject) {
rgb0 = &deadObjectColour;
rgb1 = &deadObjectColour;
rgb2 = &deadObjectColour;
}
tmp = *pPoly++;
v0 = pVertex + (tmp & 0xFFFF);
v1 = pVertex + (tmp >> 16);
tmp = *pPoly++;
v2 = pVertex + (tmp & 0xFFFF);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
// gte_RotTransPers3(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
// test the return value of flag
// The vertices have been pre-transformed into screen space and stored in the vertex pool
// The flag value is set to 0x8000 or 0 in the pad structure
if (v0->pad != 0)
continue;
if (v1->pad != 0)
continue;
if (v2->pad != 0)
continue;
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
sxy0.vx = v0->vx;
sxy0.vy = v0->vy;
sxy1.vx = v1->vx;
sxy1.vy = v1->vy;
sxy2.vx = v2->vx;
sxy2.vy = v2->vy;
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
if (flag <= 0)
continue;
POLY_G3 *poly = (POLY_G3 *)drawpacket;
// Draw untextured polygons
setPolyG3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
setRGB0(poly, rgb0->r, rgb0->g, rgb0->b);
setRGB1(poly, rgb1->r, rgb1->g, rgb1->b);
setRGB2(poly, rgb2->r, rgb2->g, rgb2->b);
// Give the GTE some time to recover
gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
// Put it into the global ot at the correct place
myAddPrimClip(z0, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_G3));
}
}
// Fast: no options, Flat, Textured, Self-Luminous Triangles
void fastDrawFTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
uint16 uu0, uu1, uu2;
uint16 vv0, vv1, vv2;
uint32 tmp;
int32 flag;
uint32 i;
uint32 *pPoly;
int32 z0;
SVECTORPC sxy0, sxy1, sxy2;
uint32 uv0, uv1, uv2;
// Base colour for shading computation
// Could easily be specified per polygon
CVECTOR *rgbIn;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < n; i++) {
// Structure is :
// Bit 31 ----> Bit 0
//
// 8-bits | 8-bits | 8-bits | 8-bits
// 0x24 | Blue | Green | Red
// 16-bits | 16-bits
// --------------------------
// v0 | u0
// v1 | u1
// v2 | u2
// --------------------------
// pad | v0
// v2 | v1
rgbIn = (CVECTOR *)pPoly++;
if (deadObject == 1) {
rgbIn = &deadObjectColour;
}
uv0 = *pPoly++;
vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
uu0 = (uint16)(uv0 & 0xFFFF);
uv1 = *pPoly++;
vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
uu1 = (uint16)(uv1 & 0xFFFF);
uv2 = *pPoly++;
vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
uu2 = (uint16)(uv2 & 0xFFFF);
tmp = *pPoly++;
v0 = pVertex + (tmp & 0xFFFF);
tmp = *pPoly++;
v1 = pVertex + (uint)(tmp & 0xFFFF);
v2 = pVertex + (uint)(tmp >> 16);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
// test the return value of flag
// The vertices have been pre-transformed into screen space and stored in the vertex pool
// The flag value is set to 0x8000 or 0 in the pad structure
if (v0->pad != 0)
continue;
if (v1->pad != 0)
continue;
if (v2->pad != 0)
continue;
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
sxy0.vx = v0->vx;
sxy0.vy = v0->vy;
sxy1.vx = v1->vx;
sxy1.vy = v1->vy;
sxy2.vx = v2->vx;
sxy2.vy = v2->vy;
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
if (flag <= 0)
continue;
POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
setPolyFT3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
// No light source calculation so just set base colour
setRGB0(poly, rgbIn->r, rgbIn->b, rgbIn->b);
// Give the GTE some time to recover
gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
// Put it into the global ot at the correct place
myAddPrimClip(z0, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_FT3));
}
}
// Fast: no options, Gouraud, Textured, Self-Luminous Triangles
void fastDrawGTS3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
uint16 uu0, uu1, uu2;
uint16 vv0, vv1, vv2;
uint32 tmp;
int32 flag;
uint32 i;
uint32 *pPoly;
int32 z0;
SVECTORPC sxy0, sxy1, sxy2;
uint32 uv0, uv1, uv2;
// gouraud colours
CVECTOR *rgb0;
CVECTOR *rgb1;
CVECTOR *rgb2;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < n; i++) {
// Structure is :
// 8-bits | 8-bits | 8-bits | 8-bits
// 0x34 | Blue0 | Green0 | Red0
// 0x34 | Blue1 | Green1 | Red1
// 0x34 | Blue2 | Green2 | Red2
// 16-bits | 16-bits
// --------------------------
// v0 | u0
// v1 | u1
// v2 | u2
// --------------------------
// pad | v0
// v2 | v1
rgb0 = (CVECTOR *)pPoly++;
rgb1 = (CVECTOR *)pPoly++;
rgb2 = (CVECTOR *)pPoly++;
if (deadObject) {
rgb0 = &deadObjectColour;
rgb1 = &deadObjectColour;
rgb2 = &deadObjectColour;
}
uv0 = *pPoly++;
vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
uu0 = (uint16)(uv0 & 0xFFFF);
uv1 = *pPoly++;
vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
uu1 = (uint16)(uv1 & 0xFFFF);
uv2 = *pPoly++;
vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
uu2 = (uint16)(uv2 & 0xFFFF);
tmp = *pPoly++;
v0 = pVertex + (tmp & 0xFFFF);
tmp = *pPoly++;
v1 = pVertex + (tmp & 0xFFFF);
v2 = pVertex + (tmp >> 16);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
// test the return value of flag
// The vertices have been pre-transformed into screen space and stored in the vertex pool
// The flag value is set to 0x8000 or 0 in the pad structure
if (v0->pad != 0)
continue;
if (v1->pad != 0)
continue;
if (v2->pad != 0)
continue;
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
sxy0.vx = v0->vx;
sxy0.vy = v0->vy;
sxy1.vx = v1->vx;
sxy1.vy = v1->vy;
sxy2.vx = v2->vx;
sxy2.vy = v2->vy;
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
if (flag <= 0)
continue;
// Set the RGB colours
POLY_GT3 *poly = (POLY_GT3 *)drawpacket;
setPolyGT3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
setRGB0(poly, rgb0->r, rgb0->b, rgb0->b);
setRGB1(poly, rgb1->r, rgb1->b, rgb1->b);
setRGB2(poly, rgb2->r, rgb2->b, rgb2->b);
// Give the GTE some time to recover
gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
// Put it into the global ot at the correct place
myAddPrimClip(z0, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_GT3));
}
}
// Fast: no options, Flat, Un-Textured, Lit, triangles
void fastDrawFUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
SVECTOR *n0;
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
int32 flag;
uint32 i;
uint32 *pPoly;
int32 z0;
SVECTORPC sxy0, sxy1, sxy2;
CVECTOR *rgbIn;
CVECTOR rgb0;
uint32 tmp;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < n; i++) {
// Structure is :
// 0x20 | B | G | R
// v0 | n0
// v2 | v1
rgbIn = (CVECTOR *)pPoly++;
tmp = *pPoly++;
v0 = pVertex + (tmp >> 16);
n0 = pNormal + (tmp & 0xFFFF);
tmp = *pPoly++;
v2 = pVertex + (tmp >> 16);
v1 = pVertex + (tmp & 0xFFFF);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
// test the return value of flag
// The vertices have been pre-transformed into screen space and stored in the vertex pool
// The flag value is set to 0x8000 or 0 in the pad structure
if (v0->pad != 0)
continue;
if (v1->pad != 0)
continue;
if (v2->pad != 0)
continue;
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
sxy0.vx = v0->vx;
sxy0.vy = v0->vy;
sxy1.vx = v1->vx;
sxy1.vy = v1->vy;
sxy2.vx = v2->vx;
sxy2.vy = v2->vy;
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
if (flag <= 0)
continue;
// Do the flat lighting computation
LIGHTPOLYGON(n0, rgbIn, &rgb0);
// Draw untextured polygons
POLY_F3 *poly = (POLY_F3 *)drawpacket;
setPolyF3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// Set the RGB colours
// Flat shaded so give each vertex the same colour
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
// Give the GTE some time to recover
gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
// Put it into the global ot at the correct place
myAddPrimClip(z0, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_F3));
}
}
// Fast: no options, Gouraud, Un-Textured, Lit, triangles
void fastDrawGUL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
SVECTOR *n0;
SVECTOR *n1;
SVECTOR *n2;
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
uint32 tmp;
int32 flag;
uint32 i;
uint32 *pPoly;
int32 z0;
SVECTORPC sxy0, sxy1, sxy2;
// Base colour for gouraud shading computation
// Could easily be specified per polygon
CVECTOR rgbIn = {128, 128, 128, 0};
CVECTOR rgb0, rgb1, rgb2;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < n; i++) {
// Structure is :
// 8-bits | 8-bits | 8-bits | 8-bits
// 0x20 | Blue | Green | Red
// 16-bits | 8-bits | 8-bits
// --------------------------
// v0 | n0
// v1 | n1
// v2 | n2
tmp = *pPoly++;
// code0 = tmp >> 24;
rgbIn.r = (uint8)(tmp & 0xFF);
rgbIn.g = (uint8)((tmp >> 8) & 0xFF);
rgbIn.b = (uint8)((tmp >> 16) & 0xFF);
tmp = *pPoly++;
v0 = pVertex + (tmp >> 16);
n0 = pNormal + (tmp & 0xFFFF);
tmp = *pPoly++;
v1 = pVertex + (tmp >> 16);
n1 = pNormal + (tmp & 0xFFFF);
tmp = *pPoly++;
v2 = pVertex + (tmp >> 16);
n2 = pNormal + (tmp & 0xFFFF);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
// test the return value of flag
// The vertices have been pre-transformed into screen space and stored in the vertex pool
// The flag value is set to 0x8000 or 0 in the pad structure
if (v0->pad != 0)
continue;
if (v1->pad != 0)
continue;
if (v2->pad != 0)
continue;
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
sxy0.vx = v0->vx;
sxy0.vy = v0->vy;
sxy1.vx = v1->vx;
sxy1.vy = v1->vy;
sxy2.vx = v2->vx;
sxy2.vy = v2->vy;
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
if (flag <= 0)
continue;
// Do the full gouraud computation
// NormalColorCol3( n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2 );
LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
POLY_G3 *poly = (POLY_G3 *)drawpacket;
// Draw untextured polygons
setPolyG3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
// Give the GTE some time to recover
gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
// Put it into the global ot at the correct place
myAddPrimClip(z0, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_G3));
}
}
//------------------------------------------------------------------------
// Fast: no options, Flat, Textured, Lit Triangles
void fastDrawFTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
SVECTOR *n0;
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
uint16 uu0, uu1, uu2;
uint16 vv0, vv1, vv2;
uint32 tmp;
int32 flag;
uint32 i;
uint32 *pPoly;
int32 z0;
SVECTORPC sxy0, sxy1, sxy2;
uint32 uv0, uv1, uv2;
// Base colour for shading computation
// Could easily be specified per polygon
CVECTOR rgbIn = {128, 128, 128, 0};
CVECTOR rgb0;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < n; i++) {
// Structure is :
// Bit 31 ----> Bit 0
//
// 16-bits | 16-bits
// --------------------------
// v0 | u0
// v1 | u1
// v2 | u2
// --------------------------
// v0 | n0
// v2 | v1
uv0 = *pPoly++;
vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
uu0 = (uint16)(uv0 & 0xFFFF);
uv1 = *pPoly++;
vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
uu1 = (uint16)(uv1 & 0xFFFF);
uv2 = *pPoly++;
vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
uu2 = (uint16)(uv2 & 0xFFFF);
tmp = *pPoly++;
v0 = pVertex + (tmp >> 16);
n0 = pNormal + (tmp & 0xFFFF);
tmp = *pPoly++;
v1 = pVertex + (tmp & 0xFFFF);
v2 = pVertex + (tmp >> 16);
// Now do RotTransPers3 on the vectors
// z0 = RotTransPers3( v0, v1, v2, &sxy0, &sxy1, &sxy2, &p, &flag );
// gte_RotTransPers3_pc(v0,v1,v2,&sxy0,&sxy1,&sxy2,&p,&flag,&z0);
// test the return value of flag
// The vertices have been pre-transformed into screen space and stored in the vertex pool
// The flag value is set to 0x8000 or 0 in the pad structure
if (v0->pad != 0)
continue;
if (v1->pad != 0)
continue;
if (v2->pad != 0)
continue;
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
sxy0.vx = v0->vx;
sxy0.vy = v0->vy;
sxy1.vx = v1->vx;
sxy1.vy = v1->vy;
sxy2.vx = v2->vx;
sxy2.vy = v2->vy;
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
if (flag <= 0)
continue;
// Do the full gouraud computation
// NormalColorCol( n0, &rgbIn, &rgb0 );
LIGHTPOLYGON(n0, &rgbIn, &rgb0);
POLY_FT3 *poly = (POLY_FT3 *)drawpacket;
setPolyFT3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
// Give the GTE some time to recover
gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
// Put it into the global ot at the correct place
myAddPrimClip(z0, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_FT3));
}
}
// Fast : no options : Gouraud, Textured, Lit Triangles
void fastDrawGTL3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex, SVECTOR *pNormal) {
SVECTOR *n0;
SVECTOR *n1;
SVECTOR *n2;
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
uint16 uu0;
uint16 uu1;
uint16 uu2;
uint16 vv0;
uint16 vv1;
uint16 vv2;
int32 flag;
uint32 i;
int32 z0;
uint32 uv0;
uint32 uv1;
uint32 uv2;
uint32 vt0;
uint32 vt1;
uint32 vt2;
SVECTORPC sxy0;
SVECTORPC sxy1;
SVECTORPC sxy2;
int32 pad0;
int32 pad1;
int32 pad2;
// Base colour for gouraud shading computation
// Could easily be specified per polygon
CVECTOR rgbIn = {128, 128, 128, 0};
CVECTOR rgb0, rgb1, rgb2;
POLY_GT3 *poly;
uint32 *pPoly;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < n; i++) {
// Structure is :
// v0, u0
// v1, u1
// v2, u2
// v0 | n0
// v1 | n1
// v2 | n2
uv0 = *(pPoly++);
vv0 = (uint16)((uv0 >> 16) & 0xFFFF);
uu0 = (uint16)(uv0 & 0xFFFF);
uv1 = *(pPoly++);
vv1 = (uint16)((uv1 >> 16) & 0xFFFF);
uu1 = (uint16)(uv1 & 0xFFFF);
uv2 = *(pPoly++);
vv2 = (uint16)((uv2 >> 16) & 0xFFFF);
uu2 = (uint16)(uv2 & 0xFFFF);
vt0 = *(pPoly++);
v0 = (pVertex + (vt0 >> 16));
n0 = (pNormal + (vt0 & 0xFFFF));
vt1 = *(pPoly++);
v1 = (pVertex + (vt1 >> 16));
n1 = (pNormal + (vt1 & 0xFFFF));
vt2 = *(pPoly++);
v2 = (pVertex + (vt2 >> 16));
n2 = (pNormal + (vt2 & 0xFFFF));
// The vertices have been pre-transformed into screen space and stored in the vertex pool
// The flag value is set to 0x8000 or 0 in the pad structure
pad0 = v0->pad;
pad1 = v1->pad;
pad2 = v2->pad;
flag = pad0 | pad1 | pad2;
if (flag != 0)
continue;
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
sxy0.vx = v0->vx;
sxy0.vy = v0->vy;
sxy1.vx = v1->vx;
sxy1.vy = v1->vy;
sxy2.vx = v2->vx;
sxy2.vy = v2->vy;
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
// Give the GTE some time to recover
// Ignore polygons which are too small
if (flag <= 0)
continue;
// Do the full gouraud computation
LIGHTPOLYGON3(n0, n1, n2, &rgbIn, &rgb0, &rgb1, &rgb2);
// Try to overlap this with the LIGHTPOLYGON3 !
poly = (POLY_GT3 *)drawpacket;
setPolyGT3(poly);
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// Give the GTE some time to recover
gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
setUV3(poly, uu0, vv0, uu1, vv1, uu2, vv2);
setRGB0(poly, rgb0.r, rgb0.g, rgb0.b);
setRGB1(poly, rgb1.r, rgb1.g, rgb1.b);
setRGB2(poly, rgb2.r, rgb2.g, rgb2.b);
// Put it into the global ot at the correct place
myAddPrimClip(z0, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(POLY_GT3));
}
}
// For mucking about with lighting
// Draw a solid bounding box around the actor (and so obscuring him)
// but then have the box respond to the lights e.g. give it normals
// and do flat & goraud shading
// Assume the GTE lighting registers to be pre-prepared
void drawSolidBboxPC(SVECTOR *scrn, CVECTOR *rgbIn) {
// 6 POLY_F4's i.e. 6 faces
// The 8 verticies are:
// 0 { xmin, ymin, zmin },
// 1 { xmin, ymin, zmax },
// 2 { xmax, ymin, zmin },
// 3 { xmax, ymin, zmax },
// 4 { xmax, ymax, zmin },
// 5 { xmax, ymax, zmax },
// 6 { xmin, ymax, zmin },
// 7 { xmin, ymax, zmax }
// The 6 faces are the following vertex links:
// ymin face : 0->1->3->2
// xmax face : 2->3->5->4
// zmin face : 0->2->4->6
// xmin face : 0->6->7->1
// zmax face : 1->7->5->3
// ymax face : 6->4->5->7
// The 6 face normals are (normal points into front side of face on PSX)
// ymin face : 0,+4096,0 +ve y
// xmax face : -4096,0,0 -ve x
// zmin face : 0,0,+4096 +ve z
// xmin face : +4096,0,0 +ve x
// zmax face : 0,0,-4096 -ve z
// ymax face : 0,-4096,0 -ve y
int32 z0, flag;
SVECTOR normal;
CVECTOR rgb;
POLY_F4 *face = nullptr;
gte_NormalClip_pc(&(scrn[0]), &(scrn[1]), &(scrn[2]), &flag);
if (flag > 0) {
face = (POLY_F4 *)drawpacket;
setPolyF4(face);
// ymin face normal : 0,+4096,0 +ve y
normal.vx = 0;
normal.vy = 4096;
normal.vz = 0;
if (_drawLit) {
LIGHTPOLYGON(&normal, rgbIn, &rgb);
setRGB0(face, rgb.r, rgb.g, rgb.b);
} else {
setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
}
// ymin face : 0->1->3->2 : note PSX is 0-1-3-2 for a quad
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);
z0 = (scrn[0].vz + scrn[1].vz + scrn[2].vz + scrn[3].vz) / 4;
z0 = myAddPrimClip(z0, drawpacket);
myAddPacket(sizeof(POLY_F4));
}
gte_NormalClip_pc(&(scrn[2]), &(scrn[3]), &(scrn[4]), &flag);
if (flag > 0) {
// xmax face : 2->3->5->4 : note PSX is 0-1-3-2 for a quad
face = (POLY_F4 *)drawpacket;
setPolyF4(face);
// xmax face : -4096,0,0 -ve x
normal.vx = -4096;
normal.vy = 0;
normal.vz = 0;
if (_drawLit) {
LIGHTPOLYGON(&normal, rgbIn, &rgb);
setRGB0(face, rgb.r, rgb.g, rgb.b);
} else {
setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
}
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);
z0 = (scrn[2].vz + scrn[3].vz + scrn[4].vz + scrn[5].vz) / 4;
z0 = myAddPrimClip(z0, drawpacket);
myAddPacket(sizeof(POLY_F4));
}
gte_NormalClip_pc(&(scrn[0]), &(scrn[2]), &(scrn[4]), &flag);
if (flag > 0) {
// zmin face : 0->2->4->6 : note PSX is 0-1-3-2 for a quad
face = (POLY_F4 *)drawpacket;
setPolyF4(face);
// zmin face : 0,0,+4096 +ve z
normal.vx = 0;
normal.vy = 0;
normal.vz = 4096;
if (_drawLit) {
LIGHTPOLYGON(&normal, rgbIn, &rgb);
setRGB0(face, rgb.r, rgb.g, rgb.b);
} else {
setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
}
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);
z0 = (scrn[0].vz + scrn[2].vz + scrn[4].vz + scrn[6].vz) / 4;
z0 = myAddPrimClip(z0, drawpacket);
myAddPacket(sizeof(POLY_F4));
}
gte_NormalClip_pc(&(scrn[0]), &(scrn[6]), &(scrn[7]), &flag);
if (flag > 0) {
// xmin face : 0->6->7->1 : note PSX is 0-1-3-2 for a quad
face = (POLY_F4 *)drawpacket;
setPolyF4(face);
// xmin face : +4096,0,0 +ve x
normal.vx = 0;
normal.vy = 0;
normal.vz = 4096;
if (_drawLit) {
LIGHTPOLYGON(&normal, rgbIn, &rgb);
setRGB0(face, rgb.r, rgb.g, rgb.b);
} else {
setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
}
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);
z0 = myAddPrimClip(scrn[7].vz, drawpacket);
myAddPacket(sizeof(POLY_F4));
}
gte_NormalClip_pc(&(scrn[1]), &(scrn[7]), &(scrn[5]), &flag);
if (flag > 0) {
// zmax face : 1->7->5->3 : note PSX is 0-1-3-2 for a quad
face = (POLY_F4 *)drawpacket;
setPolyF4(face);
// zmax face : 0,0,-4096 -ve z
normal.vx = 0;
normal.vy = 0;
normal.vz = -4096;
if (_drawLit) {
LIGHTPOLYGON(&normal, rgbIn, &rgb);
setRGB0(face, rgb.r, rgb.g, rgb.b);
} else {
setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
}
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);
z0 = (scrn[1].vz + scrn[3].vz + scrn[5].vz + scrn[7].vz) / 4;
z0 = myAddPrimClip(z0, drawpacket);
myAddPacket(sizeof(POLY_F4));
}
gte_NormalClip_pc(&(scrn[6]), &(scrn[4]), &(scrn[5]), &flag);
if (flag > 0) {
// ymax face : 6->4->5->7 : note PSX is 0-1-3-2 for a quad
face = (POLY_F4 *)drawpacket;
setPolyF4(face);
// ymax face : 0,-4096,0 -ve y
normal.vx = 0;
normal.vy = -4096;
normal.vz = 0;
if (_drawLit) {
LIGHTPOLYGON(&normal, rgbIn, &rgb);
setRGB0(face, rgb.r, rgb.g, rgb.b);
} else {
setRGB0(face, rgbIn->r, rgbIn->g, rgbIn->b);
}
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);
z0 = (scrn[4].vz + scrn[5].vz + scrn[6].vz + scrn[7].vz) / 4;
z0 = myAddPrimClip(z0, drawpacket);
myAddPacket(sizeof(POLY_F4));
}
}
// Simple flat untextured triangles
// draw backfacing triangles as well
// the colour is set by a global variable
void fastDrawTRI3PC(uint32 *polyStart, const uint32 n, SVECTORPC *pVertex) {
SVECTORPC *v0;
SVECTORPC *v1;
SVECTORPC *v2;
int32 flag;
uint32 i;
uint32 *pPoly;
int32 z0;
SVECTORPC sxy0, sxy1, sxy2, stemp;
uint32 tmp;
pPoly = polyStart;
// Loop over each polygon
for (i = 0; i < n; i++) {
// Each polygon is 2 32-bit WORDS
// Bit 31 ----> Bit 0
//
// 16-bits | 16-bits
// --------------------------
// v1 | v0
// pad | v2
tmp = *pPoly++;
v0 = pVertex + (tmp & 0xFFFF);
v1 = pVertex + (tmp >> 16);
tmp = *pPoly++;
v2 = pVertex + (tmp & 0xFFFF);
flag = (v0->pad) | (v1->pad) | (v2->pad);
if (flag != 0)
continue;
// use winding order of the polygons
// e.g. NormalClip which is cross product of screen vectors
sxy0.vx = v0->vx;
sxy0.vy = v0->vy;
sxy1.vx = v1->vx;
sxy1.vy = v1->vy;
sxy2.vx = v2->vx;
sxy2.vy = v2->vy;
// See what winding order this polygon is ?
gte_NormalClip_pc(&sxy0, &sxy1, &sxy2, &flag);
// Drawing back facing polys requires making them have
// clockwise winding order as by definition they have
// anti-clockwise winding order
if (flag < 0) {
stemp = sxy1;
sxy1 = sxy2;
sxy2 = stemp;
}
// Give the GTE some time to recover
gte_AverageZ3_pc(v0->vz, v1->vz, v2->vz, &z0);
// Draw untextured polygons
TPOLY_F3 *poly = (TPOLY_F3 *)drawpacket;
setTPolyF3(poly);
setTABRMode(poly, 2); // 2 = back - front
setTSemiTrans(poly, 1); // 1 = enable semi-transparency
// set XY's in the GPU packet 0-1-2
poly->x0 = sxy0.vx;
poly->y0 = sxy0.vy;
poly->x1 = sxy1.vx;
poly->y1 = sxy1.vy;
poly->x2 = sxy2.vx;
poly->y2 = sxy2.vy;
// Set the RGB colours
// No light source calculation
// So just set base colour
setRGB0(poly, unlitPoly.r, unlitPoly.g, unlitPoly.b);
poly->code = unlitPoly.cd;
myAddPrimClip(z0, drawpacket);
// advance the global packet pointer by correct amount
myAddPacket(sizeof(TPOLY_F3));
}
}
} // End of namespace ICB