Skip to main content
gamedev.net
🔒 Locked

Ray Tracing Problem

Started by b1gjo3 0 replies 600+ views
Original Post
b1gjo3
b1gjo3
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();
}

b1gjo3
b1gjo3
If anyone can just check my math functions that would be great. I could probably find it from there.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.