protected override void OnUpdate()
        {
            Entities.ForEach((UnityEngine.SkinnedMeshRenderer uSkinnedMeshRenderer) =>
            {
                var sharedMaterials    = uSkinnedMeshRenderer.sharedMaterials;
                UnityEngine.Mesh uMesh = uSkinnedMeshRenderer.sharedMesh;
                var meshEntity         = GetPrimaryEntity(uMesh);

                for (int i = 0; i < uMesh.subMeshCount; i++)
                {
                    // Find the target material entity to be used for this submesh
                    Entity targetMaterial = MeshRendererConversion.FindTargetMaterialEntity(this, sharedMaterials, i);

                    var isLit    = DstEntityManager.HasComponent <LitMaterial>(targetMaterial);
                    var isSimple = DstEntityManager.HasComponent <SimpleMaterial>(targetMaterial);
                    if (isSimple)
                    {
                        Debug.Log("Unlit material was not supported in SkinnedMeshRenderer:" + uMesh.name);
                        continue;
                    }

                    if (isLit)
                    {
                        if (uSkinnedMeshRenderer.bones.Length > MeshSkinningConfig.GPU_SKINNING_MAX_BONES)
                        {
                            DstEntityManager.AddComponent <NeedGenerateGPUSkinnedMeshRenderer>(meshEntity);
                        }
                        DstEntityManager.AddComponent <LitMeshRenderData>(meshEntity);
                        // Remove simple data if it was there, we don't need it
                        DstEntityManager.RemoveComponent <SimpleMeshRenderData>(meshEntity);
                    }
                }
            });
        }
        protected override void OnUpdate()
        {
            Entities.ForEach((UnityEngine.SkinnedMeshRenderer uSkinnedMeshRenderer) =>
            {
                var sharedMaterials    = uSkinnedMeshRenderer.sharedMaterials;
                UnityEngine.Mesh uMesh = uSkinnedMeshRenderer.sharedMesh;
                var meshEntity         = GetPrimaryEntity(uMesh);

                List <Entity> subSkinnedMeshRenderers = new List <Entity>();
                for (int i = 0; i < uMesh.subMeshCount; i++)
                {
                    // Find the target material entity to be used for this submesh
                    Entity targetMaterial = MeshRendererConversion.FindTargetMaterialEntity(this, sharedMaterials, i);

                    var isLit    = DstEntityManager.HasComponent <LitMaterial>(targetMaterial);
                    var isSimple = DstEntityManager.HasComponent <SimpleMaterial>(targetMaterial);
                    if (isSimple)
                    {
                        Debug.Log("Unlit material was not supported in SkinnedMeshRenderer:" + uMesh.name);
                        continue;
                    }

                    if (isLit)
                    {
                        Entity subSkinnedMeshRendererEntity =
                            ConvertOriginalSubMesh(this, uSkinnedMeshRenderer, uMesh, meshEntity, i, targetMaterial);
                        subSkinnedMeshRenderers.Add(subSkinnedMeshRendererEntity);
                    }
                }

                List <Entity> ret = ConvertGPUSkinnedSubMesh(this, uSkinnedMeshRenderer, uMesh, meshEntity);
                if (ret != null)
                {
                    subSkinnedMeshRenderers.AddRange(ret);
                }
                for (int j = 0; j < subSkinnedMeshRenderers.Count; j++)
                {
                    Entity subSkinnedMeshRenderer = subSkinnedMeshRenderers[j];
                    DstEntityManager.AddComponent <LitMeshRenderer>(subSkinnedMeshRenderer);
                }

                ConvertSkinnedMeshBoneInfoToTransformEntity(this, uSkinnedMeshRenderer);
            });
        }
Example #3
0
        public void RetrieveLitSkinnedMeshData(Mesh uMesh, Entity meshEntity, EntityManager entityManager)
        {
            List <int>                duplicateVertexIndex        = new List <int>();
            List <Vector4>            duplicateBoneIndex          = new List <Vector4>();
            Dictionary <int, Vector4> existingVertex2NewBoneIndex = new Dictionary <int, Vector4>();
            Dictionary <int, int>     boneIndexCounter            = new Dictionary <int, int>();
            List <int>                gpuDrawRange = new List <int>();

            BoneWeight[] boneWeights = uMesh.boneWeights;
            int[]        triangles   = uMesh.triangles;

            //Separate mesh into different draw range for gpu skinning use
            for (int subMeshIndex = 0; subMeshIndex < uMesh.subMeshCount; subMeshIndex++)
            {
                UnityEngine.Rendering.SubMeshDescriptor uSubMeshDescriptor = uMesh.GetSubMesh(subMeshIndex);
                int curIndex  = uSubMeshDescriptor.indexStart;
                int lastIndex = uSubMeshDescriptor.indexStart;
                int endIndex  = curIndex + uSubMeshDescriptor.indexCount;
                while (curIndex < endIndex)
                {
                    int curBoneCount = boneIndexCounter.Count;
                    for (int offset = 0; offset < 3; offset++)
                    {
                        int        vertexIndex = triangles[curIndex + offset];
                        BoneWeight boneWeight  = boneWeights[vertexIndex];
                        curBoneCount += CalcToBeAddBoneIndexCount(boneIndexCounter, boneWeight);
                    }

                    if (curBoneCount > MeshSkinningConfig.GPU_SKINNING_MAX_BONES)
                    {
                        gpuDrawRange.Add(curIndex);
                        Debug.Log("GPU SkinnedMesh Draw Range[" + lastIndex + ":" + curIndex + "] BoneCount:" + boneIndexCounter.Count);
                        lastIndex = curIndex;
                        boneIndexCounter.Clear();
                    }
                    else
                    {
                        for (int offset = 0; offset < 3; offset++)
                        {
                            int        vertexIndex   = triangles[curIndex + offset];
                            BoneWeight curBoneWeight = boneWeights[vertexIndex];

                            //restore the new bone index and set it to the mesh later
                            Vector4 newBoneIndex = new Vector4();
                            newBoneIndex.x = GetNewBoneIndex(boneIndexCounter, curBoneWeight.weight0, curBoneWeight.boneIndex0);
                            newBoneIndex.y = GetNewBoneIndex(boneIndexCounter, curBoneWeight.weight1, curBoneWeight.boneIndex1);
                            newBoneIndex.z = GetNewBoneIndex(boneIndexCounter, curBoneWeight.weight2, curBoneWeight.boneIndex2);
                            newBoneIndex.w = GetNewBoneIndex(boneIndexCounter, curBoneWeight.weight3, curBoneWeight.boneIndex3);

                            Vector4 existingNewBoneIndex = new Vector4();
                            bool    isExist = existingVertex2NewBoneIndex.TryGetValue(vertexIndex, out existingNewBoneIndex);
                            if (isExist && newBoneIndex != existingNewBoneIndex)
                            {
                                bool needAdd        = true;
                                int  newVertexIndex = 0;
                                for (int j = 0; j < duplicateVertexIndex.Count; j++)
                                {
                                    if (duplicateVertexIndex[j] == vertexIndex && duplicateBoneIndex[j] == newBoneIndex)
                                    {
                                        newVertexIndex = uMesh.vertexCount + j;
                                        triangles[curIndex + offset] = newVertexIndex;
                                        needAdd = false;
                                        break;
                                    }
                                }

                                if (needAdd)
                                {
                                    duplicateVertexIndex.Add(vertexIndex);
                                    duplicateBoneIndex.Add(newBoneIndex);
                                    newVertexIndex = uMesh.vertexCount + duplicateVertexIndex.Count - 1;
                                    triangles[curIndex + offset] = newVertexIndex;
                                    existingVertex2NewBoneIndex[newVertexIndex] = newBoneIndex;
                                }
                            }
                            else
                            {
                                existingVertex2NewBoneIndex[vertexIndex] = newBoneIndex;
                            }
                        }

                        curIndex += 3;
                    }
                }

                if (lastIndex != curIndex)
                {
                    gpuDrawRange.Add(curIndex);
                    Debug.Log("GPU SkinnedMesh Draw Range[" + lastIndex + ":" + curIndex + "] BoneCount:" + boneIndexCounter.Count);
                }
            }
            Debug.Log("GPU SkinnedMesh Duplicate VertexCount:" + duplicateVertexIndex.Count);
            Debug.Log("GPU SkinnedMesh DrawCalls: " + gpuDrawRange.Count);

            //generate UMeshDataCache and adding duplicate vertices into UMeshDataCache
            int newVertexCount = uMesh.vertexCount + duplicateVertexIndex.Count;

            RetrieveLitMeshData(uMesh, newVertexCount);
            for (int i = 0; i < duplicateVertexIndex.Count; i++)
            {
                int curVertexIndex      = uMesh.vertexCount + i;
                int originalVertexIndex = duplicateVertexIndex[i];
                uPositions[curVertexIndex]   = uPositions[originalVertexIndex];
                uUVs[curVertexIndex]         = uUVs[originalVertexIndex];
                uNormals[curVertexIndex]     = uNormals[originalVertexIndex];
                uTangents[curVertexIndex]    = uTangents[originalVertexIndex];
                uBiTangents[curVertexIndex]  = uBiTangents[originalVertexIndex];
                uBoneWeights[curVertexIndex] = uBoneWeights[originalVertexIndex];
                uBoneIndices[curVertexIndex] = uBoneIndices[originalVertexIndex];
                uColors[curVertexIndex]      = uColors[originalVertexIndex];
            }
            //Update the indices, some of the triangles reference to the duplicate vertex
            for (int i = 0; i < triangles.Length; i++)
            {
                uIndices[i] = Convert.ToUInt16(triangles[i]);
            }
            //Restore the original vertex bone index for switching GPU skinning to CPU skinning in the runtime
            DynamicBuffer <OriginalVertexBoneIndex> obiBuffer = entityManager.AddBuffer <OriginalVertexBoneIndex>(meshEntity);

            for (int i = 0; i < newVertexCount; i++)
            {
                Vector4 uBoneIndex = uBoneIndices[i];
                obiBuffer.Add(new OriginalVertexBoneIndex {
                    BoneIndex = new float4(uBoneIndex.x, uBoneIndex.y, uBoneIndex.z, uBoneIndex.w)
                });
                Vector4 newBoneIndex = existingVertex2NewBoneIndex[i];
                uBoneIndices[i] = newBoneIndex;
            }
            //Add GPUSkinnedMeshDrawRange for SkinnedMeshRendererConversion use.
            DynamicBuffer <GPUSkinnedMeshDrawRange> gsmdrBuffer = entityManager.AddBuffer <GPUSkinnedMeshDrawRange>(meshEntity);

            for (int i = 0; i < gpuDrawRange.Count; i++)
            {
                gsmdrBuffer.Add(new GPUSkinnedMeshDrawRange {
                    TriangleIndex = gpuDrawRange[i]
                });
            }
        }