Beispiel #1
0
        /// <summary>
        /// Releases the static buffers.
        /// </summary>
        public void ReleaseSharedBuffers()
        {
            if (OwnSharedBuffers())
            {
                gVertices.SetActiveSize(0);
                vertices = null;
                gNormals.SetActiveSize(0);
                normals = null;
                gTangents.SetActiveSize(0);
                tangents = null;
                gUV.SetActiveSize(0);
                uv = null;
                gUV2.SetActiveSize(0);
                uv2 = null;
                gUV3.SetActiveSize(0);
                uv3 = null;
                gUV4.SetActiveSize(0);
                uv4 = null;
                gColors32.SetActiveSize(0);
                colors32 = null;

                for (int i = 0; i < gSubmeshTris.Length; i++)
                {
                    gSubmeshTriIndices[i] = UNUSED_SUBMESH;
                    gSubmeshTris[i].SetActiveSize(0);
                }

                boneWeights      = null;
                unityBoneWeights = null;
                bufferLockOwner  = null;
            }
        }
Beispiel #2
0
        public void InitializeFromMeshData(UMAMeshData meshData)
        {
            if (meshData == null)
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogError("InitializeFromMeshData: meshData is null!");
                }

                return;
            }

            _sharedMesh = new Mesh();
#if UMA_32BITBUFFERS
            _sharedMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
#endif
            _sharedMesh.subMeshCount = meshData.subMeshCount;
            _sharedMesh.vertices     = meshData.vertices;
            _sharedMesh.normals      = meshData.normals;
            _sharedMesh.tangents     = meshData.tangents;
            _sharedMesh.uv           = meshData.uv;
            _sharedMesh.uv2          = meshData.uv2;
            _sharedMesh.uv3          = meshData.uv3;
            _sharedMesh.uv4          = meshData.uv4;
            _sharedMesh.colors32     = meshData.colors32;

            for (int i = 0; i < meshData.subMeshCount; i++)
            {
                _sharedMesh.SetTriangles(meshData.submeshes[i].triangles, i);
            }

            Initialize();
        }
        public void UpdateOcclusionMesh(UMAMeshData meshData, float offset, Vector3 pos, Vector3 rot, Vector3 s)
        {
            //Let's call CreateOcclusionMesh to reset it.
            CreateOcclusionMesh(meshData);

            UpdateOcclusionMesh(offset, pos, rot, s);
        }
Beispiel #4
0
        protected void RecalculateUV(UMAMeshData umaMesh)
        {
            int idx = 0;

            //Handle Atlassed Verts
            for (int materialIndex = 0; materialIndex < umaData.generatedMaterials.materials.Count; materialIndex++)
            {
                var generatedMaterial = umaData.generatedMaterials.materials[materialIndex];
                if (generatedMaterial.umaMaterial.materialType != UMAMaterial.MaterialType.Atlas)
                {
                    continue;
                }

                for (int materialDefinitionIndex = 0; materialDefinitionIndex < generatedMaterial.materialFragments.Count; materialDefinitionIndex++)
                {
                    var   fragment      = generatedMaterial.materialFragments[materialDefinitionIndex];
                    var   tempAtlasRect = fragment.atlasRegion;
                    int   vertexCount   = fragment.slotData.asset.meshData.vertices.Length;
                    float atlasXMin     = tempAtlasRect.xMin / atlasResolution;
                    float atlasXMax     = tempAtlasRect.xMax / atlasResolution;
                    float atlasXRange   = atlasXMax - atlasXMin;
                    float atlasYMin     = tempAtlasRect.yMin / atlasResolution;
                    float atlasYMax     = tempAtlasRect.yMax / atlasResolution;
                    float atlasYRange   = atlasYMax - atlasYMin;
                    while (vertexCount-- > 0)
                    {
                        umaMesh.uv[idx].x = atlasXMin + atlasXRange * umaMesh.uv[idx].x;
                        umaMesh.uv[idx].y = atlasYMin + atlasYRange * umaMesh.uv[idx].y;
                        idx++;
                    }
                }
            }
        }
        public void InitializeFromMeshData(UMAMeshData meshData)
        {
            if (meshData == null)
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogError("InitializeFromMeshData: meshData is null!");
                }

                return;
            }

            _sharedMesh = new Mesh();
#if UMA_32BITBUFFERS
            _sharedMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
#endif
            _sharedMesh.subMeshCount = 1; // we're only copying the current submesh
            _sharedMesh.vertices     = meshData.vertices;
            _sharedMesh.normals      = meshData.normals;
            _sharedMesh.tangents     = meshData.tangents;
            _sharedMesh.uv           = meshData.uv;
            _sharedMesh.uv2          = meshData.uv2;
            _sharedMesh.uv3          = meshData.uv3;
            _sharedMesh.uv4          = meshData.uv4;
            _sharedMesh.colors32     = meshData.colors32;

            _sharedMesh.SetTriangles(meshData.submeshes[meshAsset.asset.subMeshIndex].triangles, 0);
            Initialize();
        }
        public void InitializeFromMeshData(UMAMeshData meshData)
        {
            if (meshData == null)
            {
                Debug.LogError("InitializeFromMeshData: meshData is null!");
                return;
            }

            _sharedMesh = new Mesh();
            _sharedMesh.subMeshCount = meshData.subMeshCount;
            _sharedMesh.vertices     = meshData.vertices;
            _sharedMesh.normals      = meshData.normals;
            _sharedMesh.tangents     = meshData.tangents;
            _sharedMesh.uv           = meshData.uv;
            _sharedMesh.uv2          = meshData.uv2;
            _sharedMesh.uv3          = meshData.uv3;
            _sharedMesh.uv4          = meshData.uv4;
            _sharedMesh.colors32     = meshData.colors32;

            for (int i = 0; i < meshData.subMeshCount; i++)
            {
                _sharedMesh.SetTriangles(meshData.submeshes[i].triangles, i);
            }

            Initialize();
        }
Beispiel #7
0
        public void CreateOcclusionMesh(UMAMeshData meshData)
        {
            if (meshData == null)
            {
                return;
            }
            ;

            if (_occlusionMesh == null)
            {
                _occlusionMesh = new Mesh();
            }
            else
            {
                _occlusionMesh.Clear();
            }

            _occlusionMesh.subMeshCount = meshData.subMeshCount;
            _occlusionMesh.vertices     = meshData.vertices;
            _occlusionMesh.normals      = meshData.normals;
            _occlusionMesh.tangents     = meshData.tangents;
            _occlusionMesh.uv           = meshData.uv;
            _occlusionMesh.uv2          = meshData.uv2;
            _occlusionMesh.uv3          = meshData.uv3;
            _occlusionMesh.uv4          = meshData.uv4;
            _occlusionMesh.colors32     = meshData.colors32;

            _occlusionMesh.triangles    = new int[0];
            _occlusionMesh.subMeshCount = meshData.subMeshCount;

            for (int i = 0; i < meshData.subMeshCount; i++)
            {
                occlusionMesh.SetTriangles(meshData.submeshes[i].triangles, i);
            }
        }
Beispiel #8
0
        public void UpdateMeshData(SkinnedMeshRenderer meshRenderer)
        {
            meshData = new UMAMeshData();
            meshData.RetrieveDataFromUnityMesh(meshRenderer);
#if UNITY_EDITOR
            UnityEditor.EditorUtility.SetDirty(this);
#endif
        }
Beispiel #9
0
        public static UMAMeshData ShallowInstanceMesh(UMAMeshData source, BitArray[] triangleMask = null)
        {
            var target = new UMAMeshData();

            target.bindPoses        = source.bindPoses;
            target.boneNameHashes   = source.boneNameHashes;
            target.unityBoneWeights = UMABoneWeight.Convert(source.boneWeights);
            target.colors32         = source.colors32;
            target.normals          = source.normals;
            target.rootBoneHash     = source.rootBoneHash;
            target.subMeshCount     = source.subMeshCount;
            target.tangents         = source.tangents;
            target.umaBoneCount     = source.umaBoneCount;
            target.umaBones         = source.umaBones;
            target.uv          = source.uv;
            target.uv2         = source.uv2;
            target.uv3         = source.uv3;
            target.uv4         = source.uv4;
            target.vertexCount = source.vertexCount;
            target.vertices    = source.vertices;
            target.blendShapes = source.blendShapes;

            if (triangleMask != null)
            {
                target.submeshes = new SubMeshTriangles[source.subMeshCount];

                for (int i = 0; i < source.subMeshCount; i++)
                {
                    int   sourceLength   = source.submeshes[i].triangles.Length;
                    int   triangleLength = sourceLength - (UMAUtils.GetCardinality(triangleMask[i]) * 3);
                    int[] destTriangles  = new int[triangleLength];

                    MaskedCopyIntArrayAdd(source.submeshes[i].triangles, 0, destTriangles, 0, sourceLength, 0, triangleMask[i]);
                    target.submeshes[i].triangles = destTriangles;
                }
            }
            else
            {
                target.submeshes = source.submeshes;
            }

            if (source.clothSkinningSerialized != null && source.clothSkinningSerialized.Length != 0)
            {
                target.clothSkinning = new ClothSkinningCoefficient[source.clothSkinningSerialized.Length];
                for (int i = 0; i < source.clothSkinningSerialized.Length; i++)
                {
                    ConvertData(ref source.clothSkinningSerialized[i], ref target.clothSkinning[i]);
                }
            }
            else
            {
                target.clothSkinning = null;
            }
            return(target);
        }
Beispiel #10
0
 public void Assign(SlotDataAsset source)
 {
     slotName           = source.slotName;
     nameHash           = source.nameHash;
     material           = source.material;
     overlayScale       = source.overlayScale;
     animatedBoneNames  = source.animatedBoneNames;
     animatedBoneHashes = source.animatedBoneHashes;
     meshData           = source.meshData;
     subMeshIndex       = source.subMeshIndex;
     slotGroup          = source.slotGroup;
     tags = source.tags;
 }
        /// <summary>
        /// Updates the UMA mesh and skeleton to match current slots.
        /// </summary>
        /// <param name="updatedAtlas">If set to <c>true</c> atlas has changed.</param>
        /// <param name="umaData">UMA data.</param>
        /// <param name="atlasResolution">Atlas resolution.</param>
        public override void UpdateUMAMesh(bool updatedAtlas, UMAData umaData, int atlasResolution)
        {
            this.umaData         = umaData;
            this.atlasResolution = atlasResolution;

            combinedMeshList     = new List <SkinnedMeshCombiner.CombineInstance>(umaData.umaRecipe.slotDataList.Length);
            combinedMaterialList = new List <Material>();

            BuildCombineInstances();

            EnsureUMADataSetup(umaData);
            umaData.skeleton.BeginSkeletonUpdate();

            UMAMeshData umaMesh = new UMAMeshData();

            umaMesh.ClaimSharedBuffers();

            SkinnedMeshCombiner.CombineMeshes(umaMesh, combinedMeshList.ToArray(), umaData.ignoreBlendShapes);

            if (updatedAtlas)
            {
                RecalculateUV(umaMesh);
            }

            umaMesh.ApplyDataToUnityMesh(umaData.myRenderer, umaData.skeleton);
            umaMesh.ReleaseSharedBuffers();

            umaData.umaRecipe.ClearDNAConverters();
            for (int i = 0; i < umaData.umaRecipe.slotDataList.Length; i++)
            {
                SlotData slotData = umaData.umaRecipe.slotDataList[i];
                if (slotData != null)
                {
//                    umaData.EnsureBoneData(slotData.umaBoneData, slotData.animatedBones, boneMap);

                    umaData.umaRecipe.AddDNAUpdater(slotData.asset.slotDNA);
                }
            }

            umaData.myRenderer.quality = SkinQuality.Bone4;
            //umaData.myRenderer.useLightProbes = true;
            var materials = combinedMaterialList.ToArray();

            umaData.myRenderer.sharedMaterials = materials;
            //umaData.myRenderer.sharedMesh.RecalculateBounds();
            umaData.myRenderer.sharedMesh.name = "UMAMesh";

            umaData.firstBake = false;

            //FireSlotAtlasNotification(umaData, materials);
        }
Beispiel #12
0
        /*private static void BuildBoneWeights(NativeArray<BoneWeight1> source, NativeArray<BoneWeight1> dest, int destIndex, int destBoneweightIndex, int count, int[] bones, Matrix4x4[] bindPoses, Dictionary<int, BoneIndexEntry> bonesCollection, List<Matrix4x4> bindPosesList, List<int> bonesList)
         * {
         *      int[] boneMapping = new int[bones.Length];
         *
         *      for (int i = 0; i < boneMapping.Length; i++)
         *      {
         *              boneMapping[i] = TranslateBoneIndex(i, bones, bindPoses, bonesCollection, bindPosesList, bonesList);
         *      }
         *
         *      NativeArray<BoneWeight1>.Copy(source, 0, dest, destBoneweightIndex, source.Length);
         *      BoneWeight1 b = new BoneWeight1();
         *      for (int i=0;i<source.Length;i++)
         * {
         *              b.boneIndex = boneMapping[source[i].boneIndex];
         *              b.weight = source[i].weight;
         *
         *              dest[i + destBoneweightIndex] = b;
         * }
         * } */

        private static void BuildBoneWeights(UMAMeshData data, NativeArray <BoneWeight1> dest, NativeArray <byte> destBonesPerVertex, int destIndex, int destBoneweightIndex, int count, int[] bones, Matrix4x4[] bindPoses, Dictionary <int, BoneIndexEntry> bonesCollection, List <Matrix4x4> bindPosesList, List <int> bonesList)
        {
            int[] boneMapping = new int[bones.Length];

            for (int i = 0; i < boneMapping.Length; i++)
            {
                boneMapping[i] = TranslateBoneIndex(i, bones, bindPoses, bonesCollection, bindPosesList, bonesList);
            }

#if USE_NATIVE_ARRAYS
            NativeArray <byte> sourceBonesPerIndex = data.unityBonesPerVertex;
            int sourcecount = sourceBonesPerIndex.Length;
            int destcount   = destBonesPerVertex.Length;           // should be 0.

            NativeArray <byte> .Copy(sourceBonesPerIndex, 0, destBonesPerVertex, destIndex, sourceBonesPerIndex.Length);

            NativeArray <BoneWeight1> .Copy(data.unityBoneWeights, 0, dest, destBoneweightIndex, data.unityBoneWeights.Length);

            BoneWeight1 b = new BoneWeight1();
            for (int i = 0; i < data.unityBoneWeights.Length; i++)
            {
                b.boneIndex = boneMapping[data.unityBoneWeights[i].boneIndex];
                b.weight    = data.unityBoneWeights[i].weight;

                dest[i + destBoneweightIndex] = b;
            }
#else
            NativeArray <byte> .Copy(data.ManagedBonesPerVertex, 0, destBonesPerVertex, destIndex, data.ManagedBonesPerVertex.Length);

            NativeArray <BoneWeight1> .Copy(data.ManagedBoneWeights, 0, dest, destBoneweightIndex, data.ManagedBoneWeights.Length);

            BoneWeight1 b = new BoneWeight1();
            for (int i = 0; i < data.ManagedBoneWeights.Length; i++)
            {
                b.boneIndex = boneMapping[data.ManagedBoneWeights[i].boneIndex];
                b.weight    = data.ManagedBoneWeights[i].weight;
                dest[i + destBoneweightIndex] = b;
            }
#endif
        }
        public void CreateOcclusionMesh(UMAMeshData meshData)
        {
            if (meshData == null)
            {
                return;
            }
            ;

            if (_occlusionMesh == null)
            {
                _occlusionMesh = new Mesh();
#if UMA_32BITBUFFERS
                _occlusionMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
#endif
            }
            else
            {
                _occlusionMesh.Clear();
            }

            _occlusionMesh.subMeshCount = meshData.subMeshCount;
            _occlusionMesh.vertices     = meshData.vertices;
            _occlusionMesh.normals      = meshData.normals;
            _occlusionMesh.tangents     = meshData.tangents;
            _occlusionMesh.uv           = meshData.uv;
            _occlusionMesh.uv2          = meshData.uv2;
            _occlusionMesh.uv3          = meshData.uv3;
            _occlusionMesh.uv4          = meshData.uv4;
            _occlusionMesh.colors32     = meshData.colors32;

            _occlusionMesh.triangles    = new int[0];
            _occlusionMesh.subMeshCount = meshData.subMeshCount;

            for (int i = 0; i < meshData.subMeshCount; i++)
            {
                occlusionMesh.SetTriangles(meshData.submeshes[i].triangles, i);
            }
        }
Beispiel #14
0
        public static UMAMeshData ShallowInstanceMesh(UMAMeshData source)
        {
            var target = new UMAMeshData();

            target.bindPoses        = source.bindPoses;
            target.boneNameHashes   = source.boneNameHashes;
            target.unityBoneWeights = UMABoneWeight.Convert(source.boneWeights);
            target.colors32         = source.colors32;
            target.normals          = source.normals;
            target.rootBoneHash     = source.rootBoneHash;
            target.subMeshCount     = source.subMeshCount;
            target.submeshes        = source.submeshes;
            target.tangents         = source.tangents;
            target.umaBoneCount     = source.umaBoneCount;
            target.umaBones         = source.umaBones;
            target.uv          = source.uv;
            target.uv2         = source.uv2;
            target.uv3         = source.uv3;
            target.uv4         = source.uv4;
            target.vertexCount = source.vertexCount;
            target.vertices    = source.vertices;
            target.blendShapes = source.blendShapes;

            if (source.clothSkinningSerialized != null && source.clothSkinningSerialized.Length != 0)
            {
                target.clothSkinning = new ClothSkinningCoefficient[source.clothSkinningSerialized.Length];
                for (int i = 0; i < source.clothSkinningSerialized.Length; i++)
                {
                    ConvertData(ref source.clothSkinningSerialized[i], ref target.clothSkinning[i]);
                }
            }
            else
            {
                target.clothSkinning = null;
            }
            return(target);
        }
Beispiel #15
0
        /// <summary>
        /// Creates a deep copy of an UMAMeshData object.
        /// </summary>
        /// <returns>The new copy of the UMAMeshData</returns>
        public UMAMeshData DeepCopy()
        {
            UMAMeshData newMeshData = new UMAMeshData();

            if (bindPoses != null)
            {
                newMeshData.bindPoses = new Matrix4x4[bindPoses.Length];
                Array.Copy(bindPoses, newMeshData.bindPoses, bindPoses.Length);
            }

            if (boneWeights != null)
            {
                newMeshData.boneWeights = new UMABoneWeight[boneWeights.Length];
                Array.Copy(boneWeights, newMeshData.boneWeights, boneWeights.Length);
            }

            if (unityBoneWeights != null)
            {
                newMeshData.unityBoneWeights = new BoneWeight[unityBoneWeights.Length];
                Array.Copy(unityBoneWeights, newMeshData.unityBoneWeights, unityBoneWeights.Length);
            }

            if (vertices != null)
            {
                newMeshData.vertices = new Vector3[vertices.Length];
                Array.Copy(vertices, newMeshData.vertices, vertices.Length);
            }

            if (normals != null)
            {
                newMeshData.normals = new Vector3[normals.Length];
                Array.Copy(normals, newMeshData.normals, normals.Length);
            }

            if (tangents != null)
            {
                newMeshData.tangents = new Vector4[tangents.Length];
                Array.Copy(tangents, newMeshData.tangents, tangents.Length);
            }

            if (colors32 != null)
            {
                newMeshData.colors32 = new Color32[colors32.Length];
                Array.Copy(colors32, newMeshData.colors32, colors32.Length);
            }

            if (uv != null)
            {
                newMeshData.uv = new Vector2[uv.Length];
                Array.Copy(uv, newMeshData.uv, uv.Length);
            }

            if (uv2 != null)
            {
                newMeshData.uv2 = new Vector2[uv2.Length];
                Array.Copy(uv2, newMeshData.uv2, uv2.Length);
            }

            if (uv3 != null)
            {
                newMeshData.uv3 = new Vector2[uv3.Length];
                Array.Copy(uv3, newMeshData.uv3, uv3.Length);
            }

            if (uv4 != null)
            {
                newMeshData.uv4 = new Vector2[uv4.Length];
                Array.Copy(uv4, newMeshData.uv4, uv4.Length);
            }

            if (blendShapes != null)
            {
                newMeshData.blendShapes = new UMABlendShape[blendShapes.Length];
                Array.Copy(blendShapes, newMeshData.blendShapes, blendShapes.Length);
            }

            if (clothSkinning != null)
            {
                newMeshData.clothSkinning = new ClothSkinningCoefficient[clothSkinning.Length];
                Array.Copy(clothSkinning, newMeshData.clothSkinning, clothSkinning.Length);
            }

            if (clothSkinningSerialized != null)
            {
                newMeshData.clothSkinningSerialized = new Vector2[clothSkinningSerialized.Length];
                Array.Copy(clothSkinningSerialized, newMeshData.clothSkinningSerialized, clothSkinningSerialized.Length);
            }

            if (submeshes != null)
            {
                newMeshData.submeshes = new SubMeshTriangles[submeshes.Length];
                Array.Copy(submeshes, newMeshData.submeshes, submeshes.Length);
            }

            if (bones != null)
            {
                newMeshData.bones = bones.Clone() as Transform[];
            }

            if (rootBone != null)
            {
                newMeshData.rootBone = rootBone;
            }

            if (umaBones != null)
            {
                newMeshData.umaBones = new UMATransform[umaBones.Length];
                Array.Copy(umaBones, newMeshData.umaBones, umaBones.Length);
            }

            newMeshData.umaBoneCount = umaBoneCount;
            newMeshData.rootBoneHash = rootBoneHash;

            if (boneNameHashes != null)
            {
                newMeshData.boneNameHashes = new int[boneNameHashes.Length];
                Array.Copy(boneNameHashes, newMeshData.boneNameHashes, boneNameHashes.Length);
            }

            newMeshData.subMeshCount = subMeshCount;
            newMeshData.vertexCount  = vertexCount;
            newMeshData.RootBoneName = RootBoneName;

            return(newMeshData);
        }
Beispiel #16
0
 public bool Equals(UMAMeshData other)
 {
     return(this == other);
 }
Beispiel #17
0
        protected void RecalculateUV(UMAMeshData umaMesh)
        {
            int idx = 0;

            //Handle Atlassed Verts
            for (int materialIndex = 0; materialIndex < umaData.generatedMaterials.materials.Count; materialIndex++)
            {
                var generatedMaterial = umaData.generatedMaterials.materials[materialIndex];

                if (generatedMaterial.rendererAsset != umaData.GetRendererAsset(currentRendererIndex))
                {
                    continue;
                }

                if (generatedMaterial.umaMaterial.materialType != UMAMaterial.MaterialType.Atlas)
                {
                    var fragment    = generatedMaterial.materialFragments[0];
                    int vertexCount = fragment.slotData.asset.meshData.vertices.Length;
                    idx += vertexCount;
                    continue;
                }



                for (int materialDefinitionIndex = 0; materialDefinitionIndex < generatedMaterial.materialFragments.Count; materialDefinitionIndex++)
                {
                    var   fragment      = generatedMaterial.materialFragments[materialDefinitionIndex];
                    var   tempAtlasRect = fragment.atlasRegion;
                    int   vertexCount   = fragment.slotData.asset.meshData.vertices.Length;
                    float atlasXMin     = tempAtlasRect.xMin / atlasResolution;
                    float atlasXMax     = tempAtlasRect.xMax / atlasResolution;
                    float atlasXRange   = atlasXMax - atlasXMin;
                    float atlasYMin     = tempAtlasRect.yMin / atlasResolution;
                    float atlasYMax     = tempAtlasRect.yMax / atlasResolution;
                    float atlasYRange   = atlasYMax - atlasYMin;

                    // code below is for UVs remap based on rel pos in the atlas
                    if (fragment.isRectShared && fragment.slotData.useAtlasOverlay)
                    {
                        var foundRect = fragment.overlayList.FirstOrDefault(szname => fragment.slotData.slotName != null && szname.overlayName.Contains(fragment.slotData.slotName));
                        if (null != foundRect && foundRect.rect != Rect.zero)
                        {
                            var size    = foundRect.rect.size * generatedMaterial.resolutionScale;
                            var offsetX = foundRect.rect.x * generatedMaterial.resolutionScale.x;
                            var offsetY = foundRect.rect.y * generatedMaterial.resolutionScale.y;

                            atlasXMin  += (offsetX / generatedMaterial.cropResolution.x);
                            atlasXRange = size.x / generatedMaterial.cropResolution.x;

                            atlasYMin  += (offsetY / generatedMaterial.cropResolution.y);
                            atlasYRange = size.y / generatedMaterial.cropResolution.y;
                        }
                    }

                    while (vertexCount-- > 0)
                    {
                        umaMesh.uv[idx].x = atlasXMin + atlasXRange * umaMesh.uv[idx].x;
                        umaMesh.uv[idx].y = atlasYMin + atlasYRange * umaMesh.uv[idx].y;
                        idx++;
                    }
                }
            }
        }
Beispiel #18
0
        /// <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 #19
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();
        }
        public void Initialize()
        {
            gameObject.name = "GeometrySelector";
            if (_sharedMesh == null)
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogWarning("GeometrySelector: Initializing with no mesh!");
                }

                return;
            }

            if (meshAsset != null)
            {
                UMAMeshData meshData = meshAsset.asset.meshData;

                /* Todo: figure out how to get the races root bone orientation
                 * Transform root = meshData.rootBone;
                 * if (root == null)
                 * {
                 *  SkeletonTools.RecursiveFindBone(meshData.bones[0],"Global");
                 * }
                 */
                if (meshData.rootBoneHash == UMAUtils.StringToHash("Global"))
                {
                    gameObject.transform.localRotation = Quaternion.Euler(-90f, 0f, 0f);
                }
            }

            gameObject.transform.hideFlags = HideFlags.NotEditable | HideFlags.HideInInspector;

            if (selectedTriangles == null)
            {
                selectedTriangles = new BitArray(_sharedMesh.triangles.Length / 3);
            }

            if (!gameObject.GetComponent <MeshFilter>())
            {
                MeshFilter meshFilter = gameObject.AddComponent <MeshFilter>();
                meshFilter.mesh      = _sharedMesh;
                meshFilter.hideFlags = HideFlags.HideInInspector;
            }

            if (!gameObject.GetComponent <MeshRenderer>())
            {
                _meshRenderer = gameObject.AddComponent <MeshRenderer>();
                _meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
                _meshRenderer.receiveShadows    = false;
                _meshRenderer.hideFlags         = HideFlags.HideInInspector;
            }

            if (!gameObject.GetComponent <MeshCollider>())
            {
                _meshCollider            = gameObject.AddComponent <MeshCollider>();
                _meshCollider.convex     = false;
                _meshCollider.sharedMesh = _sharedMesh;
                _meshCollider.hideFlags  = HideFlags.HideInInspector;
            }

            if (GraphicsSettings.renderPipelineAsset == null)
            {
                _Shader = Shader.Find("Standard");
            }
            else
            {
                //Expand this to find shaders that work with other SRPs in the future.
                _Shader = Shader.Find("Unlit/Color");
            }

            if (_Materials == null && _Shader != null)
            {
                _Materials = new Material[2];

                //Selected
                _Materials[1]       = new Material(_Shader);
                _Materials[1].name  = "Selected";
                _Materials[1].color = Color.red;

                //UnSelected
                _Materials[0]       = new Material(_Shader);
                _Materials[0].name  = "UnSelected";
                _Materials[0].color = Color.gray;

                _sharedMesh.subMeshCount      = 2;
                _meshRenderer.sharedMaterials = _Materials;

                _meshRenderer.sharedMaterials[0].hideFlags = HideFlags.HideInInspector;
                _meshRenderer.sharedMaterials[1].hideFlags = HideFlags.HideInInspector;
            }
        }
Beispiel #21
0
        /// <summary>
        /// Updates the UMA mesh and skeleton to match current slots.
        /// </summary>
        /// <param name="updatedAtlas">If set to <c>true</c> atlas has changed.</param>
        /// <param name="umaData">UMA data.</param>
        /// <param name="atlasResolution">Atlas resolution.</param>
        public override void UpdateUMAMesh(bool updatedAtlas, UMAData umaData, int atlasResolution)
        {
            this.umaData         = umaData;
            this.atlasResolution = atlasResolution;

            combinedMeshList     = new List <SkinnedMeshCombiner.CombineInstance>(umaData.umaRecipe.slotDataList.Length);
            combinedMaterialList = new List <Material>();

            EnsureUMADataSetup(umaData);
            umaData.skeleton.BeginSkeletonUpdate();

            for (currentRendererIndex = 0; currentRendererIndex < umaData.generatedMaterials.rendererCount; currentRendererIndex++)
            {
                //Move umaMesh creation to with in the renderer loops
                //May want to make sure to set all it's buffers to null instead of creating a new UMAMeshData
                UMAMeshData umaMesh = new UMAMeshData();
                umaMesh.ClaimSharedBuffers();

                umaMesh.subMeshCount = 0;
                umaMesh.vertexCount  = 0;

                combinedMeshList.Clear();
                combinedMaterialList.Clear();
                clothProperties = null;

                BuildCombineInstances();

                if (combinedMeshList.Count == 1)
                {
                    // fast track
                    var tempMesh = SkinnedMeshCombiner.ShallowInstanceMesh(combinedMeshList[0].meshData);
                    tempMesh.ApplyDataToUnityMesh(renderers[currentRendererIndex], umaData.skeleton);
                }
                else
                {
                    SkinnedMeshCombiner.CombineMeshes(umaMesh, combinedMeshList.ToArray(), umaData.blendShapeSettings);

                    if (updatedAtlas)
                    {
                        RecalculateUV(umaMesh);
                    }

                    umaMesh.ApplyDataToUnityMesh(renderers[currentRendererIndex], umaData.skeleton);
                }
                var cloth = renderers[currentRendererIndex].GetComponent <Cloth>();
                if (clothProperties != null)
                {
                    if (cloth != null)
                    {
                        clothProperties.ApplyValues(cloth);
                    }
                }
                else
                {
                    Destroy(cloth);
                }

                var materials = combinedMaterialList.ToArray();
                renderers[currentRendererIndex].sharedMaterials = materials;
                umaMesh.ReleaseSharedBuffers();
            }

            umaData.umaRecipe.ClearDNAConverters();
            for (int i = 0; i < umaData.umaRecipe.slotDataList.Length; i++)
            {
                SlotData slotData = umaData.umaRecipe.slotDataList[i];
                if (slotData != null)
                {
                    umaData.umaRecipe.AddDNAUpdater(slotData.asset.slotDNA);
                }
            }

            umaData.firstBake = false;
        }
Beispiel #22
0
        /// <summary>
        /// Claims the static buffers.
        /// </summary>
        /// <returns><c>true</c>, if shared buffers were claimed, <c>false</c> otherwise.</returns>
        public bool ClaimSharedBuffers()
        {
            if (!buffersInitialized)
            {
                buffersInitialized = true;
                haveBackingArrays  = true;

                gVerticesArray = gVertices.GetBackingArray();
                if (gVerticesArray == null)
                {
                    haveBackingArrays = false;
                }
                gNormalsArray = gNormals.GetBackingArray();
                if (gNormalsArray == null)
                {
                    haveBackingArrays = false;
                }
                gTangentsArray = gTangents.GetBackingArray();
                if (gTangentsArray == null)
                {
                    haveBackingArrays = false;
                }
                gUVArray = gUV.GetBackingArray();
                if (gUVArray == null)
                {
                    haveBackingArrays = false;
                }
                gUV2Array = gUV2.GetBackingArray();
                if (gUV2Array == null)
                {
                    haveBackingArrays = false;
                }
                gUV3Array = gUV3.GetBackingArray();
                if (gUV3Array == null)
                {
                    haveBackingArrays = false;
                }
                gUV4Array = gUV4.GetBackingArray();
                if (gUV4Array == null)
                {
                    haveBackingArrays = false;
                }
                gColors32Array = gColors32.GetBackingArray();
                if (gColors32Array == null)
                {
                    haveBackingArrays = false;
                }

                gSubmeshTriIndices = new int[gSubmeshTris.Length];
                gSubmeshTriArrays  = new int[gSubmeshTris.Length][];
                for (int i = 0; i < gSubmeshTris.Length; i++)
                {
                    gSubmeshTriIndices[i] = UNUSED_SUBMESH;
                    gSubmeshTriArrays[i]  = gSubmeshTris[i].GetBackingArray();
                    if (gSubmeshTriArrays[i] == null)
                    {
                        haveBackingArrays = false;
                    }
                }

                if (haveBackingArrays == false)
                {
                    if (Debug.isDebugBuild)
                    {
                        Debug.LogError("Unable to access backing arrays for shared UMAMeshData!");
                    }
                }
            }

            if (!haveBackingArrays)
            {
                return(false);
            }

            if (bufferLockOwner == null)
            {
                bufferLockOwner = this;

                vertices = gVerticesArray;
                normals  = gNormalsArray;
                tangents = gTangentsArray;
                uv       = gUVArray;
                uv2      = gUV2Array;
                uv3      = gUV3Array;
                uv4      = gUV4Array;
                colors32 = gColors32Array;

                boneWeights = null;
#if USE_UNSAFE_CODE
                unityBoneWeights = gBoneWeightsArray;
#endif

                return(true);
            }

            if (Debug.isDebugBuild)
            {
                Debug.LogWarning("Unable to claim UMAMeshData global buffers!");
            }
            return(false);
        }
Beispiel #23
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, BlendShapeSettings blendShapeSettings = null)
        {
            if (blendShapeSettings == null)
            {
                blendShapeSettings = new BlendShapeSettings();
            }

            int vertexCount             = 0;
            int bindPoseCount           = 0;
            int transformHierarchyCount = 0;
            Dictionary <string, BlendShapeVertexData> blendShapeNames = new Dictionary <string, BlendShapeVertexData>();

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

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

            if (!blendShapeSettings.ignoreBlendShapes)
            {
                AnalyzeBlendShapeSources(sources, blendShapeSettings, ref meshComponents, out blendShapeNames);
            }

            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;

#if UNITY_2019_3_OR_NEWER
            if (nativeBoneWeights.Length < vertexCount)
            {
                if (nativeBoneWeights.IsCreated)
                {
                    nativeBoneWeights.Dispose();
                }

                nativeBoneWeights = new NativeArray <BoneWeight>(vertexCount, Allocator.Persistent);
            }
#else
            BoneWeight[] boneWeights = EnsureArrayLength(target.unityBoneWeights, vertexCount);
#endif
            Vector3[]                  vertices           = EnsureArrayLength(target.vertices, 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[blendShapeNames.Keys.Count] : 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;

            InitializeBlendShapeData(ref vertexCount, blendShapeNames, blendShapes);

            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();
            }

            foreach (var source in sources)
            {
                int sourceVertexCount = source.meshData.vertices.Length;
#if UNITY_2019_3_OR_NEWER
                BuildBoneWeights(source.meshData.boneWeights, 0, nativeBoneWeights, vertexIndex, sourceVertexCount, source.meshData.boneNameHashes, source.meshData.bindPoses, bonesCollection, bindPoses, bonesList);
#else
                BuildBoneWeights(source.meshData.boneWeights, 0, boneWeights, vertexIndex, sourceVertexCount, source.meshData.boneNameHashes, source.meshData.bindPoses, bonesCollection, bindPoses, bonesList);
#endif
                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)
                    {
                        int sourceBlendShapeLength = source.meshData.blendShapes.Length;
                        for (int shapeIndex = 0; shapeIndex < sourceBlendShapeLength; shapeIndex++)
                        {
                            string shapeName = source.meshData.blendShapes[shapeIndex].shapeName;

                            //If we aren't loading all blendshapes and we don't find the blendshape name in the list of explicit blendshapes to combine, then skip to the next one.
                            if (!blendShapeSettings.loadAllBlendShapes && !blendShapeSettings.blendShapes.ContainsKey(shapeName))
                            {
                                continue;
                            }

                            #region BlendShape Baking
                            if (BakeBlendShape(blendShapeSettings.blendShapes, source.meshData.blendShapes[shapeIndex], ref vertexIndex, vertices, normals, tangents, has_normals, has_tangents))
                            {
                                continue;                                 //If we baked this blendshape, then continue to the next one and skip adding the regular blendshape.
                            }
                            #endregion

                            //If our dictionary contains the shape name, which it should
                            if (blendShapeNames.ContainsKey(shapeName))
                            {
                                UMABlendShape[] sourceBlendShapes = source.meshData.blendShapes;
                                int             i = blendShapeNames[shapeName].index;

                                if (blendShapes[i].frames.Length != sourceBlendShapes[shapeIndex].frames.Length)
                                {
                                    if (Debug.isDebugBuild)
                                    {
                                        Debug.LogError("SkinnedMeshCombiner: mesh blendShape frame counts don't match!");
                                    }
                                    break;
                                }

                                for (int frameIndex = 0; frameIndex < sourceBlendShapes[shapeIndex].frames.Length; frameIndex++)
                                {
                                    Array.Copy(sourceBlendShapes[shapeIndex].frames[frameIndex].deltaVertices, 0, blendShapes[i].frames[frameIndex].deltaVertices, vertexIndex, sourceVertexCount);

                                    Vector3[] sourceDeltaNormals  = sourceBlendShapes[shapeIndex].frames[frameIndex].deltaNormals;
                                    Vector3[] sourceDeltaTangents = sourceBlendShapes[shapeIndex].frames[frameIndex].deltaTangents;

                                    //if out dictionary says at least one source has normals or tangents and the current source has normals or tangents then copy them.
                                    if (blendShapeNames[shapeName].hasNormals && sourceDeltaNormals.Length > 0)
                                    {
                                        Array.Copy(sourceDeltaNormals, 0, blendShapes[i].frames[frameIndex].deltaNormals, vertexIndex, sourceVertexCount);
                                    }

                                    if (blendShapeNames[shapeName].hasTangents && sourceDeltaTangents.Length > 0)
                                    {
                                        Array.Copy(sourceDeltaTangents, 0, blendShapes[i].frames[frameIndex].deltaTangents, vertexIndex, sourceVertexCount);
                                    }
                                }
                            }
                            else
                            {
                                if (Debug.isDebugBuild)
                                {
                                    Debug.LogError("BlendShape " + shapeName + " not found in dictionary!");
                                }
                            }
                        }
                    }
                }
                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)
            {
                if (Debug.isDebugBuild)
                {
                    Debug.LogError("Combined vertices size didn't match precomputed value!");
                }
            }

            // fill in new values.
            target.vertexCount = vertexCount;
            target.vertices    = vertices;
#if UNITY_2019_3_OR_NEWER
            target.unityBoneWeights = nativeBoneWeights.GetSubArray(0, vertexCount).ToArray();
#else
            target.unityBoneWeights = boneWeights;
#endif
            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 #24
0
        /// <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)
        {
            int vertexCount             = 0;
            int bindPoseCount           = 0;
            int transformHierarchyCount = 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);

            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;

#if !UNITY_4_6
            bool has_uv3 = (meshComponents & MeshComponents.has_uv3) != MeshComponents.none;
            bool has_uv4 = (meshComponents & MeshComponents.has_uv4) != MeshComponents.none;
#endif
            bool has_colors32 = (meshComponents & MeshComponents.has_colors32) != 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;
#if !UNITY_4_6
            Vector2[] uv3 = has_uv3 ? EnsureArrayLength(target.uv3, vertexCount) : null;
            Vector2[] uv4 = has_uv4 ? EnsureArrayLength(target.uv4, vertexCount) : null;
#endif
            Color32[] colors32 = has_colors32 ? EnsureArrayLength(target.colors32, vertexCount) : 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();
            }

            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 !UNITY_4_6
                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);
                    }
                }
#endif
                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);
                    }
                }

                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;
#if !UNITY_4_6
            target.uv3 = uv3;
            target.uv4 = uv4;
#endif
            target.colors32 = colors32;

            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();
        }