Skip to content

Instantly share code, notes, and snippets.

@agustinsivoplas
Created November 20, 2015 02:24
Show Gist options
  • Save agustinsivoplas/c9661126ac179554a274 to your computer and use it in GitHub Desktop.
Save agustinsivoplas/c9661126ac179554a274 to your computer and use it in GitHub Desktop.
#include "../framework/color.h"
#include <math.h>
#include "Vec4.h"
#include "Sphere.h"
#include "Intersection.h"
#include "float.h"
#include "Camera.h"
#include "Light.h"
#include "Scene.h"
#include "Raytracer.h"
Color lambert(Vec4* P, Vec4* N, Vec4* L, Vec4* V, Sphere* sphere, Light* light) {
float iluDifuso = 0;
float iluEspecular = 0;
float normasNL = norm_vec4(N) * norm_vec4(L);
float cos = (dot_vec4(N, L) / normasNL);
if (cos > 0) {
iluDifuso = cos * (light->intensidad);
if (sphere->exponenteEspecular > 0) {
float normLuz = norm_vec4(L);
Vec4* lAux = (Vec4*) calloc(1, sizeof (Vec4));
Vec4* nAux = (Vec4*) calloc(1, sizeof (Vec4));
if (normLuz != 1) {
init_vec4(lAux, L->x / normLuz, L->y / normLuz, L->z / normLuz, L->t / normLuz);
}
float normN = norm_vec4(N);
if (normN != 1) {
init_vec4(nAux, N->x / normN, N->y / normN, N->z / normN, N->t / normN);
}
float mu = dot_vec4(nAux, lAux) * 2;
Vec4* vraux = (Vec4*) calloc(1, sizeof (Vec4));
init_vec4(vraux, (nAux->x) * mu, (nAux->y) * mu, (nAux->z) * mu, (nAux->t) * mu);
Vec4* vr = (Vec4*) calloc(1, sizeof (Vec4));
minus_vec4(vr, vraux, lAux);
float normasVVr = norm_vec4(V) * norm_vec4(vr);
float cosAux = (dot_vec4(V, vr) / normasVVr);
if (cosAux > 0) {
iluEspecular = pow(cosAux, sphere->exponenteEspecular) * (light->intensidad);
}
free(vraux);
free(vr);
free(lAux);
free(nAux);
}
}
return sum_color(multi_color(sphere->colorDifuso, iluDifuso), multi_color(sphere->colorSpecular, iluEspecular));
}
float* intersect_sphere(Vec4* O, Vec4* D, Sphere* sphere) {
//Armamos una lista de punteros con dos posiciones para el resultado de la ecuacion
float* result = calloc(2, sizeof (float));
float lambda1 = 0;
float lambda2 = 0;
float A = dot_vec4(D, D);
float B = 2.0 * (dot_vec4(O, D) - dot_vec4(D, sphere->centro));
float C = (dot_vec4(O, O)) + (dot_vec4(sphere->centro, sphere->centro)) - (2 * dot_vec4(O, sphere->centro)) - pow(sphere->centro->t, 2);
float delta = pow(B, 2) - 4 * A * C;
if (delta < 0) {
lambda1 = FLT_MAX;
lambda2 = FLT_MAX;
} else {
lambda1 = (-B + sqrt(delta)) / (2.0 * A);
lambda2 = (-B - sqrt(delta)) / (2.0 * A);
}
result[0] = lambda1;
result[1] = lambda2;
return result;
}
Intersection* intersect(Vec4* O, Vec4* D, float lamb_min, float lamb_max, Scene* scene) {
Intersection* inter = (Intersection*) calloc(1, sizeof (Intersection));
inter->sphere = NULL;
inter->lamb = FLT_MAX;
for (int i = 0; i < scene->num_spheres; i++) {
Sphere* sphere = &scene->spheres[i];
float* result = intersect_sphere(O, D, sphere);
float lambda1 = result[0];
float lambda2 = result[1];
if (lambda1 > lamb_min && lambda1 < lamb_max && lambda1 < inter->lamb) {
inter->sphere = sphere;
inter->lamb = lambda1;
}
if (lambda2 > lamb_min && lambda2 < lamb_max && lambda2 < inter->lamb) {
inter->sphere = sphere;
inter->lamb = lambda2;
}
free(result);
}
return inter;
}
Color ray_tracing(Vec4* O, Vec4* D, float lamb_min, float lamb_max, float lim_rec, Scene* scene) {
Color res = cg_color_new(0, 0, 0);
Intersection* inter = intersect(O, D, lamb_min, lamb_max, scene);
if (inter->sphere != NULL) {
Vec4* P = (Vec4*) calloc(1, sizeof (Vec4));
Vec4* N = (Vec4*) calloc(1, sizeof (Vec4));
Vec4* V = (Vec4*) calloc(1, sizeof (Vec4));
Vec4* plusResult = (Vec4*) calloc(1, sizeof (Vec4));
plus_vec4(plusResult, D, inter->lamb);
add_vec4(P, O, plusResult);
minus_vec4(N, P, inter->sphere->centro);
plus_vec4(V, D, -1);
res = multi_color(inter->sphere->colorDifuso, scene->luzAmbiente);
Vec4* L = (Vec4*) calloc(1, sizeof (Vec4));
for (int i = 0; i < scene->num_lights; i++) {
Light* luz = &scene->lights[i];
minus_vec4(L, luz->posicion, P);
Intersection* shadow = intersect(P, L, 0.001, 1, scene);
if (shadow->sphere == NULL) {
res = sum_color(res, lambert(P, N, L, V, inter->sphere, luz));
}
}
if (lim_rec > 0 && inter->sphere->fraccionDeReflexion > 0) {
// RV = 2 ∗ N ∗ <N, V> − V
Vec4* RV = (Vec4*) calloc(1, sizeof (Vec4));
Vec4* plus = (Vec4*) calloc(1, sizeof (Vec4));
Vec4* vAux = (Vec4*) calloc(1, sizeof (Vec4));
Vec4* nAux = (Vec4*) calloc(1, sizeof (Vec4));
float normV = norm_vec4(V);
if (normV != 1) {
init_vec4(vAux, V->x / normV, V->y / normV, V->z / normV, V->t / normV);
}
float normN = norm_vec4(N);
if (normN != 1) {
init_vec4(nAux, N->x / normN, N->y / normN, N->z / normN, N->t / normN);
}
plus_vec4(plus, nAux, 2 * dot_vec4(nAux, vAux));
minus_vec4(RV, plus, vAux);
Color cr = ray_tracing(P, RV, 0.001, FLT_MAX, lim_rec - 1, scene);
res = sum_color(multi_color(res, 1 - inter->sphere->fraccionDeReflexion), multi_color(cr, inter->sphere->fraccionDeReflexion));
free(plus);
free(RV);
free(nAux);
free(vAux);
}
free(P);
free(N);
free(V);
free(L);
free(plusResult);
}
free(inter);
return res;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment