示例#1
0
        void GenerateMaterialTexture2D(VoxModel model)
        {
            var texture = new Texture2D(256, 1,
                                        TextureFormat.RGBA32, false)
            {
                name       = "Color",
                wrapMode   = TextureWrapMode.Clamp,
                filterMode = FilterMode.Point
            };

            texture.SetPixels(model.palette);

            var materials = VoxMesher.MaterialChunkToVector4(model.materialChunks);
            var material  = new Texture2D(256, 1,
                                          TextureFormat.RGBA32, false)
            {
                name       = "Material",
                wrapMode   = TextureWrapMode.Clamp,
                filterMode = FilterMode.Point
            };

            material.SetPixels(materials.Select(x =>
                                                new Color(x.x, x.y, x.z, x.w)).ToArray());
            Merge(model, texture, material);
        }
示例#2
0
 /// <summary>
 /// Clears model data
 /// </summary>
 /// <param name="model"></param>
 private void ResetModel(VoxModel model)
 {
     model.palette = null;
     if (model.voxelFrames != null)
     {
         model.voxelFrames.Clear();
     }
     else
     {
         model.voxelFrames = new List <VoxelData>();
     }
     if (model.meshes != null)
     {
         model.meshes.Clear();
     }
     else
     {
         model.meshes = new List <MeshLODs>();
     }
     model.materialChunks.Clear();
     model.transformNodeChunks.Clear();
     model.groupNodeChunks.Clear();
     model.shapeNodeChunks.Clear();
     model.layerChunks.Clear();
     model.rendererSettingChunks.Clear();
 }
示例#3
0
        public Mesh MeshVoxelData(VoxModel data, VoxelData frame, Mesh result)
        {
            var scale        = data.Settings.modelScale;
            var grid         = frame;
            var colorList    = data.palette;
            var materialList = MaterialChunkToVector4(data.materialChunks);
            var origin       = data.Settings.origin;

            return(MeshVoxelData(scale * Vector3.one, grid, colorList, materialList, origin, result));
        }
示例#4
0
        public override void OnInspectorGUI()
        {
            var model = target as VoxModel;

            if (targetModel == null || model != targetModel)
            {
                //filePath = model.modelSource;
                targetModel = model;
            }
            GUILayout.BeginHorizontal();
            GUILayout.Label("Input File", GUILayout.ExpandWidth(false));
            GUI.enabled = false;

            GUILayout.TextArea(filePath.Replace(Application.dataPath, ""));
            GUI.enabled = true;

            if (GUILayout.Button("…", GUILayout.ExpandWidth(false)))
            {
                filePath = EditorUtility.OpenFilePanel("Open model", EditorPrefs.GetString("LastVoxPath", Application.dataPath), "vox");
                if (File.Exists(filePath))
                {
                    EditorPrefs.SetString("LastVoxPath", filePath);
                }
            }
            GUILayout.EndHorizontal();
            if (filePath != string.Empty)
            {
                if (GUILayout.Button("➡Generate Model", GUILayout.ExpandWidth(false)))
                {
                    try {
                        EditorUtility.DisplayProgressBar("Vox", "", 0);
                        GenerateModel(filePath, model, targetModel);
                    } catch (System.Exception ex) {
                        Debug.LogException(ex);
                    } finally {
                        EditorUtility.ClearProgressBar();
                    }
                }

                if (GUILayout.Button("Gen Texture 3D", GUILayout.ExpandWidth(false)))
                {
                    GenerateTex3D(model);
                }
                if (GUILayout.Button("Gen Color/Material Texture 2D", GUILayout.ExpandWidth(false)))
                {
                    GenerateMaterialTexture2D(model);
                }
            }

            EditorGUILayout.Separator();

            base.OnInspectorGUI();
        }
示例#5
0
 void BuildLODGroups(VoxModel model, List <GameObject> targets)
 {
     for (int i = 0; i < model.meshes.Count; i++)
     {
         var modelGO = targets[i];
         var frame   = model.meshes[i];
         if (frame.LODs.Any(m => m.opaque != null && m.opaque.triangles.Length > 0))
         {
             BuildLODGroup(frame, m => m.opaque, model, modelGO,
                           $"Model[{i}].opaque", model.Settings.materialOpaque);
         }
         if (frame.LODs
             .Any(m => m.transparent != null && m.transparent.triangles.Length > 0))
         {
             BuildLODGroup(frame, m => m.transparent, model, modelGO,
                           $"Model[{i}].transparent", model.Settings.materialTransparent);
         }
     }
 }
示例#6
0
        void BuildContentNode(VoxModel model, GameObject parent, int node, NodeType type, List <GameObject> models, GameObject[] gos)
        {
            switch (type)
            {
            case NodeType.Group:
                foreach (var childId in model.groupNodeChunks.First(c => c.id == node).childIds)
                {
                    gos[childId].transform.SetParent(parent.transform);
                }
                break;

            case NodeType.Shape:
                foreach (var sm in model.shapeNodeChunks.First(c => c.id == node).models)
                {
                    var child = Instantiate(models[sm.modelId], parent.transform);
                    child.name = $"Model[{sm.modelId}]";
                }
                break;
            }
        }
示例#7
0
 /// <summary>
 /// Clears model data
 /// </summary>
 /// <param name="model"></param>
 private void resetModel(VoxModel model)
 {
     model.pallete = null;
     if (model.meshData != null)
     {
         model.meshData.Clear();
     }
     else
     {
         model.meshData = new List <VoxelData>();
     }
     if (model.meshes != null)
     {
         model.meshes.Clear();
     }
     else
     {
         model.meshes = new List <Mesh>();
     }
 }
示例#8
0
        void Merge(VoxModel model, IEnumerable <Texture3D> textures)
        {
            var subAssets     = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(model));
            var assetTextures = subAssets
                                .Select(s => s as Texture3D)
                                .Where(s => s != null)
                                .ToArray();

            foreach (var go in assetTextures)
            {
                DestroyImmediate(go, true);
            }

            foreach (var texture in textures)
            {
                AssetDatabase.AddObjectToAsset(texture, targetModel);
            }
            EditorUtility.SetDirty(targetModel);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }
示例#9
0
        public bool LoadModel(string absolutePath, VoxModel output)
        {
            //Load the whole file
            BinaryReader reader = new BinaryReader(new MemoryStream(File.ReadAllBytes(absolutePath)));
            string       head   = new string(reader.ReadChars(4));

            if (!head.Equals(HEADER))
            {
                Debug.LogError("Not a MagicaVoxel File!");
                return(false);
            }
            int version = reader.ReadInt32();

            if (version != VERSION)
            {
                Debug.LogWarning("Version number:" + version + " Was designed for " + VERSION);
            }
            resetModel(output);
            childCount = 0;
            while (reader.BaseStream.Position != reader.BaseStream.Length)
            {
                ReadChunk(reader, output);
            }
            reader.Close();
            if (output.pallete == null)
            {
                output.pallete = LoadDefaultPallete();
            }
            VoxMesher mesher = new VoxMesher();

            for (int i = 0; i < output.meshData.Count; i++)
            {
                Mesh m = new Mesh();
                mesher.MeshVoxelData(output, i, m);
                output.meshes.Add(m);
            }
            return(true);
        }
示例#10
0
        GameObject BuildLODGroup(MeshLODs list, MeshSelector selector,
                                 VoxModel model, GameObject modelGO, string name, Material material)
        {
            var go = new GameObject(name);

            go.transform.SetParent(modelGO.transform);
            var g = go.AddComponent <LODGroup>();

            g.SetLODs(list.LODs.Select((m, l) => selector(list.LODs[l])).Select((m, l) => {
                var goLOD = new GameObject(l.ToString(),
                                           typeof(MeshFilter), typeof(MeshRenderer));
                goLOD.transform.SetParent(go.transform);
                var h = Mathf.Pow(2 - (model.Settings.LODBias / 16f), -l);
                //Debug.Log(h);
                var r         = new[] { goLOD.GetComponent <MeshRenderer>(), };
                r[0].material = material;
                var mf        = goLOD.GetComponent <MeshFilter>();
                mf.mesh       = m;
                return(new LOD(h, r));
            }).ToArray());
            g.RecalculateBounds();
            return(go);
        }
示例#11
0
        private void ReadChunk(BinaryReader reader, VoxModel output)
        {
            string chunkName      = new string(reader.ReadChars(4));
            int    chunkSize      = reader.ReadInt32();
            int    childChunkSize = reader.ReadInt32();

            //get current chunk bytes and process
            byte[]       chunk       = reader.ReadBytes(chunkSize);
            byte[]       children    = reader.ReadBytes(childChunkSize);
            BinaryReader chunkReader = new BinaryReader(new MemoryStream(chunk));

            switch (chunkName)
            {
            case MAIN:
                break;

            case SIZE:
                int w = chunkReader.ReadInt32();
                int h = chunkReader.ReadInt32();
                int d = chunkReader.ReadInt32();
                output.meshData[childCount].Resize(w, d, h);
                childCount++;
                break;

            case XYZ:
                Vector3   pos = new Vector3();
                int       voxelCount = chunkReader.ReadInt32();
                VoxelData frame = output.meshData[childCount - 1];
                byte      x, y, z;
                for (int i = 0; i < voxelCount; i++)
                {
                    x   = chunkReader.ReadByte();
                    y   = chunkReader.ReadByte();
                    z   = chunkReader.ReadByte();
                    pos = toUnity * pos;
                    frame.Set(x, z, y, (byte)(chunkReader.ReadByte()));
                }
                break;

            case RGBA:
                output.pallete = LoadPallete(chunkReader);
                break;

            case MATT:
                break;

            case PACK:
                int frameCount = chunkReader.ReadInt32();
                for (int i = 0; i < frameCount; i++)
                {
                    output.meshData.Add(new VoxelData());
                }
                break;

            default:
                Debug.LogError("Unknown chunk id \"" + chunkName + "\"");
                break;
            }
            //read child chunks
            chunkReader.Close();
            BinaryReader childReader = new BinaryReader(new MemoryStream(children));

            while (childReader.BaseStream.Position != childReader.BaseStream.Length)
            {
                ReadChunk(childReader, output);
            }
            childReader.Close();
        }
示例#12
0
        GameObject BuildSceneGraph(VoxModel model, List <GameObject> models)
        {
            if (!model.transformNodeChunks.Any())
            {
                return(null);
            }
            var chunks = model.transformNodeChunks.Cast <NodeChunk>()
                         .Concat(model.groupNodeChunks)
                         .Concat(model.shapeNodeChunks)
                         .ToDictionary(x => x.id, x => x);

            var gos = Enumerable.Range(0, chunks.Count).Select(i => {
                switch (chunks[i].Type)
                {
                default:
                case NodeType.Transform:
                    return(new GameObject());

                case NodeType.Group:
                    return(null);

                case NodeType.Shape:
                    return(null);
                }
            }).ToArray();

            var toVox = Quaternion.Inverse(MagicaVoxelParser.toUnity);

            foreach (var t in model.transformNodeChunks)
            {
                Vector3 scale;
                var     rotation = GetTransform(t.RotationAt(0), out scale);
                rotation.x *= -1;
                rotation.z *= -1;
                //rotation.w *= -1;
                gos[t.id].transform.localScale = scale;
                var translation = t.TranslationAt(0) * model.Settings.modelScale;
                translation.z = -translation.z;
                gos[t.id].transform.localPosition = translation;
                gos[t.id].transform.localRotation = rotation * toVox;
                //Debug.Log($"t{t.id}→{t.childId}");
                BuildContentNode(model, gos[t.id], t.childId, chunks[t.childId].Type, models, gos);
                var go = gos[t.id];
                go.name = t.Name;
                if (go.name == string.Empty)
                {
                    go.name = $"Transform[{t.id}]";
                }
                go.SetActive(!t.Hidden && !(t.layerId >= 0 && model.layerChunks.ElementAt(t.layerId).Hidden));
            }

            if (gos.Any())
            {
                var root = gos.First();
                root.name = model.name;
                var translation = MagicaVoxelParser.toUnity * root.transform.localPosition;
                var rotation    = root.transform.localRotation * MagicaVoxelParser.toUnity * MagicaVoxelParser.toUnity;
                translation.z = -translation.z;
                rotation.w   *= -1;
                root.transform.localPosition = translation;
                root.transform.localScale    = new Vector3(
                    -root.transform.localScale.x, root.transform.localScale.y, -root.transform.localScale.z);
                root.transform.localRotation = rotation;
                return(root);
            }
            return(null);
        }
示例#13
0
        GameObject GenerateModel(VoxModel model, AssetImportContext ctx)
        {
            var parser = new MagicaVoxelParser();

            parser.LoadModel(ctx.assetPath, model,
                             s => EditorUtility.DisplayProgressBar("vox", s, 0));

            var subAssets = new List <Object>();

            ctx.GetObjects(subAssets);
            var assetMeshes = subAssets
                              .Select(s => s as Mesh)
                              .Where(s => s != null)
                              .ToArray();
            var updateOpaque      = false;
            var updateTransparent = false;

            var uv3 = new List <Vector4>();

            var assetIndex = 0;

            for (int i = 0; i < model.meshes.Count; i++)
            {
                for (int l = 0; l < model.meshes[i].LODs.Count; l++)
                {
                    MeshSet m;
                    //get mesh
                    m.opaque      = assetIndex < assetMeshes.Length ? assetMeshes[assetIndex++] : null;
                    m.transparent = assetIndex < assetMeshes.Length ? assetMeshes[assetIndex++] : null;
                    updateOpaque  = m.opaque == null;
                    if (updateOpaque)
                    {
                        m.opaque = new Mesh();
                    }
                    updateTransparent = m.transparent == null;
                    if (updateTransparent)
                    {
                        m.transparent = new Mesh();
                    }

                    //turn temp meshes into assets

                    EditorUtility.DisplayProgressBar("vox",
                                                     $"asset: frame={i}/{model.meshes.Count}, lod={l}/{model.meshes[i].LODs.Count}",
                                                     .5f + (.5f * i) / model.voxelFrames.Count);
                    var frame = model.meshes[i].LODs[l];
                    BuildMesh(m.opaque, frame.opaque,
                              $"{name}.{i}.{l}.opaque", uv3, model.Settings.OmitsUVUnwrapping);
                    BuildMesh(m.transparent, frame.transparent,
                              $"{name}.{i}.{l}.transparent", uv3, model.Settings.OmitsUVUnwrapping);
                    //new mesh
                    if (updateOpaque)
                    {
                        ctx.AddObjectToAsset(m.opaque.name, m.opaque);
                    }
                    if (updateTransparent)
                    {
                        ctx.AddObjectToAsset(m.transparent.name, m.transparent);
                    }
                    model.meshes[i].LODs[l] = m;
                }
            }

            var baseGO = ctx.mainObject as GameObject;

            if (baseGO == null)
            {
                baseGO = new GameObject();
                ctx.AddObjectToAsset("main", baseGO);
                ctx.SetMainObject(baseGO);
            }
            var gos = Enumerable.Range(0, baseGO.transform.childCount)
                      .Select(i => baseGO.transform.GetChild(i))
                      .Select(t => t.gameObject)
                      .ToList();
            var gosCount = gos.Count;

            for (int i = gosCount; i < model.meshes.Count; i++)
            {
                var target = new GameObject();
                target.transform.SetParent(baseGO.transform);
                gos.Add(target.gameObject);
            }
            BuildLODGroups(model, gos);
            if (model.Settings.asSceneGraph)
            {
                var root = BuildSceneGraph(model, gos);
                DestroyImmediate(baseGO);
                baseGO = root;
                ctx.AddObjectToAsset("main", root);
                ctx.SetMainObject(root);
            }
            //destroy unneeded meshes
            var meshSetContained = model.meshes.SelectMany(x => x.LODs).ToArray();

            foreach (var go in subAssets
                     .Where(s => (s as Mesh) != null)
                     .Where(s => !meshSetContained.Any(x => x.Contains(s as Mesh))))
            {
                DestroyImmediate(go, true);
            }

            //DestroyImmediate(baseGO);
            return(baseGO);
        }
示例#14
0
        public bool LoadModel(string absolutePath, VoxModel output, Logger logger)
        {
            var name = Path.GetFileNameWithoutExtension(absolutePath);

            logger?.Invoke("load: " + name);
            //Load the whole file
            using (var reader = new BinaryReader(new MemoryStream(File.ReadAllBytes(absolutePath)))) {
                var head = new string(reader.ReadChars(4));
                if (!head.Equals(HEADER))
                {
                    Debug.LogError("Not a MagicaVoxel File!", output);
                    return(false);
                }
                int version = reader.ReadInt32();
                if (version != VERSION)
                {
                    Debug.LogWarning("Version number:" + version + " Was designed for " + VERSION);
                }
                ResetModel(output);
                childCount = 0;
                while (reader.BaseStream.Position != reader.BaseStream.Length)
                {
                    ReadChunk(reader, output);
                }
            }
            if (output.palette == null)
            {
                output.palette = LoadDefaultPalette();
            }

            output.SetAlphaFromTranparency();

            var mesher = new VoxMesher();

            for (int i = 0; i < output.voxelFrames.Count; i++)
            {
                var frame = output.voxelFrames[i];
                logger?.Invoke($"frame={i}/{output.voxelFrames.Count}: {name}");
                if (!output.Settings.EnablesTransparent || !frame.Any(output.palette, c => c.a < 1))
                {
                    var list = new MeshLODs(new Mesh {
                        name = $"{i}.opaque"
                    });
                    mesher.MeshVoxelData(output, frame, list.LODs[0].opaque);
                    output.meshes.Add(list);
                }
                else
                {
                    var list = new MeshLODs(
                        new Mesh {
                        name = $"{i}.opaque",
                    },
                        new Mesh {
                        name = $"{i}.tranparent"
                    });
                    mesher.MeshVoxelData(output, frame.Where(output.palette, c => c.a >= 1), list.LODs[0].opaque);
                    mesher.MeshVoxelData(output, frame.Where(output.palette, c => c.a < 1), list.LODs[0].transparent);
                    output.meshes.Add(list);
                }
            }

            #region LOD supports: added by XELF
            var dataList = output.voxelFrames.ToArray();
            var sizeList = output.voxelFrames.Select(d =>
                                                     new Int3(d.VoxelsWide, d.VoxelsTall, d.VoxelsDeep)).ToArray();
            for (int l = 1; l < output.Settings.maxLOD; l++)
            {
                for (int i = 0; i < output.voxelFrames.Count; i++)
                {
                    logger?.Invoke($"frame={i}/{output.voxelFrames.Count}, lod={l}/{output.Settings.maxLOD}: {name}");
                    var previous = dataList[i];
                    var size     = sizeList[i];
                    size.X      = (size.X + 1) >> 1;
                    size.Y      = (size.Y + 1) >> 1;
                    size.Z      = (size.Z + 1) >> 1;
                    sizeList[i] = size;
                    var scale = new Vector3(
                        output.Settings.modelScale * output.voxelFrames[i].VoxelsWide / size.X,
                        output.Settings.modelScale * output.voxelFrames[i].VoxelsTall / size.Y,
                        output.Settings.modelScale * output.voxelFrames[i].VoxelsDeep / size.Z);
                    var current = previous.ToSmaller();
                    if (!output.Settings.EnablesTransparent || !current.Any(output.palette, c => c.a < 1))
                    {
                        var m = new MeshSet {
                            opaque = new Mesh(),
                        };
                        var materials = VoxMesher.MaterialChunkToVector4(output.materialChunks);
                        mesher.MeshVoxelData(scale, current, output.palette,
                                             materials, output.Settings.origin, m.opaque);
                        output.meshes[i].LODs.Add(m);
                    }
                    else
                    {
                        var m = new MeshSet {
                            opaque = new Mesh(), transparent = new Mesh(),
                        };
                        var materials = VoxMesher.MaterialChunkToVector4(output.materialChunks);
                        mesher.MeshVoxelData(scale, current.Where(output.palette, c => c.a >= 1), output.palette,
                                             materials, output.Settings.origin, m.opaque);
                        mesher.MeshVoxelData(scale, current.Where(output.palette, c => c.a < 1), output.palette,
                                             materials, output.Settings.origin, m.transparent);
                        output.meshes[i].LODs.Add(m);
                    }
                    dataList[i] = current;
                }
            }
            #endregion
            return(true);
        }
示例#15
0
        private void ReadChunk(BinaryReader reader, VoxModel output)
        {
            var chunkName      = new string(reader.ReadChars(4));
            var chunkSize      = reader.ReadInt32();
            var childChunkSize = reader.ReadInt32();
            //get current chunk bytes and process
            var chunk    = reader.ReadBytes(chunkSize);
            var children = reader.ReadBytes(childChunkSize);

            using (var chunkReader = new BinaryReader(new MemoryStream(chunk))) {
                //Debug.Log(chunkName);

                switch (chunkName)
                {
                case MAIN:
                    break;

                case SIZE:
                    int w = chunkReader.ReadInt32();
                    int h = chunkReader.ReadInt32();
                    int d = chunkReader.ReadInt32();
                    if (childCount >= output.voxelFrames.Count)
                    {
                        output.voxelFrames.Add(new VoxelData());
                    }
                    output.voxelFrames[childCount].Resize(w, d, h);
                    childCount++;
                    break;

                case XYZI:
                    var  voxelCount = chunkReader.ReadInt32();
                    var  frame = output.voxelFrames[childCount - 1];
                    byte x, y, z;
                    for (int i = 0; i < voxelCount; i++)
                    {
                        x = chunkReader.ReadByte();
                        y = chunkReader.ReadByte();
                        z = chunkReader.ReadByte();
                        frame.Set(x, z, y, chunkReader.ReadByte());
                    }
                    break;

                case RGBA:
                    output.palette = LoadPalette(chunkReader);
                    break;

                case MATT:
                    break;

                case PACK:
                    int frameCount = chunkReader.ReadInt32();
                    for (int i = 0; i < frameCount; i++)
                    {
                        output.voxelFrames.Add(new VoxelData());
                    }
                    break;

                    #region Vox extension: added by XELF

                case nTRN:
                    output.transformNodeChunks.Add(ReadTransformNodeChunk(chunkReader));
                    break;

                case nGRP:
                    output.groupNodeChunks.Add(ReadGroupNodeChunk(chunkReader));
                    break;

                case nSHP:
                    output.shapeNodeChunks.Add(ReadShapeNodeChunk(chunkReader));
                    break;

                case LAYR:
                    output.layerChunks.Add(ReadLayerChunk(chunkReader));
                    break;

                case MATL:
                    output.materialChunks.Add(ReadMaterialChunk(chunkReader));
                    break;

                case rOBJ:
                    output.rendererSettingChunks.Add(ReadRObjectChunk(chunkReader));
                    break;

                    #endregion

                default:
                    Debug.LogError($"Unknown chunk: \"{chunkName}\"");
                    break;
                }
            }
            //read child chunks
            using (var childReader = new BinaryReader(new MemoryStream(children))) {
                while (childReader.BaseStream.Position != childReader.BaseStream.Length)
                {
                    ReadChunk(childReader, output);
                }
            }
        }
示例#16
0
        void GenerateModel(string filePath, VoxModel model, VoxModel targetModel)
        {
            var parser = new MagicaVoxelParser();

            //model.modelSource = filePath;
            parser.LoadModel(filePath, model,
                             s => EditorUtility.DisplayProgressBar("vox", s, 0));

            EditorUtility.SetDirty(model);
            var path      = AssetDatabase.GetAssetPath(model);
            var name      = Path.GetFileNameWithoutExtension(path);
            var subAssets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(model));
            //load asset meshes
            var assetMeshes = subAssets
                              .Select(s => s as Mesh)
                              .Where(s => s != null)
                              .ToArray();
            var updateOpaque      = false;
            var updateTransparent = false;

            var uv3 = new List <Vector4>();

            var assetIndex = 0;

            for (int i = 0; i < model.meshes.Count; i++)
            {
                for (int l = 0; l < model.meshes[i].LODs.Count; l++)
                {
                    MeshSet m;
                    //get mesh
                    m.opaque      = assetIndex < assetMeshes.Length ? assetMeshes[assetIndex++] : null;
                    m.transparent = assetIndex < assetMeshes.Length ? assetMeshes[assetIndex++] : null;
                    updateOpaque  = m.opaque == null;
                    if (updateOpaque)
                    {
                        m.opaque = new Mesh();
                    }
                    updateTransparent = m.transparent == null;
                    if (updateTransparent)
                    {
                        m.transparent = new Mesh();
                    }

                    //turn temp meshes into assets

                    EditorUtility.DisplayProgressBar("vox",
                                                     $"asset: frame={i}/{model.meshes.Count}, lod={l}/{model.meshes[i].LODs.Count}",
                                                     .5f + (.5f * i) / model.voxelFrames.Count);
                    var frame = model.meshes[i].LODs[l];
                    BuildMesh(m.opaque, frame.opaque,
                              $"{name}.{i}.{l}.opaque", uv3, model.Settings.OmitsUVUnwrapping);
                    BuildMesh(m.transparent, frame.transparent,
                              $"{name}.{i}.{l}.transparent", uv3, model.Settings.OmitsUVUnwrapping);
                    //new mesh
                    if (updateOpaque)
                    {
                        AssetDatabase.AddObjectToAsset(m.opaque, targetModel);
                    }
                    if (updateTransparent)
                    {
                        AssetDatabase.AddObjectToAsset(m.transparent, targetModel);
                    }
                    model.meshes[i].LODs[l] = m;
                }
            }

            var baseGO = new GameObject();
            var gos    = Enumerable.Range(0, baseGO.transform.childCount)
                         .Select(i => baseGO.transform.GetChild(i))
                         .Select(t => t.gameObject)
                         .ToList();
            var gosCount = gos.Count;

            for (int i = gosCount; i < model.meshes.Count; i++)
            {
                var target = new GameObject();
                target.transform.SetParent(baseGO.transform);
                gos.Add(target.gameObject);
            }
            BuildLODGroups(model, gos);
            if (model.Settings.asSceneGraph)
            {
                var root = BuildSceneGraph(model, gos);
                DestroyImmediate(baseGO);
                baseGO = root;
            }
            //destroy unneeded meshes
            foreach (var go in subAssets
                     .Where(s => (s as Mesh) != null)
                     .Where(s => !model.meshes.SelectMany(x => x.LODs).Any(x => x.Contains(s as Mesh))))
            {
                DestroyImmediate(go, true);
            }

            if (targetModel.prefab == null)
            {
                targetModel.prefab = PrefabUtility.CreatePrefab(path + ".prefab", new GameObject());
            }
            PrefabUtility.ReplacePrefab(baseGO, targetModel.prefab, ReplacePrefabOptions.ReplaceNameBased);
            DestroyImmediate(baseGO);
            EditorUtility.SetDirty(targetModel);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }
示例#17
0
        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();
            VoxModel model = target as VoxModel;

            if (targetModel == null || model != targetModel)
            {
                filePath    = model.modelSource;
                targetModel = model;
            }
            GUILayout.BeginHorizontal();
            GUILayout.Label("File:", GUILayout.ExpandWidth(false));
            GUILayout.TextArea(filePath.Replace(Application.dataPath, ""));
            if (GUILayout.Button("Open file", GUILayout.ExpandWidth(false)))
            {
                filePath = EditorUtility.OpenFilePanel("Open model", EditorPrefs.GetString("LastVoxPath", Application.dataPath), "vox");
                if (File.Exists(filePath))
                {
                    EditorPrefs.SetString("LastVoxPath", filePath);
                }
            }
            GUILayout.EndHorizontal();
            if (filePath != string.Empty)
            {
                if (GUILayout.Button("Generate Model", GUILayout.ExpandWidth(false)))
                {
                    MagicaVoxelParser parser = new MagicaVoxelParser();
                    model.modelSource = filePath;
                    parser.LoadModel(filePath, model);
                    EditorUtility.SetDirty(model);
                    string   path      = AssetDatabase.GetAssetPath(model);
                    string   name      = Path.GetFileNameWithoutExtension(path);
                    Object[] subAssets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(model));
                    //load asset meshes
                    List <Mesh> assetMeshes = new List <Mesh>();
                    for (int i = 0; i < subAssets.Length; i++)
                    {
                        if (subAssets[i] is Mesh)
                        {
                            assetMeshes.Add(subAssets[i] as Mesh);
                        }
                    }
                    int  max = model.meshes.Count;
                    bool update = false;
                    Mesh m, temp;
                    for (int i = 0; i < max; i++)
                    {
                        //get mesh
                        if (i < assetMeshes.Count)
                        {
                            update = false;
                            m      = assetMeshes[i];
                            if (m == null)
                            {
                                update = true;
                                m      = new Mesh();
                            }
                        }
                        else
                        {
                            m      = new Mesh();
                            update = true;
                        }
                        //turn temp meshes into assets
                        if (i < model.meshes.Count)
                        {
                            m.name = name + "_frame_" + i;
                            temp   = model.meshes[i];
                            m.Clear();
                            m.vertices  = temp.vertices;
                            m.colors    = temp.colors;
                            m.normals   = temp.normals;
                            m.triangles = temp.triangles;
                            m.uv        = Unwrapping.GeneratePerTriangleUV(m);
                            Unwrapping.GenerateSecondaryUVSet(m);
                            //new mesh
                            if (update)
                            {
                                AssetDatabase.AddObjectToAsset(m, targetModel);
                            }
                            model.meshes[i] = m;
                        }
                    }
                    //destroy un needed meshes
                    for (int i = 0; i < subAssets.Length; i++)
                    {
                        m = subAssets[i] as Mesh;
                        if (m != null)
                        {
                            if (model.meshes.Contains(m) == false)
                            {
                                DestroyImmediate(m, true);
                            }
                        }
                    }
                    EditorUtility.SetDirty(targetModel);
                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();
                }
            }
        }
示例#18
0
 void GenerateTex3D(VoxModel model)
 {
     Merge(model, model.voxelFrames
           .Select((f, i) => CreateTexture3D(f, $"{i}")));
 }