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(); } } }
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(); }