#include <stdio.h>#include <stdlib.h>#include <math.h>#include <time.h>#include "render.h"#include "liftio.h"/* distance from camera to object. */#define DIST 500.0/* width and height of output bitmap in pixels */#define WIDTH 400L#define HEIGHT 300L/* distance from camera eyepoint to projection plane */#define ZOOM (WIDTH*2.0)/* time of day, in seconds past midnight */#define CUR_TIME 7*60*60/*-------- Some useful altitudes to play with ----------*//* just inside cloud bank *///#define ALTITUDE 1180.0/* above clouds */#define ALTITUDE 1300.0/* deep inside clouds *///#define ALTITUDE 500.0/*-------- Some useful camera angles ----------*//* when making a new camera angle, be sure the basis	array is orthanormal, or strance things will happen *//* quarter-front view  */PG_CAMERA cam={	1.0,	{-DIST,-DIST,ALTITUDE},	 {{0.707,-0.707,0.0},		{0.0,0.0,1.0},		{0.707,0.707,0.0}},	ZOOM,	NULL,	NULL};/* side view PG_CAMERA cam={	1.0,	{0,-DIST,ALTITUDE},	 {{1.0,0.0,0.0},		{0.0,0.0,1.0},		{0.0,1.0,0.0}},	ZOOM,	NULL,	NULL};*//*-------------------------------------------------------------* * structures below here should not be casually modified       * *-------------------------------------------------------------*/PG_LIGHT lights[2]={{0,{0,0,0},0.0,0.0,0.0},{1,{0,0,0},0.0,0.0,0.0}};PG_FOG fog={	1,	{0,0,0,0},	0.0,	0.0};PG_ENVIRONMENT env={	2,	lights,	&fog};/* general purpose object loader routine */int GetObjects(PG_OBJECT **objs,char *fname){FILE *fp;static OBJECTPART mypart;static PG_OBJECT myobject={    0.0,    100.0,    {0.0,0.0,ALTITUDE},    {{1.0,0.0,0.0},     {0.0,1.0,0.0},     {0.0,0.0,1.0}},		1,		&(mypart.part),		0,NULL,		0,NULL,		0};char tag[4];	fp=fopen(fname,"rb");	if (!fp) {		printf("can't open file: %s\n",fname);		return 0;	}	StartFile(fp);	if (!GetTag(tag)) goto die;	if ((tag[0]!='P')		||(tag[1]!='A')		||(tag[2]!='R')		||(tag[3]!='T')) goto die;	if (!ReadPart(&mypart,fp)) goto die;	fclose(fp);	*objs=&myobject;	return 1;die:	puts("read failed");	fclose(fp);	return 0;}static PG_OBJECT *objs;static int nobjs;BITMAP bmap;int mySetup(char *fname){	cam.bmap=&bmap;	bmap.dx=WIDTH;	bmap.dy=HEIGHT;	bmap.left=0;	bmap.top=0;	bmap.width=WIDTH;	bmap.height=HEIGHT;	bmap.buffer=malloc(sizeof(PIX_RGB32)*WIDTH*HEIGHT);	if (!bmap.buffer) {		return 0;	}	cam.zbuf=malloc(sizeof(float)*WIDTH*HEIGHT);	if (!cam.zbuf) {		free(bmap.buffer);		return 0;	}	nobjs=GetObjects(&objs,fname);	if (nobjs==0) {		free(bmap.buffer);		free(cam.zbuf);		return 0;	}	return 1;}void myShutdown(void){	free(bmap.buffer);	free(cam.zbuf);}PG_VECTOR axis={0.0,0.0,1.0};typedef struct tagclouds {	float start;	float stop;	PIX_RGB32 fog;	PIX_RGB32 skytop;	PIX_RGB32 skybottom;	//FIXME lighting control} CLOUDS;CLOUDS myclouds={	1200.0,	500.0,	InitRGBA(128,128,150,0),	InitRGBA(40,50,120,0),	InitRGBA(70,80,120,0)};void SetFog(PG_ENVIRONMENT *env,CLOUDS *cl,float z,PIX_RGB32 sky[513]);void SetLights(int seconds,PG_LIGHT lights[2]);/* the main rendering loop.		This one is pretty boring.  It just renders the same scene		1000 times and measures the compute speed. */void Draw(void){PIX_RGB32 sky[513];int i,j;time_t t1,t2;	t1=clock();	for (j=0;j<1000;j++) {		SetLights(CUR_TIME,lights);		SetFog(&env,&myclouds,cam.center.z,sky);		BeginRender3D(&cam,&env);		memset(cam.zbuf,0,WIDTH*HEIGHT*4);			DrawTable(&axis,&cam.basis,cam.zoom,sky);		for (i=0;i<nobjs;i++)			DrawObject(&(objs[i]));		EndRender3D(&cam);	}	t2=clock();	printf("%ld milliseconds per frame\n",(t2-t1)/CLOCKS_PER_SEC);}/* Routines to output BITMAP structures as BMP files. */#define HEADSIZE 54unsigned char bmphead[]={	'B','M',	0,0,0,0,	0,0,0,0,	HEADSIZE,0,0,0,	0x28,0,0,0,	0,0,0,0,	0,0,0,0,	1,0,	24,0,	0,0,0,0,	0,0,0,0,	0,0,0,0,	0,0,0,0,	0,0,0,0,	0,0,0,0	};int WriteBMPHead(FILE *fp,int dx,int dy,int bits){long t,bytes;	if (dx<1)		return 0;	if (dy<1)		return 0;	if (bits!=24)		return 0;	bytes=3;	t=(long)dx*(long)dy*bytes;	/* file size */	bmphead[2]=(t+HEADSIZE)&0xFF;	bmphead[3]=((t+HEADSIZE)>>8)&0xFF;	bmphead[4]=((t+HEADSIZE)>>16)&0xFF;	bmphead[5]=((t+HEADSIZE)>>24)&0xFF;	/* width */	bmphead[18]=dx&0xFF;	bmphead[19]=(dx>>8)&0xFF;	bmphead[20]=(dx>>16)&0xFF;	bmphead[21]=(dx>>24)&0xFF;	/* height */	bmphead[22]=dy&0xFF;	bmphead[23]=(dy>>8)&0xFF;	bmphead[24]=(dy>>16)&0xFF;	bmphead[25]=(dy>>24)&0xFF;	/* image size */	0,0,0,0,	bmphead[34]=t&0xFF;	bmphead[35]=(t>>8)&0xFF;	bmphead[36]=(t>>16)&0xFF;	bmphead[37]=(t>>24)&0xFF;	if (fwrite(bmphead,1,sizeof(bmphead),fp)!=sizeof(bmphead)) {		puts("bad write");		return 0;	}	return 1;}int WriteBMP(char *fname,BITMAP *bmap){FILE *fp;int x,y;	fp=fopen(fname,"wb");	if (!fp) {		printf("couldn't open file %s\n",fname);		return 0;	}	WriteBMPHead(fp,bmap->dx,bmap->dy,24);	for (y=bmap->dy-1;y>=0;y--)	for (x=0;x<bmap->dx;x++) {			putc(bmap->buffer[x+bmap->dx*y].blue,fp);			putc(bmap->buffer[x+bmap->dx*y].green,fp);			putc(bmap->buffer[x+bmap->dx*y].red,fp);	}	fclose(fp);	return 1;}/* ...and the trivial main program */int main(int argc,char *argv[]){	if (argc!=3) {		puts("syntax: draw <object name> <bmp name>");		return 1;	}	if (!mySetup(argv[1])) 		return 1;	Draw();	WriteBMP(argv[2],&bmap);	myShutdown();	return 0;}