Пример #1
0
    public Color Trace(Ray ray, TraceData traceData)
    {
        RaycastHit forwardHit;
        Color      color;

        traceData.Counters.Raycasts++;

        if (Physics.Raycast(ray, out forwardHit))
        {
            if (traceData.PenetrationStack.Count != 0)
            {
                Vector3 pushedOutOrigin = forwardHit.point + forwardHit.normal * PushOutMagnitude;
                Ray     backwardRay     = new Ray(pushedOutOrigin, -ray.direction);

                if (TraceBackward(ray, backwardRay, forwardHit.distance, traceData, out color))
                {
                    return(color);
                }
            }

            color = GetColor(ray, forwardHit, traceData);
            traceData.AddHistoryItem(ray, forwardHit, color);

            return(color);
        }
        else
        {
            if (traceData.PenetrationStack.Count != 0)
            {
                var soughtCollider = traceData.PenetrationStack.Peek().collider;
                var bounds         = soughtCollider.bounds;

                Vector3 extents = bounds.extents;
                float   boundingSphereRadius = extents.magnitude;
                Vector3 vToBbCenter          = bounds.center - ray.origin;
                float   projLen = Vector3.Dot(vToBbCenter, ray.direction);

                Vector3 pushedOutOrigin = ray.origin + ray.direction * (projLen + boundingSphereRadius + PushOutMagnitude);
                Ray     backwardRay     = new Ray(pushedOutOrigin, -ray.direction);

                if (TraceBackward(ray, backwardRay, Vector3.Distance(ray.origin, pushedOutOrigin), traceData, out color))
                {
                    return(color);
                }
            }

            traceData.AddHistoryItem(ray, null, traceData.BackgroundColor);

            return(traceData.BackgroundColor);
        }
    }
Пример #2
0
    private bool TraceBackward(Ray forwardRay, Ray backwardRay, float maxDistance, TraceData traceData, out Color color)
    {
        var soughtCollider = traceData.PenetrationStack.Peek().collider;

        traceData.Counters.Backtraces++;

        /* Sometimes, due to imprecision of calculations,
         * maxDistance is less than or equal to zero.
         * We can fix this issue by setting it to some small value,
         * it will not cause any error since origin point and
         * ray direction are fine. */
        if (maxDistance < MinRaycastDistance)
        {
            maxDistance = MinRaycastDistance;
        }

        var hits = Physics.RaycastAll(backwardRay, maxDistance)
                   .OrderByDescending(h => h.distance)
                   .Where(
            h => h.collider == soughtCollider &&
            h.distance < maxDistance                            // TODO: necessary? We already requested hits not farther than maxDistance. Test it.
            )
                   .ToArray();

        if (hits.Length != 0)
        {
            RaycastHit backwardHit = hits [0];
            backwardHit.distance = maxDistance - backwardHit.distance;
            color = GetColor(forwardRay, backwardHit, traceData);

            traceData.AddHistoryItem(forwardRay, backwardHit, color);

            return(true);
        }
        else
        {
            color = default(Color);

            return(false);
        }
    }