void PhotonMapping::TracePhoton(const Vec3f &position, const Vec3f &direction, const Vec3f &energy, int iter) { if(iter>args->num_bounces){ return; } Hit h = Hit(); Ray R = Ray(position, direction); bool intersect = raytracer->CastRay(R, h, false); if(!intersect){ return; } Material *m = h.getMaterial(); Vec3f normal = h.getNormal(); Vec3f point = R.pointAtParameter(h.getT()); Vec3f opDirec = direction; opDirec.Negate(); opDirec.Normalize(); Vec3f diffuse = m->getDiffuseColor(), reflec = m->getReflectiveColor(); double diffuseAnswer = diffuse.x()+diffuse.y()+diffuse.z(); double reflecAnswer = reflec.x()+reflec.y()+reflec.z(); double total = reflecAnswer+diffuseAnswer; diffuseAnswer /= total; reflecAnswer /= total; double seed = GLOBAL_mtrand.rand(); if(seed <= diffuseAnswer && seed >= 0){ Vec3f newEnergy = energy * diffuse; Vec3f newPosition = point; Vec3f newDirection = Vec3f(GLOBAL_mtrand.rand(),GLOBAL_mtrand.rand(),GLOBAL_mtrand.rand()); newDirection.Normalize(); Photon answer = Photon(point,opDirec,newEnergy,iter+1); kdtree->AddPhoton(answer); TracePhoton(newPosition, newDirection, newEnergy, iter+1); } else if(seed>diffuseAnswer && seed <= 1){ Vec3f newEnergy = energy * reflec; Vec3f newPosition = point; Vec3f newDirection = direction - 2 * direction.Dot3(normal) * normal; Photon answer = Photon(point,opDirec,newEnergy,iter+1); kdtree->AddPhoton(answer); TracePhoton(newPosition, newDirection, newEnergy, iter+1); } // ============================================== // ASSIGNMENT: IMPLEMENT RECURSIVE PHOTON TRACING // ============================================== // Trace the photon through the scene. At each diffuse or // reflective bounce, store the photon in the kd tree. // One optimization is to *not* store the first bounce, since that // direct light can be efficiently computed using classic ray // tracing. }
void Plate::applyForce(const Plate& other, const Overlap& overlap, double timestep) { Vec3f reverseVelocity = velocity; reverseVelocity.Negate(); // Create friction force based on reversed velocity and the ratio of overlap area to plate area. // This ensures the force only stops the velocity and doesn't reverse it. acceleration = reverseVelocity * (sqrt(fabs(5 * overlap.getArea())) / sqrt(getArea())); // Just in case, make sure the force doesn't reverse the velocity if (acceleration.Length() > velocity.Length()) acceleration = reverseVelocity; }
Vec3f PhongMaterial::Shade(const Ray &ray, const Hit &hit, const Vec3f &dirToLight, const Vec3f &lightColor) const { Vec3f eyeDir = ray.getDirection(); eyeDir.Negate(); Vec3f eyePlusLight = eyeDir + dirToLight; eyePlusLight.Normalize(); float hn = eyePlusLight.Dot3(hit.getNormal()); hn = pow(hn, mPhongComponent); Vec3f color = lightColor * mHighLightColor; color = hn * color; return color; }
bool transmittedDirection(const Vec3f &normal, const Vec3f &incoming, float index_i, float index_t, Vec3f &transmitted) { //折射光方向:T = e(N.I) - sqrt(1 - e ^ 2(1 - (N.I) ^ 2)))N - eI //从物体内部向外:T = (-N.I - sqrt(1 - 1 / e ^ 2(1 - N.I) ^ 2) * 1 / e)N - I / e //The dot product of the normal and ray direction is negative when we are outside //the object, and positive when we are inside. //不需要在这里判断光线是在内还是在外,求法是一样的 //不同的是一方面normal是反的,另一方面比值是互倒的 Vec3f I = incoming; I.Negate(); float e = index_i / index_t; float tmp = normal.Dot3(I); float sqrt_value = 1 - e*e*(1 - tmp*tmp); if (sqrt_value < 0) return false; transmitted = (e*tmp - sqrt(sqrt_value))*normal - e*I; return true; }