/// Returns the distance of the given ray to this line. /// @param d [out] Receives the distance along this line that specifies the closest point on this line to the given point. /// @param d2 [out] Receives the distance along the other line that specifies the closest point on that line to this line. float Ray::Distance(const Ray &other, float *d, float *d2) const { float u2; float3 c = ClosestPoint(other, d, &u2); if (d2) *d2 = u2; return c.Distance(other.GetPoint(u2)); }
bool Polygon::Intersects(const Ray &ray) const { float d; if (!PlaneCCW().Intersects(ray, &d)) return false; return Contains(ray.GetPoint(d)); }
bool Circle::IntersectsDisc(const Ray &ray) const { float d; bool intersectsPlane = ray.Intersects(ContainingPlane(), &d); if (intersectsPlane) return false; return ray.GetPoint(d).DistanceSq(pos) <= r*r; }
int Plane::Intersect(Ray& ray, IntersectResult* result) { Normal3dF normal(0, 1, 0); float dotA = ray.d.Dot(normal); if (dotA >= 0) { result = &IntersectResult::NoHit; return 0; } float dotB = normal.Dot(ray.o - position); float distance = -dotB / dotA; *result = IntersectResult(this, distance, ray.GetPoint(distance), normal); return 0; }
bool Triangle::Intersects(const Ray &r, float *d, float3 *intersectionPoint) const { float u, v, t; bool success = IntersectLineTri(r.pos, r.dir, a, b, c, u, v, t); if (!success || t <= 0.f) return false; if (d) *d = t; if (intersectionPoint) *intersectionPoint = r.GetPoint(t); return success; }
bool Triangle::Intersects(const Ray &r, float *d, float3 *intersectionPoint) const { float u, v; float t = IntersectLineTri(r.pos, r.dir, a, b, c, u, v); bool success = (t >= 0 && t != FLOAT_INF); if (!success) return false; if (d) *d = t; if (intersectionPoint) *intersectionPoint = r.GetPoint(t); return success; }
//http://www.qiujiawei.com/triangle-intersect/ int Triangle::Intersect(Ray& ray, IntersectResult* result) { const VectorArray& vertices = mesh->vertices; const Vector3dF& p0 = vertices[indexes[0]]; const Vector3dF& p1 = vertices[indexes[1]]; const Vector3dF& p2 = vertices[indexes[2]]; const Vector3dF&& e1 = p1 - p0; const Vector3dF&& e2 = p2 - p0; if (mesh->normals[tri_idx].isEmpty()) { mesh->normals[tri_idx] = (e1.Cross(e2)).Normalize(); if (mesh->reverse) { mesh->normals[tri_idx] = -mesh->normals[tri_idx]; } } const Normal3dF& normal = mesh->normals[tri_idx]; float nDotRay = normal.Dot(ray.d); if (mesh->face == 0) { //only front face if (nDotRay >= 0) { return 0; } } else if (mesh->face == 1) { //only back face if (nDotRay <= 0) { return 0; } } //printf("nDotRay %.1f ray.d: %.2f,%.2f,%.2f len:%.1f n: %.1f,%.1f,%.1f\n", nDotRay, ray.d.x, ray.d.y, ray.d.z, ray.d.Length(), normal.x, normal.y, normal.z); const Vector3dF& s = ray.o - p0; const Vector3dF& s1 = ray.d.Cross(e2); Real d = s1.Dot(e1); if (almost_equal(d, Real(0), 2)) return 0; d = 1. / d; const Vector3dF& s2 = s.Cross(e1); const Real& r1 = s2.Dot(e2); const Real& r2 = s1.Dot(s); const Real& r3 = s2.Dot(ray.d); const Real& t = r1 * d; const Real& b1 = r2 * d; if (b1 < 0. || b1 > 1.) return 0; const Real& b2 = r3 * d; if (b2 < 0. || b1 + b2 > 1.) return 0; const Vector3dF&& position = ray.GetPoint(t); *result = IntersectResult(mesh, t, std::forward<const Vector3dF>(position), normal); return 0; }
vec Plane::ClosestPoint(const Ray &ray) const { assume(ray.IsFinite()); assume(!IsDegenerate()); // The plane and a ray have three configurations: // 1) the ray and the plane don't intersect: the closest point is the ray origin point. // 2) the ray and the plane do intersect: the closest point is the intersection point. // 3) the ray is parallel to the plane: any point on the ray projected to the plane is a closest point. float denom = Dot(normal, ray.dir); if (denom == 0.f) return Project(ray.pos); // case 3) float t = (d - Dot(normal, ray.pos)) / denom; if (t >= 0.f && t < 1e6f) // Numerical stability check: Instead of checking denom against epsilon, check the resulting t for very large values. return ray.GetPoint(t); // case 2) else return Project(ray.pos); // case 1) }
bool operator()(KdTree<Triangle> &tree, const KdTreeNode &leaf, const Ray &ray, float tNear, float tFar) { u32 *bucket = tree.Bucket(leaf.bucketIndex); assert(bucket); while(*bucket != KdTree<Triangle>::BUCKET_SENTINEL) { const Triangle &tri = tree.Object(*bucket); float u, v, t; t = Triangle::IntersectLineTri(ray.pos, ray.dir, tri.a, tri.b, tri.c, u, v); bool intersects = t < std::numeric_limits<float>::infinity(); if (intersects && t >= tNear && t <= tFar && t < result.t) { result.t = t; result.pos = ray.GetPoint(t); result.triangleIndex = *bucket; result.submeshIndex = (u32)-1; result.barycentricUV = float2(u,v); } ++bucket; } return result.t < std::numeric_limits<float>::infinity(); // If we hit a triangle, no need to visit any farther nodes, since we are only interested in the nearest hit. }
float Ray::Distance(const Ray &other, float &d, float &d2) const { vec c = ClosestPoint(other, d, d2); return c.Distance(other.GetPoint(d2)); }
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; }