bool Transform::intersect(const Ray & r, Hit & h, float tmin) { // Need to Transform Ray before do intersection Matrix reverseMat = transformMat; reverseMat.Inverse(); // cout << "Original Origin:\t" << r.getOrigin() << endl; // cout << "Original Direction:\t" << r.getDirection() << endl; Vec4f aug_origin(r.getOrigin(), 1); Vec3f aug_dir = r.getDirection(); reverseMat.Transform(aug_origin); reverseMat.TransformDirection(aug_dir); // cout << "Now Origin:\t" << r.getOrigin() << endl; // cout << "Now Direction:\t" << r.getDirection() << endl; // aug_dir.Normalize(); Ray transRay(aug_dir, Vec3f(aug_origin[0], aug_origin[1], aug_origin[2])); if ( !( object -> intersect(transRay, h, tmin) ) ) return false; // After transforming Ray, we need to transform Normal Matrix transposeRevMat = reverseMat; transposeRevMat.Transpose(); Vec3f hn = h.getNormal(); transposeRevMat.Transform(hn); hn.Normalize(); h.set(h.getT(), NULL, hn, r); return true; }
void shade(const Scene * scene, const int level, const C_FLT weight, const Ray &ray, Intercept * intercepts, Color * color) { Material * entryMat = intercepts[0].material, * hitMat = intercepts[0].enter? intercepts[0].primitive->material: ray.medium; C_FLT specWeight = hitMat->specular.magnitude() * weight, transWeight = hitMat->transmission.magnitude() * weight; Vector3D specDir, transDir, normal; std::vector<P_FLT> mapping; Point3D interceptPoint = ray.rayPoint(intercepts[0].t); intercepts[0].primitive->getIntersect(interceptPoint, &normal, &mapping); if (dotProduct(ray.dir, normal) > 0.0f) { normal.negate(); } specularDirection(ray.dir, normal, &specDir); bool transmission = transmissionDirection(entryMat, hitMat, ray.dir, normal, &transDir); *color += scene->ambience * hitMat->ambience; for (std::vector<Light *>::const_iterator itr = scene->lights.begin(); itr != scene->lights.end(); itr++) { Vector3D pointToLight = (*itr)->orig - interceptPoint; P_FLT distanceToLight = pointToLight.normalize(); Ray rayToLight(interceptPoint, pointToLight, NULL); P_FLT lightDotNormal = dotProduct(pointToLight, normal); if (fGreaterZero(lightDotNormal) && fGreaterZero(shadow(scene, rayToLight, distanceToLight))) { // Light source diffuse reflection *color += (*itr)->color * hitMat->diffuse * lightDotNormal; // Light source specular reflection Vector3D h = pointToLight - ray.dir; h.normalize(); P_FLT specDot = dotProduct(normal, h); if (specDot > 0.0f) { *color += (*itr)->color * hitMat->specular * pow(specDot, hitMat->shine); } } else if (transmission && fLessZero(lightDotNormal) && fLessZero(shadow(scene, rayToLight, distanceToLight))) { // Light source specular transmission C_FLT refrRatio = hitMat->refraction / entryMat->refraction; if (!fEqual(refrRatio, 1.0f)) { Vector3D h_j = (-ray.dir - pointToLight * refrRatio) / (refrRatio - 1); h_j.normalize(); // TODO(kent): Define transmission highlight coefficient *color += (*itr)->color * hitMat->transmission * pow(dotProduct(-normal, h_j), hitMat->shine); } } } if (level < MAX_LEVEL) { // Other body specular reflection if (specWeight > MIN_WEIGHT) { Ray specRay(interceptPoint, specDir, entryMat); Color specColor; trace(scene, level + 1, specWeight, specRay, &specColor); *color += specColor * hitMat->specular; } // Other body specular transmission if (transWeight > MIN_WEIGHT) { if (transmission) { Ray transRay(interceptPoint, transDir, hitMat); Color transColor; trace(scene, level + 1, transWeight, transRay, &transColor); *color += transColor * hitMat->transmission; } else { // TODO(kent): Handle total internal reflection } } } if (intercepts[0].enter && intercepts[0].primitive->texture != NULL) { *color *= intercepts[0].primitive->getTexColor(mapping); } }