//HAVE THEM IMPLEMENT THIS //The ray in this function is not transformed because it was *already* transformed in Mesh::GetIntersection Intersection Triangle::GetIntersection(Ray r){ //1. Ray-plane intersection Intersection result; float t = glm::dot(plane_normal, (points[0] - r.origin)) / glm::dot(plane_normal, r.direction); glm::vec3 P = r.origin + t * r.direction; //2. Barycentric test float S = 0.5f * glm::length(glm::cross(points[0] - points[1], points[0] - points[2])); float s1 = 0.5f * glm::length(glm::cross(P - points[1], P - points[2]))/S; float s2 = 0.5f * glm::length(glm::cross(P - points[2], P - points[0]))/S; float s3 = 0.5f * glm::length(glm::cross(P - points[0], P - points[1]))/S; float sum = s1 + s2 + s3; if(s1 >= 0 && s1 <= 1 && s2 >= 0 && s2 <= 1 && s3 >= 0 && s3 <= 1 && fequal(sum, 1.0f)){ result.t = t; result.texture_color = Material::GetImageColorInterp(GetUVCoordinates(glm::vec3(P)), material->texture); result.object_hit = this; //TODO: Store the tangent and bitangent glm::vec3 dis[2] = {points[1] - points[0], points[2] - points[0]}; glm::vec2 uv_points[3] = {GetUVCoordinates(points[1]), GetUVCoordinates(points[1]), GetUVCoordinates(points[2])}; glm::vec2 uv_dis[2] = {uv_points[1] - uv_points[0], uv_points[2] - uv_points[0]}; result.tangent = (uv_dis[1].y*dis[0] - uv_dis[0].y*dis[1])/(uv_dis[1].y*uv_dis[0].x - uv_dis[0].x*uv_dis[1].y); result.bitangent = (dis[1] - uv_dis[1].x*result.tangent)/uv_dis[1].y; } return result; }
Intersection Disc::GetIntersection(Ray r) { //Transform the ray Ray r_loc = r.GetTransformedCopy(transform.invT()); Intersection result; //Ray-plane intersection float t = glm::dot(glm::vec3(0,0,1), (glm::vec3(0.5f, 0.5f, 0) - r_loc.origin)) / glm::dot(glm::vec3(0,0,1), r_loc.direction); glm::vec4 P = glm::vec4(t * r_loc.direction + r_loc.origin, 1); //Check that P is within the bounds of the disc (not bothering to take the sqrt of the dist b/c we know the radius) float dist2 = (P.x * P.x + P.y * P.y); if(t > 0 && dist2 <= 0.25f) { result.point = glm::vec3(transform.T() * P); result.normal = glm::normalize(glm::vec3(transform.invTransT() * glm::vec4(ComputeNormal(glm::vec3(P)), 0))); result.object_hit = this; result.t = glm::distance(result.point, r.origin); //was interp result.texture_color = Material::GetImageColor(GetUVCoordinates(glm::vec3(P)), material->texture); //Compute tangent and bitangent glm::vec3 T = glm::normalize(glm::cross(glm::vec3(0,1,0), ComputeNormal(glm::vec3(P)))); glm::vec3 B = glm::cross(ComputeNormal(glm::vec3(P)), T); result.tangent = glm::normalize(glm::vec3(transform.T() * glm::vec4(T, 0))); result.bitangent = glm::normalize(glm::vec3(transform.T() * glm::vec4(B, 0))); } return result; }
//HAVE THEM IMPLEMENT THIS //The ray in this function is not transformed because it was *already* transformed in Mesh::GetIntersection Intersection Triangle::GetIntersection(Ray r){ //1. Ray-plane intersection Intersection result; float t = glm::dot(plane_normal, (points[0] - r.origin)) / glm::dot(plane_normal, r.direction); glm::vec3 P = r.origin + t * r.direction; //2. Barycentric test float S = 0.5f * glm::length(glm::cross(points[1] - points[0], points[2] - points[0])); float s1 = 0.5f * glm::length(glm::cross(points[1]-P, points[2]-P))/S; float s2 = 0.5f * glm::length(glm::cross(points[2]-P, points[0]-P))/S; float s3 = 0.5f * glm::length(glm::cross(points[0]-P, points[1]-P))/S; float sum = s1 + s2 + s3; if(s1 >= 0 && s1 <= 1 && s2 >= 0 && s2 <= 1 && s3 >= 0 && s3 <= 1){ result.t = t; result.texture_color = Material::GetImageColorInterp(GetUVCoordinates(glm::vec3(P)), material->texture); result.object_hit = this; result.point = glm::vec3(transform.invT()*glm::vec4(P, 1.0f)); //tranform T to world coords result.normal = glm::vec3(glm::normalize(transform.invTransT()*glm::vec4(plane_normal, 1.0f))); //transform normal to world coords //TODO: Store the tangent and bitangent glm::vec3 changeP1 = this->points[1] - this->points[0]; glm::vec3 changeP2 = this->points[2] - this->points[0]; glm::vec2 changeUV1 = this->uvs[1] - this->uvs[0]; glm::vec2 changeUV2 = this->uvs[2] - this->uvs[0]; result.tangent = glm::normalize(changeUV2[1]*changeP1 - changeUV1[1]*changeP2); result.bitangent =glm::normalize((changeP2 - changeUV2[0]*result.tangent)/changeUV2[1]); } return result; }
//HAVE THEM IMPLEMENT THIS //The ray in this function is not transformed because it was *already* transformed in Mesh::GetIntersection Intersection Triangle::GetIntersection(Ray r){ //1. Ray-plane intersection Intersection result; float t = glm::dot(plane_normal, (points[0] - r.origin)) / glm::dot(plane_normal, r.direction); glm::vec3 P = r.origin + t * r.direction; //2. Barycentric test float S = 0.5f * glm::length(glm::cross(points[0] - points[1], points[0] - points[2])); float s1 = 0.5f * glm::length(glm::cross(P - points[1], P - points[2]))/S; float s2 = 0.5f * glm::length(glm::cross(P - points[2], P - points[0]))/S; float s3 = 0.5f * glm::length(glm::cross(P - points[0], P - points[1]))/S; float sum = s1 + s2 + s3; if(s1 >= 0 && s1 <= 1 && s2 >= 0 && s2 <= 1 && s3 >= 0 && s3 <= 1 && fequal(sum, 1.0f)){ result.t = t; result.texture_color = Material::GetImageColorInterp(GetUVCoordinates(glm::vec3(P)), material->texture); result.object_hit = this; //TODO: Store the tangent and bitangent glm::vec2 dUV1 = uvs[0] - uvs[1]; glm::vec2 dUV2 = uvs[0] - uvs[2]; glm::vec3 pos1 = points[0] - points[1]; glm::vec3 pos2 = points[0] - points[2]; glm::vec3 tangent = (dUV2.y * pos1 - dUV1.y * pos2)/(dUV2.y * dUV1.x - dUV1.y * dUV2.x); glm::vec3 bitangent; if(!fequal(dUV2.y, 0.0f)) bitangent = (pos2 - dUV2.x * tangent) / dUV2.y; else bitangent = (pos1 - dUV1.x * tangent) / dUV1.y; result.tangent = tangent; result.bitangent = bitangent; } return result; }
Intersection SquarePlane::GetIntersection(Ray r) { //Transform the ray Ray rLocal = r.GetTransformedCopy(transform.invT()); Intersection result; //Ray-plane intersection float t = glm::dot(glm::vec3(0,0,1), (glm::vec3(0.5f, 0.5f, 0) - rLocal.origin)) / glm::dot(glm::vec3(0,0,1), rLocal.direction); glm::vec4 P = glm::vec4(t * rLocal.direction + rLocal.origin, 1); //Check that P is within the bounds of the square if(t > 0 && P.x >= -0.5f && P.x <= 0.5f && P.y >= -0.5f && P.y <= 0.5f) { result.point = glm::vec3(transform.T() * P); result.normal = glm::normalize(glm::vec3(transform.invTransT() * glm::vec4(ComputeNormal(glm::vec3(P)), 0))); result.object_hit = this; result.t = glm::distance(result.point, r.origin); //was interp result.texture_color = Material::GetImageColor(GetUVCoordinates(glm::vec3(P)), material->texture); glm::vec3 T = glm::normalize(glm::cross(glm::vec3(0,1,0), ComputeNormal(glm::vec3(P)))); glm::vec3 B = glm::cross(ComputeNormal(glm::vec3(P)), T); result.tangent = glm::normalize(glm::vec3(transform.T() * glm::vec4(T, 0))); result.bitangent = glm::normalize(glm::vec3(transform.T() * glm::vec4(B, 0))); return result; } return result; }
Intersection SquarePlane::GetIntersection(Ray r) { //Transform the ray Ray r_loc = r.GetTransformedCopy(transform.invT()); Intersection result; //Ray-plane intersection float t = glm::dot(glm::vec3(0,0,1), (glm::vec3(0.5f, 0.5f, 0) - r_loc.origin)) / glm::dot(glm::vec3(0,0,1), r_loc.direction); glm::vec4 P = glm::vec4(t * r_loc.direction + r_loc.origin, 1); //Check that P is within the bounds of the square if(t > 0 && P.x >= -0.5f && P.x <= 0.5f && P.y >= -0.5f && P.y <= 0.5f) { result.point = glm::vec3(transform.T() * P); result.normal = glm::normalize(glm::vec3(transform.invTransT() * glm::vec4(ComputeNormal(glm::vec3(P)), 0))); result.object_hit = this; result.t = glm::distance(result.point, r.origin); result.texture_color = Material::GetImageColorInterp(GetUVCoordinates(glm::vec3(P)), material->texture); // Store the tangent and bitangent glm::vec3 tangent; glm::vec3 bitangent; ComputeTangents(ComputeNormal(glm::vec3(P)), tangent, bitangent); result.tangent = glm::normalize(glm::vec3(transform.T() * glm::vec4(tangent, 0))); result.bitangent = glm::normalize(glm::vec3(transform.T() * glm::vec4(bitangent, 0))); return result; } return result; }
Intersection Ring::GetIntersection(Ray r) { //Transform the ray Ray r_loc = r.GetTransformedCopy(transform.invT()); Intersection result; //Ray-plane intersection float t = glm::dot(glm::vec3(0,0,1), (glm::vec3(0.5f, 0.5f, 0) - r_loc.origin)) / glm::dot(glm::vec3(0,0,1), r_loc.direction); glm::vec4 P = glm::vec4(t * r_loc.direction + r_loc.origin, 1); float dist2 = (P.x * P.x + P.y * P.y); if(t > 0 && dist2 <= 1.0f && dist2 >= 0.25f) { result.point = glm::vec3(transform.T() * P); result.object_hit = this; result.t = glm::distance(result.point, r.origin); result.texture_color = Material::GetImageColorInterp(GetUVCoordinates(glm::vec3(P)), material->texture); //Store the tangent and bitangent SetNormalTangentBitangent(glm::vec3(P),result); return result; } return result; }
Intersection SquarePlane::SquarePlane::GetIntersection(Ray r) { //---Q5--- //TODO static const float EPS( 1e-4 ); Ray rInWorld = r; Intersection result; r = r.GetTransformedCopy( transform.invT() ); result.t = -r.origin[ 2 ] / r.direction[ 2 ]; if( result.t - EPS < 0.f ) return Intersection(); result.point = r.origin + result.t * r.direction; if( glm::abs( result.point[ 0 ] ) > .5f ) return Intersection(); if( glm::abs( result.point[ 1 ] ) > .5f ) return Intersection(); result.color = material->GetImageColor( GetUVCoordinates( result.point ), material->texture ) * material->base_color; result.point = glm::vec3( transform.T() * glm::vec4( result.point, 1.f ) ); result.normal = glm::normalize(glm::vec3( transform.invTransT() * glm::vec4( 0.f, 0.f, 1.f, 0.f ) ) ); result.t = glm::length( result.point - rInWorld.origin ); result.object_hit = this; return result; }
Intersection SquarePlane::GetSampledIntersection(float randX, float randY, const glm::vec3 &isx_normal) { glm::vec4 point = glm::vec4(-0.5 + randX, -0.5 + randY, 0.f, 1.f); Intersection result; result.point = glm::vec3(transform.T() * point); result.normal = glm::normalize(glm::vec3(transform.invTransT() * glm::vec4(ComputeNormal(glm::vec3(point)), 0))); result.object_hit = this; result.texture_color = Material::GetImageColor(GetUVCoordinates(glm::vec3(point)), material->texture); return result; }
Intersection Sphere::GetIntersection(Ray r) { //Transform the ray Ray r_loc = r.GetTransformedCopy(transform.invT()); Intersection result; float A = pow(r_loc.direction[0], 2) + pow(r_loc.direction[1], 2) + pow(r_loc.direction[2], 2); float B = 2*(r_loc.direction[0]*r_loc.origin[0] + r_loc.direction[1] * r_loc.origin[1] + r_loc.direction[2] * r_loc.origin[2]); float C = pow(r_loc.origin[0], 2) + pow(r_loc.origin[1], 2) + pow(r_loc.origin[2], 2) - 0.25f;//Radius is 0.5f float discriminant = B*B - 4*A*C; //If the discriminant is negative, then there is no real root if(discriminant < 0){ return result; } float t = (-B - sqrt(discriminant))/(2*A); if(t < 0) { t = (-B + sqrt(discriminant))/(2*A); } if(t >= 0) { glm::vec4 P = glm::vec4(r_loc.origin + t*r_loc.direction, 1); result.point = glm::vec3(transform.T() * P); glm::vec2 uv = GetUVCoordinates(glm::vec3(P)); result.normal = glm::normalize(glm::vec3(transform.invTransT() * (P - glm::vec4(0,0,0,1)))); result.t = glm::distance(result.point, r.origin); result.texture_color = Material::GetImageColorInterp(uv, material->texture); result.object_hit = this; //TODO: Store the tangent and bitangent glm::vec3 N( glm::normalize( glm::vec3( P ) ) ); glm::vec4 T, B; if( glm::length( N - glm::vec3( 0.f, 0.f, 1.f ) ) < 1e-5 ){ T = glm::vec4( 1.f, 0.f, 0.f, 0.f ); B = glm::vec4( 0.f, 1.f, 0.f, 0.f ); }else if( glm::length( N - glm::vec3( 0.f, 0.f, -1.f ) ) ){ T = glm::vec4( 1.f, 0.f, 0.f, 0.f ); B = glm::vec4( 0.f, -1.f, 0.f, 0.f ); }else{ glm::vec3 Z( 0.f, 0.f, 1.f ); T = glm::vec4( glm::cross( Z, N ), 0.f ); B = glm::vec4( glm::cross( N, glm::vec3( T ) ), 0.f ); } result.tangent = glm::normalize( glm::vec3( transform.T() * T ) ); result.bitangent = glm::normalize( glm::vec3( transform.T() * B ) ); return result; } return result; }
Intersection Disc::GetSampledIntersection(float randX, float randY, const glm::vec3 &isx_normal) { float r = sqrtf(randX); float theta = 2.f * M_PI * randY; glm::vec4 point = glm::vec4( r*cosf(theta), r*sinf(theta), 0.f, 1.f ); Intersection result; result.point = glm::vec3(transform.T() * point); result.normal = glm::normalize(glm::vec3(transform.invTransT() * glm::vec4(ComputeNormal(glm::vec3(point)), 0))); result.object_hit = this; result.texture_color = Material::GetImageColor(GetUVCoordinates(glm::vec3(point)), material->texture); return result; }
Intersection Ring::SampleOnGeometrySurface(const float &u, const float &v, const glm::vec3 &point) { float r = 0.5f + u * 0.5f; float theta = v * 2.0f * PI; glm::vec3 hitPoint(r * cos(theta), r * sin(theta), 0.0f); Intersection result; result.point = glm::vec3(transform.T() * glm::vec4(hitPoint, 1.0f)); result.object_hit = this; result.texture_color = Material::GetImageColorInterp(GetUVCoordinates(hitPoint), material->texture); //Store the tangent and bitangent SetNormalTangentBitangent(hitPoint,result); result.t = 1.0f; return result; }
Intersection Cube::GetIntersection(Ray r) { //Transform the ray Ray r_loc = r.GetTransformedCopy(transform.invT()); Intersection result; float t_n = -1000000.f; float t_f = 1000000.f; for(int i = 0; i < 3; i++){ //Ray parallel to slab check if(r_loc.direction[i] == 0){ if(r_loc.origin[i] < -0.5f || r_loc.origin[i] > 0.5f){ return result; } } //If not parallel, do slab intersect check float t0 = (-0.5f - r_loc.origin[i])/r_loc.direction[i]; float t1 = (0.5f - r_loc.origin[i])/r_loc.direction[i]; if(t0 > t1){ float temp = t1; t1 = t0; t0 = temp; } if(t0 > t_n){ t_n = t0; } if(t1 < t_f){ t_f = t1; } } float t_final = -1; if(t_n < t_f) { if(t_n >= 0) { t_final = t_n; } else if(t_f >= 0) { t_final = t_f; } } if(t_final >= 0) { //Lastly, transform the point found in object space by T glm::vec4 P = glm::vec4(r_loc.origin + t_final*r_loc.direction, 1); glm::vec4 N( glm::normalize( GetCubeNormal( P ) ) ); result.point = glm::vec3(transform.T() * P); result.normal = glm::normalize(glm::vec3(transform.invTransT() * N)); result.object_hit = this; result.t = glm::distance(result.point, r.origin); result.texture_color = Material::GetImageColorInterp(GetUVCoordinates(glm::vec3(P)), material->texture); //TODO: Store the tangent and bitangent glm::vec4 T( 0.f ), B( 0.f ); if( N[ 0 ] < -.9f ){ T = glm::vec4( 0.f, -1.f, 0.f, 0.f ); }else if( N[ 0 ] > .9f ){ T = glm::vec4( 0.f, 1.f, 0.f, 0.f ); }else if( N[ 1 ] < -.9f ){ T = glm::vec4( 0.f, 0.f, -1.f, 0.f ); }else if( N[ 1 ] > .9f ){ T = glm::vec4( 0.f, 0.f, 1.f, 0.f ); }else if( N[ 2 ] < -.9f ){ T = glm::vec4( -1.f, 0.f, 0.f, 0.f ); }else{ T = glm::vec4( 1.f, 0.f, 0.f, 0.f ); } B = glm::vec4( glm::cross( glm::vec3( N ), glm::vec3( T ) ), 0.f ); result.tangent = glm::normalize( glm::vec3( transform.T() * T ) ); result.bitangent = glm::normalize( glm::vec3( transform.T() * B ) ); return result; } else{ return result; } }
Intersection Cube::GetIntersection(Ray r) { //---Q5--- //TODO Ray rInWorld( r ); r = r.GetTransformedCopy( transform.invT() ); static const float EPS = 1e-4; float t_near = -1e6; float t_far = 1e6; for( int i = 0; i < 3; ++i ){ if( glm::abs( r.direction[ i ] ) < EPS ){ if( r.origin[ i ] - EPS < -.5f || r.origin[ i ] + EPS > .5f ){ return Intersection(); }else{ continue; } } float t0, t1; t0 = ( -.5f - r.origin[ i ] ) / r.direction[ i ]; t1 = ( .5f - r.origin[ i ] ) / r.direction[ i ]; if( t0 + EPS > t1 ){ float tmp = t0; t0 = t1; t1 = tmp; } if( t0 + EPS > t_near ){ t_near = t0; } if( t1 - EPS < t_far ){ t_far = t1; } } if( t_near + EPS > t_far || t_far - EPS < 0.f ){ return Intersection(); } if( t_near - EPS < 0.f ){ t_near = t_far; } int hit_face = -1; float least_distance = 1e6; glm::vec3 hit = r.origin + t_near * r.direction; if( glm::abs( hit[ 0 ] + .5f ) < least_distance ){ hit_face = 0; least_distance = glm::abs( hit[ 0 ] + .5f ); } if( glm::abs( hit[ 0 ] - .5f ) < least_distance ){ hit_face = 1; least_distance = glm::abs( hit[ 0 ] - .5f ); } if( glm::abs( hit[ 1 ] + .5f ) < least_distance ){ hit_face = 2; least_distance = glm::abs( hit[ 1 ] + .5f ); } if( glm::abs( hit[ 1 ] - .5f ) < least_distance ){ hit_face = 3; least_distance = glm::abs( hit[ 1 ] - .5f ); } if( glm::abs( hit[ 2 ] + .5f ) < least_distance ){ hit_face = 4; least_distance = glm::abs( hit[ 2 ] + .5f ); } if( glm::abs( hit[ 2 ] - .5f ) < least_distance ){ hit_face = 5; least_distance = glm::abs( hit[ 2 ] - .5f ); } Intersection result; result.point = glm::vec3( transform.T() * glm::vec4( hit, 1.f ) ); switch( hit_face ){ case 0: result.normal = glm::vec3( -1, 0, 0 ); break; case 1: result.normal = glm::vec3( 1, 0, 0 ); break; case 2: result.normal = glm::vec3( 0, -1, 0 ); break; case 3: result.normal = glm::vec3( 0, 1, 0 ); break; case 4: result.normal = glm::vec3( 0, 0, -1 ); break; case 5: result.normal = glm::vec3( 0, 0, 1 ); break; } result.normal = glm::normalize( glm::vec3( transform.invTransT() * glm::vec4( result.normal, 0.f ) ) ); result.t = glm::distance( result.point, rInWorld.origin ); result.object_hit = this; result.color = material->GetImageColor( GetUVCoordinates( hit ), material->texture ) * material->base_color; return result; }