// Build voxel object public override float Build(Storage voxels, Bounds bounds, Informer informer, object parameter) { processor.powerOfTwo = powerOfTwo; // Execute real build-up method float progress = processor.Build(voxels, bounds); // Check if processing has been finished if (progress >= 1) { // Check if this texture should be used by Voxel Mesh(es) if (voxelMeshUsage) { // Get all voxel meshes, which are attached to the game object Mesh[] voxelMeshes = gameObject.GetComponents <Mesh>(); if (voxelMeshes != null) { // Set processor to all meshes foreach (Mesh mesh in voxelMeshes) { mesh.voxelTexture2D = processor; } } } // Store file, if it is specified if (fileStoring && filePath != null && filePath.Length > 0 && Texture != null) { try { byte[] data; string path; // Build target path switch (fileFormat) { case FileFormat.JPG: case FileFormat.PNG: case FileFormat.TGA: case FileFormat.EXR: path = System.IO.Path.Combine(Application.dataPath, filePath); break; default: path = filePath; break; } switch (fileFormat) { case FileFormat.JPG: // Convert texture to JPEG data data = Texture.EncodeToJPG(100); break; case FileFormat.PNG: // Convert texture to PNG data data = Texture.EncodeToPNG(); break; case FileFormat.TGA: // Convert texture to TGA data data = Texture.EncodeToTGA(); break; case FileFormat.EXR: // Convert texture to EXR data data = Texture.EncodeToEXR(UnityEngine.Texture2D.EXRFlags.CompressZIP); break; default: data = null; break; } // Check for encoded data if (data != null) { // Make sure the target folders exist if (Helper.CreateDirectory(path, true)) { // Save data to file System.IO.File.WriteAllBytes(path, data); } } else { // Save texture as asset file Helper.StoreAsset(processor.Texture, path, null); } } catch (System.Exception exception) { Debug.Log(exception.Message); } } #if UNITY_EDITOR // Add object creation undo operation if (!Application.isPlaying) { UnityEditor.Undo.RegisterCreatedObjectUndo(processor.Texture, "\"VoxelTexture2D\" Creation"); } #endif // Execute informer callback informer?.Invoke(new UnityEngine.Object[] { processor.Texture }, parameter); } return(progress); }
// Build voxel object public override float Build(Storage voxels, Bounds bounds, Informer informer, object parameter) { processor.superSamplingCount = superSamplingCount; processor.powerOfTwo = powerOfTwo; processor.expandEdges = expandEdges; processor.backgroundColor = backgroundColor; processor.hdr = fileFormat == FileFormat.EXR; // Execute real build-up method float progress = processor.Build(voxels, bounds); // Check if processing has been finished if (progress >= 1) { // Store file, if it is specified if (fileStoring && filePath != null && filePath.Length > 0 && Texture != null) { try { // Build target path switch (fileFormat) { #if UNITY_2020_2_OR_NEWER case FileFormat.JPG: case FileFormat.PNG: case FileFormat.TGA: case FileFormat.EXR: var source = processor.Texture; if (source) { var sourceData = source.GetPixelData <byte>(0); if (sourceData != null) { var length = source.width * source.height * source.depth; //var textureWidth = Mathf.CeilToInt(Mathf.Sqrt(length)); var textureWidth = (int)Math.Pow(2, Math.Ceiling(Math.Log(Mathf.Sqrt(length)) / Math.Log(2))); var columnsCount = Mathf.CeilToInt((float)textureWidth / source.width); var rowsCount = Mathf.CeilToInt((float)source.depth / columnsCount); textureWidth = source.width * columnsCount; var textureHeight = source.height * rowsCount; var pixelSize = processor.hdr ? 8 : 4; var lineSize = source.width * pixelSize; var buffer = new byte[lineSize]; var targetData = new byte[textureWidth * textureHeight * pixelSize]; if (targetData != null) { var sourceOffset = 0; // Process depth slices for (int slice = 0; slice < source.depth; ++slice) { // Calculate column and row of the target sub image var column = slice % columnsCount; var row = rowsCount - slice / columnsCount - 1; // Process lines of the current slice for (int line = 0; line < source.height; ++line) { // Get data for line into the cache sourceData.GetSubArray(sourceOffset, lineSize).CopyTo(buffer); // Copy it to the target buffer Array.Copy(buffer, 0, targetData, (column + (line + row * source.height) * columnsCount) * lineSize, lineSize); sourceOffset += lineSize; } } byte[] data; switch (fileFormat) { case FileFormat.JPG: // Convert image data to JPEG data data = ImageConversion.EncodeArrayToJPG(targetData, source.graphicsFormat, (uint)textureWidth, (uint)textureHeight, 0, 100); break; case FileFormat.PNG: // Convert image data to PNG data data = ImageConversion.EncodeArrayToPNG(targetData, source.graphicsFormat, (uint)textureWidth, (uint)textureHeight); break; case FileFormat.TGA: // Convert image data to TGA data data = ImageConversion.EncodeArrayToTGA(targetData, source.graphicsFormat, (uint)textureWidth, (uint)textureHeight); break; case FileFormat.EXR: // Convert image data to EXR data data = ImageConversion.EncodeArrayToEXR(targetData, source.graphicsFormat, (uint)textureWidth, (uint)textureHeight, 0, UnityEngine.Texture2D.EXRFlags.CompressZIP); break; default: data = null; break; } if (data != null) { // Make sure the target folders exist var path = System.IO.Path.Combine(Application.dataPath, filePath); if (Helper.CreateDirectory(path, true)) { #if UNITY_EDITOR // Remove existing asset file if (System.IO.File.Exists(path)) { System.IO.File.Delete(path); } // Update database UnityEditor.AssetDatabase.Refresh(); #endif // Save data to file System.IO.File.WriteAllBytes(path, data); #if UNITY_EDITOR // Store columns and rows for the asset to be applied later voxelTexturePaths.Add(System.IO.Path.GetFullPath(path), new Vector2Int(columnsCount, rowsCount)); // Update database to enable changing import settings UnityEditor.AssetDatabase.Refresh(); #endif } } } } } break; #endif default: // Save texture as asset file Helper.StoreAsset(processor.Texture, filePath, null); break; } } catch (System.Exception exception) { Debug.Log(exception.Message); } } #if UNITY_EDITOR // Add object creation undo operation if (!Application.isPlaying) { UnityEditor.Undo.RegisterCreatedObjectUndo(processor.Texture, "\"VoxelTexture3D\" Creation"); } #endif // Execute informer callback informer?.Invoke(new UnityEngine.Object[] { processor.Texture }, parameter); } return(progress); }