Created
October 4, 2016 02:04
-
-
Save apsicle/0f19a8ca3858237aecb371c139cd8fce to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Light.hpp" | |
#include <cmath> | |
void Light::set (double x, double y, double z) { | |
this -> loc.set(x, y, z); | |
} | |
Light::Light(void) { | |
set(5, 10, 0); | |
} | |
Light::Light(double x, double y, double z) { | |
set(x, y, z); | |
} | |
COLOR_T Light::illuminate(RAY_T ray, COLOR_T surface_col, Vector int_pt, Vector normal) { | |
COLOR_T col; | |
//Ambient | |
col.R = surface_col.R * 0.1; | |
col.G = surface_col.G * 0.1; | |
col.B = surface_col.B * 0.1; | |
//Diffuse | |
Vector L; | |
L = loc - int_pt; | |
L.normalize(); | |
double dotted = L.dot(normal); | |
if(dotted > 0) { | |
col.R += dotted * surface_col.R; | |
col.G += dotted * surface_col.G; | |
col.B += dotted * surface_col.B; | |
//Specular | |
Vector R = L - (normal * (normal.dot(L)) * 2); | |
R.normalize(); | |
double dot2 = R.dot(ray.dir); | |
if(dot2 > 0) { | |
col.R += pow(dot2, 200); | |
col.G += pow(dot2, 200); | |
col.B += pow(dot2, 200); | |
} | |
} | |
return col; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef LIGHT_HPP_ | |
#define LIGHT_HPP_ | |
#include "Vector.hpp" | |
#include "rt.hpp" | |
class Light { | |
private: | |
Vector loc; | |
public: | |
Light(void); | |
Light(double, double, double); | |
void set(double, double, double); | |
COLOR_T illuminate(RAY_T ray, COLOR_T surface_col, Vector int_pt, Vector normal); | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef OBJ_HPP_ | |
#define OBJ_HPP_ | |
#include "rt.hpp" | |
#include "Sphere.hpp" | |
typedef struct OBJ { | |
//The node class. Contains sphere | |
Sphere sphere; | |
COLOR_T color; | |
struct OBJ *next; | |
} OBJ_T; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <cstdio> | |
#include <cmath> | |
#include "rt.hpp" | |
#include "obj.hpp" | |
#include "Light.hpp" | |
#include "Sphere.hpp" | |
#include "Vector.hpp" | |
/* Author: Ryan Yan | |
* Date: 04/24/16 | |
* | |
* Description: This is a raytracing program. This produces a 2-d graphical depiction of | |
* spheres based on information in a formatted text file from the vantage point of a viewer behind a canvas. | |
* This works with the input files sphere.txt and spheres.txt. | |
*/ | |
void read_objs (OBJ_T** list) { | |
//This function takes a declared linked list, and reads in stdinput (redirected from console) of spheres or sphere.txt | |
//Declare vars | |
double x, y, z; | |
double radius; | |
Sphere input_sphere; | |
COLOR_T color; | |
//Scan in series of 7 floats describing a sphere (formatted in spheres.txt) | |
while(std::cin >> x >> y >> z >> radius >> color.R >> color.G >> color.B != NULL) { | |
OBJ_T * node = new OBJ_T; //allocate memory for new node object. | |
input_sphere.set(Vector(x, y, z), radius); //create sphere based on inputs | |
node->sphere = input_sphere; | |
node->color = color; | |
node->next = *list; //add node (containing sphere) to head of linked list and change head pointer. | |
*list = node; | |
} | |
} | |
COLOR_T Trace (RAY_T ray, OBJ_T* list, Light light) { | |
//Iterates through the linked list of nodes (spheres) and finds the color associated with the sphere closest to the viewer. | |
//Trace is called in the main loop on each pixel in order to color it. | |
//Declare vars | |
OBJ_T* mylist = list; | |
double min_t; | |
double t; | |
t = min_t = 1000; | |
OBJ_T* closest_obj = NULL; | |
OBJ_T* curr_obj = NULL; | |
Vector closest_int_pt; | |
Vector curr_int_pt; | |
Vector closest_normal; | |
Vector curr_normal; | |
COLOR_T color = {0,0,0}; //If we find no intersections, default to black | |
for(curr_obj = list; curr_obj != NULL; curr_obj = curr_obj -> next){ //Search through linked list for closest visible sphere | |
if (curr_obj->sphere.intersect(ray, t, curr_int_pt, curr_normal)) { | |
if (t < min_t) { //This loop finds the closest sphere | |
closest_obj = curr_obj; | |
closest_int_pt = curr_int_pt; | |
closest_normal = curr_normal; | |
min_t = t; | |
} | |
} | |
mylist = mylist -> next; | |
} | |
if(closest_obj != NULL){ | |
color = light.illuminate(ray, closest_obj -> color, closest_int_pt, closest_normal); //colors in the closest sphere | |
} | |
return color; | |
} | |
int main() { | |
//Set vars | |
int maxy = 1000, maxx = 1000; | |
double y, x; | |
Vector origin(0,0,0); | |
double t; | |
COLOR_T pixel; | |
Light light; | |
light.set(5, 10, 0); | |
//Write ppm header. | |
std::cout << "P6\n" << maxx << "\n" << maxy << "\n255\n"; | |
//Create a linked list, setting sentinel node. | |
OBJ_T* mylist = new OBJ_T; | |
mylist -> next = NULL; | |
read_objs (&mylist); | |
//Write image data by looping through pixels and checking intersections with all spheres | |
for (y = maxy; y > 0; y--) { | |
for (x = 0; x < maxx; x++) { | |
//Set ray | |
Vector dir(-0.5 + (x / 1000), -0.5 + (y / 1000), 1); | |
dir.normalize(); | |
RAY_T ray = {origin, dir}; | |
//Set pixel color with cast and multiply by 255. We use a number from 0 to 1 multiplied by 255 for extra precision. | |
pixel = Trace(ray, mylist, light); | |
if(pixel.R > 1.0) { | |
pixel.R = 1.0; | |
} | |
if(pixel.G > 1.0) { | |
pixel.G = 1.0; | |
} | |
if(pixel.B > 1.0) { | |
pixel.B = 1.0; | |
} | |
pixel.R = pixel.R * 255; | |
pixel.G = pixel.G * 255; | |
pixel.B = pixel.B * 255; | |
//Print out pixels as characters to the ppm. | |
std::cout << (unsigned char) pixel.R << (unsigned char) pixel.G << (unsigned char) pixel.B; | |
} | |
} | |
//delete the dynamically allocated memory by iterating through the linked list | |
OBJ_T* curr; | |
while (mylist != NULL) { | |
curr = mylist; | |
mylist = mylist -> next; | |
delete(curr); | |
} | |
//Always return 0, kids. | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef RT_HPP_ | |
#define RT_HPP_ | |
#include "Vector.hpp" | |
/* Author: Ryan Yan | |
* Date: 04/24/16 | |
* | |
* Description: This is a raytracing program. This header file defines several useful structures | |
*/ | |
typedef struct RAY { | |
//An infinite length Vector | |
Vector origin; | |
Vector dir; | |
} RAY_T; | |
typedef struct COLOR { | |
//For pixel shading | |
double R; | |
double G; | |
double B; | |
} COLOR_T; | |
#endif | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Sphere.hpp" | |
#include "rt.hpp" | |
#include <iostream> | |
#include <cmath> | |
void Sphere::set (Vector ctr, double radius) { | |
this -> ctr = ctr; | |
this -> radius = radius; | |
} | |
bool Sphere::intersect (RAY_T ray, double &t, Vector &int_pt, Vector &normal) { | |
//Passed in a ray, a sphere, and the previously held minimum distance t. | |
//Returns 1 when found intersection and 0 when not. Sets t to minimum of the roots (intersections) when found. | |
//Declare vars | |
Vector origin = ray.origin; | |
Vector dir = ray.dir; | |
//Analytical solution to the intersection of a ray and a sphere in 3 dimensions. We can write a parametric equation | |
//of the normalized Vector representing the ray, and solve a quadratic equation for the distance t between the origin | |
//of the ray and the intersection. | |
double A = 1; | |
double B = dir.dot(origin - ctr) * 2; | |
double C = (origin - ctr).dot(origin - ctr) - radius*radius; | |
double discriminant = B*B - 4*A*C; | |
if(discriminant <= 0) { | |
//no real roots, so exit w/o finding intersection. | |
return 0; | |
} | |
else { | |
double root1 = (-B + std::sqrt(discriminant)) / 2; | |
double root2 = (-B - std::sqrt(discriminant)) / 2; | |
if (root1 <= 0 && root2 <= 0) { | |
return 0; //both negative roots means we're in front of the image, so we can't see it. | |
} | |
else if (root1 <= root2) { | |
//We return the smaller root (minimum distance) | |
t = root1; | |
int_pt = origin + (dir * t); | |
normal = (int_pt - ctr) / radius; | |
return 1; | |
} | |
else { | |
t = root2; | |
int_pt = origin + (dir * t); | |
normal = (int_pt - ctr) / radius; | |
return 1; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SPHERE_HPP_ | |
#define SPHERE_HPP_ | |
#include "rt.hpp" | |
#include "Vector.hpp" | |
class Sphere { | |
//Sphere class. Center, radius, check intersection. | |
private: | |
Vector ctr; | |
double radius; | |
public: | |
void set (Vector, double); | |
bool intersect (RAY_T ray, double &t, Vector &int_pt, Vector &normal); | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
0.0 0.0 10.0 | |
2.0 | |
1.0 0.0 0.0 | |
-3.0 -3.0 6.0 | |
3.5 | |
1.0 0.0 1.0 | |
1.8 -1.3 6.0 | |
0.9 | |
0.7 1.0 0.3 | |
-0.6 -0.9 3.0 | |
0.25 | |
0.0 0.0 0.6 | |
3.0 2.5 12.0 | |
2.8 | |
0.6 0.5 0.8 | |
-2.0 2.0 4.0 | |
1.0 | |
0.2 0.5 0.2 | |
-0.55 0.7 2.0 | |
0.1 | |
0.9 0.9 0.1 | |
2.0 0.9 7.0 | |
0.07 | |
0.6 1.0 1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cmath> | |
#include <iostream> | |
#include "Vector.hpp" | |
/* Author: Ryan Yan | |
* Date: 04/11/16 | |
* | |
* Description: This is a raytracing program. This file defines several useful functions on vectors | |
*/ | |
Vector::Vector (double x, double y, double z) { | |
set(x, y, z); | |
} | |
Vector::Vector (void) { | |
set(0, 0, 0); | |
} | |
void Vector::set (double x, double y, double z) { | |
this -> x = x; | |
this -> y = y; | |
this -> z = z; | |
} | |
Vector Vector::add(Vector v){ | |
Vector rv; | |
rv.x = x + v.x; | |
rv.y = y + v.y; | |
rv.z = z + v.z; | |
return rv; | |
} | |
Vector Vector::operator + (Vector v) { | |
return this -> add(v); | |
} | |
Vector Vector::subtract(Vector v){ | |
Vector rv; | |
rv.x = x - v.x; | |
rv.y = y - v.y; | |
rv.z = z - v.z; | |
return rv; | |
} | |
Vector Vector::operator - (Vector v){ | |
return this -> subtract(v); | |
} | |
Vector Vector::mult(Vector v){ | |
Vector rv; | |
rv.x = x * v.x; | |
rv.y = y * v.y; | |
rv.z = z * v.z; | |
return rv; | |
} | |
Vector Vector::operator * (Vector v) { | |
return this -> mult(v); | |
} | |
Vector Vector::scalar_mult(double d) { | |
Vector rv; | |
rv.x = d * x; | |
rv.y = d * y; | |
rv.z = d * z; | |
return rv; | |
} | |
Vector Vector::operator * (double d) { | |
return this -> scalar_mult(d); | |
} | |
Vector Vector::scalar_divide(double d) { | |
Vector rv; | |
rv.x = x / d; | |
rv.y = y / d; | |
rv.z = z / d; | |
return rv; | |
} | |
Vector Vector::operator / (double d) { | |
return this -> scalar_divide(d); | |
} | |
double Vector::sum_components (void) { | |
return x + y + z; | |
} | |
double Vector::length (void) { | |
return std::sqrt(x*x + y*y + z*z); | |
} | |
void Vector::normalize (void) { | |
//Normalizing the vector normalizes each component such that the length of the vector is 1. | |
double magnitude = length(); | |
this -> x = x / magnitude; | |
this -> y = y / magnitude; | |
this -> z = z / magnitude; | |
} | |
double Vector::dot (Vector v) { | |
//Sum of elementwise products of two vectors. | |
double sum = mult(v).sum_components(); | |
return sum; | |
} | |
void Vector::print (void) { | |
std::cout << "x: " << this -> x << "\ny: " << this -> y << "\nz: " << this -> z << "\n"; | |
} | |
/* | |
int main() { | |
Vector test; | |
Vector test1; | |
Vector test2; | |
test.print(); | |
test2 = test.add(Vector (2,3,4)); | |
test2.print(); | |
test1.set(1,1,1); | |
std::cout << test1.dot(test2); | |
test2.print(); | |
std::cout << test2.length(); | |
test2.normalize(); | |
test2.print(); | |
(test1 / 4).print(); | |
(test1 * 2).print(); | |
return 0; | |
}*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef VECTOR_HPP_ | |
#define VECTOR_HPP_ | |
/* Author: Ryan Yan | |
* Date: 04/11/16 | |
* This header file defines the vector structure | |
*/ | |
class Vector { | |
//Magnitude and direction. | |
private: | |
double x; | |
double y; | |
double z; | |
public: | |
Vector(void); | |
Vector(double x, double y, double z); | |
void set(double x, double y, double z); | |
Vector add(Vector); | |
Vector operator+(Vector); | |
Vector subtract(Vector); | |
Vector operator-(Vector); | |
Vector mult(Vector); | |
Vector operator*(Vector); | |
Vector scalar_mult(double); | |
Vector operator*(double); | |
Vector scalar_divide(double); | |
Vector operator/(double); | |
double sum_components(void); | |
double length(void); | |
double dot (Vector); | |
void normalize (void); | |
void print(void); | |
}; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment