offobject.cc.html
//***************************************************************************
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>             /* ANSI C standard library routines */
#include <string.h>             /* ANSI standard string routines */
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include "image.h"
#include "offobject.h"
#include "matrix.h"
//***************************************************************************
OFFobject::OFFobject ( )	// Constructor
{
allocateFlag = 0;
boxRange = DEFAULT_BOXRANGE;
imageSize = DEFAULT_IMAGE_SIZE;
}
//***************************************************************************
OFFobject::OFFobject (char *filename)	// Constructor
{
boxRange = DEFAULT_BOXRANGE;
imageSize = DEFAULT_IMAGE_SIZE;
ReadFromFile(filename);
}
//***************************************************************************
OFFobject::~OFFobject ( )	// Destructor
{
deAllocateMem( );
}
//***************************************************************************
void OFFobject::allocateMem (int numV, int numE)
{
if (allocateFlag)
        {
         cerr << "OFFobject::allocateMem: Memory already allocated!!" << endl;
         return;
        }
allocateFlag = 1;

v = new double[3] [numV];
vi = new double[2] [numV];
e = new int[2] [numE];
}
//***************************************************************************
void OFFobject::deAllocateMem ( )
{
if (allocateFlag)
	{
	 delete v;
	 delete vi;
	 delete e;
	 allocateFlag = 0;
	}
}
//***************************************************************************
void OFFobject::setBoxRange (double range)
{
boxRange = range;
}
//***************************************************************************
void OFFobject::setImageSize (int size)
{
imageSize = size;
}
//***************************************************************************
void OFFobject::setFocalLength (double f)
{
lambda = f;
}
//***************************************************************************
void OFFobject::ReadFromFile (char *FileName)
{
ifstream inp(FileName);

if (!inp)               // Invalid FileName
        {
         cerr << "Invalid filname: \"" << FileName << "\" does not exist!!"
                << endl;
         exit(-1);
        }

cout << "---------------------------------------" 
	<< "---------------------------------------" << endl;
cout << "Reading object from file \"" << FileName << "\" ->" << endl;
cout << "---------------------------------------" 
	<< "---------------------------------------" << endl;

inp >> CameraOrigin[0] >> CameraOrigin[1] >> CameraOrigin[2]
	>> CameraAxis[0] >> CameraAxis[1] >> CameraAxis[2]
	>> lambda;

inp >> nV >> nE;
allocateMem (nV, nE);

for (int i = 0; i < nV; i++)
	inp >> v[i][0] >> v[i][1] >> v[i][2];

for (int i = 0; i < nE; i++)
	{
	 inp >> e[i][0] >> e[i][1];
	 --e[i][0];		// Decrement to match the Vertex number in v
	 --e[i][1];		// Decrement to match the Vertex number in v
	}

inp.close();

cout << "Camera Origin  = [" 
	<< CameraOrigin[0] << "," << CameraOrigin[1] << ","
	<< CameraOrigin[2] << "]" << endl;
cout << "Camera facing towards [" 
	<< CameraAxis[0] << "," << CameraAxis[1] << ","
	<< CameraAxis[2] << "]" << endl;
cout << "Focal length of camera = " << lambda << endl;
cout << "Number of vertices = " << nV << endl;
cout << "Number of edges = " << nE << endl;
cout << "---------------------------------------" 
	<< "---------------------------------------" << endl;

return;
}
//***************************************************************************
void OFFobject::mapToImagePlane ( )
{
double x = CameraAxis[0]-CameraOrigin[0];
double y = CameraAxis[1]-CameraOrigin[1];
double z = CameraAxis[2]-CameraOrigin[2];
double r = sqrt(x*x+y*y+z*z);
double theta = atan2(x,-y);
double alpha = acos(z/r);

Matrix P = Perspective(lambda);
Matrix Tw0 = Translate(-CameraOrigin[0],-CameraOrigin[1],-CameraOrigin[2]);
Matrix R_theta = zRotate(theta);
Matrix R_alpha = xRotate(alpha);
Matrix Tr = Translate(0,0,0);

Matrix T = P * Tr * R_alpha * R_theta * Tw0;

//cout << T;

for (int i = 0; i < nV; i++)
	{
	 Matrix w(4,1);

	 w.p[0][0] = v[i][0];
	 w.p[1][0] = v[i][1];
	 w.p[2][0] = v[i][2];
	 w.p[3][0] = 1.0;

	 Matrix c_h = T * w;
	 vi[i][0] = c_h(0,0)/c_h(3,0);
	 vi[i][1] = c_h(1,0)/c_h(3,0);
	}
}
//***************************************************************************
void OFFobject::drawImage ( )
{
int width = imageSize;
int height = imageSize;
int numLevels = 255;
image.Init(width, height, numLevels);
for (int i = 0; i < image.width; i++)
	for (int j = 0; j < image.height; j++)
		image.p[i][j] = 255;		// Initialize to white bg

for (int i = 0; i < nE; i++)
	drawEdge (i);
}
//***************************************************************************
void OFFobject::drawEdge (int edgeNum)
{
int p1[2], p2[2];
getImageCoords (edgeNum, &p1[0], &p1[1], &p2[0], &p2[1]);

double tmin, tmax;
getTrange (p1[0], p1[1], p2[0], p2[1], &tmin, &tmax);

#define EPSILON (1.0e-5)
if (fabs(tmax - tmin) < EPSILON)	// No points inside clipping box
	return;

int numPoints = getNumPoints (p1[0], p1[1], p2[0], p2[1], tmin, tmax);

for (int i = 1; i <= numPoints; i++)
	{
	 double t = tmin + (1.0*(i-1)/(numPoints-1)) * (tmax - tmin);
	 int x = (int) (p1[0] + t * (p2[0] - p1[0]));
	 int y = (int) (p1[1] + t * (p2[1] - p1[1]));

	 if (x >= 0 && x < image.width && y >= 0 && y < image.height)
		image.p[x][y] = 0;		// black pixel
	}
}
//***************************************************************************
void OFFobject::WriteImageToFile (char *FileName)
{
image.WriteToFile(FileName);
}
//***************************************************************************
void OFFobject::getTrange (int x1,int y1, int x2,int y2, double *t1,double *t2)
{
double xt1, xt2, yt1, yt2;

xt1 = xt2 = yt1 = yt2 = 0.0;

#define MIN(x,y)	(((x) > (y)) ? (y) : (x))
#define MAX(x,y)	(((x) > (y)) ? (x) : (y))
int horiz = 0, vert = 0;

if (x2 != x1)
	{
	 xt1 = (double) -x1/(x2-x1);
	 xt2 = (double) (image.width-x1-1)/(x2-x1);

	 double xtmin = MIN(xt1,xt2);
	 double xtmax = MAX(xt1,xt2);
	 xt1 = xtmin;
	 xt2 = xtmax;
	}
else
	++horiz;

if (y2 != y1)
	{
	 yt1 = (double) -y1/(y2-y1);
	 yt2 = (double) (image.height-y1-1)/(y2-y1);

	 double ytmin = MIN(yt1,yt2);
	 double ytmax = MAX(yt1,yt2);
	 yt1 = ytmin;
	 yt2 = ytmax;
	}
else
	++vert;

double tmin = 0.0, tmax = 1.0;

if  (!horiz && !vert)
	{
	 tmin = MAX(xt1,yt1);
	 tmax = MIN(xt2,yt2);
	}
else if  (horiz && !vert)
	{
	 tmin = yt1;
	 tmax = yt2;
	}
else if  (vert && !horiz)
	{
	 tmin = xt1;
	 tmax = xt2;
	}

if (tmin > 1.0)
	tmin = 1.0;
else if (tmin < 0.0)
	tmin = 0.0;

if (tmax > 1.0)
	tmax = 1.0;
else if (tmax < 0.0)
	tmax = 0.0;

if (tmin > tmax)
	tmin = tmax = 0.0;

*t1 = tmin;
*t2 = tmax;
}
//***************************************************************************
void OFFobject::getImageCoords (int edgeNum, int *x1,int *y1, int *x2,int *y2)
{
int center[2];

center[0] = image.width/2;
center[1] = image.height/2;
double xmin = -boxRange;
double xmax = boxRange;
double ymin = -boxRange;
double ymax = boxRange;
int xf = (int) (image.width/(xmax - xmin));
int yf = (int) (image.height/(ymax - ymin));

*x1 = (int) (vi[e[edgeNum][0]][0]*xf + center[0]);
*y1 = (int) (vi[e[edgeNum][0]][1]*yf + center[1]);
*x2 = (int) (vi[e[edgeNum][1]][0]*xf + center[0]);
*y2 = (int) (vi[e[edgeNum][1]][1]*yf + center[1]);
}
//***************************************************************************
int OFFobject::getNumPoints (int x1, int y1, int x2, int y2, double tmin,
	double tmax)
{
int xx1 = (int) (x1 + tmin * (x2 - x1));
int yy1 = (int) (y1 + tmin * (y2 - y1));
int xx2 = (int) (x1 + tmax * (x2 - x1));
int yy2 = (int) (y1 + tmax * (y2 - y1));

int dist = (int) sqrt(pow(xx1-xx2,2) + pow(yy1-yy2,2));

return dist+2;
}
//***************************************************************************
void OFFobject::printMappingData ( )
{
int center[2];

center[0] = imageSize/2;
center[1] = imageSize/2;
double xmin = -boxRange;
double xmax = boxRange;
double ymin = -boxRange;
double ymax = boxRange;
int xf = (int) (imageSize/(xmax - xmin));
int yf = (int) (imageSize/(ymax - ymin));

cout << "---------------------------------------" 
	<< "---------------------------------------" << endl;
cout << "Mapping from World co-ordinates to Image plane co-ordinates:" << endl;
cout << "---------------------------------------" 
	<< "---------------------------------------" << endl;
for (int i = 0; i < nV; i++)
	{
	 int x = (int) (vi[i][0]*xf + center[0]);
	 int y = (int) (vi[i][1]*yf + center[1]);

	 cout << "(" << v[i][0] << "," << v[i][1] << "," << v[i][2] 
		<< ") => [" << x << "," << y << "]" << endl;
	}
cout << "---------------------------------------" 
	<< "---------------------------------------" << endl;
}
//***************************************************************************
int OFFobject::getNumVerts ( )
{
return nV;
}
//***************************************************************************
int OFFobject::getNumEdges ( )
{
return nE;
}
//***************************************************************************