Original Post
Hello everyone, i have a nasty logical error somewhere in this code for ray tracing and I hope that someone can take the time to look at it. This is simplified and all its supposed to do is draw a plane with a single sphere. It loops through every pixel of the window to do this. Thank you very much in advance
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <glut.h>
int window_width = 800, window_height = 600;
//forward declarations
void glResizeFunc(int x, int y);
void glDisplayFunc();
void glInitFunc();
//variables
float eye_pos[3] = {(float)window_width/2, 150.0f, 1500.0f};
float light_pos[3] = {(float)window_width/2, 200.0f, 0.0f};
float sphere_center[1][3] = { {(float)window_width/2, 140.0f, 500.0f} };
float sphere_radii[1] = { 5.0f };
float plane_norm[3] = {0.0f, 1.0f, 0.0f};
float plane_intercept = -25.0f;
/********************************************************************
HELPFULL FUNCTIONS
********************************************************************/
void fill_vector(float* vector, float x, float y, float z)
{
vector[0] = x; vector[1] = y; vector[2] = z;
}
float normalize(float* v)
{
return sqrt(pow(v[0],2) + pow(v[1],2) + pow(v[2],2));
}
float dot_product(const float* v, const float* w)
{
return ((v[0])*(w[0]) + (v[1])*(w[1]) + (v[2])*(w[2]));
}
/********************************************************************
LINEAR ALGEBRA
********************************************************************/
float* norm_sphere(float x, float xorig, float y, float yorig, float z, float zorig)
{
int k = 0;
float* normal = (float*)malloc(sizeof(float)*3);
normal[0] = x-xorig; normal[1] = y-yorig; normal[2] = z-zorig;
for (k = 0; k < 3; k++)
normal[k] /= normalize(normal);
return normal;
}
float sphere_intersect(float* direction, float* cur_vec_pos, float* sphere_center, float sphere_radius)
{
int i = 0;
float delta_p[3];
for (i = 0; i < 3; i++)
delta_p = sphere_center - cur_vec_pos;
float radical = pow(dot_product(direction, delta_p),2) -
dot_product(delta_p, delta_p) + pow(sphere_radius, 2);
if (radical < 0)
return -1.0f;
return (dot_product(direction, delta_p) - sqrt(radical));
}
void sphere_reflect_vector(float* reflect, float* direction, float* cur_vec_pos, float* sphere_center, float* light_pos, float sphere_intersect)
{
int i = 0;
float* N = norm_sphere(cur_vec_pos[0] + sphere_intersect * direction[0], sphere_center[0],
cur_vec_pos[1] + sphere_intersect * direction[1], sphere_center[1],
cur_vec_pos[2] + sphere_intersect * direction[2], sphere_center[2]);
float L[3] = {light_pos[0] - N[0], light_pos[1] - N[1], light_pos[2] - N[2]};
float dot = dot_product(N, L);
for (i = 0; i < 3; i++)
reflect = N - direction / (2 * dot);
for (i = 0; i < 3; i++)
reflect /= normalize(reflect);
free(N);
}
float plane_intersect(float* direction, float* cur_vec_pos, float* norm_of_plane, float plane_intercept)
{
float numer = -plane_intercept - (dot_product(cur_vec_pos, norm_of_plane));
float denom = dot_product(direction, norm_of_plane);
if (denom <= 0) return -1; //check this
return (numer/denom);
}
float find_shade(float* direction, float* cur_vec_pos, float* light_pos, float* plane_normal, float plane_intersect)
{
int i = 0;
float L[3];
float cos_ang;
for (i = 0; i < 3; i++)
L = light_pos - (cur_vec_pos + plane_intersect * direction);
cos_ang = (dot_product(plane_normal, L) / (normalize(plane_normal) * normalize(L)));
return (cos_ang < 0 ? 0.0f : cos_ang);
}
/********************************************************************
OPEN-GL
********************************************************************/
int main(int argc, char* argv[])
{
glutInitWindowSize(window_width, window_height);
glutCreateWindow("Ray Tracing");
glInitFunc();
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutDisplayFunc(glDisplayFunc);
glutReshapeFunc(glResizeFunc);
glutMainLoop();
}
void glResizeFunc(int w, int h)
{
window_width = w;
window_height = h;
}
void glInitFunc()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, window_width, 0, window_height);
}
void glDisplayFunc()
{
bool plotted = false;
int x = 0, y = 0, k = 0;
float sp_intersect = 0.0f;
float pl_intersect = 0.0f;
float shade = 0.0f;
float cur_vec_pos[3];
float direction[3];
float reflect[3];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (x = 0; x < window_width; x++)
{
for (y = 0; y < window_height; y++)
{
//set cur_vec_pos to start with the eye vector
fill_vector(cur_vec_pos, eye_pos[0], -eye_pos[1], eye_pos[2]);
plotted = false;
while (!plotted)
{
//get direction vector
fill_vector(direction, x-cur_vec_pos[0], y+cur_vec_pos[1], -cur_vec_pos[2]);
//normalize the direction vector
for (k = 0; k < 3; k++)
direction[k] /= normalize(direction);
//find intersects
sp_intersect = sphere_intersect(direction, cur_vec_pos, sphere_center[0], sphere_radii[0]);
pl_intersect = plane_intersect(direction, cur_vec_pos, plane_norm, plane_intercept);
//no intersection was found
if (sp_intersect < 0 && pl_intersect < 0)
{
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_POINTS);
glVertex2i(x, window_height-y);
glEnd();
plotted = true;
}
//intersection at sphere, calculate reflect vector and start over
else if (sp_intersect > 0 && (pl_intersect < 0 || sp_intersect < pl_intersect))
{
sphere_reflect_vector(reflect, direction, cur_vec_pos, sphere_center[0], light_pos, sp_intersect);
fill_vector(cur_vec_pos, reflect[0], reflect[1], reflect[2]);
}
//intersected with plane, can intersect from a reflect vector, or from initial vector
else
{
shade = find_shade(direction, cur_vec_pos, light_pos, plane_norm, pl_intersect);
float a = pl_intersect * direction[0] + cur_vec_pos[0];
float b = pl_intersect * direction[2] + cur_vec_pos[2];
int ta = (int)a/40;
int tb = (int)b/40;
if (abs(ta)%2 == abs(tb)%2)
glColor3f(0,shade,shade/2);
else
glColor3f(shade/2, shade/2, shade/2);
glBegin(GL_POINTS);
glVertex2i(x, window_height-y);
glEnd();
plotted = true;
}
}//while
}//height
}//width
glFlush();
}