tris.c 4.18 KB
#include <ultra64.h>

#include "fill.h"

#ifndef MAX
#define MAX(x, y)	((x) > (y) ? (x) : (y))
#endif

#ifndef MIN
#define MIN(x, y)	((x) < (y) ? (x) : (y))
#endif

#define CLAMP(a, min, max)	(MAX(MIN(a, max), min))


typedef struct {
	float v[3];
	u8	  c[4];
} Point3D;

/* active vertex is blue */
static Point3D		ActVtx[3];

/* centered around (0,0,0) */
static Point3D		initVtx[] = {
	{  -10,  10, 10,    0,   0, 255, 255 },
	{    0,   0, 10,  255, 255, 255, 255 },
	{   10,  10, 10,  255, 255, 255, 255 },
	{  -32,  10, 10,    0,   0, 255, 255 },
	{  -22,   0, 10,  255, 255, 255, 255 },
	{  -12,  10, 10,  255, 255, 255, 255 }
};

static float boxWidth  = 10;
static float boxHeight = 10;

void
initTri(int align) {
	int i, off = align ? 3 : 0;
	for(i = 0; i < 3; i++)
		ActVtx[i] = initVtx[i+off];
}

static void
fixVertex(Vtx *vtx, int v, float *delta)
{
	int i;
	for(i = 0; i < 3; i++) {
		vtx[v].v.ob[i] = (short)ActVtx[v].v[i] + (short)delta[i];
	}

	for(i = 0; i < 4; i++) {
		vtx[v].v.cn[i] = (unsigned char)ActVtx[v].c[i];
	}

	for(i = 0; i < 2; i++) {
		vtx[v].v.tc[i] = 0;
	}

	dynamic.FillVtx[v].v.flag  = 0;
}


/*
 *  Create triangle, move active vertex to new position
 *  Should we check for bow-ties or let hardware handle it?
 *
 *  actv = active vertex to translate, if >= 3, translate whole
 *     triangle
 */
void
makeTriList(int actv, float dx, float dy)
{
	int i, trix, triy, tri; 
	float nspans;
	float ox, oy;
	float offset[3];
	Gfx *tlistp = dynamicp->trilist;

	BoxTy = 1000000.0; BoxLx = -1000000.0;
	BoxTx = 1000000.0; BoxLy = -1000000.0;

	if(actv < 3) {
		ActVtx[actv].v[0] = CLAMP(ActVtx[actv].v[0]+dx, 
		-(float)SCREEN_WD/2, (float)SCREEN_WD/2-1.0);
		ActVtx[actv].v[1] = CLAMP(ActVtx[actv].v[1]+dy, 
		-(float)SCREEN_HT/2, (float)SCREEN_HT/2-1.0);
	} else {
		for(i = 0; i < 3; i++) {
			ActVtx[i].v[0] = CLAMP(ActVtx[i].v[0]+dx, 
				-(float)SCREEN_WD/2, (float)SCREEN_WD/2-1.0);
			ActVtx[i].v[1] = CLAMP(ActVtx[i].v[1]+dy, 
				-(float)SCREEN_HT/2, (float)SCREEN_HT/2-1.0);
		}
	}

	for(TriArea = i = 0; i < 3; i++) {
		TriArea += ActVtx[i].v[0] * ActVtx[(i+1)%3].v[1] -
				ActVtx[i].v[1] * ActVtx[(i+1)%3].v[0];

		if(ActVtx[i].v[1] > BoxLy)
			BoxLy = ActVtx[i].v[1];
		if(ActVtx[i].v[1] < BoxTy)
			BoxTy = ActVtx[i].v[1];

		if(ActVtx[i].v[0] > BoxLx)
			BoxLx = ActVtx[i].v[0];
		if(ActVtx[i].v[0] < BoxTx)
			BoxTx = ActVtx[i].v[0];

		if(actv == i) {
			ActVtx[i].c[0] = 0;
			ActVtx[i].c[1] = 0;
			ActVtx[i].c[2] = 255;
			ActVtx[i].c[3] = 255;
		} else {
			ActVtx[i].c[0] = 255;
			ActVtx[i].c[1] = 255;
			ActVtx[i].c[2] = 255;
			ActVtx[i].c[3] = 255;
		}
	}

	TriArea /= 2.0;
	if(TriArea < 0.0)
		TriArea = -TriArea;

	TriHeight = BoxLy - BoxTy + 1;
	TriWidth  = BoxLx - BoxTx + 1;

    if(TriHeight)
		TriAspectRatio = TriWidth / TriHeight;
	else
		TriAspectRatio = 0;

	ox = SCREEN_WD/(TriNx+1);
	oy = SCREEN_HT/(TriNy+1);
	offset[2] = 0.0;

	offset[0] = ox;
	for(tri = trix = 0; trix < TriNx; trix++) {
		offset[1] = oy;
		for(triy = 0; triy < TriNy; triy++, tri++) {	
			for(i = 0; i < 	3; i++) {
				fixVertex(&dynamic.FillVtx[tri*3], i, offset);
			}
			gSPVertex(tlistp++, &dynamic.FillVtx[tri*3], 3, 0);	
			gSP1Triangle(tlistp++, 0, 1, 2, 0);
			offset[1] += oy;
		}
		offset[0] += ox;
	}

	gSPEndDisplayList(tlistp++);
}



/*
 *  Create textured rectangle
 */
void
makeTexRectList(float dx, float dy)
{
	int i, trix, triy, tri; 
	float nspans;
	float ox, oy;
	float offset[3];
	Gfx *tlistp = dynamicp->trilist;

	boxWidth = CLAMP(boxWidth + dx, 
		-(float)SCREEN_WD/2, (float)SCREEN_WD/2-1.0);
	boxHeight = CLAMP(boxHeight + dy, 
		-(float)SCREEN_WD/2, (float)SCREEN_WD/2-1.0);


	TriArea = boxWidth * boxHeight;

	TriHeight = boxHeight;
	TriWidth  = boxWidth;

    if(TriHeight)
		TriAspectRatio = TriWidth / TriHeight;
	else
		TriAspectRatio = 0;

	ox = SCREEN_WD/(TriNx+1);
	oy = SCREEN_HT/(TriNy+1);
	offset[2] = 0.0;

	offset[0] = ox;
	for(tri = trix = 0; trix < TriNx; trix++) {
		offset[1] = oy;
		for(triy = 0; triy < TriNy; triy++, tri++) {	
			gSPTextureRectangle(tlistp++,
					(int)ox << 2, (int)oy << 2, 
					(int)(ox+boxWidth) << 2, (int)(oy+boxHeight) << 2,
					G_TX_RENDERTILE,
					0 << 5, 0 << 5, 4 << 10, 1 << 10);
			offset[1] += oy;
		}
		offset[0] += ox;
	}

	gSPEndDisplayList(tlistp++);
}