/// <summary>
        /// Calculates the per-vertex weight for each raycast hit and fills in brush target weights.
        /// </summary>
        /// <param name="target"></param>
        /// <param name="settings"></param>
        /// <param name="tool"></param>
        /// <param name="bMode"></param>
        internal static void CalculateWeightedVertices(BrushTarget target, BrushSettings settings, BrushTool tool = BrushTool.None, BrushMode bMode = null)
        {
            if (target == null || settings == null)
            {
                return;
            }

            if (target.editableObject == null)
            {
                return;
            }

            bool  uniformScale = Math.VectorIsUniform(target.transform.lossyScale);
            float scale        = uniformScale ? 1f / target.transform.lossyScale.x : 1f;

            PolyMesh mesh = target.editableObject.visualMesh;

            Transform transform   = target.transform;
            int       vertexCount = mesh.vertexCount;

            Vector3[] vertices = mesh.vertices;

            if (!uniformScale)
            {
                // As we only increase size only when it's needed, always make sure to
                // use the vertexCount variable in loop statements and not the buffer length.
                if (s_WorldBuffer.Length < vertexCount)
                {
                    System.Array.Resize <Vector3>(ref s_WorldBuffer, vertexCount);
                }

                for (int i = 0; i < vertexCount; i++)
                {
                    s_WorldBuffer[i] = transform.TransformPoint(vertices[i]);
                }
                vertices = s_WorldBuffer;
            }

            AnimationCurve curve = settings.falloffCurve;
            float          radius = settings.radius * scale, falloff_mag = Mathf.Max((radius - radius * settings.falloff), 0.00001f);

            Vector3        hitPosition = Vector3.zero;
            PolyRaycastHit hit;

            if (tool == BrushTool.Texture && mesh.subMeshCount > 1)
            {
                var   mode           = bMode as BrushModeTexture;
                int[] submeshIndices = mesh.subMeshes[mode.m_CurrentMeshACIndex].indexes;

                for (int n = 0; n < target.raycastHits.Count; n++)
                {
                    hit = target.raycastHits[n];
                    hit.SetVertexCount(vertexCount);

                    for (int i = 0; i < vertexCount; i++)
                    {
                        hit.weights[i] = 0f;
                    }

                    hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position);

                    for (int i = 0; i < submeshIndices.Length; i++)
                    {
                        int   currentIndex = submeshIndices[i];
                        float dist         = (hitPosition - vertices[currentIndex]).magnitude;
                        float delta        = radius - dist;

                        if (delta >= 0)
                        {
                            float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp(delta / falloff_mag, 0f, 1f)), 0f, 1f);

                            hit.weights[currentIndex] = weight;
                        }
                    }
                }
            }
            else
            {
                int[][] common = PolyMeshUtility.GetCommonVertices(mesh);

                Vector3 buf = Vector3.zero;

                for (int n = 0; n < target.raycastHits.Count; n++)
                {
                    hit = target.raycastHits[n];
                    hit.SetVertexCount(vertexCount);

                    hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position);

                    for (int i = 0; i < common.Length; i++)
                    {
                        int[] commonItem       = common[i];
                        int   commonArrayCount = commonItem.Length;

                        Math.Subtract(vertices[commonItem[0]], hitPosition, ref buf);

                        float sqrDist = buf.sqrMagnitude;

                        if (sqrDist > radius * radius)
                        {
                            for (int j = 0; j < commonArrayCount; j++)
                            {
                                hit.weights[commonItem[j]] = 0f;
                            }
                        }
                        else
                        {
                            float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp((radius - Mathf.Sqrt(sqrDist)) / falloff_mag, 0f, 1f)), 0f, 1f);

                            for (int j = 0; j < commonArrayCount; j++)
                            {
                                hit.weights[commonItem[j]] = weight;
                            }
                        }
                    }
                }
            }

            target.GetAllWeights(true);
        }
示例#2
0
        /// <summary>
        /// Calculates the per-vertex weight for each raycast hit and fills in brush target weights.
        /// </summary>
        /// <param name="target"></param>
        /// <param name="settings"></param>
        /// <param name="tool"></param>
        /// <param name="bMode"></param>
        internal static void CalculateWeightedVertices(BrushTarget target, BrushSettings settings, BrushTool tool = BrushTool.None, BrushMode bMode = null)
        {
            //null checks
            if (target == null || settings == null)
            {
                return;
            }

            if (target.editableObject == null)
            {
                return;
            }

            bool  uniformScale = PolyMath.VectorIsUniform(target.transform.lossyScale);
            float scale        = uniformScale ? 1f / target.transform.lossyScale.x : 1f;

            PolyMesh mesh = target.editableObject.visualMesh;

            if (tool == BrushTool.Texture && mesh.subMeshCount > 1)
            {
                var   mode           = bMode as BrushModeTexture;
                int[] submeshIndices = mesh.subMeshes[mode.currentMeshACIndex].indexes;

                //List<List<int>> common = PolyMeshUtility.GetCommonVertices(mesh);

                Transform transform   = target.transform;
                int       vertexCount = mesh.vertexCount;
                Vector3[] vertices    = mesh.vertices;

                if (!uniformScale)
                {
                    Vector3[] world = new Vector3[vertexCount];
                    for (int i = 0; i < vertexCount; i++)
                    {
                        world[i] = transform.TransformPoint(vertices[i]);
                    }
                    vertices = world;
                }

                AnimationCurve curve = settings.falloffCurve;
                float          radius = settings.radius * scale, falloff_mag = Mathf.Max((radius - radius * settings.falloff), 0.00001f);

                Vector3        hitPosition = Vector3.zero;
                PolyRaycastHit hit;

                for (int n = 0; n < target.raycastHits.Count; n++)
                {
                    hit = target.raycastHits[n];
                    hit.SetVertexCount(vertexCount);

                    for (int i = 0; i < vertexCount; i++)
                    {
                        hit.weights[i] = 0f;
                    }

                    hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position);

                    for (int i = 0; i < submeshIndices.Length; i++)
                    {
                        int   currentIndex = submeshIndices[i];
                        float dist         = (hitPosition - vertices[currentIndex]).magnitude;
                        float delta        = radius - dist;

                        if (delta >= 0)
                        {
                            float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp(delta / falloff_mag, 0f, 1f)), 0f, 1f);

                            hit.weights[currentIndex] = weight;
                        }
                    }
                }
            }
            else
            {
                List <List <int> > common = PolyMeshUtility.GetCommonVertices(mesh);

                Transform transform   = target.transform;
                int       vertexCount = mesh.vertexCount;
                Vector3[] vertices    = mesh.vertices;

                if (!uniformScale)
                {
                    Vector3[] world = new Vector3[vertexCount];
                    for (int i = 0; i < vertexCount; i++)
                    {
                        world[i] = transform.TransformPoint(vertices[i]);
                    }
                    vertices = world;
                }

                AnimationCurve curve = settings.falloffCurve;
                float          radius = settings.radius * scale, falloff_mag = Mathf.Max((radius - radius * settings.falloff), 0.00001f);

                Vector3        hitPosition = Vector3.zero;
                PolyRaycastHit hit;

                for (int n = 0; n < target.raycastHits.Count; n++)
                {
                    hit = target.raycastHits[n];
                    hit.SetVertexCount(vertexCount);

                    hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position);

                    for (int i = 0; i < common.Count; i++)
                    {
                        int   commonArrayCount = common[i].Count;
                        float sqrDist          = (hitPosition - vertices[common[i][0]]).sqrMagnitude;

                        if (sqrDist > radius * radius)
                        {
                            for (int j = 0; j < commonArrayCount; j++)
                            {
                                hit.weights[common[i][j]] = 0f;
                            }
                        }
                        else
                        {
                            float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp((radius - Mathf.Sqrt(sqrDist)) / falloff_mag, 0f, 1f)), 0f, 1f);

                            for (int j = 0; j < commonArrayCount; j++)
                            {
                                hit.weights[common[i][j]] = weight;
                            }
                        }
                    }
                }
            }
            target.GetAllWeights(true);
        }