Beispiel #1
0
        public Option <RayHitpoint> TryHit(PositionableSphere positionableSphere, Ray ray, RayParameter bottomBoundary,
                                           RayParameter topBoundary)
        {
            var(positionable, sphere) = positionableSphere;
            var originToCenter = ray.Origin - positionable.Translation;
            var a = Vector3.Dot(ray.Direction, ray.Direction);
            var b = 2.0f * Vector3.Dot(originToCenter, ray.Direction);
            var c = Vector3.Dot(originToCenter, originToCenter) -
                    sphere.Radius * sphere.Radius;
            var discriminant = b * b - 4 * a * c;

            if (discriminant < 0)
            {
                return(Option <RayHitpoint> .Empty);
            }

            var temp = new RayParameter((-b - (float)Math.Sqrt(discriminant)) / (2.0f * a));

            if (temp < topBoundary.Value && temp > bottomBoundary.Value)
            {
                var hitPoint = ray.PointAt(temp);
                var normal   = GetNormalAtPoint(hitPoint, positionableSphere);
                return(new Option <RayHitpoint>(new RayHitpoint(hitPoint, normal, temp)));
            }

            temp = new RayParameter((-b + (float)Math.Sqrt(discriminant)) / (2.0f * a));
            if (temp < topBoundary.Value && temp > bottomBoundary.Value)
            {
                var hitPoint = ray.PointAt(temp);
                var normal   = GetNormalAtPoint(hitPoint, positionableSphere);
                return(new Option <RayHitpoint>(new RayHitpoint(hitPoint, normal, temp)));
            }

            return(Option <RayHitpoint> .Empty);
        }
        public bool Hit(Bounds bounds,
                        Ray ray,
                        RayParameter bottomBoundary,
                        RayParameter topBoundary)
        {
            var tMin = bottomBoundary.Value;
            var tMax = topBoundary.Value;

            for (var i = 0; i < 3; ++i)
            {
                var invRayDir = 1 / ray.Direction.Enumerate(i);
                var t0        = (bounds.Minimum.Enumerate(i) - ray.Origin.Enumerate(i)) * invRayDir;
                var t1        = (bounds.Maximum.Enumerate(i) - ray.Origin.Enumerate(i)) * invRayDir;
                if (invRayDir < 0.0f)
                {
                    Maths.Swap(ref t0, ref t1);
                }

                tMin = t0 > tMin ? t0 : tMin;
                tMax = t1 < tMax ? t1 : tMax;
                if (t0 > t1)
                {
                    return(false);
                }
            }

            return(true);
        }
        public Option <EntityRayHitpoint> TryHit(Ray ray, RayParameter bottomBoundary, RayParameter topBoundary)
        {
            if (!_hitableBoundsComputer.Hit(_bounds, ray, bottomBoundary, topBoundary))
            {
                return(Option <EntityRayHitpoint> .Empty);
            }

            var leftHit  = Left.TryHit(ray, bottomBoundary, topBoundary);
            var rightHit = Right.TryHit(ray, bottomBoundary, topBoundary);

            return(leftHit.HasValue switch
            {
                true when rightHit.HasValue => leftHit.Value.Hitpoint.T < rightHit.Value.Hitpoint.T
                    ? leftHit
                    : rightHit,
                true => leftHit,
                _ => rightHit.HasValue ? rightHit : Option <EntityRayHitpoint> .Empty
            });
        private Color ThrowRay(Ray ray, RayParameter minParameter, RayParameter maxParameter, Color color, int depth)
        {
            var hitPoint = Scene.TryHit(ray, minParameter, maxParameter);

            if (hitPoint.HasValue)
            {
                // Scatter
                var rayScattered = Scene.Scatterables[hitPoint.Value.Id]
                                   .Scatter(ray, hitPoint.Value.Hitpoint, new Color(color.Value));
                if (++depth > 50)
                {
                    return(new Color(new Vector3(0.0f)));
                }

                return(ThrowRay(rayScattered.Scattered, minParameter, hitPoint.Value.Hitpoint.T, rayScattered.Color,
                                depth));
            }

            return(color);
        }
Beispiel #5
0
        public Option <EntityRayHitpoint> TryHit(Ray ray, RayParameter bottomBoundary, RayParameter topBoundary)
        {
            var hasHit             = false;
            var candidateParameter = topBoundary;
            var candidateHitpoint  = new EntityRayHitpoint();

            foreach (var(id, hitable) in _hitables)
            {
                var contact = hitable.TryHit(ray, bottomBoundary, topBoundary);
                if (contact.HasValue && contact.Value.T < candidateParameter)
                {
                    candidateParameter = contact.Value.T;
                    candidateHitpoint  = new EntityRayHitpoint(id, contact);
                    hasHit             = true;
                }
            }

            return(hasHit
                ? new Option <EntityRayHitpoint>(candidateHitpoint)
                : Option <EntityRayHitpoint> .Empty);
        }
Beispiel #6
0
 public bool Hit(Ray ray, RayParameter bottomBoundary, RayParameter topBoundary)
 {
     return(_computer.Hit(_bounds, ray, bottomBoundary, topBoundary));
 }
Beispiel #7
0
 public Option <EntityRayHitpoint> TryHit(Ray ray, RayParameter bottomBoundary, RayParameter topBoundary)
 {
     return(_hitableStructure.TryHit(ray, bottomBoundary, topBoundary));
 }
Beispiel #8
0
 public Option <RayHitpoint> TryHit(Ray ray, RayParameter bottomBoundary, RayParameter topBoundary)
 {
     return(_computer.TryHit(_sphere, ray, bottomBoundary, topBoundary));
 }