// invoke by Pointer3DInputModule
        public virtual void Raycast()
        {
            sortedRaycastResults.Clear();
            breakPoints.Clear();

            var zScale         = transform.lossyScale.z;
            var amountDistance = (FarDistance - NearDistance) * zScale;
            var origin         = transform.TransformPoint(0f, 0f, NearDistance);

            breakPoints.Add(origin);

            bool          hasNext = true;
            Vector3       direction;
            float         distance;
            Ray           ray;
            RaycastResult firstHit = default(RaycastResult);

            var generator = CurrentSegmentGenerator();

            if (ReferenceEquals(generator, null))
            {
                // process default raycast

                direction = transform.forward;
                distance  = amountDistance;
                ray       = new Ray(origin, direction);

                // move event camera in place
                eventCamera.farClipPlane       = eventCamera.nearClipPlane + distance;
                eventCamera.transform.position = ray.origin - (ray.direction * eventCamera.nearClipPlane);
                eventCamera.transform.rotation = Quaternion.LookRotation(ray.direction, transform.up);

                ForeachRaycastMethods(ray, distance, sortedRaycastResults);

                firstHit = FirstRaycastResult();
                breakPoints.Add(firstHit.isValid ? firstHit.worldPosition : ray.GetPoint(distance));
                if (!_Result.Equals(firstHit))
                {
                    _Result = firstHit;
                }
                if (firstHit.isValid)
                {
                    //Debug.Log("ReferenceEquals firstHit:" + firstHit.gameObject.name);
                }
#if UNITY_EDITOR
                if (showDebugRay)
                {
                    Debug.DrawLine(breakPoints[0], breakPoints[1], firstHit.isValid ? Color.green : Color.red);
                }
#endif
            }
            else
            {
                generator.ResetSegments();

                do
                {
                    hasNext = generator.NextSegment(out direction, out distance);

                    if (distance < MIN_SEGMENT_DISTANCE)
                    {
                        Debug.LogWarning("RaySegment.distance cannot smaller than " + MIN_SEGMENT_DISTANCE + "! distance=" + distance.ToString("0.000"));
                        break;
                    }

                    distance *= zScale;

                    if (distance < amountDistance)
                    {
                        amountDistance -= distance;
                    }
                    else
                    {
                        distance       = amountDistance;
                        amountDistance = 0f;
                    }

                    ray = new Ray(origin, direction);

                    // move event camera in place
                    eventCamera.farClipPlane       = eventCamera.nearClipPlane + distance;
                    eventCamera.transform.position = ray.origin - (ray.direction * eventCamera.nearClipPlane);
                    eventCamera.transform.rotation = Quaternion.LookRotation(ray.direction, transform.up);

                    ForeachRaycastMethods(ray, distance, sortedRaycastResults);

                    firstHit = FirstRaycastResult();

                    // end loop if raycast hit
                    if (firstHit.isValid)
                    {
                        breakPoints.Add(firstHit.worldPosition);
                        // Debug.Log("ReferenceEquals null firstHit:" + firstHit.gameObject.name);
#if UNITY_EDITOR
                        if (showDebugRay)
                        {
                            Debug.DrawLine(breakPoints[breakPoints.Count - 2], breakPoints[breakPoints.Count - 1], Color.green);
                        }
#endif
                        break;
                    }
                    // otherwise, shift to next iteration
                    origin = ray.GetPoint(distance);
                    breakPoints.Add(origin);
                    if (!_Result.Equals(firstHit))
                    {
                        _Result = firstHit;
                    }
#if UNITY_EDITOR
                    if (showDebugRay)
                    {
                        Debug.DrawLine(breakPoints[breakPoints.Count - 2], breakPoints[breakPoints.Count - 1], Color.red);
                    }
#endif
                }while (hasNext && amountDistance > 0f);
            }
        }