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