public VoxData GetLODVoxelData(int lodLevel) { if (SizeX <= 1 || SizeY <= 1 || SizeZ <= 1) { return(null); } lodLevel = Mathf.Clamp(lodLevel, 0, 8); if (lodLevel <= 1) { return(this); } if (SizeX <= lodLevel && SizeY <= lodLevel && SizeZ <= lodLevel) { return(null); } VoxData data = new VoxData(); data.SizeX = Mathf.Max(Mathf.CeilToInt((float)SizeX / lodLevel), 1); data.SizeY = Mathf.Max(Mathf.CeilToInt((float)SizeY / lodLevel)); data.SizeZ = Mathf.Max(Mathf.CeilToInt((float)SizeZ / lodLevel)); data.Version = Version; data.Palatte = Palatte; data.Voxels = new int[data.SizeX, data.SizeY, data.SizeZ]; for (int x = 0; x < data.SizeX; x++) { for (int y = 0; y < data.SizeY; y++) { for (int z = 0; z < data.SizeZ; z++) { data.Voxels[x, y, z] = this.GetMajorityColorIndex(x * lodLevel, y * lodLevel, z * lodLevel, lodLevel); } } } return(data); }
static int ReadVoxelChunk(BinaryReader _br, VoxData _mainData, List <Vector3> tempSize, ref List <int[, , ]> tempVoxels) { int chunkSize = _br.ReadInt32(); int childrenSize = _br.ReadInt32(); int numVoxels = _br.ReadInt32(); int[,,] temp = new int[ (int)tempSize[tempVoxels.Count].x, (int)tempSize[tempVoxels.Count].y, (int)tempSize[tempVoxels.Count].z ]; for (int i = 0; i < numVoxels; ++i) { int x = (int)_br.ReadByte(); int y = (int)_br.ReadByte(); int z = (int)_br.ReadByte(); temp[x, y, z] = _br.ReadByte(); } tempVoxels.Add(temp); if (childrenSize > 0) { _br.ReadBytes(childrenSize); } return(chunkSize + childrenSize + 4 * 3); }
public static byte[] GetMainByte(VoxData _voxData) { List <byte> _byte = new List <byte>(); ///* // "VOX " _byte.AddRange(Encoding.Default.GetBytes("VOX ")); // "VERSION " _byte.AddRange(_voxData.Version); // ID --> MAIN _byte.AddRange(Encoding.Default.GetBytes("MAIN")); // Main Chunk Size _byte.AddRange(BitConverter.GetBytes(0)); // Main Chunk Children Size byte[] _vox = GetVoxByte(_voxData, _voxData.Palatte); _byte.AddRange(BitConverter.GetBytes(_vox.Length)); // Vox Chunk _byte.AddRange(_vox); //*/ byte[] _ans = new byte[_byte.Count]; _byte.CopyTo(_ans); return(_ans); }
public void CreateObj(VoxData voxData, int frame) { InitVoxels(voxData, frame); FixVisible(); CreateVoxelObj(); }
public VoxData GetLODVoxelData(int lodLevel) { VoxData data = new VoxData() { SizeX = new int[Voxels.Length], SizeY = new int[Voxels.Length], SizeZ = new int[Voxels.Length], Version = Version, Palatte = Palatte, Voxels = new int[Voxels.Length][, , ], }; for (int index = 0; index < Voxels.Length; index++) { if (SizeX[index] <= 1 || SizeY[index] <= 1 || SizeZ[index] <= 1) { data.Voxels[index] = null; continue; } lodLevel = Mathf.Clamp(lodLevel, 0, 8); if (lodLevel <= 1) { data.SizeX[index] = SizeX[index]; data.SizeY[index] = SizeY[index]; data.SizeZ[index] = SizeZ[index]; data.Voxels[index] = Voxels[index]; continue; } if (SizeX[index] <= lodLevel && SizeY[index] <= lodLevel && SizeZ[index] <= lodLevel) { data.Voxels[index] = null; continue; } data.SizeX[index] = Mathf.Max(Mathf.CeilToInt((float)SizeX[index] / lodLevel), 1); data.SizeY[index] = Mathf.Max(Mathf.CeilToInt((float)SizeY[index] / lodLevel)); data.SizeZ[index] = Mathf.Max(Mathf.CeilToInt((float)SizeZ[index] / lodLevel)); data.Voxels[index] = new int[data.SizeX[index], data.SizeY[index], data.SizeZ[index]]; for (int x = 0; x < data.SizeX[index]; x++) { for (int y = 0; y < data.SizeY[index]; y++) { for (int z = 0; z < data.SizeZ[index]; z++) { data.Voxels[index][x, y, z] = GetMajorityColorIndex(index, x * lodLevel, y * lodLevel, z * lodLevel, lodLevel); } } } } return(data); }
public VoxData GetVoxData() { VoxData vox = new VoxData(); Vector3 sizeAll = SizeAll; vox.SizeX = new int[1] { (int)sizeAll.x }; vox.SizeY = new int[1] { (int)sizeAll.y }; vox.SizeZ = new int[1] { (int)sizeAll.z }; vox.Voxels = new int[1][, , ]; vox.Voxels[0] = new int[vox.SizeX[0], vox.SizeY[0], vox.SizeZ[0]]; List <Color> pl = new List <Color> { new Color() }; for (int i = 0; i < MatrixList.Count; i++) { for (int x = 0; x < MatrixList[i].SizeX; x++) { for (int y = 0; y < MatrixList[i].SizeY; y++) { for (int z = 0; z < MatrixList[i].SizeZ; z++) { int v = MatrixList[i][x, y, z]; if (v != 0) { Color color = ColorFormat == 0 ? RGB(v) : BGR(v); int index = pl.IndexOf(color); if (index == -1) { pl.Add(color); index = pl.Count - 1; } vox.Voxels[0][x + MatrixList[i].PosX, y + MatrixList[i].PosY, z + MatrixList[i].PosZ] = index + 1; } } } } } vox.Palatte = pl.ToArray(); return(vox); }
public void CreateVoxelMesh(VoxData voxelData, float scale, Vector3 pivot, ref Mesh[] meshs, ref Texture2D texture) { // Init Voxels InitVoxels(voxelData, scale, pivot); // Visibility FixVisible(); // Faces Getfaces(); // Mesh CreateMesh(voxelData, ref meshs, ref texture); }
static int ReadSizeChunk(BinaryReader _br, VoxData _mainData) { int chunkSize = _br.ReadInt32(); int childrenSize = _br.ReadInt32(); _mainData.SizeX = _br.ReadInt32(); _mainData.SizeY = _br.ReadInt32(); _mainData.SizeZ = _br.ReadInt32(); ///* _mainData.Voxels = new int[_mainData.SizeX, _mainData.SizeY, _mainData.SizeZ]; //*/ if (childrenSize > 0) { _br.ReadBytes(childrenSize); } return(chunkSize + childrenSize + 4 * 3); }
public void CreateVoxelMesh(VoxData voxelData, float scale, Vector3 pivot, ref Texture2D texture, ref string objFile) { // Init Voxels InitVoxels(voxelData, scale, pivot); // Visibility FixVisible(); // Faces Getfaces(); // Mesh Mesh[] meshs = null; CreateMesh(voxelData, ref meshs, ref texture); // Obj objFile = CreateObj(meshs, objFile); }
/// <summary> /// 初始化 voxel 信息数据 /// </summary> /// <param name="voxData"></param> /// <param name="frame"></param> private void InitVoxels(VoxData voxData, int frame) { this._voxData = voxData; SizeX = voxData.SizeX[frame]; SizeY = voxData.SizeY[frame]; SizeZ = voxData.SizeZ[frame]; Voxels = new Voxel[SizeX, SizeY, SizeZ]; for (int i = 0; i < SizeX; i++) { for (int j = 0; j < SizeY; j++) { for (int k = 0; k < SizeZ; k++) { Voxels[i, j, k].Init(); Voxels[i, j, k].ColorIndex = voxData.Voxels[frame][i, j, k]; } } } }
private void InitVoxels(VoxData voxelData, float scale, Vector3 pivot) { Scale = scale; Pivot = pivot; SizeX = voxelData.SizeX; SizeY = voxelData.SizeY; SizeZ = voxelData.SizeZ; MainVoxelData = voxelData; Voxels = new Voxel[SizeX, SizeY, SizeZ]; for (int i = 0; i < SizeX; i++) { for (int j = 0; j < SizeY; j++) { for (int k = 0; k < SizeZ; k++) { Voxels[i, j, k].Init(); Voxels[i, j, k].ColorIndex = MainVoxelData.Voxels[i, j, k]; } } } }
static int ReadVoxelChunk(BinaryReader _br, VoxData _mainData) { int chunkSize = _br.ReadInt32(); int childrenSize = _br.ReadInt32(); int numVoxels = _br.ReadInt32(); for (int i = 0; i < numVoxels; ++i) { int x = (int)_br.ReadByte(); int y = (int)_br.ReadByte(); int z = (int)_br.ReadByte(); _mainData.Voxels[x, y, z] = _br.ReadByte(); } if (childrenSize > 0) { _br.ReadBytes(childrenSize); } return(chunkSize + childrenSize + 4 * 3); }
public static byte[] GetVoxByte(VoxData _data, Color[] _palatte) { List <byte> _byte = new List <byte>(); ///* // content for (int index = 0; index < _data.Voxels.Length; index++) { // --- SIZE --- //size / children size _byte.AddRange(Encoding.Default.GetBytes("SIZE")); _byte.AddRange(BitConverter.GetBytes(12)); _byte.AddRange(BitConverter.GetBytes(0)); _byte.AddRange(BitConverter.GetBytes(_data.SizeX[index])); _byte.AddRange(BitConverter.GetBytes(_data.SizeY[index])); _byte.AddRange(BitConverter.GetBytes(_data.SizeZ[index])); // --- XYZI --- //size / children size _byte.AddRange(Encoding.Default.GetBytes("XYZI")); _byte.AddRange(BitConverter.GetBytes(_data.VoxelNum(index) * 4 + 4)); _byte.AddRange(BitConverter.GetBytes(0)); _byte.AddRange(BitConverter.GetBytes(_data.VoxelNum(index))); for (int i = 0; i < _data.SizeX[index]; i++) { for (int j = 0; j < _data.SizeY[index]; j++) { for (int k = 0; k < _data.SizeZ[index]; k++) { if (_data.Voxels[index][i, j, k] != 0) { _byte.Add((byte)i); _byte.Add((byte)j); _byte.Add((byte)k); _byte.Add((byte)_data.Voxels[index][i, j, k]); } } } } } // --- RGBA --- //size / children size _byte.AddRange(Encoding.Default.GetBytes("RGBA")); _byte.AddRange(BitConverter.GetBytes(1024)); _byte.AddRange(BitConverter.GetBytes(0)); for (int i = 0; i < 256; i++) { Color _color = i < _palatte.Length ? _palatte[i] : new Color(); _byte.Add((byte)(_color.r * 255.0f)); _byte.Add((byte)(_color.g * 255.0f)); _byte.Add((byte)(_color.b * 255.0f)); _byte.Add((byte)(_color.a * 255.0f)); } //*/ // --- Final --- byte[] _ans = new byte[_byte.Count]; _byte.CopyTo(_ans); return(_ans); }
public static VoxData LoadVoxel(byte[] _data) { if (_data[0] != 'V' || _data[1] != 'O' || _data[2] != 'X' || _data[3] != ' ') { Debug.LogError("Error Magic Number"); return(null); } using (MemoryStream _ms = new MemoryStream(_data)) { using (BinaryReader _br = new BinaryReader(_ms)) { VoxData _mainData = new VoxData(); List <int[, , ]> tempVoxels = new List <int[, , ]>(); List <Vector3> tempSizes = new List <Vector3>(); ///* // VOX_ _br.ReadInt32(); // VERSION _mainData.Version = _br.ReadBytes(4); byte[] _chunkId = _br.ReadBytes(4); if (_chunkId[0] != 'M' || _chunkId[1] != 'A' || _chunkId[2] != 'I' || _chunkId[3] != 'N') { Debug.LogError("Error main ID"); return(null); } int _chunkSize = _br.ReadInt32(); int _childrenSize = _br.ReadInt32(); _br.ReadBytes(_chunkSize); int _readSize = 0; while (_readSize < _childrenSize) { _chunkId = _br.ReadBytes(4); if (_chunkId[0] == 'S' && _chunkId[1] == 'I' && _chunkId[2] == 'Z' && _chunkId[3] == 'E') { _readSize += ReadSizeChunk(_br, ref tempSizes); } else if (_chunkId[0] == 'X' && _chunkId[1] == 'Y' && _chunkId[2] == 'Z' && _chunkId[3] == 'I') { _readSize += ReadVoxelChunk(_br, _mainData, tempSizes, ref tempVoxels); } else if (_chunkId[0] == 'R' && _chunkId[1] == 'G' && _chunkId[2] == 'B' && _chunkId[3] == 'A') { _mainData.Palatte = new Color[256]; _readSize += ReadPalattee(_br, _mainData.Palatte); } else { int chunkSize = _br.ReadInt32(); int childrenSize = _br.ReadInt32(); _br.ReadBytes(chunkSize + childrenSize); _readSize += chunkSize + childrenSize + 4 + 4 + 4; } } // Add Voxels _mainData.Voxels = tempVoxels.ToArray(); // Add Sizes _mainData.SizeX = new int[tempSizes.Count]; _mainData.SizeY = new int[tempSizes.Count]; _mainData.SizeZ = new int[tempSizes.Count]; for (int i = 0; i < tempSizes.Count; i++) { _mainData.SizeX[i] = (int)tempSizes[i].x; _mainData.SizeY[i] = (int)tempSizes[i].y; _mainData.SizeZ[i] = (int)tempSizes[i].z; } if (_mainData.Palatte == null) { _mainData.Palatte = DefaultPallete; } return(_mainData); } } }
public static VoxData LoadVoxel(byte[] _data) { if (_data[0] != 'V' || _data[1] != 'O' || _data[2] != 'X' || _data[3] != ' ') { Debug.LogError("Error Magic Number"); return(null); } using (MemoryStream _ms = new MemoryStream(_data)) { using (BinaryReader _br = new BinaryReader(_ms)) { VoxData _mainData = new VoxData(); ///* // VOX_ _br.ReadInt32(); // VERSION _mainData.Version = _br.ReadBytes(4); byte[] _chunkId = _br.ReadBytes(4); if (_chunkId[0] != 'M' || _chunkId[1] != 'A' || _chunkId[2] != 'I' || _chunkId[3] != 'N') { Debug.LogError("Error main ID"); return(null); } int _chunkSize = _br.ReadInt32(); int _childrenSize = _br.ReadInt32(); _br.ReadBytes(_chunkSize); int _readSize = 0; while (_readSize < _childrenSize) { _chunkId = _br.ReadBytes(4); if (_chunkId[0] == 'S' && _chunkId[1] == 'I' && _chunkId[2] == 'Z' && _chunkId[3] == 'E') { _readSize += ReadSizeChunk(_br, _mainData); } else if (_chunkId[0] == 'X' && _chunkId[1] == 'Y' && _chunkId[2] == 'Z' && _chunkId[3] == 'I') { _readSize += ReadVoxelChunk(_br, _mainData); } else if (_chunkId[0] == 'R' && _chunkId[1] == 'G' && _chunkId[2] == 'B' && _chunkId[3] == 'A') { _mainData.Palatte = new Color[256]; _readSize += ReadPalattee(_br, _mainData.Palatte); } else { int chunkSize = _br.ReadInt32(); int childrenSize = _br.ReadInt32(); _br.ReadBytes(chunkSize + childrenSize); _readSize += chunkSize + childrenSize + 4 + 4 + 4; } } if (_mainData.Palatte == null) { _mainData.Palatte = DefaultPallete; } return(_mainData); } } }
private void CreateMesh(VoxData voxelData, ref Mesh[] meshs, ref Texture2D aimTexture) { int num = VoxelFaces.Count / MaxFacesInOneMesh + 1; if (VoxelFaces.Count % MaxFacesInOneMesh == 0) { num--; } meshs = new Mesh[num]; List <Dictionary <int, int> > uvIdMaps = new List <Dictionary <int, int> >(); List <Texture2D[]> temptxtList = new List <Texture2D[]>(); for (int index = 0; index < num; index++) { List <VoxelFace> Faces = new List <VoxelFace>(VoxelFaces.GetRange(index * MaxFacesInOneMesh, Mathf.Min(MaxFacesInOneMesh, VoxelFaces.Count - index * MaxFacesInOneMesh))); #region --- Vertices --- List <Vector3> voxelVertices = new List <Vector3>(); for (int i = 0; i < Faces.Count; i++) { Vector3[] points = Faces[i].Points; for (int j = 0; j < 4; j++) { points[j] -= new Vector3(SizeX * Pivot.x, SizeZ * Pivot.y, SizeY * Pivot.z); points[j] *= Scale; } voxelVertices.AddRange(points); } #endregion #region --- Triangles --- List <int> voxelTriangles = new List <int>(); for (int i = 0; i < Faces.Count; i++) { if (Faces[i].direction == Direction.Front || Faces[i].direction == Direction.Up || Faces[i].direction == Direction.Right) { voxelTriangles.AddRange(new int[6] { i * 4 + 2, i * 4 + 1, i * 4 + 0, i * 4 + 3, i * 4 + 1, i * 4 + 2 }); } else { voxelTriangles.AddRange(new int[6] { i * 4 + 2, i * 4 + 0, i * 4 + 1, i * 4 + 3, i * 4 + 2, i * 4 + 1 }); } } #endregion meshs[index] = new Mesh(); meshs[index].Clear(); meshs[index].SetVertices(voxelVertices); meshs[index].SetTriangles(voxelTriangles, 0); #region --- Texture --- List <Texture2D> tempTextureList = new List <Texture2D>(); List <int> tempColorIndexs = new List <int>(); Dictionary <int, int> UVidMap = new Dictionary <int, int>(); for (int i = 0; i < Faces.Count; i++) { int width = Faces[i].Width + 2; int height = Faces[i].Height + 2; Color[] _colors = new Color[width * height]; bool sameIndex = true; int currentIndex = -1; for (int u = 0; u < Faces[i].Width; u++) { for (int v = 0; v < Faces[i].Height; v++) { int colorIndex = 0; switch (Faces[i].direction) { case Direction.Front: case Direction.Back: colorIndex = Voxels[u + Faces[i].VoxelX, Faces[i].VoxelY, v + Faces[i].VoxelZ].ColorIndex - 1; break; case Direction.Left: case Direction.Right: colorIndex = Voxels[Faces[i].VoxelX, u + Faces[i].VoxelY, v + Faces[i].VoxelZ].ColorIndex - 1; break; case Direction.Up: case Direction.Down: colorIndex = Voxels[u + Faces[i].VoxelX, v + Faces[i].VoxelY, Faces[i].VoxelZ].ColorIndex - 1; break; } Color _c = MainVoxelData.Palatte[colorIndex]; _colors[(v + 1) * width + u + 1] = _c; if (currentIndex == -1) { currentIndex = colorIndex; } if (sameIndex && currentIndex != colorIndex) { sameIndex = false; } #region --- Side --- if (u == 0) { _colors[(v + 1) * width + u] = _c; } if (u == Faces[i].Width - 1) { _colors[(v + 1) * width + u + 2] = _c; } if (v == 0) { _colors[v * width + u + 1] = _c; } if (v == Faces[i].Height - 1) { _colors[(v + 2) * width + u + 1] = _c; } if (u == 0 && v == 0) { _colors[0] = _c; } if (u == 0 && v == Faces[i].Height - 1) { _colors[(v + 2) * width + u] = _c; } if (u == Faces[i].Width - 1 && v == 0) { _colors[v * width + u + 2] = _c; } if (u == Faces[i].Width - 1 && v == Faces[i].Height - 1) { _colors[(v + 2) * width + u + 2] = _c; } #endregion } } Texture2D _texture = null; int oldID = i; if (sameIndex && currentIndex > 0) { if (tempColorIndexs.Contains(currentIndex)) { oldID = tempColorIndexs.IndexOf(currentIndex); } else { Color c = MainVoxelData.Palatte[currentIndex]; _texture = new Texture2D(3, 3, TextureFormat.ARGB32, false, false); _texture.SetPixels(new Color[9] { c, c, c, c, c, c, c, c, c }); tempTextureList.Add(_texture); tempColorIndexs.Add(currentIndex); oldID = tempTextureList.Count - 1; } } else { _texture = new Texture2D(width, height, TextureFormat.ARGB32, false, false); _texture.SetPixels(_colors); tempTextureList.Add(_texture); tempColorIndexs.Add(-1); oldID = tempTextureList.Count - 1; } if (_texture) { _texture.wrapMode = TextureWrapMode.Clamp; _texture.filterMode = FilterMode.Point; _texture.mipMapBias = 0f; _texture.Apply(); } UVidMap.Add(i, oldID); } temptxtList.Add(tempTextureList.ToArray()); tempTextureList.Clear(); uvIdMaps.Add(UVidMap); #endregion } // Combine Textures && Reset UV aimTexture = new Texture2D(1, 1); List <Texture2D> txtList = new List <Texture2D>(); for (int i = 0; i < temptxtList.Count; i++) { txtList.AddRange(temptxtList[i]); } Rect[] tempUVs = aimTexture.PackTextures(txtList.ToArray(), 0); CutTexture(ref aimTexture, ref tempUVs); List <Rect> aimUVs = new List <Rect>(tempUVs); aimTexture.wrapMode = TextureWrapMode.Clamp; aimTexture.filterMode = FilterMode.Point; aimTexture.mipMapBias = 0f; aimTexture.Apply(); #region --- UV --- int rectIndexOffset = 0; for (int index = 0; index < num; index++) { List <VoxelFace> Faces = new List <VoxelFace>(VoxelFaces.GetRange( index * MaxFacesInOneMesh, Mathf.Min(MaxFacesInOneMesh, VoxelFaces.Count - index * MaxFacesInOneMesh) )); Rect[] rects = aimUVs.GetRange( rectIndexOffset, temptxtList[index].Length ).ToArray(); float gapX = 1f / aimTexture.width; float gapY = 1f / aimTexture.height; Vector2[] voxelUV = new Vector2[Faces.Count * 4]; for (int i = 0; i < Faces.Count; i++) { int rectID = uvIdMaps[index][i]; if (rectID >= rects.Length) { continue; } voxelUV[i * 4 + 0] = new Vector2(rects[rectID].xMin + gapX, rects[rectID].yMin + gapY); voxelUV[i * 4 + 1] = new Vector2(rects[rectID].xMax - gapX, rects[rectID].yMin + gapY); voxelUV[i * 4 + 2] = new Vector2(rects[rectID].xMin + gapX, rects[rectID].yMax - gapY); voxelUV[i * 4 + 3] = new Vector2(rects[rectID].xMax - gapX, rects[rectID].yMax - gapY); } uvIdMaps[index].Clear(); rectIndexOffset += temptxtList[index].Length; meshs[index].uv = voxelUV; meshs[index].RecalculateNormals(); } uvIdMaps.Clear(); aimUVs.Clear(); #endregion }