#
# This awk script will convert an NFF-format input file (as output by
# Eric Haines' SPD) to something rayshade can understand.
# The World object will be enclosed in a single grid of 22*22*22 voxels.
#
# Example usage:
#	mount | awk -f sped2shade.awk | rayshade > mountains.rle
#
# For best results, one should modify the output for all but the tetra
# and mountain databases to provide a tighter bounding box around the
# object of interest (tree, gears, etc.).  This is done by moving
# ground polygons and the like outside of the topmost grid object.
# This will decrease ray-tracing time dramatically.
#
# Note that we have to make sure that the viewing paramters are output
# outside of the object definition block.  We do this by printing
# the eye position, etc., at the very end of the output.
#
BEGIN{
	init = 0;
	lights = 0;
	print "maxdepth 4"
	print "adaptive 0"
	print "cutoff 0."
	print "report verbose"
}
substr($1, 1, 1) == "#" { print "/* " $0 " */"; next;}
$1 == "v" { next;}
$1 == "from" { eyex = $2; eyey = $3; eyez = $4; next;}
$1 == "at" { atx = $2; aty = $3; atz = $4; next;}
$1 == "up" { upx = $2; upy = $3; upz = $4; next;}
$1 == "angle" { fov = $2; next;}
$1 == "hither" {next;}
$1 == "resolution" {screenx = $2; screeny = $3; next;}

$1 == "l" { lightd[lights] = $2 " "$3 " "$4; lights++; next; }
$1 == "b" {print "background " $2 " "$3 " "$4; next; }
$1 == "f" {
	if (init == 0) {
		print "grid 22 22 22";
		init = 1;
	}
	printf("applysurf ");
	if (lights != 0)
		aintens = sqrt(lights) / (4*lights);
	else
		aintens = .1;
	dr = $2*$5;
	dg = $3*$5;
	db = $4*$5;
# this is a good guess....
	ar = aintens*dr;
	ag = aintens*dg;
	ab = aintens*db;
	if (ar != 0 || ag != 0 || ab != 0)
		printf("\tambient %f %f %f\n", ar, ag, ab);
	if (dr != 0 || dg != 0 || db != 0)
		printf("\tdiffuse %f %f %f\n", dr, dg, db);
#
# We set "reflectance" to the minimum of Ks and 1. - T, as
# Eric Haines' SPD includes several objects that have Ks + T > 1.
#
	if ($6 < 1. - $8)
		reflect = $6;
	else
		reflect = 1. - $8;
	if ($6)
		printf("\tspecular %f %f %f specpow %f\n", $6, $6, $6, $7);
	if (reflect)
		printf("\treflect %f\n", reflect);
	if ($8 || $9)
		printf("\ttransp %f index %f\n", $8, $9);
	next;
}

$1 == "c" {
	getline;
	x1 = $1;
	y1 = $2;
	z1 = $3;
	br = $4;
	getline;
	printf("cone %f %f %f %f %f %f %f %f\n", \
		br, x1, y1, z1, $4, $1, $2, $3);
	next;
}
$1 == "s" {
	print "sphere "$5 " "$2 " "$3 " "$4;
	next;
}
$1 == "pp" {
	if ($2 == 3)
		print "triangle ";
	else
		print "poly ";
	next;
}
$1 == "p" {
#
# Polygon -- the vertices will print out in the default statement.
# If there are three vertices, make it a triangle.
#
	if ($2 == 3)
		print "triangle ";
	else
		print "poly ";
	next;
}
{
# Matched nothing (or is a vertex data) -- print it.
	print;
	next;
}
END{
	print "end"
#
# Output light definitions.
#
	intens = sqrt(lights) / (lights);
	for (i = 0; i < lights; i++) {
		print "light " intens " point " lightd[i]
	}
	printf("eyep %g %g %g\n", eyex, eyey, eyez);
	printf("lookp %g %g %g\n", atx, aty, atz);
	printf("up %g %g %g\n", upx, upy, upz);
	printf("fov %g\n", fov);
	printf("screen %d %d\n", screenx, screeny);
}
