public bool TryAdd(tmBatchObject part) { if (CanAdd(part)) { Add(part); return(true); } return(false); }
public void ForcedBatchChanged(tmBatchObject part) { if (part.ForcedBatching) { AddToForced(part); } else { RemoveFromForced(part); } }
public void Add(tmBatchObject part) { if (part.Mesh != null && !parts.Contains(part)) { part.BatchInstance = this; parts.Add(part); Modified = true; OrderDirty = true; vertexCount += part.Mesh.vertexCount; if (part.ForcedBatching) { AddToForced(part); } } }
public void Remove(tmBatchObject part) { if (parts.Contains(part)) { part.Batched = false; part.BatchInstance = null; parts.Remove(part); Modified = true; vertexCount -= part.Mesh.vertexCount; if (part.ForcedBatching) { RemoveFromForced(part); } } }
void Update() { Bounds newBounds = new Bounds(); if (BatchedParts.Count > 0) { for (int index = 0, partsCount = BatchedParts.Count; index < partsCount; index++) { tmBatchObject part = BatchedParts[index]; if (!part.IsNull()) { var curBounds = part.Mesh.bounds; curBounds.center += part.CachedTransform.position; newBounds.Encapsulate(curBounds); } } newBounds.center -= CachedTransform.position; } CachedSkinnedRender.localBounds = newBounds; }
public tmBatchedInstance BatchObject(tmBatchObject bo, Transform root, bool move = true) { if (bo.BatchInstance != null || bo.Mesh == null || bo.Material == null) { CustomDebug.LogError("invalid batch object : " + bo.name + " reason: instance:" + (bo.BatchInstance != null) + ", mesh:" + (bo.Mesh == null) + ", material:" + (bo.Material == null), bo); return(null); } move = root == null; if (root == null) { root = transform; } bool needSkin = (bo.BatchingType == tmBatchingType.Skinning); string key = "" + root.GetInstanceID() + bo.Material.GetInstanceID() + needSkin; List <tmBatchedInstance> batches = null; if (batchTable.ContainsKey(key)) { batches = batchTable[key]; } else { batches = new List <tmBatchedInstance>(); batchTable.Add(key, batches); } tmBatchedInstance availibleBatch = null; foreach (tmBatchedInstance batch in batches) { if (batch.CanAdd(bo)) { availibleBatch = batch; break; } } if (availibleBatch == null) { GameObject go = new GameObject(); go.transform.parent = root; go.transform.localPosition = Vector3.zero; go.name = "Batch_" + root.name + "_" + bo.Material.name.Replace(tk2dSpriteCollectionData.internalResourcePrefix, "") + "_" + needSkin; go.layer = bo.gameObject.layer; availibleBatch = needSkin ? go.AddComponent <tmSkinnedBatchedInstance>() : go.AddComponent <tmBatchedInstance>(); availibleBatch.shouldMove = move; availibleBatch.SharedMaterial = bo.Material; tmTextureRenderBase original = bo.GetComponent <tmTextureRenderBase>(); if (original) { tmBatchRender render = go.AddComponent <tmBatchRender>(); render.MainTexCollectionGUID = original.MainTexCollectionGUID; render.MainTextureID = original.MainTextureID; render.LightmapCollectionGUID = original.LightmapCollectionGUID; render.LightmapTextureID = original.LightmapTextureID; render.Material = original.Material; } batches.Add(availibleBatch); availibleBatch.OnDestroyEvent += () => batches.Remove(availibleBatch); } if (availibleBatch != null) { availibleBatch.Add(bo); } return(availibleBatch); }
public void BatchObject(tmBatchObject render, bool move = true) { BatchObject(render, transform, move); }
public static void Convert(GameObject target) { // GameObject target = Selection.activeGameObject; Mesh mesh = null; MeshFilter mf = target.GetComponent <MeshFilter>(); bool isSkinned = false; if (mf != null) { mesh = mf.sharedMesh; } else { SkinnedMeshRenderer smr = target.GetComponent <SkinnedMeshRenderer>(); if (smr != null) { isSkinned = true; mesh = smr.sharedMesh; } } int index = 0; for (int i = 0; i < target.GetComponent <Renderer>().sharedMaterials.Length; i++) { Material mat = target.GetComponent <Renderer>().sharedMaterials[i]; Texture main = mat.mainTexture; Texture lightmap = mat.GetLightmapTexture(); if (mat.name.Equals("Shadows_LOW")) { main = AssetUtility.GetAssetsAtPath <Texture2D>("Obstacles/Shadow_LOW")[0]; mat = AssetUtility.GetAssetsAtPath <Material>("Materials/Shadows")[0]; } if (mat.name.Equals("Shadows_MEDIUM")) { main = AssetUtility.GetAssetsAtPath <Texture2D>("Obstacles/Shadow_MEDIUM")[0]; mat = AssetUtility.GetAssetsAtPath <Material>("Materials/Shadows")[0]; } GameObject g = null; if (!isSkinned && target.GetComponent <Renderer>().sharedMaterials.Length > 1) { g = new GameObject(target.name + index, typeof(MeshRenderer), typeof(MeshFilter)); g.name = target.name + index; g.transform.parent = target.transform; g.transform.localPosition = Vector3.zero; g.transform.localScale = Vector3.one; g.transform.localRotation = Quaternion.identity; } else { g = target; } tmTextureRenderBase render = null; g.GetComponent <Renderer>().sharedMaterial = mat; if (g.GetComponent <ParticleSystem>()) { render = g.AddComponent <tmParticleSystemRender>(); } if (main != null) { string path = AssetDatabase.GetAssetPath(main); tmTextureCollectionIndex inst = tmIndex.Instance.CollectionIndexForTexturePath(path); if (inst != null) { if (render == null) { render = g.AddComponent <tmTextureRender>(); } render.MainTexCollectionGUID = inst.textureCollectionGUID; render.MainTextureID = render.MainTexCollection.GetTextureDefenitionByName(main.name).textureGuid; } } if (lightmap != null) { string path = AssetDatabase.GetAssetPath(lightmap); tmTextureCollectionIndex inst = tmIndex.Instance.CollectionIndexForTexturePath(path); if (inst != null) { if (render == null) { render = g.AddComponent <tmTextureRender>(); } render.LightmapCollectionGUID = inst.textureCollectionGUID; render.LightmapTextureID = render.LightmapCollection.GetTextureDefenitionByName(lightmap.name).textureGuid; } } if (target.GetComponent <Renderer>().sharedMaterials.Length == 1) { SetSharedMesh(g, mesh); if (render != null) { render.Mesh = mesh; } } else if (mesh != null) { string meshName = mesh.name + "_" + index; string[] guids = AssetDatabase.FindAssets(meshName); if (guids.Length > 0) { int indexCount = mesh.GetIndices(index).Length; Object[] meshes = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GUIDToAssetPath(guids[0])); foreach (Object submesh in meshes) { Mesh subm = submesh as Mesh; if (subm != null) { if (subm.GetIndices(0).Length == indexCount) { SetSharedMesh(g, subm); if (render != null) { render.Mesh = subm; } g.name = subm.name; } } } } } if (render != null) { render.Material = tmMaterialUtility.SharedMaterial(mat); } { tmBatchObject bb = g.GetComponent <tmBatchObject>(); if (bb == null) { bb = g.AddComponent <tmBatchObject>(); } bb.SetUp(); } index++; } }
protected override void PostRecombine(CombineInstance[] combos) { int bones = 0; for (int i = 0, combosLength = combos.Length; i < combosLength; i++) { var mci = combos[i]; int meshHash = mci.mesh.GetInstanceID(); int meshBones; if (!bonesPerMesh.TryGetValue(meshHash, out meshBones)) { var bindposes = mci.mesh.bindposes;// here leak ~1kb per frame bool bonesExist = (bindposes != null) && bindposes.Length > 0; meshBones += bonesExist ? bindposes.Length : 1; bonesPerMesh.Add(meshHash, meshBones); } bones += meshBones; } tempBones = ArrayExtention.EnsureLength(tempBones, bones); tempBindPoses = ArrayExtention.EnsureLength(tempBindPoses, bones); tempBoneWeights = ArrayExtention.EnsureLength(tempBoneWeights, Mesh.vertexCount); int boneIndex = 0; int vertexIndexBase = 0; for (int partIndex = 0, partsCount = BatchedParts.Count; partIndex < partsCount; partIndex++) { tmBatchObject part = BatchedParts[partIndex]; SkinnedMeshRenderer partSMR = part.SkinnedMeshRender; if (partSMR) { Transform[] partBones = partSMR.bones; BoneWeight[] partWeights = part.Mesh.boneWeights; Matrix4x4[] partBindPoses = part.Mesh.bindposes; Matrix4x4 partToBatchMatrix = part.CachedTransform.worldToLocalMatrix * CachedTransform.localToWorldMatrix; int meshBonesCount = partBones.Length; for (int i = 0; i < meshBonesCount; i++) { tempBones[boneIndex + i] = partBones[i]; tempBindPoses[boneIndex + i] = partBindPoses[i] * partToBatchMatrix; } int partWeightsLength = partWeights.Length; for (int i = 0; i < partWeightsLength; i++) { BoneWeight bw = partWeights[i]; bw.boneIndex0 += boneIndex; bw.boneIndex1 += boneIndex; bw.boneIndex2 += boneIndex; bw.boneIndex3 += boneIndex; tempBoneWeights[vertexIndexBase] = bw; vertexIndexBase++; } boneIndex += meshBonesCount; } else { Transform bone = part.CachedTransform; tempBones[boneIndex] = bone; tempBindPoses[boneIndex] = bone.worldToLocalMatrix * CachedTransform.localToWorldMatrix; int curVertCount = part.Mesh.vertexCount; for (int vertexIndex = 0; vertexIndex < curVertCount; ++vertexIndex) { tempBoneWeights[vertexIndexBase].boneIndex0 = boneIndex; tempBoneWeights[vertexIndexBase].weight0 = 1; vertexIndexBase++; } boneIndex++; } } Mesh.boneWeights = tempBoneWeights; Mesh.bindposes = tempBindPoses; CachedSkinnedRender.quality = SkinQuality.Auto; CachedSkinnedRender.bones = tempBones; CachedSkinnedRender.sharedMesh = Mesh; CachedSkinnedRender.localBounds = Mesh.bounds; CachedSkinnedRender.enabled = (Mesh.vertexCount > 0); }
void RemoveFromForced(tmBatchObject part) { forcedParts.Remove(part); }
void AddToForced(tmBatchObject part) { forcedParts.Add(part); }
public void Recombine() { // update order if (OrderDirty && parts.Count > 0) { parts.Sort((a, b) => b.CachedTransform.position.z.CompareTo(a.CachedTransform.position.z)); } OrderDirty = false; // update mesh // recalc non empty meshes batchedParts.Clear(); foreach (var curObject in parts) { if (curObject.Mesh != null && curObject.Mesh.vertexCount > 0) { batchedParts.Add(curObject); } } if (batchedParts.Count > 0) { CachedTransform.position = Vector3.zero; tempCombos = ArrayExtention.EnsureLength(tempCombos, batchedParts.Count); for (int index = 0, partsCount = batchedParts.Count; index < partsCount; index++) { tmBatchObject part = batchedParts[index]; part.Batched = true; #if UNITY_EDITOR if (part.Mesh != null && !part.Mesh.isReadable) //this work only for batches without tmTextureRender { CustomDebug.Log(part.Mesh); string path = UnityEditor.AssetDatabase.GetAssetPath(part.Mesh); UnityEditor.ModelImporter mImporter = UnityEditor.AssetImporter.GetAtPath(path) as UnityEditor.ModelImporter; if (mImporter != null) { mImporter.isReadable = true; UnityEditor.AssetDatabase.ImportAsset(path, UnityEditor.ImportAssetOptions.ForceUpdate); } } #endif tempCombos[index].mesh = part.Mesh; tempCombos[index].subMeshIndex = 0; tempCombos[index].transform = CachedTransform.worldToLocalMatrix * part.CachedTransform.localToWorldMatrix; } Mesh.CombineMeshes(tempCombos, true); PostRecombine(tempCombos); } else { Mesh.Clear(); ClearMesh(); } Modified = false; }
public bool CanAdd(tmBatchObject part) { return((vertexCount + part.Mesh.vertexCount) < tmBatchingManager.VERTEX_LIMIT); }