public void HLODDataTest() { using (Stream stream = new FileStream(mHlodArtifactName, FileMode.Open, FileAccess.Read)) { HLODData data = HLODDataSerializer.Read(stream); Assert.AreEqual(0, data.GetMaterialCount()); Assert.AreEqual(85, data.GetObjects().Count); } }
private TextureFormat GetCompressFormat(HLODData data, BuildTargetGroup group) { if (group == BuildTargetGroup.Android) { return(data.CompressionData.AndroidTextureFormat); } if (group == BuildTargetGroup.iOS) { return(data.CompressionData.iOSTextureFormat); } if (group == BuildTargetGroup.tvOS) { return(data.CompressionData.tvOSTextureFormat); } if (group == BuildTargetGroup.WebGL) { return(data.CompressionData.WebGLTextureFormat); } return(data.CompressionData.PCTextureFormat); }
public override void OnEnable() { base.OnEnable(); string path = AssetDatabase.GetAssetPath(serializedObject.targetObject); using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { HLODData data = HLODDataSerializer.Read(stream); long totalTextureSize = 0; long totalMeshSize = 0; var serializableMaterials = data.GetMaterials(); for (int mi = 0; mi < serializableMaterials.Count; ++mi) { var material = serializableMaterials[mi]; for (int ti = 0; ti < material.GetTextureCount(); ++ti) { var texture = material.GetTexture(ti); totalTextureSize += texture.BytesLength; m_texture.Add(new KeyValuePair <string, string>(texture.TextureName, FormattingSize(texture.BytesLength))); } } var serializableObjects = data.GetObjects(); for (int oi = 0; oi < serializableObjects.Count; ++oi) { var mesh = serializableObjects[oi].GetMesh(); int meshSpaceUsage = mesh.GetSpaceUsage(); totalMeshSize += meshSpaceUsage; m_mesh.Add(new KeyValuePair <string, string>(mesh.Name, FormattingSize(meshSpaceUsage))); } m_totalTexture = FormattingSize(totalTextureSize); m_totalMesh = FormattingSize(totalMeshSize); } }
public void Build(SpaceNode rootNode, DisposableList <HLODBuildInfo> infos, GameObject root, float cullDistance, float lodDistance, bool writeNoPrefab, bool extractMaterial, Action <float> onProgress) { dynamic options = m_streamingOptions; string path = options.OutputDirectory; HLODTreeNodeContainer container = new HLODTreeNodeContainer(); HLODTreeNode convertedRootNode = ConvertNode(container, rootNode); //create settings if there is no settings. if (AddressableAssetSettingsDefaultObject.Settings == null) { AddressableAssetSettings.Create(AddressableAssetSettingsDefaultObject.kDefaultConfigFolder, AddressableAssetSettingsDefaultObject.kDefaultConfigAssetName, true, true); } var settings = AddressableAssetSettingsDefaultObject.GetSettings(true); var group = GetGroup(settings, options.AddressablesGroupName); m_shaderGuids.Clear(); if (onProgress != null) { onProgress(0.0f); } HLODData.TextureCompressionData compressionData; compressionData.PCTextureFormat = options.PCCompression; compressionData.WebGLTextureFormat = options.WebGLCompression; compressionData.AndroidTextureFormat = options.AndroidCompression; compressionData.iOSTextureFormat = options.iOSCompression; compressionData.tvOSTextureFormat = options.tvOSCompression; string filenamePrefix = $"{path}{root.name}"; if (Directory.Exists(path) == false) { Directory.CreateDirectory(path); } Dictionary <int, HLODData> hlodDatas = new Dictionary <int, HLODData>(); for (int i = 0; i < infos.Count; ++i) { if (hlodDatas.ContainsKey(infos[i].ParentIndex) == false) { HLODData newData = new HLODData(); newData.CompressionData = compressionData; hlodDatas.Add(infos[i].ParentIndex, newData); } HLODData data = hlodDatas[infos[i].ParentIndex]; data.AddFromWokringObjects(infos[i].Name, infos[i].WorkingObjects); data.AddFromWorkingColliders(infos[i].Name, infos[i].Colliders); if (writeNoPrefab) { if (hlodDatas.ContainsKey(i) == false) { HLODData newData = new HLODData(); newData.CompressionData = compressionData; hlodDatas.Add(i, newData); } HLODData prefabData = hlodDatas[i]; var spaceNode = infos[i].Target; for (int oi = 0; oi < spaceNode.Objects.Count; ++oi) { if (PrefabUtility.IsAnyPrefabInstanceRoot(spaceNode.Objects[oi]) == false) { prefabData.AddFromGameObject(spaceNode.Objects[oi]); } } } if (onProgress != null) { onProgress((float)i / (float)infos.Count); } } if (extractMaterial) { ExtractMaterial(hlodDatas, filenamePrefix); } Dictionary <int, RootData> rootDatas = new Dictionary <int, RootData>(); foreach (var item in hlodDatas) { string filename = $"{filenamePrefix}_group{item.Key}.hlod"; using (Stream stream = new FileStream(filename, FileMode.Create)) { HLODDataSerializer.Write(stream, item.Value); stream.Close(); } AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate); RootData rootData = AssetDatabase.LoadAssetAtPath <RootData>(filename); m_manager.AddGeneratedResource(rootData); AddAddress(settings, group, rootData); rootDatas.Add(item.Key, rootData); } var addressableController = root.AddComponent <AddressableHLODController>(); for (int i = 0; i < infos.Count; ++i) { var spaceNode = infos[i].Target; var hlodTreeNode = convertedTable[infos[i].Target]; for (int oi = 0; oi < spaceNode.Objects.Count; ++oi) { int highId = -1; GameObject obj = spaceNode.Objects[oi]; if (PrefabUtility.IsPartOfAnyPrefab(obj) == false) { GameObject rootGameObject = null; if (rootDatas.ContainsKey(i)) { rootGameObject = rootDatas[i].GetRootObject(obj.name); } if (rootGameObject != null) { GameObject go = PrefabUtility.InstantiatePrefab(rootGameObject) as GameObject; go.transform.SetParent(obj.transform.parent); go.transform.localPosition = obj.transform.localPosition; go.transform.localRotation = obj.transform.localRotation; go.transform.localScale = obj.transform.localScale; if (m_manager.IsGeneratedResource(obj)) { m_manager.AddGeneratedResource(go); } else { m_manager.AddConvertedPrefabResource(go); } spaceNode.Objects.Add(go); Object.DestroyImmediate(obj); continue; } } var address = GetAddress(spaceNode.Objects[oi]); if (string.IsNullOrEmpty(address) && PrefabUtility.IsAnyPrefabInstanceRoot(spaceNode.Objects[oi])) { AddAddress(settings, group, spaceNode.Objects[oi]); address = GetAddress(spaceNode.Objects[oi]); } if (address != null) { highId = addressableController.AddHighObject(address, spaceNode.Objects[oi]); } else { highId = addressableController.AddHighObject(spaceNode.Objects[oi]); } hlodTreeNode.HighObjectIds.Add(highId); } { if (rootDatas[infos[i].ParentIndex].GetRootObject(infos[i].Name) != null) { string filename = $"{filenamePrefix}_group{infos[i].ParentIndex}.hlod"; int lowId = addressableController.AddLowObject(filename + "[" + infos[i].Name + "]"); hlodTreeNode.LowObjectIds.Add(lowId); } } } var shaderEntriesAdded = new List <AddressableAssetEntry>(); foreach (var shaderGuid in m_shaderGuids) { if (IsExistsInAddressables(shaderGuid) == false) { shaderEntriesAdded.Add(settings.CreateOrMoveEntry(shaderGuid, group, false, false)); } } settings.SetDirty(AddressableAssetSettings.ModificationEvent.EntryMoved, shaderEntriesAdded, true); m_shaderGuids.Clear(); addressableController.Container = container; addressableController.Root = convertedRootNode; addressableController.CullDistance = cullDistance; addressableController.LODDistance = lodDistance; }
public override void OnImportAsset(AssetImportContext ctx) { ctx.DependsOnCustomDependency("HLODSystemPlatform"); var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(ctx.selectedBuildTarget); try { UpdateProgress(ctx.assetPath, 0, 1); using (Stream stream = new FileStream(ctx.assetPath, FileMode.Open, FileAccess.Read)) { HLODData data = HLODDataSerializer.Read(stream); RootData rootData = RootData.CreateInstance <RootData>(); TextureFormat compressFormat = GetCompressFormat(data, buildTargetGroup); int currentProgress = 0; int maxProgress = 0; if (data.GetMaterials() != null) { maxProgress += data.GetMaterials().Count; } if (data.GetObjects() != null) { maxProgress += data.GetObjects().Count; } if (data.GetColliders() != null) { maxProgress += data.GetColliders().Count; } rootData.name = "Root"; var serializableMaterials = data.GetMaterials(); var loadedMaterials = new Dictionary <string, Material>(); if (serializableMaterials != null) { for (int mi = 0; mi < serializableMaterials.Count; ++mi) { UpdateProgress(ctx.assetPath, currentProgress++, maxProgress); var sm = serializableMaterials[mi]; if (loadedMaterials.ContainsKey(sm.ID)) { continue; } Material mat = sm.To(); loadedMaterials.Add(sm.ID, mat); if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(mat)) == false) { continue; } ctx.AddObjectToAsset(mat.name, mat); for (int ti = 0; ti < sm.GetTextureCount(); ++ti) { HLODData.SerializableTexture st = sm.GetTexture(ti); Texture2D texture = st.To(); EditorUtility.CompressTexture(texture, compressFormat, TextureCompressionQuality.Normal); mat.SetTexture(st.Name, texture); ctx.AddObjectToAsset(texture.name, texture); } mat.EnableKeyword("_NORMALMAP"); } } var serializableObjects = data.GetObjects(); var serializableColliders = data.GetColliders(); Dictionary <string, List <GameObject> > createdGameObjects = new Dictionary <string, List <GameObject> >(); Dictionary <string, GameObject> createdColliders = new Dictionary <string, GameObject>(); if (serializableObjects != null) { for (int oi = 0; oi < serializableObjects.Count; ++oi) { UpdateProgress(ctx.assetPath, currentProgress++, maxProgress); var so = serializableObjects[oi]; GameObject go = new GameObject(); go.name = so.Name; MeshFilter mf = go.AddComponent <MeshFilter>(); MeshRenderer mr = go.AddComponent <MeshRenderer>(); List <string> materialIds = so.GetMaterialIds(); List <Material> materials = new List <Material>(); for (int mi = 0; mi < materialIds.Count; ++mi) { string id = materialIds[mi]; if (loadedMaterials.ContainsKey(id)) { materials.Add(loadedMaterials[id]); } else { string path = AssetDatabase.GUIDToAssetPath(id); if (string.IsNullOrEmpty(path) == false) { materials.Add(AssetDatabase.LoadAssetAtPath <Material>(path)); } else { materials.Add(null); } } } Mesh mesh = so.GetMesh().To(); mf.sharedMesh = mesh; mr.sharedMaterials = materials.ToArray(); mr.lightProbeUsage = so.LightProbeUsage; ctx.AddObjectToAsset(mesh.name, mesh); if (createdGameObjects.ContainsKey(go.name) == false) { createdGameObjects.Add(go.name, new List <GameObject>()); } createdGameObjects[go.name].Add(go); } } if (serializableColliders != null) { for (int ci = 0; ci < serializableColliders.Count; ++ci) { UpdateProgress(ctx.assetPath, currentProgress++, maxProgress); var sc = serializableColliders[ci]; GameObject go; if (createdColliders.ContainsKey(sc.Name) == false) { createdColliders[sc.Name] = new GameObject("Collider"); } go = createdColliders[sc.Name]; var collider = sc.CreateGameObject(); if (collider != null) { collider.name = "Collider" + ci; collider.transform.SetParent(go.transform, true); } } } foreach (var objects in createdGameObjects.Values) { GameObject root; if (objects.Count > 1) { root = new GameObject(); root.name = objects[0].name; for (int i = 0; i < objects.Count; ++i) { objects[i].name = objects[i].name + "_" + i; objects[i].transform.SetParent(root.transform, true); } } else { root = objects[0]; } if (createdColliders.ContainsKey(root.name)) { createdColliders[root.name].transform.SetParent(root.transform, true); } rootData.SetRootObject(root.name, root); ctx.AddObjectToAsset(root.name, root); } ctx.AddObjectToAsset("Root", rootData); ctx.SetMainObject(rootData); } } finally { EditorUtility.ClearProgressBar(); } }
public static void Write(Stream stream, HLODData data) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, data); }
public void Build(SpaceNode rootNode, DisposableList <HLODBuildInfo> infos, GameObject root, float cullDistance, float lodDistance, bool writeNoPrefab, bool extractMaterial, Action <float> onProgress) { dynamic options = m_streamingOptions; string path = options.OutputDirectory; HLODTreeNodeContainer container = new HLODTreeNodeContainer(); HLODTreeNode convertedRootNode = ConvertNode(container, rootNode); if (onProgress != null) { onProgress(0.0f); } HLODData.TextureCompressionData compressionData; compressionData.PCTextureFormat = options.PCCompression; compressionData.WebGLTextureFormat = options.WebGLCompression; compressionData.AndroidTextureFormat = options.AndroidCompression; compressionData.iOSTextureFormat = options.iOSCompression; compressionData.tvOSTextureFormat = options.tvOSCompression; string filename = $"{path}{root.name}.hlod"; if (Directory.Exists(path) == false) { Directory.CreateDirectory(path); } using (Stream stream = new FileStream(filename, FileMode.Create)) { HLODData data = new HLODData(); data.CompressionData = compressionData; for (int i = 0; i < infos.Count; ++i) { data.AddFromWokringObjects(infos[i].Name, infos[i].WorkingObjects); data.AddFromWorkingColliders(infos[i].Name, infos[i].Colliders); if (onProgress != null) { onProgress((float)i / (float)infos.Count); } } if (writeNoPrefab) { for (int ii = 0; ii < infos.Count; ++ii) { var spaceNode = infos[ii].Target; for (int oi = 0; oi < spaceNode.Objects.Count; ++oi) { if (PrefabUtility.IsAnyPrefabInstanceRoot(spaceNode.Objects[oi]) == false) { data.AddFromGameObject(spaceNode.Objects[oi]); } } } } if (extractMaterial == true) { ExtractMaterial(data, $"{path}{root.name}"); } HLODDataSerializer.Write(stream, data); } AssetDatabase.ImportAsset(filename, ImportAssetOptions.ForceUpdate); RootData rootData = AssetDatabase.LoadAssetAtPath <RootData>(filename); m_manager.AddGeneratedResource(rootData); var defaultController = root.AddComponent <DefaultHLODController>(); GameObject hlodRoot = new GameObject("HLODRoot"); hlodRoot.transform.SetParent(root.transform, false); m_manager.AddGeneratedResource(hlodRoot); for (int ii = 0; ii < infos.Count; ++ii) { var spaceNode = infos[ii].Target; var hlodTreeNode = convertedTable[infos[ii].Target]; for (int oi = 0; oi < spaceNode.Objects.Count; ++oi) { GameObject obj = spaceNode.Objects[oi]; GameObject rootGameObject = rootData.GetRootObject(obj.name); if (rootGameObject != null) { GameObject go = PrefabUtility.InstantiatePrefab(rootGameObject) as GameObject; go.transform.SetParent(obj.transform.parent); go.transform.localPosition = obj.transform.localPosition; go.transform.localRotation = obj.transform.localRotation; go.transform.localScale = obj.transform.localScale; int highId = defaultController.AddHighObject(go); hlodTreeNode.HighObjectIds.Add(highId); if (m_manager.IsGeneratedResource(obj)) { m_manager.AddGeneratedResource(go); } else { m_manager.AddConvertedPrefabResource(go); } Object.DestroyImmediate(obj); } else { int highId = defaultController.AddHighObject(obj); hlodTreeNode.HighObjectIds.Add(highId); } } if (infos[ii].WorkingObjects.Count > 0) { GameObject prefab = rootData.GetRootObject(infos[ii].Name); if (prefab == null) { Debug.LogError("Prefab not found: " + infos[ii].Name); } else { GameObject go = PrefabUtility.InstantiatePrefab(prefab) as GameObject; go.transform.SetParent(hlodRoot.transform, false); go.SetActive(false); int lowId = defaultController.AddLowObject(go); hlodTreeNode.LowObjectIds.Add(lowId); m_manager.AddGeneratedResource(go); } } } defaultController.Container = container; defaultController.Root = convertedRootNode; defaultController.CullDistance = cullDistance; defaultController.LODDistance = lodDistance; }
private void ExtractMaterial(HLODData hlodData, string filenamePrefix) { Dictionary <string, HLODData.SerializableMaterial> extractedMaterials = new Dictionary <string, HLODData.SerializableMaterial>(); //save files to disk foreach (var hlodMaterial in hlodData.GetMaterials()) { string id = hlodMaterial.ID; hlodMaterial.GetTextureCount(); Material mat = hlodMaterial.To(); for (int ti = 0; ti < hlodMaterial.GetTextureCount(); ++ti) { var serializeTexture = hlodMaterial.GetTexture(ti); Texture2D texture = serializeTexture.To(); byte[] bytes = texture.EncodeToPNG(); string textureFilename = $"{filenamePrefix}_{mat.name}_{serializeTexture.TextureName}.png"; File.WriteAllBytes(textureFilename, bytes); AssetDatabase.ImportAsset(textureFilename); var assetImporter = AssetImporter.GetAtPath(textureFilename); var textureImporter = assetImporter as TextureImporter; if (textureImporter) { textureImporter.wrapMode = serializeTexture.WrapMode; textureImporter.sRGBTexture = GraphicsFormatUtility.IsSRGBFormat(serializeTexture.GraphicsFormat); textureImporter.SaveAndReimport(); } var storedTexture = AssetDatabase.LoadAssetAtPath <Texture>(textureFilename); m_manager.AddGeneratedResource(storedTexture); mat.SetTexture(serializeTexture.Name, storedTexture); } string matFilename = $"{filenamePrefix}_{mat.name}.mat"; AssetDatabase.CreateAsset(mat, matFilename); AssetDatabase.ImportAsset(matFilename); var storedMaterial = AssetDatabase.LoadAssetAtPath <Material>(matFilename); m_manager.AddGeneratedResource(storedMaterial); using (WorkingMaterial newWM = new WorkingMaterial(Collections.Allocator.Temp, storedMaterial)) { var newSM = new HLODData.SerializableMaterial(); newSM.From(newWM); extractedMaterials.Add(id, newSM); } } //apply to HLODData var materials = hlodData.GetMaterials(); for (int i = 0; i < materials.Count; ++i) { if (extractedMaterials.ContainsKey(materials[i].ID) == false) { continue; } materials[i] = extractedMaterials[materials[i].ID]; } var objects = hlodData.GetObjects(); for (int oi = 0; oi < objects.Count; ++oi) { var matIds = objects[oi].GetMaterialIds(); for (int mi = 0; mi < matIds.Count; ++mi) { if (extractedMaterials.ContainsKey(matIds[mi]) == false) { continue; } matIds[mi] = extractedMaterials[matIds[mi]].ID; } } }