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 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; }
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 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 Mesh::GetIntersection(Ray r){ Ray r_loc = r.GetTransformedCopy(transform.invT()); Intersection closest; for(int i = 0; i < faces.size(); i++){ Intersection isx = faces[i]->GetIntersection(r_loc); if(isx.object_hit != NULL && isx.t > 0 && (isx.t < closest.t || closest.t < 0)){ closest = isx; } } if(closest.object_hit != NULL) { Triangle* tri = (Triangle*)closest.object_hit; glm::vec4 P = glm::vec4(closest.t * r_loc.direction + r_loc.origin, 1); closest.point = glm::vec3(transform.T() * P); closest.normal = glm::normalize(glm::vec3(transform.invTransT() * tri->GetNormal(P))); closest.object_hit = this; closest.t = glm::distance(closest.point, r.origin);//The t used for the closest triangle test was in object space //TODO: Store the tangent and bitangent } return closest; }
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; }