// For Shading Purposes void RT_shade(Ray* ray, int depth) { if (depth <= MAX_DEPTH){ // Color Coefficients Vector4* diffuseCoeff = new Vector4(); Vector4* specularCoeff = new Vector4(); double shininess; // Diffuse and Specular Terms double diffuseTerm[3] = {0.0, 0.0, 0.0}; double specularTerm[3] = {0.0, 0.0, 0.0}; if (ray->intersectedObject == SPHERE) { diffuseCoeff->ReInitialize(spheres[ray->intersectID].color_diffuse); specularCoeff->ReInitialize(spheres[ray->intersectID].color_specular); shininess = spheres[ray->intersectID].shininess; } else if (ray->intersectedObject == TRIANGLE) { // Interpolate diffuse and specular coefficients double alpha, beta; ObtainIntermediateTriangleIntersection(ray->intersectID, ray->intersectPoint, &alpha, &beta); diffuseCoeff->ReInitialize(); InterpolateTriangleProperty(triangles[ray->intersectID].v[0].color_diffuse, triangles[ray->intersectID].v[1].color_diffuse, triangles[ray->intersectID].v[2].color_diffuse, alpha, beta, diffuseCoeff, false); specularCoeff->ReInitialize(); InterpolateTriangleProperty(triangles[ray->intersectID].v[0].color_specular, triangles[ray->intersectID].v[1].color_specular, triangles[ray->intersectID].v[2].color_specular, alpha, beta, specularCoeff, false); // Interpolate shininess if (alpha > 0) { double intermediateShininess = beta * triangles[ray->intersectID].v[2].shininess + (1 - beta) * triangles[ray->intersectID].v[1].shininess; shininess = ((alpha - 1) * triangles[ray->intersectID].v[0].shininess + intermediateShininess) / alpha; } else { shininess = triangles[ray->intersectID].v[0].shininess; } } // Boundary Checking assert(diffuseCoeff->HasNonNegativeEntries()); assert(!diffuseCoeff->HasGreaterThanOneEntries()); assert(specularCoeff->HasNonNegativeEntries()); assert(!specularCoeff->HasGreaterThanOneEntries()); assert(shininess >= 0); // Normal Vector: N Vector4* N = new Vector4(ray->normal); N->ConvertToUnitVector(); // Viewer Direction: V = ray->intersectedPoint - ray->source = -ray->dir Vector4* V = new Vector4(ray->dir); V->Scale(-1); V->ConvertToUnitVector(); int dontCheckObject = NONE; int dontCheckObjectID = NONE; if (ray->intersectedObject == TRIANGLE) { dontCheckObject = ray->intersectedObject; dontCheckObjectID = ray->intersectID; } unsigned int i; for (i = 0; i < num_lights; i++) { // Shoot a ray in the direction of the light Vector4* lightPos = new Vector4(lights[i].position); Ray* checkShadow = new Ray(ray->intersectPoint, lightPos); bool shadow = false; double nearestTIntersect = FindNearestTIntersection(checkShadow,dontCheckObject,dontCheckObjectID); double point2LightDistance = FindDistanceOfIntersectedPointWithLight(ray,i); if (nearestTIntersect != INFINITY && nearestTIntersect< point2LightDistance) { shadow = true; } // Point to Light Vector: L = light_pos - intersectedPoint Vector4* L = new Vector4(lights[i].position); L->Subtraction(ray->intersectPoint); L->ConvertToUnitVector(); // Reflected Ray: R = 2(N.L)N - L Vector4* R = new Vector4(ray->normal); R->Scale(2 * N->DotProduct(L)); R->Subtraction(L); R->ConvertToUnitVector(); // Dot Product of N and L: NL double NL = N->DotProduct(L); if (NL < 0) { NL = 0; } // Dot Product of R and V: RV double RV = R->DotProduct(V); if (RV < 0) { RV = 0; } assert(NL <= 1 && RV <= 1); double attenuationTerm = depth==1?1:1; if (!shadow) { unsigned int j; for (j = 0; j < 3; j++) { diffuseTerm[j] += attenuationTerm * lights[i].color[j] * diffuseCoeff->vector[j] * NL; specularTerm[j] += attenuationTerm * lights[i].color[j] * specularCoeff->vector[j] * pow(RV, shininess); } } delete(L); delete(R); delete(lightPos); delete(checkShadow); } // Adding diffused light Vector4* diffusedColor = new Vector4(diffuseTerm); // //For Debugging Purposes // if(ray->intersectedObject == SPHERE){ // ray->color->Display(); // diffusedColor->Display(); // cout<<"................................................."<<endl; // } ray->color->Addition(diffusedColor); delete(diffusedColor); // Adding specular light Vector4* specularColor = new Vector4(specularTerm); ray->color->Addition(specularColor); delete(specularColor); //R = 2*(NI)N - I ; N = N; I = V = ray->source - ray->IntersectPoint Vector4* R_ = new Vector4(ray->normal); Vector4* I = new Vector4(ray->dir); I->Scale(-1); R_->Scale(2*N->DotProduct(I)); R_->Subtraction(I); Vector4* end = new Vector4(ray->intersectPoint); end->Addition(R_); Ray* reflectedRay = new Ray(ray->intersectPoint, end); delete(R_); delete(I); delete(end); assert(dontCheckObject!=SPHERE); RT_trace(reflectedRay, depth+1, dontCheckObject, dontCheckObjectID); //For Debugging // if(ray->intersectedObject==TRIANGLE/* && ray->intersectPoint->vector[1]<-2*screenX/4 // && ray->intersectPoint->vector[1]>-3*screenX/4*/){ // cout<<ray->intersectID; // cout<<"---->"; // ray->normal->Display(); // cout<<"------>"; // I->Display(); // cout<<I->DotProduct(ray->normal)<<"\t"; // cout<<reflectedRay->dir->DotProduct(ray->normal); // reflectedRay->dir->Display(); // cout<<": "<<reflectedRay->tIntersect<<"\t"; // reflectedRay->color->Display(); // cout<<endl; // } if(reflectedRay->tIntersect!=INFINITY){ reflectedRay->color->Scale(specularCoeff->vector[0], specularCoeff->vector[1], specularCoeff->vector[2]); ray->color->Addition(reflectedRay->color); } delete(reflectedRay); delete(N); delete(V); delete(specularCoeff); delete(diffuseCoeff); } }
double FindNearestTIntersectionWithTriangle(Ray* ray, int* index, int noCheckID = NONE){ assert(noCheckID==NONE || (noCheckID>=0 && noCheckID<num_triangles)); double nearestTIntersect = INFINITY; *index = NONE; unsigned int i; for (i = 0; i < num_triangles; i++) { if (i==noCheckID){ continue; } // Vertices V0, V1 and V2 Vector4* V0 = new Vector4(triangles[i].v[0].position); Vector4* V1 = new Vector4(triangles[i].v[1].position); Vector4* V2 = new Vector4(triangles[i].v[2].position); // Edges: VOV1, V0V2 Vector4* V0V1 = new Vector4(V1); V0V1->Subtraction(V0); Vector4* V0V2 = new Vector4(V2); V0V2->Subtraction(V0); // Normal: N = V0V1 X V0V2 Vector4* N = new Vector4(V0V1); N->CrossProductPost(V0V2); N->ConvertToUnitVector(); // ray and normal should be opposite if (N->DotProduct(ray->dir)>0){ N->Scale(-1); } // N = [A B C] // AX0 + BY0 + CZ0 + D = 0 double D = -1*N->DotProduct(V0); if (N->DotProduct(ray->dir) != (double) 0) { // t = -(N.Ro + D)/ (N.Rd) double candidateT = -1 * (N->DotProduct(ray->source) + D) / N->DotProduct(ray->dir); if (candidateT > 0){ // P = Ro + tRd Vector4* point = new Vector4(ray->dir); point->Scale(candidateT); point->Addition(ray->source); // alpha*V0V1 + beta*V0V2 = V0P Vector4* V0P = new Vector4(point); V0P->Subtraction(V0); double alpha = 0.0; double beta = 0.0; //(x01)alpha + (x02)beta = x0p; //(y01)alpha + (y02)beta = y0p; //(z01)alpha + (z02)beta = z0p; double A1 = V0V1->vector[0]; double B1 = V0V2->vector[0]; double C1 = V0P->vector[0]; double A2 = V0V1->vector[1]; double B2 = V0V2->vector[1]; double C2 = V0P->vector[1]; double A3 = V0V1->vector[2]; double B3 = V0V2->vector[2]; double C3 = V0P->vector[2]; SolveLinearEquation(A1, B1, C1, A2, B2, C2, &alpha, &beta); if (alpha == NONE) { SolveLinearEquation(A2, B2, C2, A3, B3, C3, &alpha, &beta); } if (alpha == NONE) { SolveLinearEquation(A1, B1, C1, A3, B3, C3, &alpha, &beta); } // // For Debugging Purposes // printf("\nTriangle: %d ==> CandidateT: %f ==> (%f,%f)",i,candidateT,alpha,beta); if (alpha > 0 && beta > 0 && (alpha + beta) < 1) { if (nearestTIntersect > candidateT) { nearestTIntersect = candidateT; *index = i; } } delete(V0P); delete(point); } } delete(N); delete(V0V2); delete(V0V1); delete(V2); delete(V1); delete(V0); } return nearestTIntersect; }