/* Jeremy Stribling
 * cs184-cf, Fall 2000
 * Final project
 * 
 * This file contains serveral functions for generating surfaces of revolutions.  They are 
 * modified versions of the SurfOR function found on page 102 of The Renderman Companion, 
 * by Steve Upsill.
 */

#include "F:\cs184\bmrt2.5\include\ri.h"
#include "u:\final\apple\rendcomp.h"
#include <stdlib.h>
#include <time.h>

#define NU 24
#define MAXNPTS 100
#define F (.4142135*4/3)
#define G ( (.5 + F/2) + .0185 )

float coeff[NU][2] = {
	{ 1, 0 }, {1, F/2}, { 1, F }, {G, G}, {F, 1}, {F/2, 1}, 
	{ 0, 1 }, {-F/2, 1}, { -F, 1 }, {-G, G}, { -1, F }, {-1, F/2},
	{ -1, 0 }, {-1, -F/2}, { -1, -F }, {-G, -G}, { -F, -1 }, {-F/2, -1}, 
	{ 0, -1 }, {F/2, -1}, { F, -1 }, {G, -G}, { 1, -F }, {1, -F/2} };

RtPoint last[NU];	

/*
 * Make a surface of rotation given a set of a certain number of points in 2D,
 * but randomize the position of the point around the rotation, to give the bottom
 * edge of the object created appear randomly jagged at certain intervals.
 */

void SurfORJagged( Point2D points[], int npoints ) {

	RtPoint mesh[MAXNPTS][NU];
	int u,v;

	srand( time(NULL) );

	float r;

	for( v = 0; v < npoints; v++ ) {

		for( u = 0; u < NU; u++ ) {


			mesh[v][u][0] = points[v].x * coeff[u][0];
			mesh[v][u][1] = points[v].x * coeff[u][1];
			if( v == npoints-1 ) {
				float r = (rand() % 100);
				mesh[v][u][2] = points[v].y - (r / 75) * ( (rand()%2) * -2 + 1);
				last[u][0] = mesh[v][u][0];
				last[u][1] = mesh[v][u][1];
				last[u][2] = mesh[v][u][2];
			} else {
				mesh[v][u][2] = points[v].y;
			}

		}

	}


	RtFloat nu = NU;
	RtFloat np = npoints;

	RiBasis( RiBezierBasis, RI_BEZIERSTEP, RiBezierBasis, RI_BEZIERSTEP );
	RiPatchMesh( RI_BICUBIC, (RtInt) NU, RI_PERIODIC, (RtInt) npoints, RI_PERIODIC, RI_P, (RtPointer) mesh, RI_NULL );

}

/*
 * Make a jagged surface of rotation as above, but make the top edge of this one join up with the
 * bottom edge of the last surface emitted.
 */
void joinJagged( Point2D points[], int npoints ) {

	RtPoint mesh[MAXNPTS][NU];
	int u,v;

	srand( time(NULL) );

	float r;

	for( v = 0; v < npoints; v++ ) {

		for( u = 0; u < NU; u++ ) {


			mesh[v][u][0] = points[v].x * coeff[u][0];
			mesh[v][u][1] = points[v].x * coeff[u][1];
			if( v == npoints-1 ) {
				float r = (rand() % 100);
				mesh[v][u][2] = points[v].y - (r / 75) * ( (rand()%2) * -2 + 1);
				last[u][0] = mesh[v][u][0];
				last[u][1] = mesh[v][u][1];
				last[u][2] = mesh[v][u][2];
			} else if( v == 0 ) {
				mesh[v][u][0] = last[u][0];
				mesh[v][u][1] = last[u][1];
				mesh[v][u][2] = last[u][2];
			} else {
				mesh[v][u][2] = points[v].y;
			}

		}

	}


	RtFloat nu = NU;
	RtFloat np = npoints;

	RiBasis( RiBezierBasis, RI_BEZIERSTEP, RiBezierBasis, RI_BEZIERSTEP );
	RiPatchMesh( RI_BICUBIC, (RtInt) NU, RI_PERIODIC, (RtInt) npoints, RI_PERIODIC, RI_P, (RtPointer) mesh, RI_NULL );



}

/*
 * Make a joined jagged surface of rotation as above, but perturb the entire surface as it is rotated about,
 * resulting in various peaks and valleys around th esurface, like an eaten apple core.
 */

void joinJaggedCore( Point2D points[], int npoints ) {

	RtPoint mesh[MAXNPTS][NU];
	int u,v;

	srand( time(NULL) );

	float r;

	for( v = 0; v < npoints; v++ ) {

		for( u = 0; u < NU; u++ ) {


			mesh[v][u][0] = points[v].x * coeff[u + ( (rand()%3) - 1 ) ][0]*(1+(rand() % 100)/100*( (rand()%2) * -2 + 1));
			mesh[v][u][1] = points[v].x * coeff[u + ( (rand()%3) - 1 ) ][1]*(1+(rand() % 100)/100*( (rand()%2) * -2 + 1));
			if( v == npoints-1 ) {
				float r = (rand() % 100);
				mesh[v][u][2] = points[v].y + (r / 75) * ( (rand()%2) * -2 + 1);
				last[u][0] = mesh[v][u][0];
				last[u][1] = mesh[v][u][1];
				last[u][2] = mesh[v][u][2];
			} else if( v == 0 ) {
				mesh[v][u][0] = last[u][0];
				mesh[v][u][1] = last[u][1];
				mesh[v][u][2] = last[u][2];
			} else {
				mesh[v][u][2] = points[v].y + ((rand() % 100) / 75) * ( (rand()%2) * -2 + 1);
			}

		}

	}


	RtFloat nu = NU;
	RtFloat np = npoints;

	RiBasis( RiBezierBasis, RI_BEZIERSTEP, RiBezierBasis, RI_BEZIERSTEP );
	RiPatchMesh( RI_BICUBIC, (RtInt) NU, RI_PERIODIC, (RtInt) npoints, RI_PERIODIC, RI_P, (RtPointer) mesh, RI_NULL );



}
