MaterialBlock CreateBlock(VertexCache cache, Material[] materials) { MaterialBlock block = new MaterialBlock(); int packageCount = GetPackageCount(cache); block.instanceData = CreateInstanceData(packageCount); block.packageList = new List <InstancingPackage> [packageCount]; for (int i = 0; i != block.packageList.Length; ++i) { block.packageList[i] = new List <InstancingPackage>(); InstancingPackage package = CreatePackage(block.instanceData, cache.mesh, materials, i); block.packageList[i].Add(package); PreparePackageMaterial(package, cache, i); package.instancingCount = 1; } block.runtimePackageIndex = new int[packageCount]; return(block); }
private void SetupVertexCache(VertexCache vertexCache, MaterialBlock block, MeshRenderer render, Mesh mesh, Transform[] boneTransform, int bonePerVertex) { int boneIndex = -1; if (boneTransform != null) { for (int k = 0; k != boneTransform.Length; ++k) { if (render.transform.parent.name.GetHashCode() == boneTransform[k].name.GetHashCode()) { boneIndex = k; break; } } } if (boneIndex >= 0) { //todo BindAttachment(vertexCache, vertexCache, vertexCache.mesh, boneIndex); } if (vertexCache.materials == null) { vertexCache.materials = render.sharedMaterials; } SetupAdditionalData(vertexCache); for (int i = 0; i != block.packageList.Length; ++i) { InstancingPackage package = CreatePackage(block.instanceData, vertexCache.mesh, render.sharedMaterials, i); block.packageList[i].Add(package); PreparePackageMaterial(package, vertexCache, i); } }
private void SetupVertexCache(VertexCache vertexCache, MaterialBlock block, SkinnedMeshRenderer render, Transform[] boneTransform, int bonePerVertex) { int[] boneIndex = null; if (render.bones.Length != boneTransform.Length) { if (render.bones.Length == 0) { boneIndex = new int[1]; int hashRenderParentName = render.transform.parent.name.GetHashCode(); for (int k = 0; k != boneTransform.Length; ++k) { if (hashRenderParentName == boneTransform[k].name.GetHashCode()) { boneIndex[0] = k; break; } } } else { boneIndex = new int[render.bones.Length]; for (int j = 0; j != render.bones.Length; ++j) { boneIndex[j] = -1; Transform trans = render.bones[j]; int hashTransformName = trans.name.GetHashCode(); for (int k = 0; k != boneTransform.Length; ++k) { if (hashTransformName == boneTransform[k].name.GetHashCode()) { boneIndex[j] = k; break; } } } if (boneIndex.Length == 0) { boneIndex = null; } } } UnityEngine.Profiling.Profiler.BeginSample("Copy the vertex data in SetupVertexCache()"); Mesh m = render.sharedMesh; BoneWeight[] boneWeights = m.boneWeights; Debug.Assert(boneWeights.Length > 0); for (int j = 0; j != m.vertexCount; ++j) { vertexCache.weight[j].x = boneWeights[j].weight0; Debug.Assert(vertexCache.weight[j].x > 0.0f); vertexCache.weight[j].y = boneWeights[j].weight1; vertexCache.weight[j].z = boneWeights[j].weight2; vertexCache.weight[j].w = boneWeights[j].weight3; vertexCache.boneIndex[j].x = boneIndex == null ? boneWeights[j].boneIndex0 : boneIndex[boneWeights[j].boneIndex0]; vertexCache.boneIndex[j].y = boneIndex == null ? boneWeights[j].boneIndex1 : boneIndex[boneWeights[j].boneIndex1]; vertexCache.boneIndex[j].z = boneIndex == null ? boneWeights[j].boneIndex2 : boneIndex[boneWeights[j].boneIndex2]; vertexCache.boneIndex[j].w = boneIndex == null ? boneWeights[j].boneIndex3 : boneIndex[boneWeights[j].boneIndex3]; Debug.Assert(vertexCache.boneIndex[j].x >= 0); if (bonePerVertex == 3) { float rate = 1.0f / (vertexCache.weight[j].x + vertexCache.weight[j].y + vertexCache.weight[j].z); vertexCache.weight[j].x = vertexCache.weight[j].x * rate; vertexCache.weight[j].y = vertexCache.weight[j].y * rate; vertexCache.weight[j].z = vertexCache.weight[j].z * rate; vertexCache.weight[j].w = -0.1f; } else if (bonePerVertex == 2) { float rate = 1.0f / (vertexCache.weight[j].x + vertexCache.weight[j].y); vertexCache.weight[j].x = vertexCache.weight[j].x * rate; vertexCache.weight[j].y = vertexCache.weight[j].y * rate; vertexCache.weight[j].z = -0.1f; vertexCache.weight[j].w = -0.1f; } else if (bonePerVertex == 1) { vertexCache.weight[j].x = 1.0f; vertexCache.weight[j].y = -0.1f; vertexCache.weight[j].z = -0.1f; vertexCache.weight[j].w = -0.1f; } } UnityEngine.Profiling.Profiler.EndSample(); if (vertexCache.materials == null) { vertexCache.materials = render.sharedMaterials; } SetupAdditionalData(vertexCache); for (int i = 0; i != block.packageList.Length; ++i) { InstancingPackage package = CreatePackage(block.instanceData, vertexCache.mesh, render.sharedMaterials, i); block.packageList[i].Add(package); //vertexCache.packageList[i].Add(package); PreparePackageMaterial(package, vertexCache, i); } }
// alias is to use for attachment, it should be a bone name public void AddMeshVertex(string prefabName, AnimationInstancing.LodInfo[] lodInfo, Transform[] bones, List <Matrix4x4> bindPose, int bonePerVertex, string alias = null) { UnityEngine.Profiling.Profiler.BeginSample("AddMeshVertex()"); for (int x = 0; x != lodInfo.Length; ++x) { AnimationInstancing.LodInfo lod = lodInfo[x]; for (int i = 0; i != lod.skinnedMeshRenderer.Length; ++i) { Mesh m = lod.skinnedMeshRenderer[i].sharedMesh; if (m == null) { continue; } int nameCode = lod.skinnedMeshRenderer[i].name.GetHashCode(); int identify = GetIdentify(lod.skinnedMeshRenderer[i].sharedMaterials); VertexCache cache = null; if (vertexCachePool.TryGetValue(nameCode, out cache)) { MaterialBlock block = null; if (!cache.instanceBlockList.TryGetValue(identify, out block)) { block = CreateBlock(cache, lod.skinnedMeshRenderer[i].sharedMaterials); cache.instanceBlockList.Add(identify, block); } lod.vertexCacheList[i] = cache; lod.materialBlockList[i] = block; continue; } VertexCache vertexCache = CreateVertexCache(prefabName, nameCode, 0, m); vertexCache.bindPose = bindPose.ToArray(); MaterialBlock matBlock = CreateBlock(vertexCache, lod.skinnedMeshRenderer[i].sharedMaterials); vertexCache.instanceBlockList.Add(identify, matBlock); SetupVertexCache(vertexCache, matBlock, lod.skinnedMeshRenderer[i], bones, bonePerVertex); lod.vertexCacheList[i] = vertexCache; lod.materialBlockList[i] = matBlock; } for (int i = 0, j = lod.skinnedMeshRenderer.Length; i != lod.meshRenderer.Length; ++i, ++j) { Mesh m = lod.meshFilter[i].sharedMesh; if (m == null) { continue; } int renderName = lod.meshRenderer[i].name.GetHashCode(); int aliasName = (alias != null ? alias.GetHashCode() : 0); int identify = GetIdentify(lod.meshRenderer[i].sharedMaterials); VertexCache cache = null; if (vertexCachePool.TryGetValue(renderName + aliasName, out cache)) { MaterialBlock block = null; if (!cache.instanceBlockList.TryGetValue(identify, out block)) { block = CreateBlock(cache, lod.meshRenderer[i].sharedMaterials); cache.instanceBlockList.Add(identify, block); } lod.vertexCacheList[j] = cache; lod.materialBlockList[j] = block; continue; } VertexCache vertexCache = CreateVertexCache(prefabName, renderName, aliasName, m); if (bindPose != null) { vertexCache.bindPose = bindPose.ToArray(); } MaterialBlock matBlock = CreateBlock(vertexCache, lod.meshRenderer[i].sharedMaterials); vertexCache.instanceBlockList.Add(identify, matBlock); SetupVertexCache(vertexCache, matBlock, lod.meshRenderer[i], m, bones, bonePerVertex); lod.vertexCacheList[lod.skinnedMeshRenderer.Length + i] = vertexCache; lod.materialBlockList[lod.skinnedMeshRenderer.Length + i] = matBlock; } } UnityEngine.Profiling.Profiler.EndSample(); }
void ApplyBoneMatrix() { Vector3 cameraPosition = cameraTransform.position; for (int i = 0; i != aniInstancingList.Count; ++i) { AnimationInstancing instance = aniInstancingList[i]; if (!instance.IsPlaying()) { continue; } if (instance.aniIndex < 0 && instance.parentInstance == null) { continue; } if (instance.applyRootMotion) { ApplyRootMotion(instance); } instance.UpdateAnimation(); instance.boundingSpere.position = instance.worldTransform.position; boundingSphere[i] = instance.boundingSpere; if (!instance.visible) { continue; } instance.UpdateLod(cameraPosition); AnimationInstancing.LodInfo lod = instance.lodInfo[instance.lodLevel]; int aniTextureIndex = -1; if (instance.parentInstance != null) { aniTextureIndex = instance.parentInstance.aniTextureIndex; } else { aniTextureIndex = instance.aniTextureIndex; } Matrix4x4 worldMat = instance.worldTransform.localToWorldMatrix; for (int j = 0; j != lod.vertexCacheList.Length; ++j) { VertexCache cache = lod.vertexCacheList[j]; MaterialBlock block = lod.materialBlockList[j]; Debug.Assert(block != null); int packageIndex = block.runtimePackageIndex[aniTextureIndex]; Debug.Assert(packageIndex < block.packageList[aniTextureIndex].Count); InstancingPackage package = block.packageList[aniTextureIndex][packageIndex]; if (package.instancingCount + 1 > instancingPackageSize) { ++block.runtimePackageIndex[aniTextureIndex]; packageIndex = block.runtimePackageIndex[aniTextureIndex]; if (packageIndex >= block.packageList[aniTextureIndex].Count) { InstancingPackage newPackage = CreatePackage(block.instanceData, cache.mesh, cache.materials, aniTextureIndex); block.packageList[aniTextureIndex].Add(newPackage); PreparePackageMaterial(newPackage, cache, aniTextureIndex); newPackage.instancingCount = 1; } block.packageList[aniTextureIndex][packageIndex].instancingCount = 1; } else { ++package.instancingCount; } { VertexCache vertexCache = cache; InstanceData data = block.instanceData; int index = block.runtimePackageIndex[aniTextureIndex]; InstancingPackage pkg = block.packageList[aniTextureIndex][index]; int count = pkg.instancingCount - 1; if (count >= 0) { Matrix4x4[] arrayMat = data.worldMatrix[aniTextureIndex][index]; arrayMat[count].m00 = worldMat.m00; arrayMat[count].m01 = worldMat.m01; arrayMat[count].m02 = worldMat.m02; arrayMat[count].m03 = worldMat.m03; arrayMat[count].m10 = worldMat.m10; arrayMat[count].m11 = worldMat.m11; arrayMat[count].m12 = worldMat.m12; arrayMat[count].m13 = worldMat.m13; arrayMat[count].m20 = worldMat.m20; arrayMat[count].m21 = worldMat.m21; arrayMat[count].m22 = worldMat.m22; arrayMat[count].m23 = worldMat.m23; arrayMat[count].m30 = worldMat.m30; arrayMat[count].m31 = worldMat.m31; arrayMat[count].m32 = worldMat.m32; arrayMat[count].m33 = worldMat.m33; float frameIndex = 0, preFrameIndex = -1, transition = 0f; if (instance.parentInstance != null) { frameIndex = instance.parentInstance.aniInfo[instance.parentInstance.aniIndex].animationIndex + instance.parentInstance.curFrame; if (instance.parentInstance.preAniIndex >= 0) { preFrameIndex = instance.parentInstance.aniInfo[instance.parentInstance.preAniIndex].animationIndex + instance.parentInstance.preAniFrame; } transition = instance.parentInstance.transitionProgress; } else { frameIndex = instance.aniInfo[instance.aniIndex].animationIndex + instance.curFrame; if (instance.preAniIndex >= 0) { preFrameIndex = instance.aniInfo[instance.preAniIndex].animationIndex + instance.preAniFrame; } transition = instance.transitionProgress; } data.frameIndex[aniTextureIndex][index][count] = frameIndex; data.preFrameIndex[aniTextureIndex][index][count] = preFrameIndex; data.transitionProgress[aniTextureIndex][index][count] = transition; } } } } }