Beispiel #1
0
        /// <summary>
        /// Initialize UMA mesh data from Unity mesh.
        /// </summary>
        /// <param name="sharedMesh">Source mesh.</param>
        public void RetrieveDataFromUnityMesh(Mesh sharedMesh)
        {
            bindPoses    = sharedMesh.bindposes;
            boneWeights  = UMABoneWeight.Convert(sharedMesh.boneWeights);
            vertices     = sharedMesh.vertices;
            vertexCount  = vertices.Length;
            normals      = sharedMesh.normals;
            tangents     = sharedMesh.tangents;
            colors32     = sharedMesh.colors32;
            uv           = sharedMesh.uv;
            uv2          = sharedMesh.uv2;
            uv3          = sharedMesh.uv3;
            uv4          = sharedMesh.uv4;
            subMeshCount = sharedMesh.subMeshCount;
            submeshes    = new SubMeshTriangles[subMeshCount];
            for (int i = 0; i < subMeshCount; i++)
            {
                submeshes[i].triangles = sharedMesh.GetTriangles(i);
            }

            //Create the blendshape data on the slot asset from the unity mesh
            #region Blendshape
            blendShapes = new UMABlendShape[sharedMesh.blendShapeCount];
            for (int shapeIndex = 0; shapeIndex < sharedMesh.blendShapeCount; shapeIndex++)
            {
                blendShapes [shapeIndex]           = new UMABlendShape();
                blendShapes [shapeIndex].shapeName = sharedMesh.GetBlendShapeName(shapeIndex);

                int frameCount = sharedMesh.GetBlendShapeFrameCount(shapeIndex);
                blendShapes [shapeIndex].frames = new UMABlendFrame[frameCount];

                for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                {
                    blendShapes [shapeIndex].frames [frameIndex]           = new UMABlendFrame(sharedMesh.vertexCount);
                    blendShapes[shapeIndex].frames[frameIndex].frameWeight = sharedMesh.GetBlendShapeFrameWeight(shapeIndex, frameIndex);
                    sharedMesh.GetBlendShapeFrameVertices(shapeIndex, frameIndex,
                                                          blendShapes [shapeIndex].frames [frameIndex].deltaVertices,
                                                          blendShapes [shapeIndex].frames [frameIndex].deltaNormals,
                                                          blendShapes [shapeIndex].frames [frameIndex].deltaTangents);
                }
            }
            #endregion
        }
Beispiel #2
0
        private static void InitializeBlendShapeData(ref int vertexCount, Dictionary <string, BlendShapeVertexData> blendShapeNames, UMABlendShape[] blendShapes)
        {
            int blendShapeIndex = 0;

            foreach (string shapeName in blendShapeNames.Keys)
            {
                blendShapeNames[shapeName].index       = blendShapeIndex;
                blendShapes[blendShapeIndex]           = new UMABlendShape();
                blendShapes[blendShapeIndex].shapeName = shapeName;
                blendShapes[blendShapeIndex].frames    = new UMABlendFrame[blendShapeNames[shapeName].frameCount];

                for (int frameIndex = 0; frameIndex < blendShapes[blendShapeIndex].frames.Length; frameIndex++)
                {
                    blendShapes[blendShapeIndex].frames[frameIndex]             = new UMABlendFrame(vertexCount, blendShapeNames[shapeName].hasNormals, blendShapeNames[shapeName].hasTangents);
                    blendShapes[blendShapeIndex].frames[frameIndex].frameWeight = blendShapeNames[shapeName].frameWeights[frameIndex];
                }

                blendShapeIndex++;
            }
        }
Beispiel #3
0
        /// <summary>
        /// Initialize UMA mesh data from Unity mesh.
        /// </summary>
        /// <param name="sharedMesh">Source mesh.</param>
        public void RetrieveDataFromUnityMesh(Mesh sharedMesh)
        {
            bindPoses    = sharedMesh.bindposes;
            boneWeights  = UMABoneWeight.Convert(sharedMesh.boneWeights);
            vertices     = sharedMesh.vertices;
            vertexCount  = vertices.Length;
            normals      = sharedMesh.normals;
            tangents     = sharedMesh.tangents;
            colors32     = sharedMesh.colors32;
            uv           = sharedMesh.uv;
            uv2          = sharedMesh.uv2;
            uv3          = sharedMesh.uv3;
            uv4          = sharedMesh.uv4;
            subMeshCount = sharedMesh.subMeshCount;
            submeshes    = new SubMeshTriangles[subMeshCount];
            for (int i = 0; i < subMeshCount; i++)
            {
                submeshes[i].triangles = sharedMesh.GetTriangles(i);
            }

            //Create the blendshape data on the slot asset from the unity mesh
            #region Blendshape
            blendShapes = new UMABlendShape[sharedMesh.blendShapeCount];

            Vector3[] deltaVertices;
            Vector3[] deltaNormals;
            Vector3[] deltaTangents;

            for (int shapeIndex = 0; shapeIndex < sharedMesh.blendShapeCount; shapeIndex++)
            {
                blendShapes [shapeIndex]           = new UMABlendShape();
                blendShapes [shapeIndex].shapeName = sharedMesh.GetBlendShapeName(shapeIndex);

                int frameCount = sharedMesh.GetBlendShapeFrameCount(shapeIndex);
                blendShapes [shapeIndex].frames = new UMABlendFrame[frameCount];

                for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                {
                    deltaVertices = new Vector3[sharedMesh.vertexCount];
                    deltaNormals  = new Vector3[sharedMesh.vertexCount];
                    deltaTangents = new Vector3[sharedMesh.vertexCount];

                    bool hasNormals  = false;
                    bool hasTangents = false;

                    //Get the delta arrays first so we can determine if we don't need the delta normals or the delta tangents.
                    sharedMesh.GetBlendShapeFrameVertices(shapeIndex, frameIndex, deltaVertices, deltaNormals, deltaTangents);

                    if (!UMABlendFrame.isAllZero(deltaNormals))
                    {
                        hasNormals = true;
                    }

                    if (!UMABlendFrame.isAllZero(deltaTangents))
                    {
                        hasTangents = true;
                    }

                    blendShapes [shapeIndex].frames [frameIndex]           = new UMABlendFrame();
                    blendShapes[shapeIndex].frames[frameIndex].frameWeight = sharedMesh.GetBlendShapeFrameWeight(shapeIndex, frameIndex);

                    blendShapes[shapeIndex].frames[frameIndex].deltaVertices = deltaVertices;
                    if (hasNormals)
                    {
                        blendShapes[shapeIndex].frames[frameIndex].deltaNormals = deltaNormals;
                    }
                    if (hasTangents)
                    {
                        blendShapes[shapeIndex].frames[frameIndex].deltaTangents = deltaTangents;
                    }
                }
            }
            #endregion
        }
        /// <summary>
        /// Combines a set of meshes into the target mesh.
        /// </summary>
        /// <param name="target">Target.</param>
        /// <param name="sources">Sources.</param>
        public static void CombineMeshes(UMAMeshData target, CombineInstance[] sources, bool ignoreBlendShapes = false)
        {
            int vertexCount             = 0;
            int bindPoseCount           = 0;
            int transformHierarchyCount = 0;
            int blendShapeCount         = 0;

            MeshComponents meshComponents        = MeshComponents.none;
            int            subMeshCount          = FindTargetSubMeshCount(sources);
            var            subMeshTriangleLength = new int[subMeshCount];

            AnalyzeSources(sources, subMeshTriangleLength, ref vertexCount, ref bindPoseCount, ref transformHierarchyCount, ref meshComponents, ref blendShapeCount);

            int[][] submeshTriangles = new int[subMeshCount][];
            for (int i = 0; i < subMeshTriangleLength.Length; i++)
            {
                submeshTriangles[i]      = new int[subMeshTriangleLength[i]];
                subMeshTriangleLength[i] = 0;
            }

            bool has_normals     = (meshComponents & MeshComponents.has_normals) != MeshComponents.none;
            bool has_tangents    = (meshComponents & MeshComponents.has_tangents) != MeshComponents.none;
            bool has_uv          = (meshComponents & MeshComponents.has_uv) != MeshComponents.none;
            bool has_uv2         = (meshComponents & MeshComponents.has_uv2) != MeshComponents.none;
            bool has_uv3         = (meshComponents & MeshComponents.has_uv3) != MeshComponents.none;
            bool has_uv4         = (meshComponents & MeshComponents.has_uv4) != MeshComponents.none;
            bool has_colors32    = (meshComponents & MeshComponents.has_colors32) != MeshComponents.none;
            bool has_blendShapes = (meshComponents & MeshComponents.has_blendShapes) != MeshComponents.none;

            if (ignoreBlendShapes)
            {
                has_blendShapes = false;
            }

            Vector3[]    vertices    = EnsureArrayLength(target.vertices, vertexCount);
            BoneWeight[] boneWeights = EnsureArrayLength(target.unityBoneWeights, vertexCount);
            Vector3[]    normals     = has_normals ? EnsureArrayLength(target.normals, vertexCount) : null;
            Vector4[]    tangents    = has_tangents ? EnsureArrayLength(target.tangents, vertexCount) : null;
            Vector2[]    uv          = has_uv ? EnsureArrayLength(target.uv, vertexCount) : null;
            Vector2[]    uv2         = has_uv2 ? EnsureArrayLength(target.uv2, vertexCount) : null;
            Vector2[]    uv3         = has_uv3 ? EnsureArrayLength(target.uv3, vertexCount) : null;
            Vector2[]    uv4         = has_uv4 ? EnsureArrayLength(target.uv4, vertexCount) : null;
            Color32[]    colors32    = has_colors32 ? EnsureArrayLength(target.colors32, vertexCount) : null;

            UMABlendShape[] blendShapes = has_blendShapes ? new UMABlendShape[blendShapeCount] : null;

            UMATransform[] umaTransforms = EnsureArrayLength(target.umaBones, transformHierarchyCount);

            int boneCount = 0;

            foreach (var source in sources)
            {
                MergeSortedTransforms(umaTransforms, ref boneCount, source.meshData.umaBones);
            }
            int vertexIndex = 0;

            if (bonesCollection == null)
            {
                bonesCollection = new Dictionary <int, BoneIndexEntry>(boneCount);
            }
            else
            {
                bonesCollection.Clear();
            }
            if (bindPoses == null)
            {
                bindPoses = new List <Matrix4x4>(bindPoseCount);
            }
            else
            {
                bindPoses.Clear();
            }
            if (bonesList == null)
            {
                bonesList = new List <int>(boneCount);
            }
            else
            {
                bonesList.Clear();
            }

            int blendShapeIndex = 0;

            foreach (var source in sources)
            {
                vertexCount = source.meshData.vertices.Length;
                BuildBoneWeights(source.meshData.boneWeights, 0, boneWeights, vertexIndex, vertexCount, source.meshData.boneNameHashes, source.meshData.bindPoses, bonesCollection, bindPoses, bonesList);

                Array.Copy(source.meshData.vertices, 0, vertices, vertexIndex, vertexCount);

                if (has_normals)
                {
                    if (source.meshData.normals != null && source.meshData.normals.Length > 0)
                    {
                        Array.Copy(source.meshData.normals, 0, normals, vertexIndex, vertexCount);
                    }
                    else
                    {
                        FillArray(tangents, vertexIndex, vertexCount, Vector3.zero);
                    }
                }
                if (has_tangents)
                {
                    if (source.meshData.tangents != null && source.meshData.tangents.Length > 0)
                    {
                        Array.Copy(source.meshData.tangents, 0, tangents, vertexIndex, vertexCount);
                    }
                    else
                    {
                        FillArray(tangents, vertexIndex, vertexCount, Vector4.zero);
                    }
                }
                if (has_uv)
                {
                    if (source.meshData.uv != null && source.meshData.uv.Length >= vertexCount)
                    {
                        Array.Copy(source.meshData.uv, 0, uv, vertexIndex, vertexCount);
                    }
                    else
                    {
                        FillArray(uv, vertexIndex, vertexCount, Vector4.zero);
                    }
                }
                if (has_uv2)
                {
                    if (source.meshData.uv2 != null && source.meshData.uv2.Length >= vertexCount)
                    {
                        Array.Copy(source.meshData.uv2, 0, uv2, vertexIndex, vertexCount);
                    }
                    else
                    {
                        FillArray(uv2, vertexIndex, vertexCount, Vector4.zero);
                    }
                }
                if (has_uv3)
                {
                    if (source.meshData.uv3 != null && source.meshData.uv3.Length >= vertexCount)
                    {
                        Array.Copy(source.meshData.uv3, 0, uv3, vertexIndex, vertexCount);
                    }
                    else
                    {
                        FillArray(uv3, vertexIndex, vertexCount, Vector4.zero);
                    }
                }
                if (has_uv4)
                {
                    if (source.meshData.uv4 != null && source.meshData.uv4.Length >= vertexCount)
                    {
                        Array.Copy(source.meshData.uv4, 0, uv4, vertexIndex, vertexCount);
                    }
                    else
                    {
                        FillArray(uv4, vertexIndex, vertexCount, Vector4.zero);
                    }
                }

                if (has_colors32)
                {
                    if (source.meshData.colors32 != null && source.meshData.colors32.Length > 0)
                    {
                        Array.Copy(source.meshData.colors32, 0, colors32, vertexIndex, vertexCount);
                    }
                    else
                    {
                        Color32 white32 = Color.white;
                        FillArray(colors32, vertexIndex, vertexCount, white32);
                    }
                }

                if (has_blendShapes)
                {
                    if (source.meshData.blendShapes != null && source.meshData.blendShapes.Length > 0)
                    {
                        for (int shapeIndex = 0; shapeIndex < source.meshData.blendShapes.Length; shapeIndex++)
                        {
                            bool nameAlreadyExists = false;
                            int  i = 0;
                            //Probably this would be better with a dictionary
                            for (i = 0; i < blendShapeIndex; i++)
                            {
                                if (blendShapes [i].shapeName == source.meshData.blendShapes [shapeIndex].shapeName)
                                {
                                    nameAlreadyExists = true;
                                    break;
                                }
                            }

                            if (nameAlreadyExists)                            //Lets add the vertices data to the existing blendShape
                            {
                                if (blendShapes [i].frames.Length != source.meshData.blendShapes [shapeIndex].frames.Length)
                                {
                                    Debug.LogError("SkinnedMeshCombiner: mesh blendShape frame counts don't match!");
                                    break;
                                }
                                for (int frameIndex = 0; frameIndex < source.meshData.blendShapes [shapeIndex].frames.Length; frameIndex++)
                                {
                                    Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaVertices, 0, blendShapes [i].frames [frameIndex].deltaVertices, vertexIndex, vertexCount);
                                    Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaNormals, 0, blendShapes [i].frames [frameIndex].deltaNormals, vertexIndex, vertexCount);
                                    Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaTangents, 0, blendShapes [i].frames [frameIndex].deltaTangents, vertexIndex, vertexCount);
                                }
                            }
                            else
                            {
                                blendShapes [blendShapeIndex]           = new UMABlendShape();
                                blendShapes [blendShapeIndex].shapeName = source.meshData.blendShapes [shapeIndex].shapeName;
                                blendShapes [blendShapeIndex].frames    = new UMABlendFrame[source.meshData.blendShapes [shapeIndex].frames.Length];

                                for (int frameIndex = 0; frameIndex < source.meshData.blendShapes [shapeIndex].frames.Length; frameIndex++)
                                {
                                    blendShapes [blendShapeIndex].frames [frameIndex]             = new UMABlendFrame(vertices.Length);
                                    blendShapes [blendShapeIndex].frames [frameIndex].frameWeight = source.meshData.blendShapes [shapeIndex].frames [frameIndex].frameWeight;
                                    Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaVertices, 0, blendShapes [blendShapeIndex].frames [frameIndex].deltaVertices, vertexIndex, vertexCount);
                                    Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaNormals, 0, blendShapes [blendShapeIndex].frames [frameIndex].deltaNormals, vertexIndex, vertexCount);
                                    Array.Copy(source.meshData.blendShapes [shapeIndex].frames [frameIndex].deltaTangents, 0, blendShapes [blendShapeIndex].frames [frameIndex].deltaTangents, vertexIndex, vertexCount);
                                }
                                blendShapeIndex++;
                            }
                        }
                    }
                }

                for (int i = 0; i < source.meshData.subMeshCount; i++)
                {
                    if (source.targetSubmeshIndices[i] >= 0)
                    {
                        int[] subTriangles   = source.meshData.submeshes[i].triangles;
                        int   triangleLength = subTriangles.Length;
                        int   destMesh       = source.targetSubmeshIndices[i];

                        CopyIntArrayAdd(subTriangles, 0, submeshTriangles[destMesh], subMeshTriangleLength[destMesh], triangleLength, vertexIndex);
                        subMeshTriangleLength[destMesh] += triangleLength;
                    }
                }

                vertexIndex += vertexCount;
            }
            vertexCount = vertexIndex;

            // fill in new values.
            target.vertexCount      = vertexCount;
            target.vertices         = vertices;
            target.unityBoneWeights = boneWeights;
            target.bindPoses        = bindPoses.ToArray();
            target.normals          = normals;
            target.tangents         = tangents;
            target.uv       = uv;
            target.uv2      = uv2;
            target.uv3      = uv3;
            target.uv4      = uv4;
            target.colors32 = colors32;

            if (has_blendShapes)
            {
                target.blendShapes = blendShapes;
            }

            target.subMeshCount = subMeshCount;
            target.submeshes    = new SubMeshTriangles[subMeshCount];
            target.umaBones     = umaTransforms;
            target.umaBoneCount = boneCount;
            for (int i = 0; i < subMeshCount; i++)
            {
                target.submeshes[i].triangles = submeshTriangles[i];
            }
            target.boneNameHashes = bonesList.ToArray();
        }
Beispiel #5
0
        /// <summary>
        /// Combines a set of meshes into the target mesh.
        /// </summary>
        /// <param name="target">Target.</param>
        /// <param name="sources">Sources.</param>
        /// <param name="blendShapeSettings">BlendShape Settings.</param>
        public static void CombineMeshes(UMAMeshData target, CombineInstance[] sources, UMAData.BlendShapeSettings blendShapeSettings = null)
        {
            if (blendShapeSettings == null)
            {
                blendShapeSettings = new UMAData.BlendShapeSettings();
            }

            int vertexCount             = 0;
            int bindPoseCount           = 0;
            int transformHierarchyCount = 0;
            int blendShapeCount         = 0;

            MeshComponents meshComponents        = MeshComponents.none;
            int            subMeshCount          = FindTargetSubMeshCount(sources);
            var            subMeshTriangleLength = new int[subMeshCount];

            AnalyzeSources(sources, subMeshTriangleLength, ref vertexCount, ref bindPoseCount, ref transformHierarchyCount, ref meshComponents, ref blendShapeCount);

            int[][] submeshTriangles = new int[subMeshCount][];
            for (int i = 0; i < subMeshTriangleLength.Length; i++)
            {
                submeshTriangles[i]      = target.GetSubmeshBuffer(subMeshTriangleLength[i], i);
                subMeshTriangleLength[i] = 0;
            }

            bool has_normals     = (meshComponents & MeshComponents.has_normals) != MeshComponents.none;
            bool has_tangents    = (meshComponents & MeshComponents.has_tangents) != MeshComponents.none;
            bool has_uv          = (meshComponents & MeshComponents.has_uv) != MeshComponents.none;
            bool has_uv2         = (meshComponents & MeshComponents.has_uv2) != MeshComponents.none;
            bool has_uv3         = (meshComponents & MeshComponents.has_uv3) != MeshComponents.none;
            bool has_uv4         = (meshComponents & MeshComponents.has_uv4) != MeshComponents.none;
            bool has_colors32    = (meshComponents & MeshComponents.has_colors32) != MeshComponents.none;
            bool has_blendShapes = (meshComponents & MeshComponents.has_blendShapes) != MeshComponents.none;

            if (blendShapeSettings.ignoreBlendShapes)
            {
                has_blendShapes = false;
            }
            bool has_clothSkinning = (meshComponents & MeshComponents.has_clothSkinning) != MeshComponents.none;

            Vector3[]                  vertices           = EnsureArrayLength(target.vertices, vertexCount);
            BoneWeight[]               boneWeights        = EnsureArrayLength(target.unityBoneWeights, vertexCount);
            Vector3[]                  normals            = has_normals ? EnsureArrayLength(target.normals, vertexCount) : null;
            Vector4[]                  tangents           = has_tangents ? EnsureArrayLength(target.tangents, vertexCount) : null;
            Vector2[]                  uv                 = has_uv ? EnsureArrayLength(target.uv, vertexCount) : null;
            Vector2[]                  uv2                = has_uv2 ? EnsureArrayLength(target.uv2, vertexCount) : null;
            Vector2[]                  uv3                = has_uv3 ? EnsureArrayLength(target.uv3, vertexCount) : null;
            Vector2[]                  uv4                = has_uv4 ? EnsureArrayLength(target.uv4, vertexCount) : null;
            Color32[]                  colors32           = has_colors32 ? EnsureArrayLength(target.colors32, vertexCount) : null;
            UMABlendShape[]            blendShapes        = has_blendShapes ? new UMABlendShape[blendShapeCount] : null;
            UMATransform[]             umaTransforms      = EnsureArrayLength(target.umaBones, transformHierarchyCount);
            ClothSkinningCoefficient[] clothSkinning      = has_clothSkinning ? EnsureArrayLength(target.clothSkinning, vertexCount) : null;
            Dictionary <Vector3, int>  clothVertices      = has_clothSkinning ? new Dictionary <Vector3, int>(vertexCount) : null;
            Dictionary <Vector3, int>  localClothVertices = has_clothSkinning ? new Dictionary <Vector3, int>(vertexCount) : null;

            int boneCount = 0;

            foreach (var source in sources)
            {
                MergeSortedTransforms(umaTransforms, ref boneCount, source.meshData.umaBones);
            }
            int vertexIndex = 0;

            if (bonesCollection == null)
            {
                bonesCollection = new Dictionary <int, BoneIndexEntry>(boneCount);
            }
            else
            {
                bonesCollection.Clear();
            }
            if (bindPoses == null)
            {
                bindPoses = new List <Matrix4x4>(bindPoseCount);
            }
            else
            {
                bindPoses.Clear();
            }
            if (bonesList == null)
            {
                bonesList = new List <int>(boneCount);
            }
            else
            {
                bonesList.Clear();
            }

            int blendShapeIndex = 0;

            foreach (var source in sources)
            {
                int sourceVertexCount = source.meshData.vertices.Length;
                BuildBoneWeights(source.meshData.boneWeights, 0, boneWeights, vertexIndex, sourceVertexCount, source.meshData.boneNameHashes, source.meshData.bindPoses, bonesCollection, bindPoses, bonesList);

                Array.Copy(source.meshData.vertices, 0, vertices, vertexIndex, sourceVertexCount);

                if (has_normals)
                {
                    if (source.meshData.normals != null && source.meshData.normals.Length > 0)
                    {
                        Array.Copy(source.meshData.normals, 0, normals, vertexIndex, sourceVertexCount);
                    }
                    else
                    {
                        FillArray(tangents, vertexIndex, sourceVertexCount, Vector3.zero);
                    }
                }
                if (has_tangents)
                {
                    if (source.meshData.tangents != null && source.meshData.tangents.Length > 0)
                    {
                        Array.Copy(source.meshData.tangents, 0, tangents, vertexIndex, sourceVertexCount);
                    }
                    else
                    {
                        FillArray(tangents, vertexIndex, sourceVertexCount, Vector4.zero);
                    }
                }
                if (has_uv)
                {
                    if (source.meshData.uv != null && source.meshData.uv.Length >= sourceVertexCount)
                    {
                        Array.Copy(source.meshData.uv, 0, uv, vertexIndex, sourceVertexCount);
                    }
                    else
                    {
                        FillArray(uv, vertexIndex, sourceVertexCount, Vector4.zero);
                    }
                }
                if (has_uv2)
                {
                    if (source.meshData.uv2 != null && source.meshData.uv2.Length >= sourceVertexCount)
                    {
                        Array.Copy(source.meshData.uv2, 0, uv2, vertexIndex, sourceVertexCount);
                    }
                    else
                    {
                        FillArray(uv2, vertexIndex, sourceVertexCount, Vector4.zero);
                    }
                }
                if (has_uv3)
                {
                    if (source.meshData.uv3 != null && source.meshData.uv3.Length >= sourceVertexCount)
                    {
                        Array.Copy(source.meshData.uv3, 0, uv3, vertexIndex, sourceVertexCount);
                    }
                    else
                    {
                        FillArray(uv3, vertexIndex, sourceVertexCount, Vector4.zero);
                    }
                }
                if (has_uv4)
                {
                    if (source.meshData.uv4 != null && source.meshData.uv4.Length >= sourceVertexCount)
                    {
                        Array.Copy(source.meshData.uv4, 0, uv4, vertexIndex, sourceVertexCount);
                    }
                    else
                    {
                        FillArray(uv4, vertexIndex, sourceVertexCount, Vector4.zero);
                    }
                }

                if (has_colors32)
                {
                    if (source.meshData.colors32 != null && source.meshData.colors32.Length > 0)
                    {
                        Array.Copy(source.meshData.colors32, 0, colors32, vertexIndex, sourceVertexCount);
                    }
                    else
                    {
                        Color32 white32 = Color.white;
                        FillArray(colors32, vertexIndex, sourceVertexCount, white32);
                    }
                }

                if (has_blendShapes)
                {
                    if (source.meshData.blendShapes != null && source.meshData.blendShapes.Length > 0)
                    {
                        for (int shapeIndex = 0; shapeIndex < source.meshData.blendShapes.Length; shapeIndex++)
                        {
                            #region BlendShape Baking
                            if (blendShapeSettings.bakeBlendShapes != null && blendShapeSettings.bakeBlendShapes.Count > 0)
                            {
                                // If there are names in the bakeBlendShape dictionary and we find them in the meshData blendshape list, then lets bake them instead of adding them.
                                UMABlendShape currentShape = source.meshData.blendShapes[shapeIndex];

                                if (blendShapeSettings.bakeBlendShapes.ContainsKey(currentShape.shapeName))
                                {
                                    float weight = blendShapeSettings.bakeBlendShapes[currentShape.shapeName] * 100.0f;
                                    if (weight <= 0f)
                                    {
                                        continue;                                                   // Baking in nothing, so skip it entirely
                                    }
                                    // Let's find the frame this weight is in
                                    int frameIndex;
                                    int prevIndex;
                                    for (frameIndex = 0; frameIndex < currentShape.frames.Length; frameIndex++)
                                    {
                                        if (currentShape.frames[frameIndex].frameWeight >= weight)
                                        {
                                            break;
                                        }
                                    }

                                    // Let's calculate the weight for the frame we're in
                                    float frameWeight = 1f;
                                    float prevWeight  = 0f;
                                    bool  doLerp      = false;
                                    // Weight is higher than the last frame, shape is over 100%
                                    if (frameIndex >= currentShape.frames.Length)
                                    {
                                        frameIndex  = currentShape.frames.Length - 1;
                                        frameWeight = (weight / currentShape.frames[frameIndex].frameWeight);
                                    }
                                    else if (frameIndex > 0)
                                    {
                                        doLerp      = true;
                                        prevWeight  = currentShape.frames[frameIndex - 1].frameWeight;
                                        frameWeight = ((weight - prevWeight) / (currentShape.frames[frameIndex].frameWeight - prevWeight));
                                        prevWeight  = 1f - frameWeight;
                                    }
                                    else
                                    {
                                        frameWeight = (weight / currentShape.frames[frameIndex].frameWeight);
                                    }
                                    prevIndex = frameIndex - 1;

                                    // The blend shape frames lerp between the deltas of two adjacent frames.
                                    int vertIndex = vertexIndex;
                                    for (int bakeIndex = 0; bakeIndex < currentShape.frames[frameIndex].deltaVertices.Length; bakeIndex++, vertIndex++)
                                    {
                                        // Add the current frame's deltas
                                        vertices[vertIndex] += currentShape.frames[frameIndex].deltaVertices[bakeIndex] * frameWeight;
                                        // Add in the previous frame's deltas
                                        if (doLerp)
                                        {
                                            vertices[vertIndex] += currentShape.frames[prevIndex].deltaVertices[bakeIndex] * prevWeight;
                                        }
                                    }

                                    if (has_normals)
                                    {
                                        vertIndex = vertexIndex;
                                        for (int bakeIndex = 0; bakeIndex < currentShape.frames[frameIndex].deltaNormals.Length; bakeIndex++, vertIndex++)
                                        {
                                            normals[vertIndex] += currentShape.frames[frameIndex].deltaNormals[bakeIndex] * frameWeight;
                                            if (doLerp)
                                            {
                                                normals[vertIndex] += currentShape.frames[prevIndex].deltaNormals[bakeIndex] * prevWeight;
                                            }
                                        }
                                    }

                                    if (has_tangents)
                                    {
                                        vertIndex = vertexIndex;
                                        for (int bakeIndex = 0; bakeIndex < currentShape.frames[frameIndex].deltaTangents.Length; bakeIndex++, vertIndex++)
                                        {
                                            tangents[vertIndex] += (Vector4)currentShape.frames[frameIndex].deltaTangents[bakeIndex] * frameWeight;
                                            if (doLerp)
                                            {
                                                tangents[vertIndex] += (Vector4)currentShape.frames[prevIndex].deltaTangents[bakeIndex] * prevWeight;
                                            }
                                        }
                                    }
                                    continue; // If we bake then don't perform the rest of this interation of the loop.
                                }
                            }
                            #endregion

                            bool nameAlreadyExists = false;
                            int  i = 0;
                            //Probably this would be better with a dictionary
                            for (i = 0; i < blendShapeIndex; i++)
                            {
                                if (blendShapes[i].shapeName == source.meshData.blendShapes[shapeIndex].shapeName)
                                {
                                    nameAlreadyExists = true;
                                    break;
                                }
                            }

                            if (nameAlreadyExists)                            //Lets add the vertices data to the existing blendShape
                            {
                                if (blendShapes[i].frames.Length != source.meshData.blendShapes[shapeIndex].frames.Length)
                                {
                                    Debug.LogError("SkinnedMeshCombiner: mesh blendShape frame counts don't match!");
                                    break;
                                }
                                for (int frameIndex = 0; frameIndex < source.meshData.blendShapes[shapeIndex].frames.Length; frameIndex++)
                                {
                                    Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaVertices, 0, blendShapes[i].frames[frameIndex].deltaVertices, vertexIndex, sourceVertexCount);
                                    Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaNormals, 0, blendShapes[i].frames[frameIndex].deltaNormals, vertexIndex, sourceVertexCount);
                                    Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaTangents, 0, blendShapes[i].frames[frameIndex].deltaTangents, vertexIndex, sourceVertexCount);
                                }
                            }
                            else
                            {
                                blendShapes[blendShapeIndex]           = new UMABlendShape();
                                blendShapes[blendShapeIndex].shapeName = source.meshData.blendShapes[shapeIndex].shapeName;
                                blendShapes[blendShapeIndex].frames    = new UMABlendFrame[source.meshData.blendShapes[shapeIndex].frames.Length];

                                for (int frameIndex = 0; frameIndex < source.meshData.blendShapes[shapeIndex].frames.Length; frameIndex++)
                                {
                                    blendShapes[blendShapeIndex].frames[frameIndex]             = new UMABlendFrame(vertexCount);
                                    blendShapes[blendShapeIndex].frames[frameIndex].frameWeight = source.meshData.blendShapes[shapeIndex].frames[frameIndex].frameWeight;
                                    Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaVertices, 0, blendShapes[blendShapeIndex].frames[frameIndex].deltaVertices, vertexIndex, sourceVertexCount);
                                    Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaNormals, 0, blendShapes[blendShapeIndex].frames[frameIndex].deltaNormals, vertexIndex, sourceVertexCount);
                                    Array.Copy(source.meshData.blendShapes[shapeIndex].frames[frameIndex].deltaTangents, 0, blendShapes[blendShapeIndex].frames[frameIndex].deltaTangents, vertexIndex, sourceVertexCount);
                                }
                                blendShapeIndex++;
                            }
                        }
                    }
                }
                if (has_clothSkinning)
                {
                    localClothVertices.Clear();
                    if (source.meshData.clothSkinningSerialized != null && source.meshData.clothSkinningSerialized.Length > 0)
                    {
                        for (int i = 0; i < source.meshData.vertexCount; i++)
                        {
                            var vertice = source.meshData.vertices[i];
                            if (!localClothVertices.ContainsKey(vertice))
                            {
                                int localCount = localClothVertices.Count;
                                localClothVertices.Add(vertice, localCount);
                                if (!clothVertices.ContainsKey(vertice))
                                {
                                    ConvertData(ref source.meshData.clothSkinningSerialized[localCount], ref clothSkinning[clothVertices.Count]);
                                    clothVertices.Add(vertice, clothVertices.Count);
                                }
                                else
                                {
                                    ConvertData(ref source.meshData.clothSkinningSerialized[localCount], ref clothSkinning[clothVertices[vertice]]);
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < source.meshData.vertexCount; i++)
                        {
                            var vertice = source.meshData.vertices[i];
                            if (!clothVertices.ContainsKey(vertice))
                            {
                                clothSkinning[clothVertices.Count].maxDistance             = 0;
                                clothSkinning[clothVertices.Count].collisionSphereDistance = float.MaxValue;
                                clothVertices.Add(vertice, clothVertices.Count);
                                localClothVertices.Add(vertice, clothVertices.Count);
                            }
                        }
                    }
                }

                for (int i = 0; i < source.meshData.subMeshCount; i++)
                {
                    if (source.targetSubmeshIndices[i] >= 0)
                    {
                        int[] subTriangles   = source.meshData.submeshes[i].triangles;
                        int   triangleLength = subTriangles.Length;
                        int   destMesh       = source.targetSubmeshIndices[i];

                        if (source.triangleMask == null)
                        {
                            CopyIntArrayAdd(subTriangles, 0, submeshTriangles[destMesh], subMeshTriangleLength[destMesh], triangleLength, vertexIndex);
                            subMeshTriangleLength[destMesh] += triangleLength;
                        }
                        else
                        {
                            MaskedCopyIntArrayAdd(subTriangles, 0, submeshTriangles[destMesh], subMeshTriangleLength[destMesh], triangleLength, vertexIndex, source.triangleMask[i]);
                            subMeshTriangleLength[destMesh] += (triangleLength - (UMAUtils.GetCardinality(source.triangleMask[i]) * 3));
                        }
                    }
                }

                vertexIndex += sourceVertexCount;
            }

            if (vertexCount != vertexIndex)
            {
                Debug.LogError("Combined vertices size didn't match precomputed value!");
            }

            // fill in new values.
            target.vertexCount      = vertexCount;
            target.vertices         = vertices;
            target.unityBoneWeights = boneWeights;
            target.bindPoses        = bindPoses.ToArray();
            target.normals          = normals;
            target.tangents         = tangents;
            target.uv       = uv;
            target.uv2      = uv2;
            target.uv3      = uv3;
            target.uv4      = uv4;
            target.colors32 = colors32;

            if (has_blendShapes)
            {
                target.blendShapes = blendShapes;
            }

            if (has_clothSkinning)
            {
                Array.Resize(ref clothSkinning, clothVertices.Count);
            }
            target.clothSkinning = clothSkinning;

            target.subMeshCount = subMeshCount;
            target.submeshes    = new SubMeshTriangles[subMeshCount];
            target.umaBones     = umaTransforms;
            target.umaBoneCount = boneCount;
            for (int i = 0; i < subMeshCount; i++)
            {
                target.submeshes[i].triangles = submeshTriangles[i];
            }
            target.boneNameHashes = bonesList.ToArray();
        }
Beispiel #6
0
        public static bool BakeBlendShape(Dictionary <string, BlendShapeData> blendShapes, UMABlendShape currentShape, ref int vertexIndex, Vector3[] vertices, Vector3[] normals, Vector4[] tangents, bool has_Normals, bool has_Tangents)
        {
            //If we can't find this blendshape then it can't have been baked so return false.
            BlendShapeData data;

            if (!blendShapes.TryGetValue(currentShape.shapeName, out data))
            {
                return(false);
            }

            //If we find this blendshape but it is not set to be baked, then return false.
            if (!data.isBaked)
            {
                return(false);
            }

            float weight = blendShapes[currentShape.shapeName].value * 100.0f;

            // Allow < 0 weights.
            // if (weight <= 0f) return true; // Baking in nothing, so skip it entirely
            if (Mathf.Abs(weight) <= Mathf.Epsilon)
            {
                return(true);
            }

            // Let's find the frame this weight is in
            int frameIndex;
            int prevIndex;

            for (frameIndex = 0; frameIndex < currentShape.frames.Length; frameIndex++)
            {
                if (currentShape.frames[frameIndex].frameWeight >= weight)
                {
                    break;
                }
            }

            // Let's calculate the weight for the frame we're in
            float frameWeight = 1f;
            float prevWeight  = 0f;
            bool  doLerp      = false;

            // Weight is higher than the last frame, shape is over 100%
            if (frameIndex >= currentShape.frames.Length)
            {
                frameIndex  = currentShape.frames.Length - 1;
                frameWeight = (weight / currentShape.frames[frameIndex].frameWeight);
            }
            else if (frameIndex > 0)
            {
                doLerp      = true;
                prevWeight  = currentShape.frames[frameIndex - 1].frameWeight;
                frameWeight = ((weight - prevWeight) / (currentShape.frames[frameIndex].frameWeight - prevWeight));
                prevWeight  = 1f - frameWeight;
            }
            else
            {
                frameWeight = (weight / currentShape.frames[frameIndex].frameWeight);
            }
            prevIndex = (frameIndex > 0) ? (frameIndex - 1) : 0;

            // The blend shape frames lerp between the deltas of two adjacent frames.
            Vector3[] currentFrameVertices  = currentShape.frames[frameIndex].deltaVertices;
            Vector3[] previousFrameVertices = currentShape.frames[prevIndex].deltaVertices;

            Vector3[] currentFrameNormals  = null;
            Vector3[] previousFrameNormals = null;

            Vector3[] currentFrameTangents  = null;
            Vector3[] previousFrameTangents = null;

            bool has_deltaNormals = (has_Normals && currentShape.frames[frameIndex].deltaNormals != null && currentShape.frames[frameIndex].deltaNormals.Length > 0);

            if (has_deltaNormals)
            {
                currentFrameNormals  = currentShape.frames[frameIndex].deltaNormals;
                previousFrameNormals = currentShape.frames[prevIndex].deltaNormals;
            }

            bool has_deltaTangents = (has_Tangents && currentShape.frames[frameIndex].deltaTangents != null && currentShape.frames[frameIndex].deltaTangents.Length > 0);

            if (has_deltaTangents)
            {
                currentFrameTangents  = currentShape.frames[frameIndex].deltaTangents;
                previousFrameTangents = currentShape.frames[prevIndex].deltaTangents;
            }

            int vertIndex = vertexIndex;

            for (int bakeIndex = 0; bakeIndex < currentFrameVertices.Length; bakeIndex++, vertIndex++)
            {
                // Add the current frame's deltas
                if (currentFrameVertices[bakeIndex].sqrMagnitude > 0.0000001f)
                {
                    vertices[vertIndex] += currentFrameVertices[bakeIndex] * frameWeight;
                    // Add in the previous frame's deltas
                    if (doLerp)
                    {
                        vertices[vertIndex] += previousFrameVertices[bakeIndex] * prevWeight;
                    }
                }

                if (has_deltaNormals)
                {
                    if (currentFrameNormals[bakeIndex].sqrMagnitude > 0.0000001f)
                    {
                        normals[vertIndex] += currentFrameNormals[bakeIndex] * frameWeight;
                        if (doLerp)
                        {
                            normals[vertIndex] += previousFrameNormals[bakeIndex] * prevWeight;
                        }
                    }
                }

                if (has_deltaTangents)
                {
                    if (currentFrameTangents[bakeIndex].sqrMagnitude > 0.0000001f)
                    {
                        tangents[vertIndex] += (Vector4)currentFrameTangents[bakeIndex] * frameWeight;
                        if (doLerp)
                        {
                            tangents[vertIndex] += (Vector4)previousFrameTangents[bakeIndex] * prevWeight;
                        }
                    }
                }
            }
            return(true);
        }