[comp.graphics] Ray traced teapot

ronbo@vixen.uucp (Ron Hitchens) (09/28/88)

   I mailed this to Mark VandeWettering and Dean S. Jones, but got no response
from either of them so I don't know if it made it.  So, I figured I might as
well just go ahead and post it, since this may be of interest to a lot of
people.

   Below is a modification of a program that Dean S. Jones posted a few weeks
ago that draws the well known teapot in wire frame using SunCore.  I changed
it so that it would use the same data to produce an NFF file that Mark
VandeWettering's ray tracer can use.  The result looks surprisingly good. 
Using the default step value of 6 is satisfactory, 12 looks very nice.

   I'd like to know what's causing the little specks on the spout and the
handle.  I don't know if it's a problem with how this guy generates the
NFF file, or some glitch in Mark's ray tracer.  I don't have the time to
investigate.

   The original program that Dean posted was Sun specific, since it used
SunCore.  This one is not Sun-specific, all it does is some computation
and spit out some text data, so it should run most anywhere.  You'll probably
need to remove the -f68881 from the makefile spec if you compile it on a
non-Sun system though.

   Enjoy.

Ron Hitchens		ronbo@vixen.uucp	hitchens@cs.utexas.edu
----

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by vixen!ronbo on Wed Sep 28 00:44:39 CDT 1988
# Contents:  Makefile tea.h raypot.c ducks.c patches.c
 
echo x - Makefile
sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'

OFILES= tea.o patches.o ducks.o
RAYOFILES= raypot.o patches.o ducks.o
LIBS=	-lcore -lsunwindow -lpixrect -lm
CFLAGS=	-O -f68881


raypot:	$(RAYOFILES)
	$(CC) $(CFLAGS) -o $@ $(RAYOFILES)

tea:	$(OFILES)
	$(CC) $(CFLAGS) -o $@ $(OFILES) $(LIBS)

@//E*O*F Makefile//
chmod u=rw,g=r,o=r Makefile
 
echo x - tea.h
sed 's/^@//' > "tea.h" <<'@//E*O*F tea.h//'
#define DEGREE		4
#define DUCK_COUNT	306
#define PATCH_COUNT	32

typedef struct {
	float x, y, z;
} dt;

typedef int pt[DEGREE][DEGREE];
@//E*O*F tea.h//
chmod u=rw,g=r,o=r tea.h
 
echo x - raypot.c
sed 's/^@//' > "raypot.c" <<'@//E*O*F raypot.c//'


/*
 *	Ray-trace a teapot.
 *	This code generates an NFF file of a teapot sitting on a polished
 *	table.  It uses the patch data to generate rectangular polygons.
 *	A step count may be given as an argument.  If so, the patches will
 *	be divided down into smaller subpatches.
 *	The output NFF file, written to stdout, is intended for input to
 *	Mark VandeWettering's ray tracer, but could easily be adapted
 *	for other software that takes lists of polygons.
 *
 *	Posted SunCore version by Dean S. Jones (dean@homxb.uucp)
 *	Ray trace/polygon mods by Ron Hitchens (ronbo@vixen.uucp)
 */

#include <stdio.h>
#include "tea.h"

#define MAX_STEPS		50

extern dt ducks [DUCK_COUNT];
extern pt patches [PATCH_COUNT];


char	*nff_hdr [] = {
	"v",					/* viewport parms */
	"from -2.1 -7.8 3.6",
	"at 0 0 1",
	"up 0 0 1",
	"angle 45",
	"hither 1",
	"resolution 512 512",			/* image size */
	"b 0.078 0.361 0.753",			/* background color */
	"l 8 -4 6",				/* lights */
	"l -1 -3 5",
	"l -1 -4 9",
	"l -2 -4 .4",
	"f 1 0.85 0.7 0.75 0.25 25 0 0",	/* surface properties */
	"p 4",					/* table top square */
	"6 6 0",
	"-6 6 0",
	"-6 -6 0",
	"6 -6 0",
	"f 1 .47 0 1 0 30 0 0"			/* surf props for teapot */
};


main (argc, argv)
	int argc;
	char *argv[];
{
	int	i, s = 6;

	if (argc > 1) {
		s = atoi (argv [1]);
		s = (s > 0) ? s : 6;
		if (s > MAX_STEPS) {
			fprintf (stderr, "max step size is %d\n", MAX_STEPS);
			exit (1);
		}
	}

	for (i = 0; i < sizeof (nff_hdr) / sizeof (char *); i++) {
		printf ("%s\n", nff_hdr [i]);
	}

	display_patches (s);

	exit (0);
}

void blend_vector (d0, d1, d2, d3, t, r)
	dt	d0, d1, d2, d3;
	float	t;
	dt	*r;
{
	r->x = d0.x*(1-t)*(1-t)*(1-t) + d1.x*3*t*(1-t)*(1-t) +
	       d2.x*3*t*t*(1-t)       + d3.x*t*t*t;

	r->y = d0.y*(1-t)*(1-t)*(1-t) + d1.y*3*t*(1-t)*(1-t) +
	       d2.y*3*t*t*(1-t)       + d3.y*t*t*t;

	r->z = d0.z*(1-t)*(1-t)*(1-t) + d1.z*3*t*(1-t)*(1-t) +
	       d2.z*3*t*t*(1-t)       + d3.z*t*t*t;
}

void display_curve (d0, d1, d2, d3, steps)
	dt		d0, d1, d2, d3;
	int		steps;
{
	dt		tmp;
	float		t, step;
	int		i = 0, j;
	static int	count = 0;
	static dt	p [MAX_STEPS+1][MAX_STEPS+1];


	t = step = (1.0 / (float)steps);

	p [count][0] = d0;
	while (t < (1.0 + step / 2.0)) {
		blend_vector (d0, d1, d2, d3, t, &tmp);
		p [count][++i] = tmp;
		t += step;
	}

	count++;
	if (count <= steps) {
		return;
	}

	for (i = 0; i < steps; i++) {
		for (j = 0; j < steps; j++) {
			printf ("p 4\n");
			printf ("%f %f %f\n",
				p [i][j+1].x, p [i][j+1].y, p [i][j+1].z);
			printf ("%f %f %f\n",
				p [i][j].x, p [i][j].y, p [i][j].z);
			printf ("%f %f %f\n",
				p [i+1][j].x, p [i+1][j].y, p [i+1][j].z);
			printf ("%f %f %f\n",
				p [i+1][j+1].x, p [i+1][j+1].y,
				p [i+1][j+1].z);
		}
	}

	count = 0;
}


void display_patch (patch, steps)
	pt	patch;
	int	steps;
{
	float	t, step;
	dt	d0, d1, d2, d3;
	int	i;

	t = 0;
	step = (1.0 / (float)steps);
	while(t < (1.0 + step / 2.0)) {
		blend_vector(ducks[patch[0][0]-1],ducks[patch[0][1]-1],
			     ducks[patch[0][2]-1],ducks[patch[0][3]-1], t, &d0);

		blend_vector(ducks[patch[1][0]-1],ducks[patch[1][1]-1],
			     ducks[patch[1][2]-1],ducks[patch[1][3]-1], t, &d1);

		blend_vector(ducks[patch[2][0]-1],ducks[patch[2][1]-1],
			     ducks[patch[2][2]-1],ducks[patch[2][3]-1], t, &d2);

		blend_vector(ducks[patch[3][0]-1],ducks[patch[3][1]-1],
			     ducks[patch[3][2]-1],ducks[patch[3][3]-1], t, &d3);

		display_curve (d0, d1, d2, d3, steps);
                                                                      
		t += step;
	}
}

display_patches (s)
	int	s;
{
	int	i;

	for (i = 0; i < PATCH_COUNT; i++) {
		display_patch (patches [i], s);
	}
}
@//E*O*F raypot.c//
chmod u=rw,g=r,o=r raypot.c
 
echo x - ducks.c
sed 's/^@//' > "ducks.c" <<'@//E*O*F ducks.c//'
#include "tea.h"

dt ducks[DUCK_COUNT] = {
{1.4,0.0,2.4},
{1.4,-0.784,2.4},
{0.784,-1.4,2.4},
{0.0,-1.4,2.4},
{1.3375,0.0,2.53125},
{1.3375,-0.749,2.53125},
{0.749,-1.3375,2.53125},
{0.0,-1.3375,2.53125},
{1.4375,0.0,2.53125},
{1.4375,-0.805,2.53125},
{0.805,-1.4375,2.53125},
{0.0,-1.4375,2.53125},
{1.5,0.0,2.4},
{1.5,-0.84,2.4},
{0.84,-1.5,2.4},
{0.0,-1.5,2.4},
{-0.784,-1.4,2.4},
{-1.4,-0.784,2.4},
{-1.4,0.0,2.4},
{-0.749,-1.3375,2.53125},
{-1.3375,-0.749,2.53125},
{-1.3375,0.0,2.53125},
{-0.805,-1.4375,2.53125},
{-1.4375,-0.805,2.53125},
{-1.4375,0.0,2.53125},
{-0.84,-1.5,2.4},
{-1.5,-0.84,2.4},
{-1.5,0.0,2.4},
{-1.4,0.784,2.4},
{-0.784,1.4,2.4},
{0.0,1.4,2.4},
{-1.3375,0.749,2.53125},
{-0.749,1.3375,2.53125},
{0.0,1.3375,2.53125},
{-1.4375,0.805,2.53125},
{-0.805,1.4375,2.53125},
{0.0,1.4375,2.53125},
{-1.5,0.84,2.4},
{-0.84,1.5,2.4},
{0.0,1.5,2.4},
{0.784,1.4,2.4},
{1.4,0.784,2.4},
{0.749,1.3375,2.53125},
{1.3375,0.749,2.53125},
{0.805,1.4375,2.53125},
{1.4375,0.805,2.53125},
{0.84,1.5,2.4},
{1.5,0.84,2.4},
{1.75,0.0,1.875},
{1.75,-0.98,1.875},
{0.98,-1.75,1.875},
{0.0,-1.75,1.875},
{2.0,0.0,1.35},
{2.0,-1.12,1.35},
{1.12,-2.0,1.35},
{0.0,-2.0,1.35},
{2.0,0.0,0.9},
{2.0,-1.12,0.9},
{1.12,-2.0,0.9},
{0.0,-2.0,0.9},
{-0.98,-1.75,1.875},
{-1.75,-0.98,1.875},
{-1.75,0.0,1.875},
{-1.12,-2.0,1.35},
{-2.0,-1.12,1.35},
{-2.0,0.0,1.35},
{-1.12,-2.0,0.9},
{-2.0,-1.12,0.9},
{-2.0,0.0,0.9},
{-1.75,0.98,1.875},
{-0.98,1.75,1.875},
{0.0,1.75,1.875},
{-2.0,1.12,1.35},
{-1.12,2.0,1.35},
{0.0,2.0,1.35},
{-2.0,1.12,0.9},
{-1.12,2.0,0.9},
{0.0,2.0,0.9},
{0.98,1.75,1.875},
{1.75,0.98,1.875},
{1.12,2.0,1.35},
{2.0,1.12,1.35},
{1.12,2.0,0.9},
{2.0,1.12,0.9},
{2.0,0.0,0.45},
{2.0,-1.12,0.45},
{1.12,-2.0,0.45},
{0.0,-2.0,0.45},
{1.5,0.0,0.225},
{1.5,-0.84,0.225},
{0.84,-1.5,0.225},
{0.0,-1.5,0.225},
{1.5,0.0,0.15},
{1.5,-0.84,0.15},
{0.84,-1.5,0.15},
{0.0,-1.5,0.15},
{-1.12,-2.0,0.45},
{-2.0,-1.12,0.45},
{-2.0,0.0,0.45},
{-0.84,-1.5,0.225},
{-1.5,-0.84,0.225},
{-1.5,0.0,0.225},
{-0.84,-1.5,0.15},
{-1.5,-0.84,0.15},
{-1.5,0.0,0.15},
{-2.0,1.12,0.45},
{-1.12,2.0,0.45},
{0.0,2.0,0.45},
{-1.5,0.84,0.225},
{-0.84,1.5,0.225},
{0.0,1.5,0.225},
{-1.5,0.84,0.15},
{-0.84,1.5,0.15},
{0.0,1.5,0.15},
{1.12,2.0,0.45},
{2.0,1.12,0.45},
{0.84,1.5,0.225},
{1.5,0.84,0.225},
{0.84,1.5,0.15},
{1.5,0.84,0.15},
{-1.6,0.0,2.025},
{-1.6,-0.3,2.025},
{-1.5,-0.3,2.25},
{-1.5,0.0,2.25},
{-2.3,0.0,2.025},
{-2.3,-0.3,2.025},
{-2.5,-0.3,2.25},
{-2.5,0.0,2.25},
{-2.7,0.0,2.025},
{-2.7,-0.3,2.025},
{-3.0,-0.3,2.25},
{-3.0,0.0,2.25},
{-2.7,0.0,1.8},
{-2.7,-0.3,1.8},
{-3.0,-0.3,1.8},
{-3.0,0.0,1.8},
{-1.5,0.3,2.25},
{-1.6,0.3,2.025},
{-2.5,0.3,2.25},
{-2.3,0.3,2.025},
{-3.0,0.3,2.25},
{-2.7,0.3,2.025},
{-3.0,0.3,1.8},
{-2.7,0.3,1.8},
{-2.7,0.0,1.575},
{-2.7,-0.3,1.575},
{-3.0,-0.3,1.35},
{-3.0,0.0,1.35},
{-2.5,0.0,1.125},
{-2.5,-0.3,1.125},
{-2.65,-0.3,0.9375},
{-2.65,0.0,0.9375},
{-2.0,-0.3,0.9},
{-1.9,-0.3,0.6},
{-1.9,0.0,0.6},
{-3.0,0.3,1.35},
{-2.7,0.3,1.575},
{-2.65,0.3,0.9375},
{-2.5,0.3,1.125},
{-1.9,0.3,0.6},
{-2.0,0.3,0.9},
{1.7,0.0,1.425},
{1.7,-0.66,1.425},
{1.7,-0.66,0.6},
{1.7,0.0,0.6},
{2.6,0.0,1.425},
{2.6,-0.66,1.425},
{3.1,-0.66,0.825},
{3.1,0.0,0.825},
{2.3,0.0,2.1},
{2.3,-0.25,2.1},
{2.4,-0.25,2.025},
{2.4,0.0,2.025},
{2.7,0.0,2.4},
{2.7,-0.25,2.4},
{3.3,-0.25,2.4},
{3.3,0.0,2.4},
{1.7,0.66,0.6},
{1.7,0.66,1.425},
{3.1,0.66,0.825},
{2.6,0.66,1.425},
{2.4,0.25,2.025},
{2.3,0.25,2.1},
{3.3,0.25,2.4},
{2.7,0.25,2.4},
{2.8,0.0,2.475},
{2.8,-0.25,2.475},
{3.525,-0.25,2.49375},
{3.525,0.0,2.49375},
{2.9,0.0,2.475},
{2.9,-0.15,2.475},
{3.45,-0.15,2.5125},
{3.45,0.0,2.5125},
{2.8,0.0,2.4},
{2.8,-0.15,2.4},
{3.2,-0.15,2.4},
{3.2,0.0,2.4},
{3.525,0.25,2.49375},
{2.8,0.25,2.475},
{3.45,0.15,2.5125},
{2.9,0.15,2.475},
{3.2,0.15,2.4},
{2.8,0.15,2.4},
{0.0,0.0,3.15},
{0.0,-0.002,3.15},
{0.002,0.0,3.15},
{0.8,0.0,3.15},
{0.8,-0.45,3.15},
{0.45,-0.8,3.15},
{0.0,-0.8,3.15},
{0.0,0.0,2.85},
{0.2,0.0,2.7},
{0.2,-0.112,2.7},
{0.112,-0.2,2.7},
{0.0,-0.2,2.7},
{-0.002,0.0,3.15},
{-0.45,-0.8,3.15},
{-0.8,-0.45,3.15},
{-0.8,0.0,3.15},
{-0.112,-0.2,2.7},
{-0.2,-0.112,2.7},
{-0.2,0.0,2.7},
{0.0,0.002,3.15},
{-0.8,0.45,3.15},
{-0.45,0.8,3.15},
{0.0,0.8,3.15},
{-0.2,0.112,2.7},
{-0.112,0.2,2.7},
{0.0,0.2,2.7},
{0.45,0.8,3.15},
{0.8,0.45,3.15},
{0.112,0.2,2.7},
{0.2,0.112,2.7},
{0.4,0.0,2.55},
{0.4,-0.224,2.55},
{0.224,-0.4,2.55},
{0.0,-0.4,2.55},
{1.3,0.0,2.55},
{1.3,-0.728,2.55},
{0.728,-1.3,2.55},
{0.0,-1.3,2.55},
{1.3,0.0,2.4},
{1.3,-0.728,2.4},
{0.728,-1.3,2.4},
{0.0,-1.3,2.4},
{-0.224,-0.4,2.55},
{-0.4,-0.224,2.55},
{-0.4,0.0,2.55},
{-0.728,-1.3,2.55},
{-1.3,-0.728,2.55},
{-1.3,0.0,2.55},
{-0.728,-1.3,2.4},
{-1.3,-0.728,2.4},
{-1.3,0.0,2.4},
{-0.4,0.224,2.55},
{-0.224,0.4,2.55},
{0.0,0.4,2.55},
{-1.3,0.728,2.55},
{-0.728,1.3,2.55},
{0.0,1.3,2.55},
{-1.3,0.728,2.4},
{-0.728,1.3,2.4},
{0.0,1.3,2.4},
{0.224,0.4,2.55},
{0.4,0.224,2.55},
{0.728,1.3,2.55},
{1.3,0.728,2.55},
{0.728,1.3,2.4},
{1.3,0.728,2.4},
{0.0,0.0,0.0},
{1.5,0.0,0.15},
{1.5,0.84,0.15},
{0.84,1.5,0.15},
{0.0,1.5,0.15},
{1.5,0.0,0.075},
{1.5,0.84,0.075},
{0.84,1.5,0.075},
{0.0,1.5,0.075},
{1.425,0.0,0.0},
{1.425,0.798,0.0},
{0.798,1.425,0.0},
{0.0,1.425,0.0},
{-0.84,1.5,0.15},
{-1.5,0.84,0.15},
{-1.5,0.0,0.15},
{-0.84,1.5,0.075},
{-1.5,0.84,0.075},
{-1.5,0.0,0.075},
{-0.798,1.425,0.0},
{-1.425,0.798,0.0},
{-1.425,0.0,0.0},
{-1.5,-0.84,0.15},
{-0.84,-1.5,0.15},
{0.0,-1.5,0.15},
{-1.5,-0.84,0.075},
{-0.84,-1.5,0.075},
{0.0,-1.5,0.075},
{-1.425,-0.798,0.0},
{-0.798,-1.425,0.0},
{0.0,-1.425,0.0},
{0.84,-1.5,0.15},
{1.5,-0.84,0.15},
{0.84,-1.5,0.075},
{1.5,-0.84,0.075},
{0.798,-1.425,0.0},
{1.425,-0.798,0.0},
};
@//E*O*F ducks.c//
chmod u=rw,g=r,o=r ducks.c
 
echo x - patches.c
sed 's/^@//' > "patches.c" <<'@//E*O*F patches.c//'
#include "tea.h"

pt patches[PATCH_COUNT] = {
{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}},
{{4,17,18,19},{8,20,21,22},{12,23,24,25},{16,26,27,28}},
{{19,29,30,31},{22,32,33,34},{25,35,36,37},{28,38,39,40}},
{{31,41,42,1},{34,43,44,5},{37,45,46,9},{40,47,48,13}},
{{13,14,15,16},{49,50,51,52},{53,54,55,56},{57,58,59,60}},
{{16,26,27,28},{52,61,62,63},{56,64,65,66},{60,67,68,69}},
{{28,38,39,40},{63,70,71,72},{66,73,74,75},{69,76,77,78}},
{{40,47,48,13},{72,79,80,49},{75,81,82,53},{78,83,84,57}},
{{57,58,59,60},{85,86,87,88},{89,90,91,92},{93,94,95,96}},
{{60,67,68,69},{88,97,98,99},{92,100,101,102},{96,103,104,105}},
{{69,76,77,78},{99,106,107,108},{102,109,110,111},{105,112,113,114}},
{{78,83,84,57},{108,115,116,85},{111,117,118,89},{114,119,120,93}},
{{121,122,123,124},{125,126,127,128},{129,130,131,132},{133,134,135,136}},
{{124,137,138,121},{128,139,140,125},{132,141,142,129},{136,143,144,133}},
{{133,134,135,136},{145,146,147,148},{149,150,151,152},{69,153,154,155}},
{{136,143,144,133},{148,156,157,145},{152,158,159,149},{155,160,161,69}},
{{162,163,164,165},{166,167,168,169},{170,171,172,173},{174,175,176,177}},
{{165,178,179,162},{169,180,181,166},{173,182,183,170},{177,184,185,174}},
{{174,175,176,177},{186,187,188,189},{190,191,192,193},{194,195,196,197}},
{{177,184,185,174},{189,198,199,186},{193,200,201,190},{197,202,203,194}},
{{204,204,204,204},{207,208,209,210},{211,211,211,211},{212,213,214,215}},
{{204,204,204,204},{210,217,218,219},{211,211,211,211},{215,220,221,222}},
{{204,204,204,204},{219,224,225,226},{211,211,211,211},{222,227,228,229}},
{{204,204,204,204},{226,230,231,207},{211,211,211,211},{229,232,233,212}},
{{212,213,214,215},{234,235,236,237},{238,239,240,241},{242,243,244,245}},
{{215,220,221,222},{237,246,247,248},{241,249,250,251},{245,252,253,254}},
{{222,227,228,229},{248,255,256,257},{251,258,259,260},{254,261,262,263}},
{{229,232,233,212},{257,264,265,234},{260,266,267,238},{263,268,269,242}},
{{270,270,270,270},{279,280,281,282},{275,276,277,278},{271,272,273,274}},
{{270,270,270,270},{282,289,290,291},{278,286,287,288},{274,283,284,285}},
{{270,270,270,270},{291,298,299,300},{288,295,296,297},{285,292,293,294}},
{{270,270,270,270},{300,305,306,279},{297,303,304,275},{294,301,302,271}}
};
@//E*O*F patches.c//
chmod u=rw,g=r,o=r patches.c
 
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
      13      31     246 Makefile
       9      21     137 tea.h
     169     573    3658 raypot.c
     310     313    5617 ducks.c
      36      39    2266 patches.c
     537     977   11924 total
!!!
wc  Makefile tea.h raypot.c ducks.c patches.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0