qball.c 5.68 KB
/*
 *	Generate a mesh of quads
 */

#include <stdio.h>
#include <stdlib.h>
#include <gl/image.h>
#include "math.h"
#define DEG2RAD( a) (a*(float)(3.141/180.))


#define TRUE -1
#define FALSE 0

#define	XMIN	(-300)
#define	XMAX	300
#define	YMIN	(-300)
#define	YMAX	300

#define	TEX_ONE	4096
#define	TILE_MAXX	32
#define	TILE_MAXY	32

#define VTX_ELS 13 /* x, y, z, s, t, w, r, g, b, a */
#define VX 0
#define VY 1
#define VZ 2
#define VS 3
#define VT 4
#define VW 5
#define VR 6
#define VG 7
#define VB 8
#define VA 9
#define	VNX 10
#define	VNY 11
#define	VNZ 12

int dup_color = FALSE;
int dup_texture = FALSE;
char default_file[] = "six.t";
char *inputfile = default_file;

struct Vertex {
	float e[VTX_ELS];	
};

struct Vertex	vtx[4] = {
	{XMIN, YMIN, 0, 	0, 4095, 1,		255, 0, 0, 255},
	{XMAX, YMIN, 0, 	4095, 4095, 1,		255, 255, 0, 255},
	{XMIN, YMAX, 0, 	0, 0, 1,		0, 255, 0, 255},
	{XMAX, YMAX, 0, 	4095, 0, 1,		0, 0, 255, 255},
};

extern sortst(struct Vertex *, struct Vertex *, struct Vertex *);

main(argc, argv)
int	argc;
char	**argv;
{
	int xstep = 1, ystep = 1;
	struct Vertex vx0, vx1, vx2, vx3;
	struct Vertex vy0, vy1, vy2, vy3;
	struct Vertex st0, st1;
	int	x, y;
	float	xdel, ydel;
	int	sdel, tdel;
	int i, j;

	int tex_w, tex_h;

	float xang, yang;
	float xangd, yangd;

while (--argc) {
        if ((*++argv)[0] == '-') {
        switch ((*argv)[1]) {
        case 'c':       dup_color = TRUE; break;
        case 't':       dup_texture = TRUE; break;
	case 'f':       argc--; argv++;
			inputfile = *argv;
			break;
	case 'x':       argc--; argv++;
                        sscanf( *argv, "%d", &xstep); break;
	case 'y':       argc--; argv++;
                        sscanf( *argv, "%d", &ystep); break;

       }}}

	get_texdim(inputfile, &tex_w, &tex_h);
	do_init();

	xangd = (float)360/(xstep - 1);
	yangd = (float)180/(ystep - 1);
	xdel = (XMAX-XMIN)/xstep;
	ydel = (YMAX-YMIN)/ystep;
	sdel = (float)tex_w/xstep + 0.5;
	tdel = (float)tex_h/ystep + 0.5;

	/* XXX 4/4/4/4 for now */
	/* must be <= 31 for edges of bilinear filter*/
	if (sdel >= TILE_MAXX || tdel >= TILE_MAXY) {
		fprintf(stderr, "texture tile does not fit\n");
		exit(0);
	}

	vy0 = vtx[0];
	vy1 = vtx[1];
	vy1.e[VX] = vy0.e[VX] = 0;
	vy1.e[VY] = vy0.e[VY] = YMIN;
	vy1.e[VZ] = vy0.e[VZ] = 0;
	yang = 0;
	for (y=1; y<=ystep; y++) {
		xang = 0;
		vy3.e[VX] = vy2.e[VX] = -sin( DEG2RAD( yang)) * XMIN;
		vy3.e[VY] = vy2.e[VY] = cos( DEG2RAD( yang)) * YMIN;
		vy3.e[VZ] = vy2.e[VZ] = 0;
		ydel = (float)y/ystep;
		lerp_vtx( 3, &vtx[0], &vtx[2], ydel, &vy2);
		lerp_vtx( 3, &vtx[1], &vtx[3], ydel, &vy3);
		vx0 = vy0;
		vx2 = vy2;
	for (x=1; x<=xstep; x++) {
		vx1.e[VX] = cos( DEG2RAD( xang)) * vy0.e[VX];
		vx1.e[VY] = vy0.e[VY];
		vx1.e[VZ] = sin( DEG2RAD( xang)) * vy0.e[VX];
		vx3.e[VX] = cos( DEG2RAD( xang)) * vy2.e[VX];
		vx3.e[VY] = vy2.e[VY];
		vx3.e[VZ] = sin( DEG2RAD( xang)) * vy2.e[VX];
		xdel = 1.0 - fabs( (float)2*x/xstep - 1.0);
		lerp_vtx( 3, &vy0, &vy1, xdel, &vx1);
		lerp_vtx( 3, &vy2, &vy3, xdel, &vx3);
		if (dup_color) {
			copy_color( &vtx[0], &vx0);
			copy_color( &vtx[1], &vx1);
			copy_color( &vtx[2], &vx2);
			copy_color( &vtx[3], &vx3);
			}
		if (dup_texture) {
			copy_texture( &vtx[0], &vx0);
			copy_texture( &vtx[1], &vx1);
			copy_texture( &vtx[2], &vx2);
			copy_texture( &vtx[3], &vx3);
			}
		sortst(&vx0, &vx1, &st0);
		sortst(&vx2, &vx3, &st1);
		sortst(&st0, &st1, &st0);
		do_tramload(&st0, sdel, tdel, tex_w, tex_h);
		do_normals( &vx0);
		do_normals( &vx1);
		do_normals( &vx2);
		do_normals( &vx3);
		do_quad();
		do_vertex( &vx0);
		do_vertex( &vx1);
		do_vertex( &vx2);
		do_vertex( &vx3);
		vx0 = vx1;
		vx2 = vx3;
		xang += xangd;
		}
		vy0 = vy2;
		vy1 = vy3;
		yang += yangd;
		}
}

do_init()
{
	printf("WINDOW\t\t640 480 0x7fff\n\n");
	printf("LD_TEXTURE\t%s\tRGBA4444\n\n", inputfile);
	printf("FRUSTUM\n");
	printf("-0.128 0.128 -0.096 0.096 1.0 32000.0\n\n");
	printf("LD_MATRIX\n");
	printf("1 1 1\n0 0 0\n0 0 -2000\n\n");
	printf("MARK\n");
	printf("CLEAR\t\t0x404040\n");
	printf("LIGHT\t0.1 0.1 0.1 0.1 0.5 0.5 0.6 0.5 0.7 0.7 0.7 0.7 0.58 0.58 0.58\n");
}

do_quad()
{
	printf("QUAD\n");
}

do_vertex( v)
struct Vertex *v;
{
int i;
	for (i=0; i<VNX; i++) printf("%d ", (int)v->e[i]);
	for (i=VNX; i<VTX_ELS; i++) printf("%f ", v->e[i]);
	printf("\n");
}

do_tramload(vx0, sdel, tdel, w, h)
struct Vertex *vx0;
int	sdel;
int	tdel;
int	w;
int	h;
{
	int	s, t;

	s = (vx0->e[VS] / TEX_ONE * w);
	t = (vx0->e[VT] / TEX_ONE * h);

	/* XXX assume 4/4/4/4 & 4 samples per tram word */
	sdel = (sdel + 3) >> 2; sdel <<=2;
	tdel = (tdel + 3) >> 2; tdel <<=2;
	printf("LD_TRAM\t%s %d %d %d %d %d\n", inputfile, s, t, sdel, tdel, 0);
}

do_normals(struct Vertex *v)
{
	int	i;
	float	k;
	k = 1/sqrt(v->e[VX] * v->e[VX] + v->e[VY] * v->e[VY] + v->e[VZ] * v->e[VZ]);
	v->e[VNX] = v->e[VX] * k;
	v->e[VNY] = v->e[VY] * k;
	v->e[VNZ] = v->e[VZ] * k;

	/* preserve only 8 bits of precision */
	for (i=VNX; i<=VNZ; i++) v->e[i] = (int)(v->e[i]*256)/256.0;
}

sortst(struct Vertex *st0, struct Vertex *st1, struct Vertex *st2)
{
	int i;

	for (i=VS; i<=VT; i++)
		st2->e[i] = (st0->e[i] < st1->e[i]) ? st0->e[i] : st1->e[i];
}

get_texdim(char *file, int *w, int *h)
{
	IMAGE	*img;

	if ((img = iopen(file, "r")) == (IMAGE *)NULL) {
		fprintf(stderr, "can't open texture file %s\n", file);
		exit(EXIT_FAILURE);
	}

	*w = img->xsize;
	*h = img->ysize;
}

lerp_vtx( first, vn, vf, a, vo)
struct Vertex *vn, *vf, *vo;
float a;
{
int i;
for (i=first; i<VTX_ELS; i++)
vo->e[i] = vn->e[i] + (vf->e[i] - vn->e[i]) * a;
}
copy_color( vi, vo)
struct Vertex *vi, *vo;
{
	vo->e[VR] = vi->e[VR];
	vo->e[VG] = vi->e[VG];
	vo->e[VB] = vi->e[VB];
	vo->e[VA] = vi->e[VA];
	}
copy_texture( vi, vo)
struct Vertex *vi, *vo;
{
	vo->e[VS] = vi->e[VS];
	vo->e[VT] = vi->e[VT];
	vo->e[VW] = vi->e[VW];
	}