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;
}
//***************************************************************************