Jump to content
  • Advertisement
Sign in to follow this  
viper_2004

Ray Tracer problems

This topic is 5214 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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
Advertisement

#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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!