/// <summary> /// Done while BuildVBO generating (position in AOArray) /// </summary> void GenCubeShadowLightAO(SmallCube _cube, int _cx, int _cy, int _cz, int _aox, int _aoy, int _aoz, byte _byVFMask, ref Color[] _colors) { int i, j; Color gradCol = m_colPalette[_cube.byMatL0 - 1]; //Lighting to face for (i = 0; i < 6; i++) //6 faces { if ((_byVFMask & (1 << i)) == 0) { continue; //Face invisible } for (j = 0; j < 4; j++) { int nNumVertex = CubeHelpers.fv[i, j]; //Face,Corner byte byOcclusion = SmoothOcclusion(_cube, _aox, _aoy, _aoz, nNumVertex, i); m_shadowVerts[j] = Color.Lerp(gradCol, Color.Black, (float)byOcclusion / 6.0f); } int k = i << 2;//*4 _colors[k] = m_shadowVerts[0]; _colors[k + 1] = m_shadowVerts[1]; _colors[k + 2] = m_shadowVerts[2]; _colors[k + 3] = m_shadowVerts[3]; } }
public byte CalcVisibleFaces(SmallCube c, int cx, int cy, int cz) { byte byVFMask = 0x00; //By default no faces visibles if (c.byMatL0 == 0) { return(byVFMask); } //For each Cube's faces SmallCube nc; int i; for (i = 0; i < 6; i++) //6 faces { bool bvis = true; //check if neighbour face is solid m_array.GetNeighbourCube(cx, cy, cz, (CubeHelpers.SIDE)i, out nc); if (nc.byMatL0 != 0) { bvis = false; } //Update visible face if (bvis) { byVFMask |= (byte)(1 << i); } } return(byVFMask); }
public CubeBrush(Game _game, int _sizeX, int _sizeY, int _sizeZ, bool _createDummy) { Game = _game; //Array size SetSize(_sizeX, _sizeY, _sizeZ); //Create a plane at bottom if (_createDummy) { SmallCube cube = new SmallCube(); cube.byMatL0 = 16; int x, y, z; y = 0; for (x = 0; x < _sizeX; x++) { for (z = 0; z < _sizeZ; z++) { m_array.SetCube(x, y, z, cube); } } } //Create Palette BuildDefaultColorPalette(); //Meshes m_genMesh = new GenMesh(); }
public bool GetNeighbourCube(int x, int y, int z, CubeHelpers.SIDE side, out SmallCube _c) { _c = m_emptyCube; switch (side) { case CubeHelpers.SIDE.O_LEFT: x -= 1; break; //0: -x case CubeHelpers.SIDE.O_RIGHT: x += 1; break; //1: +x case CubeHelpers.SIDE.O_BOTTOM: y -= 1; break; //2: -y case CubeHelpers.SIDE.O_TOP: y += 1; break; //3: +y case CubeHelpers.SIDE.O_BACK: z -= 1; break; //4: -z case CubeHelpers.SIDE.O_FRONT: z += 1; break; //5: +z } if (x < 0 || y < 0 || z < 0) { return(false); } if (x >= CUBESIZEX || y >= CUBESIZEY || z >= CUBESIZEZ) { return(false); } GetCube(x, y, z, out _c); return(true); }
/// <summary> /// Get Cube vvalue at coords /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="_c"></param> public void GetCube(int x, int y, int z, out SmallCube _c) { //Get chunk int chX = x >> CHUNKSIZE_OPSHIFT; //x / CHUNKSIZE; int chY = y >> CHUNKSIZE_OPSHIFT; //y / CHUNKSIZE; int chZ = z >> CHUNKSIZE_OPSHIFT; //z / CHUNKSIZE; int offset = (chX * FlattenOffset) + (chZ * CHUNKSIZEY) + chY; CubeChunk3D chunk = m_arrayChunks[offset]; if (chunk == null) { _c = m_emptyCube; return; } if (chunk.m_array == null) { _c = chunk.m_solidChunkCube; return; } //Return Cube into chunk chX = x - (chX << CHUNKSIZE_OPSHIFT); //x - (bx * CHUNKSIZE); chY = y - (chY << CHUNKSIZE_OPSHIFT); //(by * CHUNKSIZE); chZ = z - (chZ << CHUNKSIZE_OPSHIFT); //(bz * CHUNKSIZE); offset = (chX << FlattenOffsetChunk_OPSHIFT) + (chZ << CHUNKSIZE_OPSHIFT) + chY; _c = chunk.m_array[offset]; }
public void SetCube(int _x, int _y, int _z, SmallCube _c) { if (m_array == null) { m_array = new SmallCube[CubeArray3D.CHUNKSIZE * CubeArray3D.CHUNKSIZE * CubeArray3D.CHUNKSIZE]; } m_array[(_x << CubeArray3D.FlattenOffsetChunk_OPSHIFT) + (_z << CubeArray3D.CHUNKSIZE_OPSHIFT) + _y] = _c; }
public void GetCube(int _x, int _y, int _z, out SmallCube _c) { if (m_array == null) { _c = m_solidChunkCube; } else { _c = m_array[(_x << CubeArray3D.FlattenOffsetChunk_OPSHIFT) + (_z << CubeArray3D.CHUNKSIZE_OPSHIFT) + _y]; } }
public void SetCube(int _x, int _y, int _z, SmallCube _c) { if (_x < 0 || _y < 0 || _z < 0) { return; } if (_x >= m_array.CUBESIZEX || _y >= m_array.CUBESIZEY || _z >= m_array.CUBESIZEZ) { return; } m_array.SetCube(_x, _y, _z, _c); }
/// <summary> /// Set Cube value at coords /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <param name="st"></param> public void SetCube(int x, int y, int z, SmallCube st) { int chX = x >> CHUNKSIZE_OPSHIFT; //x / CHUNKSIZE; int chY = y >> CHUNKSIZE_OPSHIFT; //y / CHUNKSIZE; int chZ = z >> CHUNKSIZE_OPSHIFT; //z / CHUNKSIZE; int offset = (chX * FlattenOffset) + (chZ * CHUNKSIZEY) + chY; CubeChunk3D chunk = m_arrayChunks[offset]; if (chunk == null) { chunk = new CubeChunk3D(); m_arrayChunks[offset] = chunk; } chX = x - (chX << CHUNKSIZE_OPSHIFT); //x - (bx * CHUNKSIZE); chY = y - (chY << CHUNKSIZE_OPSHIFT); //y - (by * CHUNKSIZE); chZ = z - (chZ << CHUNKSIZE_OPSHIFT); //z - (bz * CHUNKSIZE); chunk.SetCube(chX, chY, chZ, st); }
/// <summary> /// Smooth occlusion per face (position in AOArray) /// </summary> byte SmoothOcclusion(SmallCube _cube, int _aox, int _aoy, int _aoz, int _vidx, int _side) { byte oc = 0; int offset; Vector3Int o = new Vector3Int(_aox, _aoy, _aoz); Vector3Int r = CubeHelpers.SolidVertex[_vidx]; int sign = _side & 1; int dim = _side >> 1; if (sign != 0) { o[CubeHelpers.D[dim]] += 1; } else { o[CubeHelpers.D[dim]] -= 1; } //current int x, y, z; int xx, yy, zz; x = o[0]; y = o[1]; z = o[2]; x = x + 1; y = y + 1; z = z + 1; xx = x; yy = y; zz = z; offset = (xx * (FlattenOffsetAO)) + (zz * AO_CUBESIZE_Y) + yy; //3darray[(x * (sy*sz)) + (z * sy) + y] offset = Math.Max(0, offset); offset = Math.Min(offset, (AO_CUBESIZE_X * AO_CUBESIZE_Y * AO_CUBESIZE_Z) - 1); oc += (byte)((int)m_abyOcclusionCubeMap[offset] >> 1); if (dim == 0)//X { int s1 = 1; int s2 = 1; if (r[1] == 0) { s1 = -s1; //corner } if (r[2] == 0) { s2 = -s2; //corner } //Y-Z yy = y; zz = z + s2; offset = (xx * (FlattenOffsetAO)) + (zz * AO_CUBESIZE_Y) + yy; offset = Math.Max(0, offset); offset = Math.Min(offset, (AO_CUBESIZE_X * AO_CUBESIZE_Y * AO_CUBESIZE_Z) - 1); oc += (byte)((int)m_abyOcclusionCubeMap[offset] >> 1); yy = y + s1; zz = z; offset = (xx * (FlattenOffsetAO)) + (zz * AO_CUBESIZE_Y) + yy; offset = Math.Max(0, offset); offset = Math.Min(offset, (AO_CUBESIZE_X * AO_CUBESIZE_Y * AO_CUBESIZE_Z) - 1); oc += (byte)((int)m_abyOcclusionCubeMap[offset] >> 1); yy = y + s1; zz = z + s2; offset = (xx * (FlattenOffsetAO)) + (zz * AO_CUBESIZE_Y) + yy; offset = Math.Max(0, offset); offset = Math.Min(offset, (AO_CUBESIZE_X * AO_CUBESIZE_Y * AO_CUBESIZE_Z) - 1); oc += (byte)((int)m_abyOcclusionCubeMap[offset] >> 1); } else if (dim == 1)//Y { int s1 = 1; int s2 = 1; if (r[0] == 0) { s1 = -s1; //corner } if (r[2] == 0) { s2 = -s2; //corner } //X-Z xx = x; zz = z + s2; offset = (xx * (FlattenOffsetAO)) + (zz * AO_CUBESIZE_Y) + yy; offset = Math.Max(0, offset); offset = Math.Min(offset, (AO_CUBESIZE_X * AO_CUBESIZE_Y * AO_CUBESIZE_Z) - 1); oc += (byte)((int)m_abyOcclusionCubeMap[offset] >> 1); xx = x + s1; zz = z; offset = (xx * (FlattenOffsetAO)) + (zz * AO_CUBESIZE_Y) + yy; offset = Math.Max(0, offset); offset = Math.Min(offset, (AO_CUBESIZE_X * AO_CUBESIZE_Y * AO_CUBESIZE_Z) - 1); oc += (byte)((int)m_abyOcclusionCubeMap[offset] >> 1); xx = x + s1; zz = z + s2; offset = (xx * (FlattenOffsetAO)) + (zz * AO_CUBESIZE_Y) + yy; offset = Math.Max(0, offset); offset = Math.Min(offset, (AO_CUBESIZE_X * AO_CUBESIZE_Y * AO_CUBESIZE_Z) - 1); oc += (byte)((int)m_abyOcclusionCubeMap[offset] >> 1); } else if (dim == 2) //Z { int s1 = 1; int s2 = 1; if (r[0] == 0) { s1 = -s1; //corner } if (r[1] == 0) { s2 = -s2; //corner } //X-Y xx = x; yy = y + s2; offset = (xx * (FlattenOffsetAO)) + (zz * AO_CUBESIZE_Y) + yy; offset = Math.Max(0, offset); offset = Math.Min(offset, (AO_CUBESIZE_X * AO_CUBESIZE_Y * AO_CUBESIZE_Z) - 1); oc += (byte)((int)m_abyOcclusionCubeMap[offset] >> 1); xx = x + s1; yy = y; offset = (xx * (FlattenOffsetAO)) + (zz * AO_CUBESIZE_Y) + yy; offset = Math.Max(0, offset); offset = Math.Min(offset, (AO_CUBESIZE_X * AO_CUBESIZE_Y * AO_CUBESIZE_Z) - 1); oc += (byte)((int)m_abyOcclusionCubeMap[offset] >> 1); xx = x + s1; yy = y + s2; offset = (xx * (FlattenOffsetAO)) + (zz * AO_CUBESIZE_Y) + yy; offset = Math.Max(0, offset); offset = Math.Min(offset, (AO_CUBESIZE_X * AO_CUBESIZE_Y * AO_CUBESIZE_Z) - 1); oc += (byte)((int)m_abyOcclusionCubeMap[offset] >> 1); } return(oc); }
//Generate a cube VBO //.position in CubeArray3D void GenCubeVBO2(SmallCube _c, int _cx, int _cy, int _cz, int _x, int _y, int _z) { int i, j; ////////////////////////// COMPUTE VISIBLES FACES MASK byte byVFMask = CalcVisibleFaces(_c, _cx, _cy, _cz); if (byVFMask == 0) { return; } ////////////////////////// COMPUTE VERTICES POS int nNumVertex; for (j = 0; j < 8; j++) { m_bVertexComputed[j] = false; m_vertComputed[j] = Vector3.Zero; } int wcx = _cx; //To World coord int wcy = _cy; //To World coord int wcz = _cz; //To World Coord //For each Cube's faces for (i = 0; i < 6; i++) //6 faces { //If face visibility precalc mask if ((byVFMask & (1 << i)) != 0) { for (j = 0; j < 4; j++) //4 corners { nNumVertex = CubeHelpers.fv[i, j]; //Face,Corner if (m_bVertexComputed[nNumVertex] == false) //if never calc { CubeHelpers.GetSolidWorldVertex(wcx, wcy, wcz, nNumVertex, out m_vertComputed[nNumVertex]); m_vertComputed[nNumVertex] *= CubeHelpers.CUBE_SIZE; //Scale cube size m_bVertexComputed[nNumVertex] = true; } } } } ////////////////////////// COMPUTE SHADOW LIGHTING GenCubeShadowLightAO(_c, _cx, _cy, _cz, _x, _y, _z, byVFMask, ref m_vertCols); ////////////////////////// COMPUTE CUBE FACES int v0, v1, v2, v3; int iv0, iv1, iv2, iv3; for (i = 0; i < 6; i++) //6 faces { if ((byVFMask & (1 << i)) == 0) { continue; //Face invisible } v0 = CubeHelpers.fv[i, 0]; //Face,Corner v1 = CubeHelpers.fv[i, 1]; //Face,Corner v2 = CubeHelpers.fv[i, 2]; //Face,Corner v3 = CubeHelpers.fv[i, 3]; //Face,Corner int dim = i >> 1; // 0,0,1,1,2,2 X,Y,Z j = i << 2; //Color index in m_vertCols ///////////////////// //Get face normal Vector3 n1 = CubeHelpers.FacesPerSideNormal[i]; //////////////////////////////// //Add vertices //V0 iv0 = m_genMesh.AddVertex(ref m_vertComputed[v0], ref m_vertCols[j], ref n1); //V1 iv1 = m_genMesh.AddVertex(ref m_vertComputed[v1], ref m_vertCols[j + 1], ref n1); //V2 iv2 = m_genMesh.AddVertex(ref m_vertComputed[v2], ref m_vertCols[j + 2], ref n1); //V3 iv3 = m_genMesh.AddVertex(ref m_vertComputed[v3], ref m_vertCols[j + 3], ref n1); //////////////////////////////// //Add Face m_genMesh.AddQuad((ushort)iv0, (ushort)iv1, (ushort)iv2, (ushort)iv3); } }
public bool RayCast(Vector3 _o, Vector3 _ray, float _dist, ref BoundingBox _obb, ref Vector3Int _oposcubeTrack, out SmallCube _ocube) { float cs = (float)CubeHelpers.CUBE_SIZE; //Step from _o to _ray float d = 0.0f; Vector3 p = _o; _ocube = CubeArray3D.m_emptyCube; //Debug.WriteLine("RayCast start at {0} dir {1}", p, _ray); while (d < _dist) { //Get cube at _o int cx = (int)(p.X / CubeHelpers.CUBE_SIZE); //World To Cube unit int cy = (int)(p.Y / CubeHelpers.CUBE_SIZE); int cz = (int)(p.Z / CubeHelpers.CUBE_SIZE); if (cx >= 0 && cy >= 0 && cz >= 0 && cx < m_array.CUBESIZEX && cy < m_array.CUBESIZEY && cz < m_array.CUBESIZEZ) { SmallCube cube; m_array.GetCube(cx, cy, cz, out cube); if (cube.byMatL0 != 0) { //Debug.WriteLine("Cube Found at {0},{1},{2}", cx, cy, cz); _oposcubeTrack.X = cx; //In cube unit _oposcubeTrack.Y = cy; //In cube unit _oposcubeTrack.Z = cz; //BB _obb.Min.X = (float)(cx * CubeHelpers.CUBE_SIZE); //To world coords _obb.Min.Y = (float)(cy * CubeHelpers.CUBE_SIZE); //To world coords _obb.Min.Z = (float)(cz * CubeHelpers.CUBE_SIZE); //To world coords _obb.Max.X = _obb.Min.X + cs; _obb.Max.Y = _obb.Min.Y + cs; _obb.Max.Z = _obb.Min.Z + cs; _ocube = cube; return(true); } } d += 1.0f; p += _ray; } //Debug.WriteLine("RayCast end at {0}", p); return(false); }
public void GetCube(int _x, int _y, int _z, out SmallCube _c) { m_array.GetCube(_x, _y, _z, out _c); }
/// <summary> /// Read .VOX File and return a CubeArray3D /// </summary> /// <param name="_strPath"></param> /// <returns></returns> //public bool ReadFile(Windows.Storage.Streams.DataReader _br) public bool ReadFile(BinaryReader _br) { ////////////////////////////////////////////////// //Read Header //4 bytes: magic number ('V' 'O' 'X' 'space' ) //4 bytes: version number (current version is 150 ) UInt32 signature = _br.ReadUInt32(); if (signature != 0x20584F56) //56 4F 58 20 { Debug.WriteLine("Not an MagicaVoxel File format"); return(false); } UInt32 version = _br.ReadUInt32(); if (version < 150) { Debug.WriteLine("MagicaVoxel version too old"); return(false); } // header //4 bytes: chunk id //4 bytes: size of chunk contents (n) //4 bytes: total size of children chunks(m) //// chunk content //n bytes: chunk contents //// children chunks : m bytes //{ child chunk 0 } //{ child chunk 1 } int sizeX, sizeY, sizeZ; sizeX = sizeY = sizeZ = 0; int numVoxels = 0; int offsetX, offsetY, offsetZ; offsetX = offsetY = offsetZ = 0; SmallCube cube = new SmallCube(); #if ANDROID while (_br.BaseStream.IsDataAvailable()) #else while (_br.BaseStream.Position < _br.BaseStream.Length) #endif { string chunkName = new string(_br.ReadChars(4)); UInt32 chunkSize = _br.ReadUInt32(); UInt32 chunkTotalChildSize = _br.ReadUInt32(); if (chunkName == "SIZE") { //(4 bytes x 3 : x, y, z ) sizeX = _br.ReadInt32(); sizeY = _br.ReadInt32(); sizeZ = _br.ReadInt32(); //Align size to chunk size int sx = sizeX + ((CubeArray3D.CHUNKSIZE - (sizeX % CubeArray3D.CHUNKSIZE)) % CubeArray3D.CHUNKSIZE); int sy = sizeY + ((CubeArray3D.CHUNKSIZE - (sizeY % CubeArray3D.CHUNKSIZE)) % CubeArray3D.CHUNKSIZE); int sz = sizeZ + ((CubeArray3D.CHUNKSIZE - (sizeZ % CubeArray3D.CHUNKSIZE)) % CubeArray3D.CHUNKSIZE); m_carray.SetSize(sx, sz, sy); //Reversed y-z offsetX = (sx - sizeX) >> 1; offsetY = (sz - sizeZ) >> 1; //Reversed y-z offsetZ = (sy - sizeY) >> 1; //Reversed y-z } else if (chunkName == "XYZI") { //(numVoxels : 4 bytes ) //(each voxel: 1 byte x 4 : x, y, z, colorIndex ) x numVoxels numVoxels = _br.ReadInt32(); while (numVoxels > 0) { byte vx = _br.ReadByte(); byte vy = _br.ReadByte(); byte vz = _br.ReadByte(); byte vi = _br.ReadByte(); cube.byMatL0 = vi; m_carray.SetCube(offsetX + vx, offsetY + vz, m_carray.CUBESIZEZ - vy - 1 - offsetZ, cube); //Reserved y-z numVoxels--; } } else if (chunkName == "RGBA") { //(each pixel: 1 byte x 4 : r, g, b, a ) x 256 for (int i = 0; i < 256; i++) { byte r = _br.ReadByte(); byte g = _br.ReadByte(); byte b = _br.ReadByte(); byte a = _br.ReadByte(); m_palette[i] = Color.FromNonPremultiplied(r, g, b, a); } } } return(true); }
public SmallCube m_solidChunkCube; //If solid Chunk public CubeChunk3D() { m_solidChunkCube = CubeArray3D.m_emptyCube; }