double FindNearestTIntersectionWithSphere(Ray* ray, int* index, int noCheckID = NONE) { assert(noCheckID==NONE || (noCheckID>=0 && noCheckID<num_spheres)); double nearestTIntersect = INFINITY; *index = NONE; /* (x_d^2 + y_d^2 + z_d^2)t^2 + 2((x_o-x_c)x_d +(y_o-y_c)y_d + (z_o-z_c)z_d)t * + (x_o-x_c)^2 + (y_o-y_c)^2 + (z_o-z_c)^2 - r^2 = 0 */ unsigned int i; for (i = 0; i < num_spheres; i++) { if (i==noCheckID){ continue; } Vector4* sphereCenter = new Vector4(spheres[i].position); Vector4* sphereRay = new Vector4(ray->source); sphereRay->Subtraction(sphereCenter); double A = pow(ray->dir->Mod(), 2); double B = 2 * (ray->dir->DotProduct(sphereRay)); double C = pow(sphereRay->Mod(), 2) - pow(spheres[i].radius, 2); double soln1=0.0,soln2=0.0; SolveQuadraticEquation(A,B,C,&soln1,&soln2); if (soln1 >= 0 && soln2 >= 0){ // //For Debugging Purposes // printf("(%f,%f)\n",soln1,soln2); double candidateT = NONE; if(soln1<soln2){ candidateT = soln1; } else{ candidateT = soln2; } //assert(candidateT>=soln1 && candidateT>=soln2); if(nearestTIntersect > candidateT /*&& candidateT>(cameraZ-screenZ)*/) { nearestTIntersect = candidateT; *index = i; } } delete(sphereCenter); delete(sphereRay); } return nearestTIntersect; }
// 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); } }