void TranslationTool::Impulse(const Ray& ray) { Vector3f position = transformable->GetPosition(); switch(type) { case XAxis: { F32 distance; if (ray.Intersects(Plane(Vector3f::Up, -position.y), &distance)) { Vector3f intersection = ray.GetOrigin() + ray.GetDirection() * distance; F32 deltaX = intersection.x - prevPoint.x; transformable->SetPosition(Vector3f(position.x + deltaX, position.y, position.z)); prevPoint = intersection; } break; } case YAxis: { F32 distance; if (ray.Intersects(Plane(Vector3f::Backward, -position.z), &distance)) { Vector3f intersection = ray.GetOrigin() + ray.GetDirection() * distance; F32 deltaY = intersection.y - prevPoint.y; transformable->SetPosition(Vector3f(position.x, position.y + deltaY, position.z)); prevPoint = intersection; } break; } case ZAxis: { F32 distance; if (ray.Intersects(Plane(Vector3f::Right, -position.x), &distance)) { Vector3f intersection = ray.GetOrigin() + ray.GetDirection() * distance; F32 deltaZ = intersection.z - prevPoint.z; transformable->SetPosition(Vector3f(position.x, position.y, position.z + deltaZ)); prevPoint = intersection; } break; } } }
void TranslationTool::ImpulseBegin(const Ray& ray) { UpdateScale(); Vector3f position = transformable->GetPosition(); Matrix transform = Matrix::CreateScale(Vector3f(scale)) * Matrix::CreateTranslation(position); BoundingBox xBox = BoundingBox::Transform(xAxisBBox, transform); BoundingBox yBox = BoundingBox::Transform(yAxisBBox, transform); BoundingBox zBox = BoundingBox::Transform(zAxisBBox, transform); F32 distance; if (ray.Intersects(xBox, &distance)) { if (ray.Intersects(Plane(Vector3f::Up, -position.y), &distance)) { type = XAxis; prevPoint = ray.GetOrigin() + ray.GetDirection() * distance; } } else if (ray.Intersects(yBox, &distance)) { if (ray.Intersects(Plane(Vector3f::Backward, -position.z), &distance)) { type = YAxis; prevPoint = ray.GetOrigin() + ray.GetDirection() * distance; } } else if (ray.Intersects(zBox, &distance)) { if (ray.Intersects(Plane(Vector3f::Right, -position.x), &distance)) { type = ZAxis; prevPoint = ray.GetOrigin() + ray.GetDirection() * distance; } } }
bool BasicPrimitiveTests::IntersectingRayAgainstAABB(const Ray & ray, const AABB & aabb, float & rtn_t) { /* Main Idea: -> Uses slab representation for box. -> Finds intersection of ray/segment with each slab. Then compares intersection times for overlap in all slabs. -> Keep track of: -> A: The farthest of all entries into a slab -> B: The closest of all exits out of a slab. -> If A > B at anytime, exit with no intersection. Intersecting slabs: -> Intersect slabs by inserting ray equation into plane equations for slab. -> Solve for t -> Must handle case when ray parallel to slab separately. -> To avoid division by zero. Can test for intersection without calculating intersection point: -> Choose coordinate system where box is axis aligned and centered at origin: AABB: -> Translate segment and AABB to origin. OBB: -> Transform Segment to OBB space, then translate both segment and OBB to origin. -> Do separating axis test with 6 axes: -> Three principle axes. -> Three cross products of box face normals and segment direction vector. */ rtn_t = 0.0f; float tmax = FLT_MAX; Eigen::Vector3f aabb_min = aabb.GetCenter() - aabb.GetExtents(); Eigen::Vector3f aabb_max = aabb.GetCenter() + aabb.GetExtents(); for (int i = 0; i < 3; ++i) { if (abs(ray.GetDirection()[i]) < EPSILON) { //Ray is parallel to slab. Not hit if origin not within slab. if (ray.GetOrigin()[i] < aabb_min[i] || ray.GetOrigin()[i] > aabb_max[i]) { return false; } } else { float one_over_direction = 1.0f / ray.GetDirection()[i]; float t1 = (aabb_min[i] - ray.GetOrigin()[i]) * one_over_direction; float t2 = (aabb_max[i] - ray.GetOrigin()[i]) * one_over_direction; if (t1 > t2) Swap(t1, t2); if (t1 > rtn_t) rtn_t = t1; if (t2 > tmax) tmax = t2; if (rtn_t > tmax) return false; } } return true; }
bool Find_Intersection(Intersection *isect, ObjectPtr object, const Ray& ray, const RayObjectCondition& postcondition, TraceThreadData *threadData) { if(object != NULL) { DBL closest = HUGE_VAL; BBoxVector3d origin; BBoxVector3d invdir; BBoxDirection variant; Vector3d tmp(1.0 / ray.GetDirection()[X], 1.0 / ray.GetDirection()[Y], 1.0 /ray.GetDirection()[Z]); origin = BBoxVector3d(ray.Origin); invdir = BBoxVector3d(tmp); variant = (BBoxDirection)((int(invdir[X] < 0.0) << 2) | (int(invdir[Y] < 0.0) << 1) | int(invdir[Z] < 0.0)); if(object->Intersect_BBox(variant, origin, invdir, closest) == false) return false; if(object->Bound.empty() == false) { if(Ray_In_Bound(ray, object->Bound, threadData) == false) return false; } IStack depthstack(threadData->stackPool); POV_REFPOOL_ASSERT(depthstack->empty()); // verify that the IStack pulled from the pool is in a cleaned-up condition if(object->All_Intersections(ray, depthstack, threadData)) { bool found = false; double tmpDepth = 0; while(depthstack->size() > 0) { tmpDepth = depthstack->top().Depth; // TODO FIXME - This was SMALL_TOLERANCE, but that's too rough for some scenes [cjc] need to check what it was in the old code [trf] if(tmpDepth < closest && (ray.IsSubsurfaceRay() || tmpDepth >= MIN_ISECT_DEPTH) && postcondition(ray, object, tmpDepth)) { *isect = depthstack->top(); closest = tmpDepth; found = true; } depthstack->pop(); } return (found == true); } POV_REFPOOL_ASSERT(depthstack->empty()); // verify that the IStack is in a cleaned-up condition (again) } return false; }
Ray Ray::Transform(const Ray& ray, const Matrix& transform) { Vector3f origin = ray.GetOrigin(); Vector3f target = origin + ray.GetDirection() * ray.GetDistance(); Vector3f newOrigin = Vector3f::Transform(origin, transform); Vector3f newTarget = Vector3f::Transform(target, transform); return Ray(newOrigin, newTarget); }
Air::U1 MeshEntity::RayCast( const Ray& ray ,float* pOutDistance) { #if 1 if(!GetWorldBoundingBox().RayCast(ray.GetOrigin(),ray.GetDirection())){//.Intersect(GetWorldBoundingBox())){ return false; } #endif Matrix matWorld = *GetWorldMatrix(); Matrix matWorldInv = matWorld; matWorldInv.Inverse(); Float3 vStart = ray.m_vStart; Float3 vLookAt = vStart + ray.m_vDirection; vStart = matWorldInv*vStart; vLookAt = matWorldInv*vLookAt; Float3 vDir = (vLookAt - vStart); vDir.Normalize(); Ray objSpaceRay(vStart,vDir); float fDistance = 999999.0f; U1 bHit = m_pMesh->RayCast(objSpaceRay,&fDistance); if(bHit && pOutDistance!=NULL){ Float3 vObjSpaceHitPostion = vStart + vDir*fDistance; Float3 vWorldSpaceHiPosition = matWorld*vObjSpaceHitPostion; *pOutDistance = (vWorldSpaceHiPosition - ray.m_vStart).Length(); } return bHit; }
bool PlaneIntersector<real>::Intersect( const Plane<real>* plane, const Ray<real>& ray, Intersection<real>& oIntersection ) { const Vector3<real>& origin = ray.GetOrigin(); const Vector3<real>& direction = ray.GetDirection(); // Do not perform intersection if the direction of the ray is degenerated relative to the plane if ( fabs( direction.Y() ) > EPS ) { // Compute the intersection point and see if it's inside the plane bounds real t = -origin.Y() / direction.Y(); Vector3<real> intersectionPoint = origin + t * direction; bool isInsideXBounds = ( fabs( intersectionPoint.X() ) < plane->GetSizeX() * 0.5 ) ? true : false; bool isInsideZBounds = ( fabs( intersectionPoint.Z() ) < plane->GetSizeZ() * 0.5 ) ? true : false; // If the ray intersect and the intersection is in front if ( ( t > 0 ) && isInsideXBounds && isInsideZBounds ) { oIntersection.SetPosition( intersectionPoint ); oIntersection.SetNormal( Vector3<real>( 0, -sign<real>( direction.Y() ), 0 ) ); oIntersection.IsInside( false ); // Compute texture coodinates as (z=-0.5 => u=0 and x=-0.5 => v=0) real u = ( intersectionPoint.Z() + plane->GetSizeZ() * 0.5 ) / plane->GetSizeZ(); real v = ( intersectionPoint.X() + plane->GetSizeX() * 0.5 ) / plane->GetSizeX(); oIntersection.SetTextureCoordinates( Vector3<real>( u, v, 0 ) ); return true; } } return false; }
int Sphere::Intersect( Ray& a_Ray, float& a_Dist ) { vector3 v = a_Ray.GetOrigin() - m_Centre; float b = -DOT( v, a_Ray.GetDirection() ); float det = (b * b) - DOT( v, v ) + m_SqRadius; int retval = MISS; if (det > 0) { det = sqrtf( det ); float i1 = b - det; float i2 = b + det; if (i2 > 0) { if (i1 < 0) { if (i2 < a_Dist) { a_Dist = i2; retval = INPRIM; } } else { if (i1 < a_Dist) { a_Dist = i1; retval = HIT; } } } } return retval; }
Ray<real> NodeIntersector<real>::TransformRayToLocalCoordinates( const CoreLib::Node<real>* node, const Ray<real>& ray ) { const Matrix4<real>& globalToLocal = node->GetGlobalToLocal(); // The origin is affected by the affine transformation while the direction is not affected by translation ( operator ^ ) return Ray<real>( globalToLocal * ray.GetOrigin(), globalToLocal ^ ray.GetDirection() ); }
float Sphere::CheckCollision(Ray ray) { Vector q = ray.GetOrigin(); Vector v = ray.GetDirection(); float A = pow(v.x, 2) + pow(v.y, 2) + pow(v.z, 2); float Bx = v.x * (q.x - origin.x); float By = v.y * (q.y - origin.y); float Bz = v.z * (q.z - origin.z); float B = 2 * (Bx + By + Bz); float C = pow(q.x - origin.x, 2) + pow(q.y - origin.y, 2) + pow(q.z - origin.z, 2) - pow(radius, 2); //Determines if we have a 'hit' float discriminant = pow(B, 2) - (4 * A * C); if (discriminant >= 0.f) { //Calculate our t values float root = sqrt(discriminant); float t1 = (-B + root) / (2 * A); float t2 = (-B - root) / (2 * A); float d = t1; if (t1 > t2 && t2 > 0) //Make sure we don't take a negative d = t2; //Choose the smaller (closer) of the 2 values. if (d >= 0) //We want a positive distance from the starting vector { return d; } } return -1.0f; }
bool BasicPrimitiveTests::IntersectingRayAgainstAABB(const Ray & ray, const AABB & aabb) { const Eigen::Vector3f & ray_d_aabb = ray.GetDirection(); Eigen::Vector3f ray_o_aabb = ray.GetOrigin() - aabb.GetCenter(); return 0; }
bool SphereIntersector<real>::Intersect( const Sphere<real>* sphere, const Ray<real>& ray, Intersection<real>& oIntersection ) { // Compute the equation corresponding to x²+y²+z²=0 with p+t*d to obtain a quadratic equation real a = ray.GetDirection().SquaredLength(); real b = 2.0 * ray.GetDirection() * ray.GetOrigin(); real c = ray.GetOrigin().SquaredLength() - sphere->GetRadius() * sphere->GetRadius(); real discriminant = b*b - 4*a*c; // Discriminant >= 0 => the must be at least one intersection if ( discriminant >= 0 ) { // Compute the two potential intersections and only keep the nearest real sqrtDisc = sqrt( discriminant ); real t = 0; real t1 = ( -b - sqrtDisc ) / ( 2.0 * a ); real t2 = ( -b + sqrtDisc ) / ( 2.0 * a ); if ( t1 >= 0 ) { t = t1; oIntersection.IsInside( false ); } else if ( t2 >= 0 ) { t = t2; oIntersection.IsInside( true ); } else return false; oIntersection.SetPosition( ray.GetOrigin() + t * ray.GetDirection() ); oIntersection.SetNormal( oIntersection.GetPosition().Normalized() ); oIntersection.SetTextureCoordinates( oIntersection.GetPosition().Normalized() ); // The normal must be flipped to coincide with the hit direction if ( oIntersection.IsInside() ) oIntersection.SetNormal( -oIntersection.GetNormal() ); return true; } return false; }
FPType Plane::GetIntersectionDisk(Ray ray, Vector3d normal_, Vector3d position) { FPType denom = normal_.Dot(ray.GetDirection()); FPType t = -1; if(std::abs(denom) > ray.tMin && t <= ray.tMax) { t = (position - ray.GetOrigin()).Dot(normal_) / denom; } return t; }
bool BasicPrimitiveTests::IntersectingRayAgainstOBB(const Ray & ray, const OBB & obb) { Eigen::Matrix3f obb_rotation; obb.GetRotationMatrix(obb_rotation); Eigen::Vector3f ray_d_obb = obb_rotation * ray.GetDirection(); Eigen::Vector3f ray_o_obb = obb_rotation * (ray.GetOrigin() - obb.GetCenter()); return 0; }
FPType Plane::GetIntersection(const Ray &ray) { FPType denom = normal.Dot(ray.GetDirection()); if(std::abs(denom) > BIAS) { FPType t = (center - ray.GetOrigin()).Dot(normal) / denom; if(t > BIAS) return t; } return false; }
bool BasicPrimitiveTests::IntersectingRayAgainstSphere(const Ray & ray, const BoundingSphere & sphere, float & rtn_t) { /* Main idea: - Ray is substituted into sphere equation. Then solve quadratic formula for intersection. - Test if intersection is within segment/ray endpoints -> Use dot(X-C, X-C) = exp(r, 2) -> As sphere equation. Solving for "t": -> Quadratic equation in "t" encountered. -> where b = dot(m, d) -> where c = dot(m, m) - r*r -> where m = P-C -> t = -b + sqrt(exp(b, 2) - c) -> t = -b - sqrt(exp(b, 2) - c) Notes: -> Number of real roots => number of intersections: -> Categorized by discriminant d = exp(b, 2) - c -> May have false intersection with t < 0 when ray starts from inside sphere. */ Eigen::Vector3f m = ray.GetOrigin() - sphere.GetCenter(); float b = (m).dot(ray.GetDirection()); float c = m.dot(m); if (c > 0.0f && b > 0.0f) { //Case: Ray origin outside of sphere and points away. => No Intersections. return false; } float discriminant = b * b - c; if (discriminant < 0.0f) { //Case: Misses sphere return false; } else { //Case: Hits sphere. Calculate smallest t. rtn_t = -b - sqrt(discriminant); if (rtn_t < 0.0f) { rtn_t = 0.0f; } return true; } }
bool Renderer::RaySphereIntersection(Ray ray, Sphere sphere) { Vector d = ray.GetDirection(); Vector e = ray.GetOrigin(); Vector c = sphere.GetCenter(); int R = sphere.GetRadius(); float discriminant = (d ^ (e - c)) * (d ^ (e - c)) - ((d ^ d) * (((e - c) ^ (e - c)) - R * R)); if(discriminant >= 0.0) return true; return false; }
int PlanePrim::Intersect( Ray& a_Ray, float& a_Dist ) { float d = DOT( m_Plane.N, a_Ray.GetDirection() ); if (d < 0) { float dist = -(DOT( m_Plane.N, a_Ray.GetOrigin() ) + m_Plane.D) / d; if (dist < a_Dist) { a_Dist = dist; return HIT; } } return MISS; }
// ray tracing Colour RayTracer::TraceRay(Ray& ray, int traceDepth) { if (traceDepth > MAXTRACEDEPTH) return Colour(); Colour litColour, reflectedColour; float distanceToIntersect = MAXDISTANCE; Vector3f intersectionPoint; Primitive* nearestPrimitive = 0; nearestPrimitive = mScene->GetFirstPrimitive(ray, distanceToIntersect); if (!nearestPrimitive) return Colour(); else { // Ambient,Specular lighting intersectionPoint = ray.GetOrigin() + ray.GetDirection() * distanceToIntersect; litColour = mScene->CalculatePrimitiveLightingAtPoint((*nearestPrimitive), intersectionPoint, ray.GetDirection()); // reflection float reflectionFactor = nearestPrimitive->GetMaterial()->Reflection; if (reflectionFactor > 0.0f) { Vector3f normal = nearestPrimitive->GetNormal(intersectionPoint); Vector3f reflected = ray.GetDirection() - normal * (2.0f * (ray.GetDirection()*normal)); Ray reflectedRay = Ray(intersectionPoint , reflected); reflectedColour = TraceRay(reflectedRay, traceDepth + 1) * reflectionFactor; } return litColour + reflectedColour; } }
int Box::Intersect( Ray& a_Ray, float& a_Dist ) { m_RayID = a_Ray.GetID(); float dist[6]; vector3 ip[6], d = a_Ray.GetDirection(), o = a_Ray.GetOrigin(); bool retval = MISS; for ( int i = 0; i < 6; i++ ) dist[i] = -1; vector3 v1 = m_Box.GetPos(), v2 = m_Box.GetPos() + GetSize(); if (d.x) { float rc = 1.0f / d.x; dist[0] = (v1.x - o.x) * rc; dist[3] = (v2.x - o.x) * rc; } if (d.y) { float rc = 1.0f / d.y; dist[1] = (v1.y - o.y) * rc; dist[4] = (v2.y - o.y) * rc; } if (d.z) { float rc = 1.0f / d.z; dist[2] = (v1.z - o.z) * rc; dist[5] = (v2.z - o.z) * rc; } for ( int i = 0; i < 6; i++ ) if (dist[i] > 0) { //ip[i] = o + dist[i] * d; // Uses vector addition and multiplication ip[i].x = o.x + dist[i] * d.x; ip[i].y = o.y + dist[i] * d.y; ip[i].z = o.z + dist[i] * d.z; if ((ip[i].x > (v1.x - EPSILON)) && (ip[i].x < (v2.x + EPSILON)) && (ip[i].y > (v1.y - EPSILON)) && (ip[i].y < (v2.y + EPSILON)) && (ip[i].z > (v1.z - EPSILON)) && (ip[i].z < (v2.z + EPSILON))) { if (dist[i] < a_Dist) { a_Dist = dist[i]; retval = HIT; } } } return retval; }
int Camera::getLine(int mx, int my, const std::vector<LineSegment>& lines, LineSegment& line) { Ray ray = getRay(mx, my); Vector3 v1 = ray.GetOrigin(); Vector3 v2 = v1 + ray.GetDirection() * 100.0f; LineSegment l; l.points[0] = v1; l.points[1] = v2; float minDist = 1000.0f; int linePos = -1; for (int i = 0; i < lines.size(); ++i) { float dist = LineSegment::distSegmentSegment(lines[i], l); if (dist <= 0.1f) { minDist = dist; line = lines[i]; linePos = i; } } return linePos; }
bool BasicPrimitiveTests::IntersectingRayAgainstOBB(const Ray & ray, const OBB & obb, float & rtn_t) { Eigen::Matrix3f obb_rotation; obb.GetRotationMatrix(obb_rotation); Eigen::Vector3f ray_d_obb = obb_rotation * ray.GetDirection(); Eigen::Vector3f ray_o_obb = obb_rotation * (ray.GetOrigin() - obb.GetCenter()); rtn_t = 0.0f; float tmax = FLT_MAX; Eigen::Vector3f aabb_min = -obb.GetExtents(); Eigen::Vector3f aabb_max = obb.GetExtents(); for (int i = 0; i < 3; ++i) { if (abs(ray_d_obb[i]) < EPSILON) { //Ray is parallel to slab. Not hit if origin not within slab. if (ray_o_obb[i] < aabb_min[i] || ray_o_obb[i] > aabb_max[i]) { return false; } } else { float one_over_direction = 1.0f / ray_d_obb[i]; float t1 = (aabb_min[i] - ray_o_obb[i]) * one_over_direction; float t2 = (aabb_max[i] - ray_o_obb[i]) * one_over_direction; if (t1 > t2) Swap(t1, t2); if (t1 > rtn_t) rtn_t = t1; if (t2 > tmax) tmax = t2; if (rtn_t > tmax) return false; } } return true; }
bool AABB::Intersect(Ray &ray) { glm::vec3 invDir = 1.0f / ray.GetDirection(); float tmin = (pMin.x - ray.GetOrigin().x) * invDir.x; float tmax = (pMax.x - ray.GetOrigin().x) * invDir.x; if (tmin > tmax) swap(tmin, tmax); float tymin = (pMin.y - ray.GetOrigin().y) * invDir.y; float tymax = (pMax.y - ray.GetOrigin().y) * invDir.y; if (tymin > tymax) swap(tymin, tymax); if ((tmin > tymax) || (tymin > tmax)) return false; if (tymin > tmin) tmin = tymin; if (tymax < tmax) tmax = tymax; float tzmin = (pMin.z - ray.GetOrigin().z) * invDir.z; float tzmax = (pMax.z - ray.GetOrigin().z) * invDir.z; if (tzmin > tzmax) swap(tzmin, tzmax); if ((tmin > tzmax) || (tzmin > tmax)) return false; if (tzmin > tmin) tmin = tzmin; if (tzmax < tmax) tmax = tzmax; return true; }
bool CylinderIntersector<real>::Intersect( const Cylinder<real>* cylinder, const Ray<real>& ray, Intersection<real>& oIntersection ) { real nearestDistance = std::numeric_limits<real>::max(); real distance = 0; bool hasIntersection = false; //////////////////////////////////////////// //////////////////IFT 3355////////////////// //////////////////////////////////////////// //Ici, vous calculerez l'intersection entre //le rayon "ray" et le cylindre "cylinder" //Pensez à initialiser les quatre attributs //de oIntersection (retourné par référence) //correctement si une intersection est trouvée. //////////////////////////////////////////// //////////////////IFT 3355////////////////// //////////////////////////////////////////// real halfHeight = cylinder->GetHeight() / 2; real radius = cylinder->GetRadius(); // Intersection with extremeties. Vector3<real> extremeties[2] = { Vector3<real>(0, halfHeight, 0), Vector3<real>(0, -halfHeight, 0), }; for (int k = 0; k < 2; ++k) { Vector3<real> plane = extremeties[k]; real denom = ray.GetDirection() * plane; bool intersectsPlane = fabs(denom) > EPS; // Ray intersects with the extremety. if (intersectsPlane) { // Intersection position on the infinite plane. real t = ((plane - ray.GetOrigin()) * plane) / denom; Vector3<real> intersectionPos = ray.GetOrigin() + t * ray.GetDirection(); // Ray intersects in the window. if ((plane - intersectionPos).Length() <= radius && ray.GetDirection() * plane < 0 && t > EPS && t <= nearestDistance) { oIntersection.SetNormal(plane); oIntersection.SetPosition(intersectionPos); oIntersection.SetTextureCoordinates(intersectionPos); oIntersection.IsInside(false); nearestDistance = t; hasIntersection = true; } } } // Intersection with main body Vector3<real> o = Vector3<real>(ray.GetOrigin().X(), 0, ray.GetOrigin().Z()); Vector3<real> d = Vector3<real>(ray.GetDirection().X(), 0, ray.GetDirection().Z()); real a = d*d; real b = 2 * d * o; real c = o * o - (radius*radius); real discr = b*b - 4*a*c; if (discr < -EPS) { return hasIntersection; // No intersection. } else { real t1 = (-b - sqrt(discr)) / (2*a); real t2 = (-b + sqrt(discr)) / (2*a); real t = std::min<real>(t1, t2); Vector3<real> intersectionPos = ray.GetOrigin() + t * ray.GetDirection(); if (t >= EPS && t < nearestDistance && fabs(intersectionPos.Y()) < halfHeight+EPS) { oIntersection.SetNormal(intersectionPos - Vector3<real>(0, intersectionPos.Y(), 0)); oIntersection.SetPosition(intersectionPos); oIntersection.SetTextureCoordinates(intersectionPos); oIntersection.IsInside(false); nearestDistance = t; hasIntersection = true; } } return hasIntersection; }
bool Ray::operator== (const Ray& ray) const { return m_direction == ray.GetDirection() && m_origin == ray.GetOrigin(); }
Color trace(const Scene& scene, Ray ray, int depth) { const Color background(0,0,0); const int maxDepth = 3; if (depth >= maxDepth) return background; Color color(0,0,0); double distance = 0; const Primitive* prim = NULL; int intersectionType = 0; findNearsetIntersection(scene, ray, &prim, &distance, &intersectionType); if (prim != NULL) { if (prim->IsIlluminative()) { return prim->GetMaterial().GetColor(); } const Vector3 intersectionPoint = ray.GetPoint(distance); const Vector3 n = prim->GetNormal(intersectionPoint); if (prim->GetMaterial().GetDiffuse() > 0) { for (Scene::ConstIterator it = scene.Begin(); it != scene.End(); it++) { const double intensive = getIntensity((*it), intersectionPoint, n, scene); if (intensive != .0) { Vector3 x = (prim->GetMaterial().GetColor()); Vector3 y = ((*it)->GetMaterial().GetColor()); color = color + (intensive * prim->GetMaterial().GetDiffuse()) * x * y; } } } //refraction { const Vector3 x = ray.GetDirection(); const Vector3 y = intersectionType * (-n); double n; if (intersectionType == IntersectOutside) n = 1.0 / prim->GetMaterial().GetRefractionRate(); else n = prim->GetMaterial().GetRefractionRate(); const double sin_1 = sqrt(1 - Dot(x,y)); const double sin_2 = n * sin_1; if (sin_2 < 1) { const double cos_2 = sqrt(1 - sin_2); Vector3 xPerpendicular = x - Dot(x,y)*y; Vector3 z = cos_2 * y + sin_2 * xPerpendicular; z.Normalize(); if (prim->GetMaterial().GetRefraction() > 0) { if (intersectionType == IntersectInside) { color = color + prim->GetMaterial().GetRefraction() * exp(-prim->GetMaterial().GetAbsorptionRate()*distance) * trace(scene, Ray(intersectionPoint, z), depth + 1); } else color = color + prim->GetMaterial().GetRefraction() * trace(scene, Ray(intersectionPoint, z), depth + 1); } } } //reflection if (prim->GetMaterial().GetReflection() > 0) { const Vector3 a = ray.GetDirection(); Vector3 newA = a - 2 * (Dot(a,n)) * n; color = color + prim->GetMaterial().GetReflection() * trace(scene, Ray(intersectionPoint, newA), depth + 1); } } return color; }
bool BoundingBox::Intersect(const Ray &view_ray, float &distance_f) { float t_near_f = 0.0f, t0_f, t1_f; float t_far_f = std::numeric_limits<float>::infinity(); for(int i = 0; i < 3; ++i) { switch(i) { case 0: // X if(view_ray.GetDirection().x == 0) { if((view_ray.GetPosition().x < this->GetMin().x) || (view_ray.GetPosition().x > this->GetMax().x)) return false; // way off } else { t0_f = (this->GetMin().x - view_ray.GetPosition().x) / view_ray.GetDirection().x; // the first position for x, t1_f = (this->GetMax().x - view_ray.GetPosition().x) / view_ray.GetDirection().x; // second... } break; case 1: // Y if(view_ray.GetDirection().y == 0) { if((view_ray.GetPosition().y < this->GetMin().y) || (view_ray.GetPosition().y > this->GetMax().y)) return false; } else { t0_f = (this->GetMin().y - view_ray.GetPosition().y) / view_ray.GetDirection().y; t1_f = (this->GetMax().y - view_ray.GetPosition().y) / view_ray.GetDirection().y; } break; case 2: // Z if(view_ray.GetDirection().z == 0) { if((view_ray.GetPosition().z < this->GetMin().z) || (view_ray.GetPosition().z > this->GetMax().z)) return false; } else { t0_f = (this->GetMin().z - view_ray.GetPosition().z) / view_ray.GetDirection().z; t1_f = (this->GetMax().z - view_ray.GetPosition().z) / view_ray.GetDirection().z; } break; default: break; } // setting up the planes if(t0_f > t1_f) Math::Swap(t0_f, t1_f); t_near_f = Math::Max(t_near_f, t0_f); t_far_f = Math::Min(t1_f, t_far_f); // out of range, but the set-up is correct if((t_near_f > t_far_f) || (t_far_f < 0.0f)) return false; } return true; }