Esempio n. 1
0
        void RemoveGameObjects(PolyRaycastHit hit, BrushTarget target, BrushSettings settings)
        {
            Vector3 worldHitPosition = target.editableObject.transform.TransformPoint(hit.position);

            int count = m_PrefabsInstances.Count;

            for (int i = 0; i < count; i++)
            {
                // Skip the object if prefab is not part of the current loadout.
                if (!prefabLoadoutEditor.ContainsPrefabInstance(m_PrefabsInstances[i]))
                {
                    continue;
                }

                if (m_PrefabsInstances[i] != null && Vector3.Distance(worldHitPosition, m_PrefabsInstances[i].transform.position) < settings.radius)
                {
                    GameObject go = m_PrefabsInstances[i];
                    m_PrefabsInstances.RemoveAt(i);
                    count--;
                    Undo.DestroyObjectImmediate(go);
                }
            }
        }
        /// <summary>
        /// Draw gizmos taking into account handling of normal by raiser lower brush mode.
        /// </summary>
        /// <param name="target">Current target Object</param>
        /// <param name="settings">Current brush settings</param>
        internal override void DrawGizmos(BrushTarget target, BrushSettings settings)
        {
            if (!m_EditableObjectsData.ContainsKey(target.editableObject))
            {
                return;
            }

            EditableObjectData data = m_EditableObjectsData[target.editableObject];

            UpdateBrushGizmosColor();
            int            rayCount = target.raycastHits.Count;
            List <Vector3> brushNormalOnBeginApply = BrushNormalsOnBeginApply(target.editableObject);

            for (int ri = 0; ri < rayCount; ri++)
            {
                PolyRaycastHit hit = target.raycastHits[ri];

                Vector3 normal = hit.normal;
                switch (s_RaiseLowerDirection.value)
                {
                case PolyDirection.BrushNormal:
                {
                    if (s_UseFirstNormalVector && brushNormalOnBeginApply.Count > ri)
                    {
                        normal = brushNormalOnBeginApply[ri];
                    }
                }
                break;

                case PolyDirection.Up:
                case PolyDirection.Right:
                case PolyDirection.Forward:
                {
                    normal = DirectionUtil.ToVector3(s_RaiseLowerDirection);
                }
                break;

                case PolyDirection.VertexNormal:
                {
                    //For vertex normal mode we take the vertex with the highest weight to compute the normal
                    //if non has enough we take the hit normal.
                    float highestWeight = .0001f;
                    int   highestIndex  = -1;
                    for (int i = 0; i < data.CommonVertexCount; i++)
                    {
                        int index = data.CommonVertices[i][0];

                        if (hit.weights[index] < .0001f || (s_IgnoreOpenEdges && ContainsIndexInNonManifoldIndices(target.editableObject, index)))
                        {
                            continue;
                        }

                        if (hit.weights[index] > highestWeight)
                        {
                            highestIndex = index;
                        }
                    }

                    if (highestIndex != -1)
                    {
                        normal = data.NormalLookup[highestIndex];
                    }
                }
                break;
                }
                ;

                normal = settings.isUserHoldingControl ? normal * -1f : normal;
                PolyHandles.DrawBrush(hit.position, normal, settings, target.localToWorldMatrix, innerColor, outerColor);
            }
        }
        internal override void OnBrushApply(BrushTarget target, BrushSettings settings)
        {
            if (!m_LikelyToSupportVertexSculpt)
            {
                return;
            }

            if (!m_EditableObjectsData.ContainsKey(target.editableObject))
            {
                return;
            }

            int rayCount = target.raycastHits.Count;

            if (rayCount < 1)
            {
                return;
            }

            Vector3 n = s_RaiseLowerDirection.value.ToVector3();

            float scale = 1f / (Vector3.Scale(target.transform.lossyScale, n).magnitude);
            float sign  = settings.isUserHoldingControl ? -1f : 1f;//Event.current != null ? (Event.current.control ? -1f : 1f) : 1f;

            float maxMoveDistance = settings.strength * k_StrengthModifier * sign * s_RaiseLowerStrength;
            int   vertexCount     = target.editableObject.vertexCount;

            PolyMesh mesh = target.editableObject.editMesh;

            EditableObjectData data = m_EditableObjectsData[target.editableObject];
            List <Vector3>     brushNormalOnBeginApply = BrushNormalsOnBeginApply(target.editableObject);

            // rayCount could be different from brushNormalOnBeginApply.Count with some shapes (example: sphere).
            for (int ri = 0; ri < rayCount && ri < brushNormalOnBeginApply.Count; ri++)
            {
                PolyRaycastHit hit = target.raycastHits[ri];

                if (hit.weights == null || hit.weights.Length < vertexCount)
                {
                    continue;
                }

                if (s_RaiseLowerDirection == PolyDirection.BrushNormal)
                {
                    if (s_UseFirstNormalVector)
                    {
                        n = brushNormalOnBeginApply[ri];
                    }
                    else
                    {
                        n = hit.normal;
                    }

                    scale = 1f / (Vector3.Scale(target.transform.lossyScale, n).magnitude);
                }

                for (int i = 0; i < data.CommonVertexCount; i++)
                {
                    int index = data.CommonVertices[i][0];

                    if (hit.weights[index] < .0001f || (s_IgnoreOpenEdges && ContainsIndexInNonManifoldIndices(target.editableObject, index)))
                    {
                        continue;
                    }

                    if (s_RaiseLowerDirection == PolyDirection.VertexNormal)
                    {
                        n     = data.NormalLookup[index];
                        scale = 1f / (Vector3.Scale(target.transform.lossyScale, n).magnitude);
                    }

                    Vector3 pos = data.Vertices[index] + n * (hit.weights[index] * maxMoveDistance * scale);

                    int[] indices = data.CommonVertices[i];

                    for (int it = 0; it < indices.Length; it++)
                    {
                        data.Vertices[indices[it]] = pos;
                    }
                }
            }

            mesh.vertices = data.Vertices;
            target.editableObject.modifiedChannels |= MeshChannel.Position;

            // different than setting weights on temp component,
            // which is what BrushModeMesh.OnBrushApply does.
            if (tempComponent != null)
            {
                tempComponent.OnVerticesMoved(mesh);
            }

            base.OnBrushApply(target, settings);
        }
Esempio n. 4
0
        void PlaceGameObject(PolyRaycastHit hit, PrefabAndSettings prefabAndSettings, BrushTarget target, BrushSettings settings)
        {
            if (prefabAndSettings == null)
            {
                return;
            }

            GameObject prefab = prefabAndSettings.gameObject;

            var worldPosition = target.transform.TransformPoint(hit.position);
            var worldNormal   = target.transform.TransformDirection(hit.normal);
            Ray ray           = RandomRay(worldPosition, worldNormal, settings.radius, settings.falloff, settings.falloffCurve);

            ray.origin    = target.transform.InverseTransformPoint(ray.origin);
            ray.direction = target.transform.InverseTransformDirection(ray.direction);

            PolyRaycastHit rand_hit;

            Vector3[] vertices  = target.editableObject.editMesh.vertices;
            int[]     triangles = target.editableObject.editMesh.GetTriangles();

            if (PolySceneUtility.MeshRaycast(ray, vertices, triangles, out rand_hit))
            {
                PlacementSettings placementSettings = prefabAndSettings.settings;
                Vector3           scaleSetting      = prefab.transform.localScale;
                if (placementSettings.uniformBool)
                {
                    float uniformScale = Random.Range(placementSettings.uniformScale.x, placementSettings.uniformScale.y);
                    scaleSetting *= uniformScale;
                }
                else
                {
                    if (placementSettings.xScaleBool)
                    {
                        scaleSetting.x = Random.Range(placementSettings.scaleRangeMin.x, placementSettings.scaleRangeMax.x);
                    }
                    if (placementSettings.yScaleBool)
                    {
                        scaleSetting.y = Random.Range(placementSettings.scaleRangeMin.y, placementSettings.scaleRangeMax.y);
                    }
                    if (placementSettings.zScaleBool)
                    {
                        scaleSetting.z = Random.Range(placementSettings.scaleRangeMin.z, placementSettings.scaleRangeMax.z);
                    }
                }

                Vector3 rotationSetting = Vector3.zero;
                if (placementSettings.xRotationBool)
                {
                    rotationSetting.x = Random.Range(placementSettings.rotationRangeMin.x, placementSettings.rotationRangeMax.x);
                }
                if (placementSettings.yRotationBool)
                {
                    rotationSetting.y = Random.Range(placementSettings.rotationRangeMin.y, placementSettings.rotationRangeMax.y);
                }
                if (placementSettings.xRotationBool)
                {
                    rotationSetting.z = Random.Range(placementSettings.rotationRangeMin.z, placementSettings.rotationRangeMax.z);
                }


                Quaternion rotation = Quaternion.FromToRotation(Vector3.up, target.transform.TransformDirection(rand_hit.normal));

                GameObject inst = (GameObject)PrefabUtility.InstantiatePrefab(prefab);
                inst.transform.position   = target.transform.TransformPoint(rand_hit.position);
                inst.transform.rotation   = rotation;
                inst.transform.localScale = scaleSetting;

                float pivotOffset = s_UsePivotForPlacement ? 0f : GetPivotOffset(inst);

                inst.name = FormatInstanceName(prefab);

                inst.transform.position = inst.transform.position - (inst.transform.up * pivotOffset);
                inst.transform.rotation = inst.transform.rotation * Quaternion.Euler(rotationSetting);


                if (s_AvoidOverlappingGameObjects && TestIntersection(inst))
                {
                    Object.DestroyImmediate(inst);
                    return;
                }

                if (s_ParentObjectWithSurface)
                {
                    inst.transform.SetParent(target.transform);
                }

                m_PrefabsInstances.Add(inst);

                Undo.RegisterCreatedObjectUndo(inst, UndoMessage);
            }
        }
        internal override void OnBrushApply(BrushTarget target, BrushSettings settings)
        {
            if (!likelyToSupportVertexSculpt)
            {
                return;
            }

            int rayCount = target.raycastHits.Count;

            Vector3[] normals = (s_SmoothDirection == PolyDirection.BrushNormal) ? target.editableObject.editMesh.normals : null;

            Vector3  v, t, avg, dirVec = s_SmoothDirection.value.ToVector3();
            Plane    plane       = new Plane(Vector3.up, Vector3.zero);
            PolyMesh mesh        = target.editableObject.editMesh;
            int      vertexCount = mesh.vertexCount;

            // don't use target.GetAllWeights because brush normal needs
            // to know which ray to use for normal
            for (int ri = 0; ri < rayCount; ri++)
            {
                PolyRaycastHit hit = target.raycastHits[ri];

                if (hit.weights == null || hit.weights.Length < vertexCount)
                {
                    continue;
                }

                for (int i = 0; i < commonVertexCount; i++)
                {
                    int index = commonVertices[i][0];

                    if (hit.weights[index] < .0001f || (s_IgnoreOpenEdges && nonManifoldIndices.Contains(index)))
                    {
                        continue;
                    }

                    v = vertices[index];

                    if (s_SmoothDirection == PolyDirection.VertexNormal)
                    {
                        avg = PolyMath.Average(vertices, neighborLookup[index]);
                    }
                    else
                    {
                        avg = PolyMath.WeightedAverage(vertices, neighborLookup[index], hit.weights);

                        if (s_SmoothDirection == PolyDirection.BrushNormal)
                        {
                            if (s_UseFirstNormalVector)
                            {
                                dirVec = brushNormalOnBeginApply[ri];
                            }
                            else
                            {
                                dirVec = PolyMath.WeightedAverage(normals, neighborLookup[index], hit.weights).normalized;
                            }
                        }

                        plane.SetNormalAndPosition(dirVec, avg);
                        avg = v - dirVec * plane.GetDistanceToPoint(v);
                    }

                    t = Vector3.Lerp(v, avg, hit.weights[index]);
                    List <int> indices = commonVertices[i];

                    Vector3 pos = v + (t - v) * settings.strength * SMOOTH_STRENGTH_MODIFIER;

                    for (int n = 0; n < indices.Count; n++)
                    {
                        vertices[indices[n]] = pos;
                    }
                }
            }

            mesh.vertices = vertices;

            if (tempComponent != null)
            {
                tempComponent.OnVerticesMoved(mesh);
            }

            base.OnBrushApply(target, settings);
        }
        /// <summary>
        /// Draw gizmos taking into account handling of normal by smooth brush mode.
        /// </summary>
        /// <param name="target">Current target Object</param>
        ///// <param name="settings">Current brush settings</param>
        internal override void DrawGizmos(BrushTarget target, BrushSettings settings)
        {
            UpdateBrushGizmosColor();
            Vector3 normal = s_SmoothDirection.value.ToVector3();

            int      rayCount    = target.raycastHits.Count;
            PolyMesh mesh        = target.editableObject.editMesh;
            int      vertexCount = mesh.vertexCount;

            Vector3[] normals = (s_SmoothDirection == PolyDirection.BrushNormal) ? mesh.normals : null;

            List <Vector3> brushNormalOnBeginApply = BrushNormalsOnBeginApply(target.editableObject);
            var            data = m_EditableObjectsData[target.editableObject];

            // don't use target.GetAllWeights because brush normal needs
            // to know which ray to use for normal
            for (int ri = 0; ri < rayCount; ri++)
            {
                PolyRaycastHit hit = target.raycastHits[ri];

                if (hit.weights == null || hit.weights.Length < vertexCount)
                {
                    continue;
                }

                if (s_SmoothDirection == PolyDirection.BrushNormal)
                {
                    if (s_UseFirstNormalVector && brushNormalOnBeginApply.Count > ri)
                    {
                        normal = brushNormalOnBeginApply[ri];
                    }
                    else
                    {
                        // get the highest weighted vertex to use its direction computation
                        float highestWeight = .0001f;
                        int   highestIndex  = -1;
                        for (int i = 0; i < data.commonVertexCount; i++)
                        {
                            int index = data.commonVertices[i][0];
                            if (hit.weights[index] < .0001f || (s_IgnoreOpenEdges && ContainsIndexInNonManifoldIndices(target.editableObject, index)))
                            {
                                continue;
                            }

                            if (hit.weights[index] > highestWeight)
                            {
                                highestIndex = index;
                            }
                        }

                        normal = highestIndex != -1 ?
                                 Math.WeightedAverage(normals, data.neighborLookup[highestIndex], hit.weights).normalized :
                                 hit.normal;
                    }
                }
                else if (s_SmoothDirection == PolyDirection.VertexNormal)
                {
                    normal = hit.normal;
                }

                PolyHandles.DrawBrush(hit.position,
                                      normal,
                                      settings,
                                      target.localToWorldMatrix,
                                      innerColor,
                                      outerColor);
            }
        }
        /// <summary>
        /// Calculate the weights for this ray.
        /// </summary>
        /// <param name="mouseRay">The ray used to calculate weights</param>
        /// <param name="target">The object on which to calculate the weights</param>
        /// <returns>true if mouseRay hits the target, false otherwise</returns>
        bool DoMeshRaycast(Ray mouseRay, BrushTarget target, MirrorSettings mirrorSettings)
        {
            m_SecondaryBrushTargets.Clear();
            if (!Util.IsValid(target))
            {
                return(false);
            }

            target.ClearRaycasts();

            EditableObject editable = target.editableObject;

            s_Rays.Clear();
            s_Rays.Add(mouseRay);

            if (mirrorSettings.Axes != BrushMirror.None)
            {
                for (int i = 0; i < 3; i++)
                {
                    if (((uint)mirrorSettings.Axes & (1u << i)) < 1)
                    {
                        continue;
                    }

                    int len = s_Rays.Count;

                    for (int n = 0; n < len; n++)
                    {
                        Vector3 flipVec = ((BrushMirror)(1u << i)).ToVector3();

                        if (mirrorSettings.Space == MirrorCoordinateSpace.World)
                        {
                            Vector3 cen = editable.gameObjectAttached.GetComponent <Renderer>().bounds.center;
                            s_Rays.Add(new Ray(Vector3.Scale(s_Rays[n].origin - cen, flipVec) + cen,
                                               Vector3.Scale(s_Rays[n].direction, flipVec)));
                        }
                        else
                        {
                            Transform t = SceneView.lastActiveSceneView.camera.transform;
                            Vector3   o = t.InverseTransformPoint(s_Rays[n].origin);
                            Vector3   d = t.InverseTransformDirection(s_Rays[n].direction);
                            s_Rays.Add(new Ray(t.TransformPoint(Vector3.Scale(o, flipVec)),
                                               t.TransformDirection(Vector3.Scale(d, flipVec))));
                        }
                    }
                }
            }

            bool hitMesh = false;

            int[] triangles = editable.editMesh.GetTriangles();
            foreach (Ray ray in s_Rays)
            {
                PolyRaycastHit hit;

                if (PolySceneUtility.WorldRaycast(ray, editable.transform, editable.visualMesh.vertices, triangles,
                                                  out hit))
                {
                    target.raycastHits.Add(hit);
                    hitMesh = true;
                }
            }

            PolySceneUtility.CalculateWeightedVertices(target, brushSettings, tool, mode);

            if (hitMesh && !s_LockBrushToFirst)
            {
                Transform[] trs  = Selection.GetTransforms(SelectionMode.Unfiltered);
                var         hits = target.raycastHits;
                foreach (var selectedTransform in trs)
                {
                    bool isValid = false;
                    if (selectedTransform != editable.transform)
                    {
                        BrushTarget secondaryTarget = GetOrCreateBrushTarget(selectedTransform.gameObject);
                        isValid = Util.IsValid(secondaryTarget);
                        if (isValid)
                        {
                            m_SecondaryBrushTargets.Add(secondaryTarget);
                            secondaryTarget.ClearRaycasts();

                            foreach (var hit in hits)
                            {
                                PolyRaycastHit secondaryHit = new PolyRaycastHit(hit.distance,
                                                                                 secondaryTarget.transform.InverseTransformPoint(editable.transform.TransformPoint(hit.position)),
                                                                                 hit.normal,
                                                                                 -1);
                                secondaryTarget.raycastHits.Add(secondaryHit);
                            }
                        }
                        PolySceneUtility.CalculateWeightedVertices(secondaryTarget, brushSettings, tool, mode);
                    }
                }
            }

            return(hitMesh);
        }
        /// <summary>
        /// Cast a ray (in model space) against a mesh.
        /// </summary>
        internal static bool MeshRaycast(Ray InRay, Vector3[] vertices, int[] triangles, out PolyRaycastHit hit, float distance = Mathf.Infinity, Culling cullingMode = Culling.Front)
        {
            Vector3 hitNormal, vert0, vert1, vert2;
            Vector3 origin = InRay.origin, direction = InRay.direction;

            hit = new PolyRaycastHit(Mathf.Infinity,
                                     Vector3.zero,
                                     Vector3.zero,
                                     -1);

            // Iterate faces, testing for nearest hit to ray origin.
            for (int CurTri = 0; CurTri < triangles.Length; CurTri += 3)
            {
                if (CurTri + 2 >= triangles.Length)
                {
                    continue;
                }
                if (triangles[CurTri + 2] >= vertices.Length)
                {
                    continue;
                }

                vert0 = vertices[triangles[CurTri + 0]];
                vert1 = vertices[triangles[CurTri + 1]];
                vert2 = vertices[triangles[CurTri + 2]];

                // Second pass, test intersection with triangle
                if (Math.RayIntersectsTriangle2(origin, direction, vert0, vert1, vert2, out distance, out hitNormal))
                {
                    if (distance < hit.distance)
                    {
                        hit.distance = distance;
                        hit.triangle = CurTri / 3;
                        hit.position = InRay.GetPoint(hit.distance);
                        hit.normal   = hitNormal;
                    }
                }
            }

            return(hit.triangle > -1);
        }
        /// <summary>
        /// Find the nearest triangle intersected by InWorldRay on this mesh.  InWorldRay is in world space.
        /// @hit contains information about the hit point.  @distance limits how far from @InWorldRay.origin the hit
        /// point may be.  @cullingMode determines what face orientations are tested (Culling.Front only tests front
        /// faces, Culling.Back only tests back faces, and Culling.FrontBack tests both).
        /// Ray origin and position values are in local space.
        /// </summary>
        /// <param name="InWorldRay"></param>
        /// <param name="transform"></param>
        /// <param name="vertices"></param>
        /// <param name="triangles"></param>
        /// <param name="hit"></param>
        /// <param name="distance"></param>
        /// <param name="cullingMode"></param>
        /// <returns></returns>
        internal static bool WorldRaycast(Ray InWorldRay, Transform transform, Vector3[] vertices, int[] triangles, out PolyRaycastHit hit, float distance = Mathf.Infinity, Culling cullingMode = Culling.Front)
        {
            //null checks, must have a transform, vertices and triangles
            if (transform == null || vertices == null || triangles == null)
            {
                hit = null;
                return(false);
            }


            Ray ray = transform.InverseTransformRay(InWorldRay);

            return(MeshRaycast(ray, vertices, triangles, out hit, distance, cullingMode));
        }
Esempio n. 10
0
        internal override void OnBrushApply(BrushTarget target, BrushSettings settings)
        {
            if (!likelyToSupportVertexSculpt)
            {
                return;
            }

            int rayCount = target.raycastHits.Count;

            if (rayCount < 1)
            {
                return;
            }

            Vector3 n = s_RaiseLowerDirection.value.ToVector3();

            float scale = 1f / (Vector3.Scale(target.transform.lossyScale, n).magnitude);
            float sign  = settings.isUserHoldingControl ? -1f : 1f;//Event.current != null ? (Event.current.control ? -1f : 1f) : 1f;

            float maxMoveDistance = settings.strength * k_StrengthModifier * sign * s_RaiseLowerStrength;
            int   vertexCount     = target.editableObject.vertexCount;

            PolyMesh mesh = target.editableObject.editMesh;

            for (int ri = 0; ri < rayCount; ri++)
            {
                PolyRaycastHit hit = target.raycastHits[ri];

                if (hit.weights == null || hit.weights.Length < vertexCount)
                {
                    continue;
                }

                if (s_RaiseLowerDirection == PolyDirection.BrushNormal)
                {
                    if (s_UseFirstNormalVector)
                    {
                        n = brushNormalOnBeginApply[ri];
                    }
                    else
                    {
                        n = target.raycastHits[ri].normal;
                    }

                    scale = 1f / (Vector3.Scale(target.transform.lossyScale, n).magnitude);
                }

                for (int i = 0; i < commonVertexCount; i++)
                {
                    int index = commonVertices[i][0];

                    if (hit.weights[index] < .0001f || (s_IgnoreOpenEdges && nonManifoldIndices.Contains(index)))
                    {
                        continue;
                    }

                    if (s_RaiseLowerDirection == PolyDirection.VertexNormal)
                    {
                        n     = normalLookup[index];
                        scale = 1f / (Vector3.Scale(target.transform.lossyScale, n).magnitude);
                    }

                    Vector3 pos = vertices[index] + n * (hit.weights[index] * maxMoveDistance * scale);

                    List <int> indices = commonVertices[i];

                    for (int it = 0; it < indices.Count; it++)
                    {
                        vertices[indices[it]] = pos;
                    }
                }
            }

            mesh.vertices = vertices;

            // different than setting weights on temp component,
            // which is what BrushModeMesh.OnBrushApply does.
            if (tempComponent != null)
            {
                tempComponent.OnVerticesMoved(mesh);
            }

            base.OnBrushApply(target, settings);
        }
Esempio n. 11
0
        /// <summary>
        /// Cast a ray (in model space) against a mesh.
        /// </summary>
        /// <param name="InRay"></param>
        /// <param name="vertices"></param>
        /// <param name="triangles"></param>
        /// <param name="hit"></param>
        /// <param name="distance"></param>
        /// <param name="cullingMode"></param>
        /// <returns></returns>
        internal static bool MeshRaycast(Ray InRay, Vector3[] vertices, int[] triangles, out PolyRaycastHit hit, float distance = Mathf.Infinity, Culling cullingMode = Culling.Front)
        {
            float   hitDistance = Mathf.Infinity;
            Vector3 hitNormal = Vector3.zero;   // vars used in loop
            Vector3 vert0, vert1, vert2;
            int     hitFace = -1;
            Vector3 origin = InRay.origin, direction = InRay.direction;

            /**
             * Iterate faces, testing for nearest hit to ray origin.
             */
            for (int CurTri = 0; CurTri < triangles.Length; CurTri += 3)
            {
                if (CurTri + 2 >= triangles.Length)
                {
                    continue;
                }
                if (triangles[CurTri + 2] >= vertices.Length)
                {
                    continue;
                }

                vert0 = vertices[triangles[CurTri + 0]];
                vert1 = vertices[triangles[CurTri + 1]];
                vert2 = vertices[triangles[CurTri + 2]];

                if (PolyMath.RayIntersectsTriangle2(origin, direction, vert0, vert1, vert2, ref distance, ref hitNormal))
                {
                    hitFace     = CurTri / 3;
                    hitDistance = distance;
                    break;
                }
            }

            hit = new PolyRaycastHit(hitDistance,
                                     InRay.GetPoint(hitDistance),
                                     hitNormal,
                                     hitFace);

            return(hitFace > -1);
        }