private bool ProcessHits( double t1, double t2, double tmin, double tmax, ref RayHit3d hit) { if (t1 >= tmin) { if (t1 < tmax && t1 < hit.T) { hit.T = t1; hit.Point = GetPointOnRay(t1); hit.Coord = V2d.NaN; hit.BackSide = false; return(true); } return(false); } if (t2 >= tmin) { if (t2 < tmax && t2 < hit.T) { hit.T = t2; hit.Point = GetPointOnRay(t2); hit.Coord = V2d.NaN; hit.BackSide = true; return(true); } } return(false); }
/// <summary> /// Returns true if the ray hits the sphere given by center and /// radius within the supplied parameter interval and before the /// parameter value contained in the supplied hit. Note that a /// hit is only registered if the front or the backsurface is /// encountered within the interval. /// </summary> public bool HitsSphere( V3d center, double radius, double tmin, double tmax, ref RayHit3d hit) { V3d originSubCenter = Origin - center; double a = Direction.LengthSquared; double b = Direction.Dot(originSubCenter); double c = originSubCenter.LengthSquared - radius * radius; // --------------------- quadric equation : a t^2 + 2b t + c = 0 double d = b * b - a * c; // factor 2 was eliminated if (d < Constant <double> .PositiveTinyValue) // no root ? { return(false); // then exit } if (b > 0.0) // stable way to calculate { d = -Fun.Sqrt(d) - b; // the roots of a quadratic } else // equation { d = Fun.Sqrt(d) - b; } double t1 = d / a; double t2 = c / d; // Vieta : t1 * t2 == c/a return(t1 < t2 ? ProcessHits(t1, t2, tmin, tmax, ref hit) : ProcessHits(t2, t1, tmin, tmax, ref hit)); }
public bool HitsCircle(Circle3d circle, double tmin, double tmax, ref RayHit3d hit) { var dc = circle.Normal.Dot(Direction); var dw = circle.Normal.Dot(circle.Center - Origin); // If parallel to plane if (dc == 0.0) { return(false); } var t = dw / dc; if (!ComputeHit(t, tmin, tmax, ref hit)) { return(false); } if (V3d.Distance(hit.Point, circle.Center) > circle.Radius) { hit.Point = V3d.NaN; hit.T = tmax; return(false); } return(true); }
/// <summary> /// Returns true if the ray hits the quad before the parameter /// value contained in the supplied hit. Detailed information about /// the hit is returned in the supplied hit. In order to obtain all /// potential hits, the supplied hit can be initialized with /// RayHit3d.MaxRange. /// </summary> public bool Hits( Quad3d quad, ref RayHit3d hit ) { return(HitsQuad(quad.P0, quad.P1, quad.P2, quad.P3, double.MinValue, double.MaxValue, ref hit)); }
/// <summary> /// Returns true if the ray hits the supplied sphere within the /// supplied parameter interval and before the parameter value /// contained in the supplied hit. Note that a hit is only /// registered if the front or the backsurface is encountered /// within the interval. /// </summary> public bool Hits( Sphere3d sphere, double tmin, double tmax, ref RayHit3d hit) { return(HitsSphere(sphere.Center, sphere.Radius, tmin, tmax, ref hit)); }
/// <summary> /// Returns true if the ray hits the triangle before the parameter /// value contained in the supplied hit. Detailed information about /// the hit is returned in the supplied hit. /// </summary> public bool Hits( Triangle3d triangle, ref RayHit3d hit ) { return(HitsTrianglePointAndEdges( triangle.P0, triangle.Edge01, triangle.Edge02, double.MinValue, double.MaxValue, ref hit)); }
/// <summary> /// Returns true if the ray hits the other ray before the parameter /// value contained in the supplied hit. Detailed information about /// the hit is returned in the supplied hit. /// </summary> public bool Hits( Ray3d ray, double tmin, double tmax, ref RayHit3d hit ) { return(HitsRay(ray, tmin, tmax, ref hit)); }
private bool GetClosestHit( double t1, double t2, double tmin, double tmax, ref RayHit3d hit) { return(t1 < t2 ? ProcessHits(t1, t2, tmin, tmax, ref hit) : ProcessHits(t2, t1, tmin, tmax, ref hit)); }
/// <summary> /// Returns true if the ray hits the quad within the supplied /// parameter interval and before the parameter value contained /// in the supplied hit. Detailed information about the hit is /// returned in the supplied hit. In order to obtain all potential /// hits, the supplied hit can be initialized with RayHit3d.MaxRange. /// </summary> public bool Hits( Quad3d quad, double tmin, double tmax, ref RayHit3d hit ) { return(HitsQuad(quad.P0, quad.P1, quad.P2, quad.P3, tmin, tmax, ref hit)); }
public bool Hits( Cylinder3d cylinder, double tmin, double tmax, ref RayHit3d hit) { var intersects = HitsCylinder(cylinder, tmin, tmax, ref hit); return(intersects); }
/// <summary> /// Returns true if the ray hits the triangle within the supplied /// parameter interval and before the parameter value contained /// in the supplied hit. Detailed information about the hit is /// returned in the supplied hit. In order to obtain all potential /// hits, the supplied hit can be initialized with RayHit3d.MaxRange. /// </summary> public bool Hits( Triangle3d triangle, double tmin, double tmax, ref RayHit3d hit ) { return(HitsTrianglePointAndEdges( triangle.P0, triangle.Edge01, triangle.Edge02, tmin, tmax, ref hit)); }
/// <summary> /// Returns true if the ray hits the other ray before the parameter /// value contained in the supplied hit. Detailed information about /// the hit is returned in the supplied hit. /// </summary> public bool HitsRay( Ray3d ray, double tmin, double tmax, ref RayHit3d hit ) { V3d d = Origin - ray.Origin; V3d u = Direction; V3d v = ray.Direction; V3d n = u.Cross(v); if (Fun.IsTiny(d.Length)) { return(true); } else if (Fun.IsTiny(u.Cross(v).Length)) { return(false); } else { //-t0*u + t1*v + t2*n == d //M = {-u,v,n} //M*{t0,t1,t2}T == d //{t0,t1,t2}T == M^-1 * d M33d M = new M33d(); M.C0 = -u; M.C1 = v; M.C2 = n; if (M.Invertible) { V3d t = M.Inverse * d; if (Fun.IsTiny(t.Z)) { ProcessHits(t.X, double.MaxValue, tmin, tmax, ref hit); return(true); } else { return(false); } } else { return(false); } } }
public bool HitsPlane(Plane3d plane, double tmin, double tmax, ref RayHit3d hit) { var dc = plane.Normal.Dot(Direction); var dw = plane.Distance - plane.Normal.Dot(Origin); // If parallel to plane if (dc == 0.0) { return(false); } var t = dw / dc; return(ComputeHit(t, tmin, tmax, ref hit)); }
/// <summary> /// Returns true if the ray hits the triangle within the supplied /// parameter interval and before the parameter value contained /// in the supplied hit. Detailed information about the hit is /// returned in the supplied hit. In order to obtain all potential /// hits, the supplied hit can be initialized with RayHit3d.MaxRange. /// </summary> public bool HitsTriangle( V3d p0, V3d p1, V3d p2, double tmin, double tmax, ref RayHit3d hit ) { V3d edge01 = p1 - p0; V3d edge02 = p2 - p0; V3d plane = V3d.Cross(Direction, edge02); double det = V3d.Dot(edge01, plane); if (det > -0.0000001 && det < 0.0000001) { return(false); } // ray ~= paralell / Triangle V3d tv = Origin - p0; det = 1.0 / det; // det is now inverse det double u = V3d.Dot(tv, plane) * det; if (u < 0.0 || u > 1.0) { return(false); } plane = V3d.Cross(tv, edge01); // plane is now qv double v = V3d.Dot(Direction, plane) * det; if (v < 0.0 || u + v > 1.0) { return(false); } double t = V3d.Dot(edge02, plane) * det; if (t < tmin || t >= tmax || t >= hit.T) { return(false); } hit.T = t; hit.Point = Origin + t * Direction; hit.Coord.X = u; hit.Coord.Y = v; hit.BackSide = (det < 0.0); return(true); }
private bool ComputeHit( double t, double tmin, double tmax, ref RayHit3d hit) { if (t >= tmin) { if (t < tmax && t < hit.T) { hit.T = t; hit.Point = GetPointOnRay(t); hit.Coord = V2d.NaN; hit.BackSide = false; return(true); } return(false); } return(false); }
/// <summary> /// Returns true if the ray hits the quad within the supplied /// parameter interval and before the parameter value contained /// in the supplied hit. The quad is considered to consist of the /// two triangles [p0,p1,p2] and [p0,p2,p3]. Detailed information /// about the hit is returned in the supplied hit. In order to obtain /// all potential hits, the supplied hit can be initialized with /// RayHit3d.MaxRange. /// </summary> public bool HitsQuad( V3d p0, V3d p1, V3d p2, V3d p3, double tmin, double tmax, ref RayHit3d hit ) { V3d e02 = p2 - p0; bool result = false; if (HitsTrianglePointAndEdges(p0, p1 - p0, e02, tmin, tmax, ref hit)) { hit.Coord.X += hit.Coord.Y; result = true; } if (HitsTrianglePointAndEdges(p0, e02, p3 - p0, tmin, tmax, ref hit)) { hit.Coord.Y += hit.Coord.X; result = true; } return(result); }
/// <summary> /// Returns true if the ray hits the other ray before the parameter /// value contained in the supplied hit. Detailed information about /// the hit is returned in the supplied hit. /// </summary> public bool Hits(Ray3d ray, ref RayHit3d hit) => HitsRay(ray, double.MinValue, double.MaxValue, ref hit);
/// <summary> /// Returns true if the ray hits the other ray before the parameter /// value contained in the supplied hit. Detailed information about /// the hit is returned in the supplied hit. /// </summary> public bool Hits( Ray3d ray, ref RayHit3d hit ) { return(HitsRay(ray, double.MinValue, double.MaxValue, ref hit)); }
public bool HitsCylinder(Cylinder3d cylinder, double tmin, double tmax, ref RayHit3d hit) { var axisDir = cylinder.Axis.Direction.Normalized; // Vector Cyl.P0 -> Ray.Origin var op = Origin - cylinder.P0; // normal RayDirection - CylinderAxis var normal = Direction.Cross(axisDir); var unitNormal = normal.Normalized; // normal (Vec Cyl.P0 -> Ray.Origin) - CylinderAxis var normal2 = op.Cross(axisDir); var t = -normal2.Dot(unitNormal) / normal.Length; var radius = cylinder.Radius; if (cylinder.DistanceScale != 0) { // cylinder gets bigger, the further away it is var pnt = GetPointOnRay(t); var dis = V3d.Distance(pnt, this.Origin); radius = ((cylinder.Radius / cylinder.DistanceScale) * dis) * 2; } // between enitre rays (caps are ignored) var shortestDistance = Fun.Abs(op.Dot(unitNormal)); if (shortestDistance <= radius) { var s = Fun.Abs(Fun.Sqrt(radius.Square() - shortestDistance.Square()) / Direction.Length); var t1 = t - s; // first hit of Cylinder shell var t2 = t + s; // second hit of Cylinder shell if (t1 > tmin && t1 < tmax) { tmin = t1; } if (t2 < tmax && t2 > tmin) { tmax = t2; } hit.T = t1; hit.Point = GetPointOnRay(t1); // check if found point is outside of Cylinder Caps var bottomPlane = new Plane3d(cylinder.Circle0.Normal, cylinder.Circle0.Center); var topPlane = new Plane3d(cylinder.Circle1.Normal, cylinder.Circle1.Center); var heightBottom = bottomPlane.Height(hit.Point); var heightTop = topPlane.Height(hit.Point); // t1 lies outside of caps => find closest cap hit if (heightBottom > 0 || heightTop > 0) { hit.T = tmax; // intersect with bottom Cylinder Cap var bottomHit = HitsPlane(bottomPlane, tmin, tmax, ref hit); // intersect with top Cylinder Cap var topHit = HitsPlane(topPlane, tmin, tmax, ref hit); // hit still close enough to cylinder axis? var distance = cylinder.Axis.Ray3d.GetMinimalDistanceTo(hit.Point); if (distance <= radius && (bottomHit || topHit)) { return(true); } } else { return(true); } } hit.T = tmax; hit.Point = V3d.NaN; return(false); }
/// <summary> /// Returns true if the ray hits the other ray before the parameter /// value contained in the supplied hit. Detailed information about /// the hit is returned in the supplied hit. /// </summary> public bool Hits(Ray3d ray, double tmin, double tmax, ref RayHit3d hit) => HitsRay(ray, tmin, tmax, ref hit);