home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
fish
/
languages
/
northc_384
/
crender
/
render.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-09-09
|
10KB
|
329 lines
/*
(c) 1990 S.Hawtin.
Permission is granted to copy this file provided
1) It is not used for commercial gain
2) This notice is included in all copies
3) Altered copies are marked as such
No liability is accepted for the contents of the file.
render.c within NorthC render
*/
/*
Quick hack to play with transforms for three dimensional objects
*/
#include <stdio.h>
#include <stddef.h>
#include <math.h>
#include "3d.h"
/* Controlling variables */
int solid_fill = -1;
double rot1 = 0.120;
double rot2 = 0.011;
/* The position of the lights, they are fixed relative to the viewer */
#define LCOUNT 5
long lights[LCOUNT][3] =
{
{ 278, 356, 634},
{ 500,-1000,-250},
{-2000, 0, 1000},
{0,0,0},
{0,0,0},
};
char object_name[32] = "objects/boat.dat";
/* The object is made of an array of triangles */
Triangle **object;
int obj_count;
Vertex **vertices;
int vertex_count;
/* Here are the triangles we must draw */
Triangle **draw_list;
int draw_count;
/* Angle object is being viewed from */
double view[2] =
{0.3,4.0};
/* Transformation matrix in 1024th */
static int scale_factor = 1024;
long transform[4][4] =
{{ -512, -737, -737, 0},
{ 870, -431, -256, 0},
{ 0, 512, -870, 0},
{ 0, 0, 0, 1024}
};
trans_vertex(vtex)
Vertex *vtex;
{/* Transform a single vertex */
register long temp;
if(vtex->is_done==0)
{/* This vertex has not yet been done, do it */
temp = (transform[0][0] * vtex->logical.x +
transform[0][1] * vtex->logical.y +
transform[0][2] * vtex->logical.z)/(1024*SCALE);
vtex->screen.x = (int)temp;
temp = (transform[1][0] * vtex->logical.x +
transform[1][1] * vtex->logical.y +
transform[1][2] * vtex->logical.z)/(1024*SCALE);
vtex->screen.y = (int)temp;
temp = (transform[2][0] * vtex->logical.x +
transform[2][1] * vtex->logical.y +
transform[2][2] * vtex->logical.z)/(1024*SCALE);
vtex->screen.z = (int)temp;
vtex->is_done = -1;
}
}
int
illuminate(vect)
Vector *vect;
{/* Work out the ammount of illumination from the normal to the
surface */
long tx,ty,tz;
long i,factor,add;
long sum = 0;
tx = (transform[0][0] * vect->x + transform[0][1] * vect->y +
transform[0][2] * vect->z)/1024;
ty = (transform[1][0] * vect->x + transform[1][1] * vect->y +
transform[1][2] * vect->z)/1024;
tz = (transform[2][0] * vect->x + transform[2][1] * vect->y +
transform[2][2] * vect->z)/1024;
for(i=0;i<LCOUNT;i++)
{/* Sum the illumination from each light */
add = (tx * lights[i][0] + ty * lights[i][1] + tz * lights[i][2]);
if(add>0)
sum += add;
}
sum = sum/(LCOUNT*1024);
if(sum>1023)
return(1023);
else
return((int)sum);
}
int
cmpz(tri1,tri2)
Triangle **tri1;
Triangle **tri2;
{/* Compare the z values of the triangle centres */
#ifndef TEST_LIGHTS
if(tri1[0]->centre.screen.z > tri2[0]->centre.screen.z)
return(1);
else if(tri1[0]->centre.screen.z == tri2[0]->centre.screen.z)
#else
if(tri1[0]->centre.logical.z > tri2[0]->centre.logical.z)
return(1);
else if(tri1[0]->centre.logical.z == tri2[0]->centre.logical.z)
#endif
return(0);
else
return(-1);
}
display_object()
{/* Display the object, first work out all the points */
int i;
draw_count = 0;
for(i=0;i<obj_count;i++)
{/* Work out the real points for the whole object */
#ifndef TEST_LIGHTS
if((transform[2][0] * object[i]->normal.x +
transform[2][1] * object[i]->normal.y +
transform[2][2] * object[i]->normal.z)>0)
#else
if((object[i]->normal.z)>0)
#endif
{trans_vertex(object[i]->v1);
trans_vertex(object[i]->v2);
trans_vertex(object[i]->v3);
trans_vertex(&(object[i]->centre));
/* Work out the brightness of the lights */
object[i]->shade = illuminate(&(object[i]->normal));
draw_list[draw_count++] = object[i];
}
}
qsort(draw_list,draw_count,sizeof(Triangle *),cmpz);
clear_screen();
for(i=0;i<draw_count;i++)
draw_tri((int)((draw_list[i]->shade)/64),
(int)(draw_list[i]->v1->screen.x),
(int)(draw_list[i]->v1->screen.y),
(int)(draw_list[i]->v2->screen.x),
(int)(draw_list[i]->v2->screen.y),
(int)(draw_list[i]->v3->screen.x),
(int)(draw_list[i]->v3->screen.y));
}
/* Read the object description, */
init_triangle(tri)
Triangle *tri;
{long nx,ny,nz,length;
/* Initialise the triangle once the corners are set up */
tri->centre.logical.x = (tri->v1->logical.x + tri->v2->logical.x +
tri->v3->logical.x)/3;
tri->centre.logical.y = (tri->v1->logical.y + tri->v2->logical.y +
tri->v3->logical.y)/3;
tri->centre.logical.z = (tri->v1->logical.z + tri->v2->logical.z +
tri->v3->logical.z)/3;
nx=(tri->v1->logical.y * (tri->v3->logical.z - tri->v2->logical.z)
+ tri->v2->logical.y * (tri->v1->logical.z - tri->v3->logical.z)
+ tri->v3->logical.y * (tri->v2->logical.z - tri->v1->logical.z));
ny=(tri->v1->logical.z * (tri->v3->logical.x - tri->v2->logical.x)
+ tri->v2->logical.z * (tri->v1->logical.x - tri->v3->logical.x)
+ tri->v3->logical.z * (tri->v2->logical.x - tri->v1->logical.x));
nz=(tri->v1->logical.x * (tri->v3->logical.y - tri->v2->logical.y)
+ tri->v2->logical.x * (tri->v1->logical.y - tri->v3->logical.y)
+ tri->v3->logical.x * (tri->v2->logical.y - tri->v1->logical.y));
/* Now make the vector 1024 units long */
length = (long)sqrt((double)(nx*nx+ny*ny+nz*nz));
tri->normal.x = (nx*1024)/length;
tri->normal.y = (ny*1024)/length;
tri->normal.z = (nz*1024)/length;
}
read_file(fptr)
FILE *fptr;
{/* First a count of the vertex list */
Vertex *vdata;
Triangle *tdata;
int i,n1,n2,n3;
char next;
fscanf(fptr,"%d",&vertex_count);
if(vertex_count<=0)
printf("No vertices in object\n");
vertices = (Vertex **)calloc(sizeof(Vertex *),vertex_count);
vdata = (Vertex *)calloc(sizeof(Vertex),vertex_count);
if(vertices==NULL || vdata==NULL)
{printf("Failed to malloc space\n");
exit(EXIT_FAILURE);
}
for(i=0;i<vertex_count;i++)
{/* Set up the vertex stuff */
vertices[i] = vdata;
fscanf(fptr,"%d %d %d",&(vdata->logical.x),
&(vdata->logical.y),&vdata->logical.z);
next = fgetc(fptr);
while(next!='\n')
next = fgetc(fptr);
vdata++;
}
fscanf(fptr,"%d",&obj_count);
if(obj_count<=0)
printf("No triangles in object\n");
object = (Triangle **)calloc(sizeof(Triangle *),obj_count);
draw_list = (Triangle **)calloc(sizeof(Triangle *),obj_count);
tdata = (Triangle *)calloc(sizeof(Triangle),obj_count);
if(object==NULL || draw_list==NULL || tdata==NULL)
{printf("Failed to malloc space\n");
exit(EXIT_FAILURE);
}
for(i=0;i<obj_count;i++)
{/* Set up the triangle stuff */
object[i] = tdata;
fscanf(fptr,"%d %d %d",&n1,&n2,&n3);
tdata->v1 = vertices[n1];
tdata->v2 = vertices[n2];
tdata->v3 = vertices[n3];
next = fgetc(fptr);
while(next!='\n')
next = fgetc(fptr);
init_triangle(tdata);
tdata++;
}
}
/* Transform the view into a transform */
trans_view()
{/* Constructthe transformation matrix */
int i;
double sinth,costh,sinph,cosph;
sinth = sin(view[0]);
costh = cos(view[0]);
sinph = sin(view[1]);
cosph = cos(view[1]);
transform[0][0] = (long)(-sinth*scale_factor); /* -sin(th) */
transform[2][0] = (long)(costh*scale_factor); /* cos(th) */
transform[1][0] = (long)0; /* 0 */
transform[0][1] = (long)(-costh*cosph*scale_factor);/* -cos(th)cos(ph) */
transform[2][1] = (long)(-sinth*cosph*scale_factor);/* -sin(th)cos(ph) */
transform[1][1] = (long)(sinph*scale_factor); /* sin(ph) */
transform[0][2] = (long)(-costh*sinph*scale_factor);/* -cos(th)sin(ph) */
transform[2][2] = (long)(-sinth*sinph*scale_factor);/* -sin(th)sin(ph) */
transform[1][2] = (long)(-cosph*scale_factor); /* -cos(ph) */
/* Note that we havent done any of the transforms yet */
for(i=0;i<obj_count;i++)
{object[i]->centre.is_done = 0;
}
for(i=0;i<vertex_count;i++)
{vertices[i]->is_done = 0;
}
}
/* SHOW_FACES is set when creating objects */
/* #define SHOW_FACES */
main(argc,argv)
int argc;
char **argv;
{
FILE *fptr;
int i;
/* Read the object file */
if(argc>=2)
{strcpy(object_name,argv[argc-1]);
}
else
scale_factor = 1500;
fptr = fopen(object_name,"r");
if(fptr==NULL)
{printf("Cannot open %s\n",object_name);
exit(EXIT_FAILURE);
}
read_file(fptr);
/* Set SHOW_FACES to get a print out of the centres and normals of
all the faces, very useful when defining objects */
#ifdef SHOW_FACES
for(i=0;i<obj_count;i++)
{printf("Face %d %5d,%5d,%5d\n",i,object[i]->normal.x,
object[i]->normal.y,object[i]->normal.z);
printf(" cent %5d,%5d,%5d\n",object[i]->centre.logical.x,
object[i]->centre.logical.y,object[i]->centre.logical.z);
}
#endif /* SHOW_FACES */
/* Set up the screen */
init_screen();
/* Keep displaying forever, the code calls exit() when its done */
while(-1)
{
trans_view();
display_object();
view[0] += rot1;
view[1] += rot2;
}
}