public static void FromMagica(BinaryReader stream, GameObject root, float voxelSize, bool centerPivot)
        {
            // check out http://voxel.codeplex.com/wikipage?title=VOX%20Format&referringTitle=Home for the file format used below
            // we're going to return a voxel chunk worth of data

            Color32[] colors = new Color32[256];

            for (int i = 1; i < 256; i++)
            {
                uint hexval = defaultColors[i];
                byte cb     = (byte)((hexval >> 16) & 0xFF);
                byte cg     = (byte)((hexval >> 8) & 0xFF);
                byte cr     = (byte)((hexval >> 0) & 0xFF);

                colors[i - 1] = new Color32(cr, cg, cb, 255);
            }

            MagicaVoxelData[]        voxelData = null;
            List <MagicaVoxelData[]> frames    = new List <MagicaVoxelData[]>();

            //int numFrames = 1;


            string magic = new string(stream.ReadChars(4));

            //int version =
            stream.ReadInt32();


            // a MagicaVoxel .vox file starts with a 'magic' 4 character 'VOX ' identifier
            if (magic == "VOX ")
            {
                int  sizex = 0, sizey = 0, sizez = 0;
                bool subsample = false;

                while (stream.BaseStream.Position < stream.BaseStream.Length)
                {
                    // each chunk has an ID, size and child chunks
                    char[] chunkId   = stream.ReadChars(4);
                    int    chunkSize = stream.ReadInt32();
                    //int childChunks =
                    stream.ReadInt32();
                    string chunkName = new string(chunkId);

                    if (chunkName == "PACK")
                    {
                        stream.ReadInt32();
                    }
                    else if (chunkName == "SIZE")
                    {
                        sizex = stream.ReadInt32();
                        sizez = stream.ReadInt32();
                        sizey = stream.ReadInt32();

                        //if (sizex > 32 || sizey > 32) subsample = true;

                        stream.ReadBytes(chunkSize - 4 * 3);
                    }
                    else if (chunkName == "XYZI")
                    {
                        // XYZI contains n voxels
                        int numVoxels = stream.ReadInt32();
                        // int div = (subsample ? 2 : 1);

                        // each voxel has x, y, z and color index values
                        voxelData = new MagicaVoxelData[numVoxels];
                        for (int i = 0; i < voxelData.Length; i++)
                        {
                            voxelData[i] = new MagicaVoxelData(stream, subsample);
                        }

                        frames.Add(voxelData);
                    }
                    else if (chunkName == "RGBA")
                    {
                        for (int i = 0; i < 256; i++)
                        {
                            byte r = stream.ReadByte();
                            byte g = stream.ReadByte();
                            byte b = stream.ReadByte();
                            byte a = stream.ReadByte();

                            // convert RGBA to our custom voxel format (16 bits, 0RRR RRGG GGGB BBBB)
                            colors[i] = new Color32(r, g, b, a);
                        }
                    }
                    else
                    {
                        stream.ReadBytes(chunkSize);    // read any excess bytes
                    }
                }

                if (voxelData.Length == 0)
                {
                    return;                        // failed to read any valid voxel data
                }
                if (root != null)
                {
                    Volume voxelVolume = root.GetComponent <Volume>();

                    voxelVolume.XSize = sizex;
                    voxelVolume.YSize = sizey;
                    voxelVolume.ZSize = sizez;
                    voxelVolume.Frames[voxelVolume.CurrentFrame].XSize  = sizex;
                    voxelVolume.Frames[voxelVolume.CurrentFrame].YSize  = sizey;
                    voxelVolume.Frames[voxelVolume.CurrentFrame].ZSize  = sizez;
                    voxelVolume.Frames[voxelVolume.CurrentFrame].Voxels = new Voxel[sizex * sizey * sizez];
                    for (int i = 0; i < voxelVolume.Frames[voxelVolume.CurrentFrame].Voxels.Length; i++)
                    {
                        voxelVolume.Frames[voxelVolume.CurrentFrame].Voxels[i].Value = 128;
                    }
                    voxelVolume.VoxelSize = voxelSize;

                    if (centerPivot)
                    {
                        voxelVolume.Pivot = (new Vector3(voxelVolume.XSize, voxelVolume.YSize, voxelVolume.ZSize) * voxelVolume.VoxelSize) / 2f;
                        voxelVolume.UpdatePivot();
                    }

                    foreach (MagicaVoxelData[] d in frames)
                    {
                        foreach (MagicaVoxelData v in d)
                        {
                            try
                            {
                                voxelVolume.Frames[voxelVolume.CurrentFrame].Voxels[v.x + sizex * (v.z + sizey * v.y)] = new Voxel()
                                {
                                    State = VoxelState.Active,
                                    Color = colors[v.color - 1],
                                    Value = 128
                                };
                            }
                            catch (Exception)
                            {
                                Debug.Log(v.x + " " + v.y + " " + v.z);
                            }
                        }

                        if (frames.IndexOf(d) < frames.Count - 1)
                        {
                            voxelVolume.AddFrame(voxelVolume.CurrentFrame + 1);
                            voxelVolume.Frames[voxelVolume.CurrentFrame].Voxels = new Voxel[sizex * sizey * sizez];
                        }
                    }

                    voxelVolume.SetFrame(0);
                    voxelVolume.CreateChunks();
                    voxelVolume.SaveForSerialize();
                }
            }
        }
Beispiel #2
0
        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Editor", new GUIStyle()
            {
                fontStyle = FontStyle.Bold
            });

            if (!allRuntimeOnlyMesh)
            {
                if (GUILayout.Button(allEditorsEnabled ? "Stop Editing All" : "Start Editing All"))
                {
                    foreach (Volume v in mpvObject.Volumes)
                    {
                        v.IsEnabledForEditing = !allEditorsEnabled;
                        v.PaintMode           = EditorPaintMode.Color;

                        v.UpdateAllChunks();
                    }

                    SceneView.RepaintAll();
                    allEditorsEnabled = AllEditorsEnabled();
                }
            }

            rtomCheckBox = EditorGUILayout.ToggleLeft(new GUIContent(" Runtime-Only Mesh"),
                                                      rtomCheckBox);
            if (rtomCheckBox != allRuntimeOnlyMesh)
            {
                foreach (Volume v in mpvObject.Volumes)
                {
                    v.IsEnabledForEditing = false;
                    v.RuntimOnlyMesh      = !allRuntimeOnlyMesh;

                    v.CreateChunks();
                    v.UpdateAllChunks();
                }

                allRuntimeOnlyMesh = AllRuntimeOnlyMesh();
                allEditorsEnabled  = AllEditorsEnabled();
            }

            EditorGUILayout.Space();

            EditorGUILayout.LabelField("Size", new GUIStyle()
            {
                fontStyle = FontStyle.Bold
            });
            float size = EditorGUILayout.FloatField("Voxel Size:", voxelSizeProperty.floatValue);

            if (size != voxelSizeProperty.floatValue && size > 0f)
            {
                voxelSizeProperty.floatValue = size;
                voxelSize = voxelSizeProperty.floatValue;
                foreach (Volume v in mpvObject.Volumes)
                {
                    v.VoxelSize = voxelSize;

                    v.CreateChunks();
                }

                mpvObject.RepositionParts();
            }

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Pivot", new GUIStyle()
            {
                fontStyle = FontStyle.Bold
            });
            pivotProperty.vector3Value = EditorGUILayout.Vector3Field("", pivotProperty.vector3Value, null);
            if (pivotProperty.vector3Value != mpvObject.Pivot)
            {
                pivot           = pivotProperty.vector3Value;
                mpvObject.Pivot = pivot;
                mpvObject.RepositionParts();
            }
            if (GUILayout.Button("Set to Center"))
            {
                mpvObject.SetPivotToCenter();
            }

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Individual Pivots", new GUIStyle()
            {
                fontStyle = FontStyle.Bold
            });

            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button("Set all to Center"))
            {
                foreach (Volume v in mpvObject.Volumes)
                {
                    Vector3 piv = (new Vector3(v.XSize, v.YSize, v.ZSize) * v.VoxelSize) / 2f;
                    v.Pivot = piv;
                    v.UpdatePivot();
                }
            }
            if (GUILayout.Button("Set all to Zero"))
            {
                foreach (Volume v in mpvObject.Volumes)
                {
                    v.Pivot = Vector3.zero;
                    v.UpdatePivot();
                }
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Collision Mode", new GUIStyle()
            {
                fontStyle = FontStyle.Bold
            });
            collisionMode.enumValueIndex =
                Convert.ToInt16(EditorGUILayout.EnumPopup((CollisionMode)collisionMode.enumValueIndex));
            if (collisionMode.enumValueIndex != Convert.ToInt16(mpvObject.CollisionMode))
            {
                foreach (Volume v in mpvObject.Volumes)
                {
                    v.ChangeCollisionMode((CollisionMode)collisionMode.enumValueIndex);
                }
            }
            if (collisionMode.enumValueIndex > 0)
            {
                separateColliderMesh.boolValue = EditorGUILayout.ToggleLeft(new GUIContent(" Generate collider mesh separately (Edit-time only)"),
                                                                            separateColliderMesh.boolValue);
                if (separateColliderMesh.boolValue != mpvObject.GenerateMeshColliderSeparately)
                {
                    foreach (Volume v in mpvObject.Volumes)
                    {
                        v.GenerateMeshColliderSeparately = separateColliderMesh.boolValue;
                        v.UpdateAllChunks();
                    }
                }

                if (separateColliderMesh.boolValue)
                {
                    EditorGUILayout.LabelField("Collider Meshing Mode", new GUIStyle()
                    {
                        fontStyle = FontStyle.Bold
                    });
                    colliderMeshingMode.enumValueIndex =
                        Convert.ToInt16(EditorGUILayout.EnumPopup((MeshingMode)colliderMeshingMode.enumValueIndex));
                    if (colliderMeshingMode.enumValueIndex != Convert.ToInt16(mpvObject.MeshColliderMeshingMode))
                    {
                        foreach (Volume v in mpvObject.Volumes)
                        {
                            v.MeshColliderMeshingMode = (MeshingMode)colliderMeshingMode.enumValueIndex;
                            v.UpdateAllChunks();
                        }
                    }
                }
            }

            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Rendering", new GUIStyle()
            {
                fontStyle = FontStyle.Bold
            });
            EditorGUILayout.LabelField("Meshing Mode", new GUIStyle()
            {
                fontStyle = FontStyle.Bold
            });
            meshingMode.enumValueIndex =
                Convert.ToInt16(EditorGUILayout.EnumPopup((MeshingMode)meshingMode.enumValueIndex));
            if (meshingMode.enumValueIndex != Convert.ToInt16(mpvObject.MeshingMode))
            {
                foreach (Volume v in mpvObject.Volumes)
                {
                    v.MeshingMode = (MeshingMode)meshingMode.enumValueIndex;
                    v.UpdateAllChunks();
                }
            }

            selfShadeInt.floatValue = EditorGUILayout.Slider("Self-Shading Intensity", selfShadeInt.floatValue, 0, 1);
            if (selfShadeInt.floatValue != mpvObject.SelfShadingIntensity)
            {
                foreach (Volume v in mpvObject.Volumes)
                {
                    v.SelfShadingIntensity = selfShadeInt.floatValue;
                    v.UpdateAllChunks();
                }
            }

            material.objectReferenceValue = EditorGUILayout.ObjectField("Material: ", material.objectReferenceValue, typeof(Material),
                                                                        false);
            if (material.objectReferenceValue != mpvObject.Material)
            {
                foreach (Volume v in mpvObject.Volumes)
                {
                    v.Material = (Material)material.objectReferenceValue;
                    v.UpdateAllChunks();
                }
            }

            EditorGUILayout.Space();
            if (GUILayout.Button(new GUIContent("Mesh-Only Copy", "Create a copy of this Volume with mesh(es) only")))
            {
                GameObject newMPV = new GameObject(target.name + " (Copy)");
                foreach (Volume vol in mpvObject.Volumes)
                {
                    GameObject bake = Instantiate(EditorUtility.VoxelVolumePrefab, Vector3.zero, Quaternion.identity) as GameObject;

                    Volume v = bake.GetComponent <Volume>();
                    v.XSize                          = vol.XSize;
                    v.YSize                          = vol.YSize;
                    v.ZSize                          = vol.ZSize;
                    v.MeshingMode                    = vol.MeshingMode;
                    v.MeshColliderMeshingMode        = vol.MeshColliderMeshingMode;
                    v.GenerateMeshColliderSeparately = vol.GenerateMeshColliderSeparately;
                    v.Material                       = vol.Material;
                    for (int f = 0; f < vol.Frames.Count; f++)
                    {
                        v.AddFrame(f);
                        v.Frames[f].Voxels = vol.Frames[f].Voxels;
                    }
                    v.CreateChunks();
                    v.ChangeCollisionMode(vol.CollisionMode);
                    v.UpdateAllChunks();

                    bake.tag  = "Untagged";
                    bake.name = vol.name;
                    DestroyImmediate(bake.GetComponent <Volume>());
                    DestroyImmediate(bake.transform.FindChild("Hitbox").gameObject);
                    for (int i = 0; i < bake.transform.childCount; i++)
                    {
                        GameObject o = bake.transform.GetChild(i).gameObject;
                        if (o.GetComponent <Frame>() != null)
                        {
                            DestroyImmediate(o.GetComponent <Frame>());
                            for (int c = 0; c < o.transform.FindChild("Chunks").childCount; c++)
                            {
                                GameObject chunk = o.transform.FindChild("Chunks").GetChild(c).gameObject;
                                if (chunk.GetComponent <Chunk>() != null)
                                {
                                    DestroyImmediate(chunk.GetComponent <Chunk>());
                                }
                            }
                        }
                    }

                    bake.transform.parent        = newMPV.transform;
                    bake.transform.localPosition = vol.transform.localPosition;
                }
            }

            serializedObject.ApplyModifiedProperties();
        }