public void ConvertAllToBlockVectors() { List <BlockVectorNode> chunksToConvert = new List <BlockVectorNode>(); foreach (KeyValuePair <IntVector4, B45ChunkData> kvp in _chunks) { BlockVectorNode bvNode = kvp.Value._bvNode; if (bvNode == null) { Debug.LogError("node null!"); } chunksToConvert.Add(bvNode); } for (int i = 0; i < chunksToConvert.Count; i++) { BlockVectorNode bvNode = chunksToConvert[i]; B45ChunkData cd = bvNode.chunk; // convert the chunk data from byte array mode to block vector mode //if((cd.d_state & B45ChunkData.DS_BEING_DESTROYED) > 0) if (cd != null) { cd.bp(); bvNode.blockVectors = BlockVectorNode.ChunkData2BlockVectors(cd.DataVT); } } }
// obtain the level 0 node that associates with the given pos. public static BlockVectorNode readNode(IntVector3 atpos, BlockVectorNode root) { // calculate the index of the child in which the split will happen. int ind = 0; BlockVectorNode cur = root; IntVector3 nodeCenterPos = IntVector3.Zero; while (cur.pos.w != 0) { nodeCenterPos.x = cur.pos.x + cur.logicalSize / 2; nodeCenterPos.y = cur.pos.y + cur.logicalSize / 2; nodeCenterPos.z = cur.pos.z + cur.logicalSize / 2; ind = ((atpos.x >= nodeCenterPos.x) ? 1 : 0) | ((atpos.y >= nodeCenterPos.y) ? 2 : 0) | ((atpos.z >= nodeCenterPos.z) ? 4 : 0); if (cur.isLeaf) { cur.Split(); } cur = cur.children[ind] as BlockVectorNode; } return(cur); }
// append recursively public static void rec_append(BlockVectorNode node, BinaryWriter bw) { if (node.isLeaf) { if (node.blockVectors != null) { for (int i = 0; i < node.blockVectors.Count; i++) { IntVector3 nodePos = new IntVector3(node.pos.XYZ); BlockVector bv = node.blockVectors[i]; nodePos.x += bv.x - Block45Constants._numVoxelsPrefix; nodePos.y += bv.y - Block45Constants._numVoxelsPrefix; nodePos.z += bv.z - Block45Constants._numVoxelsPrefix; bw.Write(nodePos.x); bw.Write(nodePos.y); bw.Write(nodePos.z); bw.Write(bv.byte0); bw.Write(bv.byte1); } return; } } else { for (int i = 0; i < 8; i++) { rec_append(node.children[i] as BlockVectorNode, bw); } } }
public B45OctreeDataSource(BiLookup <int, B45ChunkData> chunkRebuildList, Block45Building _b45Building) { _chunkRebuildList = chunkRebuildList; _chunks = new Dictionary <IntVector4, B45ChunkData>(); bvtRoot = new BlockVectorNode(new IntVector4(0, 0, 0, 1), null, 0); b45Building = _b45Building; }
public void Import(byte[] buffer) { // vector octree root BlockVectorNode root = ((B45OctreeDataSource)_blockDS).bvtRoot; ((B45OctreeDataSource)_blockDS).Clear(); MemoryStream ms = new MemoryStream(buffer); BinaryReader _in = new BinaryReader(ms); int readVersion = _in.ReadInt32(); switch (readVersion) { case 2: int Size = _in.ReadInt32(); for (int i = 0; i < Size; i++) { int x = _in.ReadInt32(); int y = _in.ReadInt32(); int z = _in.ReadInt32(); IntVector3 index = new IntVector3(x, y, z); try{ root = ((B45OctreeDataSource)_blockDS).bvtRoot.reroot(index); } catch (Exception e) { Debug.LogWarning("Unexpected exception while importing" + index + e); break; } ((B45OctreeDataSource)_blockDS).bvtRoot = root; BlockVectorNode bvnode = BlockVectorNode.readNode(new IntVector3(x, y, z), root); //BlockVectorNode bvnode = node; if (bvnode.blockVectors == null) { bvnode.blockVectors = new List <BlockVector>() as List <BlockVector>; } // calculate the position relative to the block chunk's position. x = x & Block45Constants._mask; y = y & Block45Constants._mask; z = z & Block45Constants._mask; bvnode.blockVectors.Add(new BlockVector( x + Block45Constants._numVoxelsPrefix, y + Block45Constants._numVoxelsPrefix, z + Block45Constants._numVoxelsPrefix, _in.ReadByte(), _in.ReadByte())); } break; } _in.Close(); ms.Close(); }
bool isOutOfMeshDistance(IntVector3 index) { IntVector3 shiftVec = IntVector3.Zero; shiftVec.x = index.x << Block45Constants._shift; shiftVec.y = index.y << Block45Constants._shift; shiftVec.z = index.z << Block45Constants._shift; if (b45Building._observer == null) { return(true); } return(!BlockVectorNode.isCloseTo_static(shiftVec, b45Building._observer.position * Block45Constants._scaleInverted)); }
public static void rec_findLod(IntVector3 atpos, BlockVectorNode node, List <BlockVectorNode> ret) { if (node.isLeaf == false) { if (node.isInLodRange(atpos)) { ret.Add(node); } } if (node.isLeaf == false) { for (int i = 0; i < 8; i++) { rec_findLod(atpos, node.children[i] as BlockVectorNode, ret); } } }
public static void rec_find(IntVector3 atpos, BlockVectorNode node, List <BlockVectorNode> ret) { if (node.isLeaf && node.pos.w == 0) { if (node.isCloseTo(atpos)) { ret.Add(node); } } if (node.isLeaf == false) { for (int i = 0; i < 8; i++) { rec_find(atpos, node.children[i] as BlockVectorNode, ret); } } }
public static int rec_count_dbg(BlockVectorNode node) { int count = 0; if (node.chunk != null) { count = node.chunk.getFillRate(); } if (node.isLeaf == false) { for (int i = 0; i < 8; i++) { count += BlockVectorNode.rec_count_dbg(node.children[i] as BlockVectorNode); } } return(count); }
// count recursively public static int rec_count(BlockVectorNode node) { int count = 0; if (node.blockVectors != null) { count = node.blockVectors.Count; } if (node.isLeaf == false) { for (int i = 0; i < 8; i++) { count += BlockVectorNode.rec_count(node.children[i] as BlockVectorNode); } } return(count); }
B45ChunkData CreateChunk(IntVector4 index) { B45ChunkData chunk = new B45ChunkData(colliderMan); chunk.BuildList = _chunkRebuildList; writeChunk(index.x, index.y, index.z, chunk); chunk.ChunkPosLod_w = new IntVector4( (index.x), (index.y), (index.z), 0); chunk.bp(); chunk.AddToBuildList(); // make the bv node. if (true) { IntVector3 shiftVec = IntVector3.Zero; shiftVec.x = index.x << Block45Constants._shift; shiftVec.y = index.y << Block45Constants._shift; shiftVec.z = index.z << Block45Constants._shift; try{ // Add try for StackOverflowException BlockVectorNode newRootNode = bvtRoot.reroot(shiftVec); bvtRoot = newRootNode; } catch (Exception e) { Debug.LogWarning("Unexpected exception while creating chunk to" + index + e); return(chunk); } BlockVectorNode bvNode = BlockVectorNode.readNode(shiftVec, bvtRoot); if (bvNode.chunk != null) { // already a chunk has been assigned to this node. something is wrong here. return(chunk); } bvNode.chunk = chunk; chunk._bvNode = bvNode; bvNode.isByteArrayMode = true; } return(chunk); }
public void Split() { children = new BlockVectorNode[8]; int lod = pos.w; int childLogicalSize = logicalSize >> 1; for (int i = 0; i < 8; i++) { IntVector4 apos = new IntVector4(pos); apos.w = lod - 1; apos.x += (i & 1) * childLogicalSize; apos.y += ((i >> 1) & 1) * childLogicalSize; apos.z += ((i >> 2) & 1) * childLogicalSize; children[i] = new BlockVectorNode(apos, this, i); } }
public static void Clear(BlockVectorNode node) { if (node.blockVectors != null) { node.blockVectors.Clear(); node.blockVectors = null; } if (node.chunk != null) { node.chunk.DestroyGameObject(); node.chunk = null; } if (!node.isLeaf) { for (int i = 0; i < 8; i++) { Clear(node.children[i] as BlockVectorNode); } } }
public byte[] Export() { BlockVectorNode root = ((B45OctreeDataSource)_blockDS).bvtRoot; MemoryStream ms = new MemoryStream(); BinaryWriter _out = new BinaryWriter(ms); _out.Write(mVersion); switch (mVersion) { case 2: ((B45OctreeDataSource)_blockDS).ConvertAllToBlockVectors(); int elementCount = BlockVectorNode.rec_count(root); _out.Write(elementCount); BlockVectorNode.rec_append(root, _out); break; } _out.Close(); ms.Close(); return(ms.ToArray()); }
void writeToBlockVectors(IntVector3 index, IntVector3 localIndex, byte b0, byte b1) { IntVector3 shiftVec = IntVector3.Zero; shiftVec.x = index.x << Block45Constants._shift; shiftVec.y = index.y << Block45Constants._shift; shiftVec.z = index.z << Block45Constants._shift; try{ // Add try for StackOverflowException BlockVectorNode newRootNode = bvtRoot.reroot(shiftVec); bvtRoot = newRootNode; } catch (Exception e) { Debug.LogWarning("Unexpected exception while writing block to" + index + e); return; } BlockVectorNode bvNode = BlockVectorNode.readNode(shiftVec, bvtRoot); bvNode.write(localIndex.x + Block45Constants._numVoxelsPrefix, localIndex.y + Block45Constants._numVoxelsPrefix, localIndex.z + Block45Constants._numVoxelsPrefix, b0, b1); }
// this function should only be used by the root node. public BlockVectorNode reroot(IntVector3 atpos) { if (covers(atpos) == false) { // make a new node that can cover atpos IntVector4 newRootPos = new IntVector4(pos.XYZ, pos.w + 1); int maskX = 0; int maskY = 0; int maskZ = 0; if (atpos.x < pos.x) { maskX = 1; } if (atpos.y < pos.y) { maskY = 1; } if (atpos.z < pos.z) { maskZ = 1; } newRootPos.x -= maskX * logicalSize; newRootPos.y -= maskY * logicalSize; newRootPos.z -= maskZ * logicalSize; BlockVectorNode newRoot = new BlockVectorNode(newRootPos, null, 0); this.parent = newRoot; newRoot.Split(); int thisOctant = maskX + (maskY << 1) + (maskZ << 2); newRoot.children[thisOctant] = null; newRoot.children[thisOctant] = this; this.octant = thisOctant; return(newRoot.reroot(atpos)); } return(this); }
public void OctreeUpdate(IntVector3 cursorPos) { List <BlockVectorNode> blkNodeToConv = new List <BlockVectorNode>(); // check if there are block vector nodes that should be converted into lod chunks. // BlockVectorNode.rec_findLod(cursorPos, bvtRoot, blkNodeToConv); // for(int i = 0; i < blkNodeToConv.Count; i++){ // BlockVectorNode bvNode = blkNodeToConv[i]; // // // shift xyz // IntVector4 shiftXYZ = IntVector4.Zero; // shiftXYZ.x = bvNode.Pos.x >> Block45Constants._shift; // shiftXYZ.y = bvNode.Pos.y >> Block45Constants._shift; // shiftXYZ.z = bvNode.Pos.z >> Block45Constants._shift; // shiftXYZ.w = bvNode.Pos.w; // // // if(!_chunks.ContainsKey(shiftXYZ) ) // { // // B45ChunkData newChunk = CreateChunk(shiftXYZ); // // bvNode.chunk = newChunk; // newChunk._bvNode = bvNode; // // _chunks[shiftXYZ] = newChunk; // newChunk.bp(); // } // if(bvNode.blockVectors != null && bvNode.chunk != null){ // bvNode.chunk.bp(); // try // { // BlockVectorNode.BlockVectors2ChunkData(bvNode.blockVectors, bvNode.chunk.DataVT); // } // catch(Exception ex){ // int sdkf = 0; // } // bvNode.blockVectors.Clear(); // bvNode.blockVectors = null; // } // } // check if there are block vector nodes that should be converted into real chunks(byte array mode). BlockVectorNode.rec_find(cursorPos, bvtRoot, blkNodeToConv); // for(int i = 0; i < blkNodeToConv.Count; i++){ //// blkNodeToConv[i].makeCube(); // } //// B45LODNode.makeCubeRec(bvtRoot as B45LODNode); int elementCount1 = 0; int fills1 = 0; int fillsIn_Chunks1 = 0; if (b45Building.DebugMode) { elementCount1 = BlockVectorNode.rec_count(bvtRoot); fills1 = BlockVectorNode.rec_count_dbg(bvtRoot); fillsIn_Chunks1 = countpoints(); } for (int i = 0; i < blkNodeToConv.Count; i++) { BlockVectorNode bvNode = blkNodeToConv[i]; // shift xyz IntVector4 shiftXYZ = IntVector4.Zero; shiftXYZ.x = bvNode.Pos.x >> Block45Constants._shift; shiftXYZ.y = bvNode.Pos.y >> Block45Constants._shift; shiftXYZ.z = bvNode.Pos.z >> Block45Constants._shift; if (!_chunks.ContainsKey(shiftXYZ)) { B45ChunkData newChunk = CreateChunk(shiftXYZ); bvNode.chunk = newChunk; newChunk._bvNode = bvNode; _chunks[shiftXYZ] = newChunk; newChunk.bp(); } if (bvNode.blockVectors != null && bvNode.chunk != null) { bvNode.chunk.bp(); try { BlockVectorNode.BlockVectors2ChunkData(bvNode.blockVectors, bvNode.chunk.DataVT); } catch { //int sdkf = 0; } bvNode.blockVectors.Clear(); bvNode.blockVectors = null; } } if (b45Building.DebugMode) { int elementCount2 = BlockVectorNode.rec_count(bvtRoot); int fills2 = BlockVectorNode.rec_count_dbg(bvtRoot); int fillsIn_Chunks2 = countpoints(); Debug.LogError("B45 Octree State: " + elementCount1 + " / " + fills1 + " / " + fillsIn_Chunks1 + " ------------- " + elementCount2 + " / " + fills2 + " / " + fillsIn_Chunks2); // check for chunks that are out of view } //List<BlockVectorNode> bvToDispose = new List<BlockVectorNode>(); List <B45ChunkData> cdToDispose = new List <B45ChunkData>(); foreach (KeyValuePair <IntVector4, B45ChunkData> kvp in _chunks) { BlockVectorNode bvNode = kvp.Value._bvNode; B45ChunkData cd = kvp.Value; if (bvNode == null) { Debug.LogError("node null!"); } if (!bvNode.isCloseTo(cursorPos) && cd != null ) { // this node is too far from the camera, put it in the dispose list cd.bp(); cdToDispose.Add(cd); // _chunks.Remove(kvp.Key); } } for (int i = 0; i < cdToDispose.Count; i++) { B45ChunkData cd = cdToDispose[i]; // convert the chunk data from byte array mode to block vector mode if (cd != null && cd.isBeingDestroyed == false) { cd.setBeingDestroyed(); cd.bp(); cd._bvNode.blockVectors = BlockVectorNode.ChunkData2BlockVectors(cd.DataVT); cd._bvNode.isByteArrayMode = false; cd._bvNode.removeCube(); // remove this chunk from memory cd._bvNode.chunk = null; deferredRemoveList.Add(cd); } else { //int sdgf = 0; } } deferredRemoval(); }
// clear public void Clear() { BlockVectorNode.Clear(bvtRoot); B45LODNode.merge((B45LODNode)bvtRoot); _chunks.Clear(); }