Sign in to follow this  
viper_2004

Ray Tracer problems

Recommended Posts

Hi, I need some specific help with my ray tracer implementation I have implemented the ray tracing implmetation described in chapter 14 of F.S hill graphics book. Everything works fine except for one little glitch. When I place a sphere in the scene and then place another one behind it - everythings fine - it draws correctly. However when I place the sphere in front of the first sphere the wrong image is drawn. Although the front sphere is drawn I can still see the back sphere - which is not supposed to happen. I would appreciate any idea on whats wrong here Some code for reference: **********************ray trace method************************** void View::rayTrace(Scene* scn) { Ray* _Ray = new Ray(); Color* _Color = new Color(); _Ray->set_Start(ViewEye.x, ViewEye.y, ViewEye.z); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, C, 0, R); for (int row = 0; row != R+1; row++) for (int col = 0; col != C+1; col++) { GLfloat x = -W + (col*2*W)/(GLfloat)C; GLfloat y = -H + (row*2*H)/(GLfloat)R; _Ray->set_Dir(-N*n.x + x*u.x + y*v.x, -N*n.y + x*u.y + y*v.y, -N*n.z + x*u.z + y*v.z); _Ray->Dir->normalize(); _Color->set_Color(scn->shade(_Ray)); glColor3f(_Color->red, _Color->green, _Color->blue); glBegin(GL_POINTS); glVertex2f(col, row); glEnd(); }; }; /* As u can see the first sphere has a z-coordinate of 4.0 and the second sphere has a z-coordinate of 2.0. This setting produces the wrong image, however if the z-coordinates are changed with each other the right image is drawn. */ void Scene::construct_Scene(void) { make_LightSources(); Sphere* NewSphere = new Sphere(); NewSphere->set_Name("SphereA"); NewSphere->set_Centre(0.0, 0.0, 4.0); NewSphere->set_Radius(1.0); NewSphere->set_mat_ambient(0.2, 0.2, 0.0); NewSphere->set_mat_diffuse(0.8, 0.8, 0.0); NewSphere->set_mat_emission(0.1, 0.1, 0.0); NewSphere->set_mat_specular(0.4, 0.4, 0.0); add_to_ObjList(NewSphere); NewSphere = new Sphere(); NewSphere->set_Name("SphereB"); NewSphere->set_Centre(0.0, 0.0, 2.0); NewSphere->set_Radius(1.0); NewSphere->set_mat_ambient(0.2, 0.0, 0.0); NewSphere->set_mat_diffuse(0.8, 0.0, 0.0); NewSphere->set_mat_emission(0.1, 0.0, 0.0); NewSphere->set_mat_specular(0.4, 0.0, 0.0); add_to_ObjList(NewSphere); }; Camera setting:(done at the start of the program) Camera->setView(60.0, 1.0 , -1.0, -50.0); // sets up perspective Camera->setViewCoord(0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0); // acts like gluLookAt() Than you. [Edited by - viper_2004 on September 2, 2004 11:52:57 PM]

Share this post


Link to post
Share on other sites

#include <iostream>
using namespace std;

class View {
public:
Point ViewEye;
Vect u, v, n; // corresponds to x,y,z coordinates
GLfloat vAngle, aspectR, nDist, fDist, C, R, N, H, W;

View();
void setMVMatrix(void);
GLfloat DotProduct(Vect thisVector, Vect EyeVect);
void setViewCoord(GLfloat x, GLfloat y, GLfloat z, GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2);
void set(Point eye, Point lookAt, Vect updir);
void setView(GLfloat vAngle, GLfloat aspectR, GLfloat nDist, GLfloat fDist);
void rayTrace(Scene* scn);

};

View::View()
{
C = 200;
R = 200;
};

GLfloat View::DotProduct(Vect thisVector, Vect EyeVect)
{
GLfloat dProduct;
dProduct = thisVector.x*EyeVect.x + thisVector.y*EyeVect.y + thisVector.z*EyeVect.z;
return dProduct;
};

void View::setMVMatrix(void)
{
GLfloat matrix[16];
Vect EyeVect(ViewEye.x, ViewEye.y, ViewEye.z);
matrix[0] = u.x; matrix[4] = u.y; matrix[8] = u.z; matrix[12] = -(DotProduct(u, EyeVect));
matrix[1] = v.x; matrix[5] = v.y; matrix[9] = v.z; matrix[13] = -(DotProduct(v, EyeVect));
matrix[2] = n.x; matrix[6] = n.y; matrix[10] = n.z; matrix[14] = -(DotProduct(n, EyeVect));
matrix[3] = 0; matrix[7] = 0; matrix[11] = 0; matrix[15] = 1.0;
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(matrix);
};

void View::setViewCoord(GLfloat x, GLfloat y, GLfloat z, GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2)
{
Point eye;
Point lookAt;
Vect updir;

eye.x = x;
eye.y = y;
eye.z = z;
lookAt.x = x1;
lookAt.y = y1;
lookAt.z = z1;
updir.x = x2;
updir.y = y2;
updir.z = z2;

set(eye, lookAt, updir);

};

void View::set(Point eye, Point lookAt, Vect updir)
{
ViewEye.set(eye); // records eye position
n.set(ViewEye.x - lookAt.x, ViewEye.y - lookAt.y, ViewEye.z - lookAt.z); // make n
Vect VectorProduct = updir.cross(n); // calculate cross product
u.set(VectorProduct.x, VectorProduct.y, VectorProduct.z);
n.normalize();
u.normalize();
VectorProduct = n.cross(u); // calculate cross product
v.set(VectorProduct.x, VectorProduct.y, VectorProduct.z);
setMVMatrix();
};

void View::setView(GLfloat vAngle, GLfloat aspectR, GLfloat nDist, GLfloat fDist)
{
N = 1.0; // Near Distance = distance between near plane and eye(z-coordinate)
H = N*tan(vAngle/2.0); // Height of viewplane
W = H*aspectR; // Width of viewplane
cout << N << endl;
cout << H << endl;
cout << W << endl;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(vAngle, aspectR, nDist, fDist);
};


// do ray tracing od the constructed scene
void View::rayTrace(Scene* scn)
{
Ray* _Ray = new Ray();
Color* _Color = new Color();
_Ray->set_Start(ViewEye.x, ViewEye.y, ViewEye.z); // set Ray start point to eye

// setup OpenGL for ray tracing process
glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); // set modelview matrix to zero
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // set projection matrix to zero
gluOrtho2D(0, C, 0, R); // C - colums, R - Rows

for (int row = 0; row != R+1; row++)
for (int col = 0; col != C+1; col++)
{
/* dir of Ray = -Nn + uU + vV
U = -W + W*2*col/C
V = -H + H*2*row/R
*/
GLfloat x = -W + (col*2*W)/(GLfloat)C;
GLfloat y = -H + (row*2*H)/(GLfloat)R;
_Ray->set_Dir(-N*n.x + x*u.x + y*v.x, -N*n.y + x*u.y + y*v.y, -N*n.z + x*u.z + y*v.z);
_Ray->Dir->normalize();
_Color->set_Color(scn->shade(_Ray)); // get current pixel's color
glColor3f(_Color->red, _Color->green, _Color->blue); // prepare for drawing the current pixel
glBegin(GL_POINTS);
glVertex2f(col, row);
glEnd();
};
};

Share this post


Link to post
Share on other sites

class Scene
{
public:
Scene();
~Scene();
vector<Object*> ObjList; // Object list
vector<Light*> Lights; // Light list
Color* background;


void construct_Scene(void);
void add_to_ObjList(Object* thisObject);
void add_to_LightList(Light* thisLight);
void make_LightSources(void);
int Search_hitObject(string _Name);
Color* shade(Ray* _Ray);
void getFirstHit(Ray* _Ray, InterSection* First_hit);
};

// constructor
Scene::Scene()
{
background = new Color();
background->set_Color(0.0, 0.0, 0.0); // background color set to black

};

// destructor
Scene::~Scene()
{
};

// add to object list
void Scene::add_to_ObjList(Object* thisObject)
{
ObjList.push_back(thisObject);
};

// add to light list
void Scene::add_to_LightList(Light* thisLight)
{
Lights.push_back(thisLight);
};

// make light sources
void Scene::make_LightSources(void)
{
Light* NewLight = new Light();
NewLight->_Color->set_Color(1.0, 1.0, 1.0); // light color
NewLight->set_Position(0.0, 20.0, -5.0); // light position
add_to_LightList(NewLight); // increment light list
};

// find the object hit in ObjList
int Scene::Search_hitObject(string _Name)
{
int k = 0;
while (k != ObjList.size())
{
bool found = true;
if (_Name.length() == ObjList.at(k)->get_Name().length())
{
int h = 0;
while(h != ObjList.at(k)->get_Name().length())
{
if (ObjList.at(k)->get_Name().at(h) != _Name.at(h))
found = false;
h++;
};
}
else
found = false;

if (found == true)
break;
k++;
};
return k;
};

// Scene description
void Scene::construct_Scene(void)
{
make_LightSources(); // light sources for the scene

Sphere* NewSphere = new Sphere(); // make new sphere object
NewSphere->set_Name("SphereA"); // sphere name
NewSphere->set_Centre(0.0, 0.0, 4.0); // sphere centre
NewSphere->set_Radius(1.0); // sphere radius
NewSphere->set_mat_ambient(0.2, 0.2, 0.0); // ambient material component
NewSphere->set_mat_diffuse(0.8, 0.8, 0.0); // diffuse material component
NewSphere->set_mat_emission(0.1, 0.1, 0.0); // emission material component
NewSphere->set_mat_specular(0.4, 0.4, 0.0); // specular material componet
add_to_ObjList(NewSphere); // increment object list

NewSphere = new Sphere(); // make new sphere object
NewSphere->set_Name("SphereB"); // sphere name
NewSphere->set_Centre(0.0, 0.0, 2.0); // sphere centre
NewSphere->set_Radius(1.0); // sphere radius
NewSphere->set_mat_ambient(0.2, 0.0, 0.0); // ambient material component
NewSphere->set_mat_diffuse(0.8, 0.0, 0.0); // diffuse material component
NewSphere->set_mat_emission(0.1, 0.0, 0.0); // emission material component
NewSphere->set_mat_specular(0.4, 0.0, 0.0); // specular material componet
add_to_ObjList(NewSphere); // increment object list
};

// determines and returns the color of the pixel - if no color found return background color
Color* Scene::shade(Ray* _Ray)
{
Color* thisColor = new Color();
InterSection* First_hit = new InterSection();
getFirstHit(_Ray, First_hit); // find the first object the ray hits
if (First_hit->hits == 0)
return background;

int Index = Search_hitObject(First_hit->_HitInfo.front()->_ObjectName);
thisColor->set_Color(ObjList.at(Index)->get_mat_Diffuse()->red, ObjList.at(Index)->get_mat_Diffuse()->green, ObjList.at(Index)->get_mat_Diffuse()->blue);
return thisColor;
};

// get first hit
void Scene::getFirstHit(Ray* _Ray, InterSection* First_hit)
{
InterSection* InterSect = new InterSection();
First_hit->hits = 0; // initialize First->hits

vector<Object*>::iterator Iter; // get iterator to object list

// for each object in the object list..........
for (Iter = ObjList.begin(); Iter != ObjList.end(); Iter++)
{
if ((*Iter)->_hit(_Ray, InterSect) == false)
continue; // if no hits found continue
if (First_hit->hits == 0 || InterSect->_HitInfo.front()->hit_Time < First_hit->_HitInfo.front()->hit_Time)
First_hit->set(InterSect); // new hit with lesser time(t) found - copy this into First_hit
};
};

Share this post


Link to post
Share on other sites

class Object
{
public:
Object();
~Object();

virtual bool _hit(Ray* _Ray, InterSection* InterSect) = 0;
virtual string get_Name(void) = 0;
virtual Color* get_mat_Diffuse(void) = 0;
};

// constructor
Object::Object()
{
};

// destructor
Object::~Object()
{
};

Share this post


Link to post
Share on other sites

#include <vector>
#include <string>
using namespace std;

class Sphere : public Object
{
public:
Sphere();
~Sphere();
Point* Centre; // sphere centre
GLfloat Radius; // sphere radius
string Name; // sphere name
vector<GLfloat> mat_diffuse; // diffuse material
vector<GLfloat> mat_ambient; // ambient material
vector<GLfloat> mat_emission; // emission material
vector<GLfloat> mat_specular; // specular material

void set_Name(string thisName);
void set_Centre(GLfloat thisx, GLfloat thisy, GLfloat thisz);
void set_Radius(GLfloat thisRadius);
void set_mat_diffuse(GLfloat _red, GLfloat _green, GLfloat _blue);
void set_mat_ambient(GLfloat _red, GLfloat _green, GLfloat _blue);
void set_mat_emission(GLfloat _red, GLfloat _green, GLfloat _blue);
void set_mat_specular(GLfloat _red, GLfloat _green, GLfloat _blue);
void Find_hit_Spot(Point* hit_Spot, GLdouble t1, Ray* _Ray);
void Find_hit_Normal(Vect* hit_Normal, Point* hit_Spot);
bool _hit(Ray* _Ray, InterSection* InterSect);
string get_Name(void);
Color* get_mat_Diffuse(void);
};

//constructor
Sphere::Sphere()
{
Centre = new Point();
};

// destructor
Sphere::~Sphere()
{
};

// set Sphere's name
void Sphere::set_Name(string thisName)
{
Name = thisName;
};

// set sphere's centre
void Sphere::set_Centre(GLfloat thisx, GLfloat thisy, GLfloat thisz)
{
Centre->set(thisx, thisy, thisz);
};

// set sphere's radius
void Sphere::set_Radius(GLfloat thisRadius)
{
Radius = thisRadius;
};

// set material diffuse color
void Sphere::set_mat_diffuse(GLfloat _red, GLfloat _green, GLfloat _blue)
{
mat_diffuse.push_back(_red);
mat_diffuse.push_back(_green);
mat_diffuse.push_back(_blue);
};

// set material ambient color
void Sphere::set_mat_ambient(GLfloat _red, GLfloat _green, GLfloat _blue)
{
mat_ambient.push_back(_red);
mat_ambient.push_back(_green);
mat_ambient.push_back(_blue);
};

// set material emission color
void Sphere::set_mat_emission(GLfloat _red, GLfloat _green, GLfloat _blue)
{
mat_emission.push_back(_red);
mat_emission.push_back(_green);
mat_emission.push_back(_blue);
};

// set material specular color
void Sphere::set_mat_specular(GLfloat _red, GLfloat _green, GLfloat _blue)
{
mat_specular.push_back(_red);
mat_specular.push_back(_green);
mat_specular.push_back(_blue);
};

void Sphere::Find_hit_Spot(Point* hit_Spot, GLdouble _time, Ray* _Ray)
{
GLdouble hit_Spot_X = _Ray->Start->x + _Ray->Dir->x*_time;
GLdouble hit_Spot_Y = _Ray->Start->y + _Ray->Dir->y*_time;
GLdouble hit_Spot_Z = _Ray->Start->z + _Ray->Dir->z*_time;
hit_Spot->set(hit_Spot_X, hit_Spot_Y, hit_Spot_Z);
};

void Sphere::Find_hit_Normal(Vect* hit_Normal, Point* hit_Spot)
{
GLdouble hit_Normal_X = (hit_Spot->x - Centre->x)*(1/Radius);
GLdouble hit_Normal_Y = (hit_Spot->y - Centre->y)*(1/Radius);
GLdouble hit_Normal_Z = (hit_Spot->z - Centre->z)*(1/Radius);
hit_Normal->set(hit_Normal_X, hit_Normal_Y, hit_Normal_Z);
};

bool Sphere::_hit(Ray* _Ray, InterSection* InterSect)
{
/*
A = xd2 + yd2 + zd2
B =2*dx*(x0-cx) + 2*dy*(y0-cy) + 2*dz*(z0-cz);
C = cx*cx + cy*cy + cz*cz + x0*x0 + y0*y0 + z0*z0 - 2*(cx*x0 + cy*y0 + cz*z0) - R*R;
(x,y,z) = (xo + xd*t, yo + yd*t, zo + zd*t)
N = [(x - xc) / rs, (y - yc) / rs, (z - zc) / rs]
*/
GLfloat A = _Ray->Dir->x*_Ray->Dir->x + _Ray->Dir->y*_Ray->Dir->y + _Ray->Dir->z*_Ray->Dir->z;
GLfloat B = 2*(_Ray->Dir->x*(_Ray->Start->x - Centre->x) + _Ray->Dir->y*(_Ray->Start->y - Centre->y) + _Ray->Dir->z*(_Ray->Start->z - Centre->z));
GLfloat C = Centre->x*Centre->x + Centre->y*Centre->y + Centre->z*Centre->z + _Ray->Start->x*_Ray->Start->x + _Ray->Start->y*_Ray->Start->y + _Ray->Start->z*_Ray->Start->z;
C = C - 2*(Centre->x*_Ray->Start->x + Centre->y*_Ray->Start->y + Centre->z*_Ray->Start->z) - Radius*Radius;
GLdouble Discriminant = B*B - 4*A*C;

if (Discriminant < 0.0)
return false;

GLdouble Discriminant_Root = sqrt(Discriminant);
GLdouble t1 = (- B + Discriminant_Root) / 2*A;
GLdouble t2 = (- B - Discriminant_Root) / 2*A;
int hits = 0;
HitInfo* _thisHitInfo = new HitInfo();

if (t1 > 0.0)
{
_thisHitInfo->_ObjectName = Name;
_thisHitInfo->hit_Time = t1;
Point* hit_Spot = new Point();
Vect* hit_Vect = new Vect();
Find_hit_Spot(hit_Spot, t1, _Ray);
Find_hit_Normal(hit_Vect, hit_Spot);
_thisHitInfo->hit_Point->set(hit_Spot->x, hit_Spot->y, hit_Spot->z);
_thisHitInfo->hit_Normal->set(hit_Vect->x, hit_Vect->y, hit_Vect->z);
_thisHitInfo->hit_Normal->normalize();
InterSect->_HitInfo.push_back(_thisHitInfo);
hits = 1;
};

_thisHitInfo = new HitInfo();
if (t2 > 0.0)
{
_thisHitInfo->_ObjectName = Name;
_thisHitInfo->hit_Time = t2;
Point* hit_Spot = new Point();
Vect* hit_Vect = new Vect();
Find_hit_Spot(hit_Spot, t2, _Ray);
Find_hit_Normal(hit_Vect, hit_Spot);
_thisHitInfo->hit_Point->set(hit_Spot->x, hit_Spot->y, hit_Spot->z);
_thisHitInfo->hit_Normal->set(hit_Vect->x, hit_Vect->y, hit_Vect->z);
_thisHitInfo->hit_Normal->normalize();
InterSect->_HitInfo.push_back(_thisHitInfo);
hits++;
};
InterSect->hits = hits;

if (hits > 0)
return true;
else
return false;
};

string Sphere::get_Name(void)
{
return Name;
};

Color* Sphere::get_mat_Diffuse(void)
{
Color* _color = new Color();
_color->set_Color(mat_diffuse.at(0), mat_diffuse.at(1), mat_diffuse.at(2));
return _color;
};

Share this post


Link to post
Share on other sites
I am giving all my code here - this is not a homework assignment - I have been working on this during my summer break but this little glitch has held me blocked up. Anyone - please feel free to copy this code for your own use.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
never mind - got the error - its working now - thankx for all the views......
If anybody wants it I can post the complete corrected code here

Share this post


Link to post
Share on other sites
Next time you post source code, I advise either using the source tag (source and /source between square brackets), or simply zipping the code and make it available for download, because you do have a large amount of code here, its not just one small function, and its quite hard to read it all across multiple posts in a web forum like this.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this