// tmp algo public static void GenVecDataFromChildren(Block45OctNode node) { Dictionary <int, BlockVec> vecData = new Dictionary <int, BlockVec>(); for (int i = 0; i < 8; i++) { if (node._children[i]._vecData == null && !node._children[i].IsLeaf) { GenVecDataFromChildren(node._children[i]); } List <BlockVec> vecDataChild = node._children[i]._vecData; if (vecDataChild == null) { continue; } int ofsxyz = BlockVec.ToXYZ(S_NearNodeOfs[i, 0] << Block45Constants._shift, S_NearNodeOfs[i, 1] << Block45Constants._shift, S_NearNodeOfs[i, 2] << Block45Constants._shift); int n = vecDataChild.Count; for (int j = 0; j < n; j++) { int xyz = ((vecDataChild[j]._xyz + ofsxyz) >> 1) & 0x7F7F7F; vecData[xyz] = new BlockVec(xyz, vecDataChild[j]._byte0, vecDataChild[j]._byte1); } } node._vecData = new List <BlockVec>(vecData.Values); node.FreeChkData(); }
// this function should only be used by the root node. public Block45OctNode RerootToContainPos(IntVector4 pos) { if (!Covers(pos)) { // make a new node that can cover atpos and pos is ALIGNED with LOD Node width // B45Node width should be equal to or smaller than LODNode width int maskX, maskY, maskZ; if (_pos.w < Block45Constants.MAX_LOD) { int posMask = (1 << (Block45Constants._scaledShift + _pos.w + 1)) - 1; maskX = ((_pos.x & posMask) != 0 && pos.x < _pos.x) ? 1 : 0; maskY = ((_pos.y & posMask) != 0 && pos.y < _pos.y) ? 1 : 0; maskZ = ((_pos.z & posMask) != 0 && pos.z < _pos.z) ? 1 : 0; } else { maskX = (pos.x < _pos.x) ? 1 : 0; maskY = (pos.y < _pos.y) ? 1 : 0; maskZ = (pos.z < _pos.z) ? 1 : 0; } int thisOctant = maskX + (maskY << 1) + (maskZ << 2); // righttop to leftbottom IntVector4 newRootPos = new IntVector4(_pos.x - maskX * ScaledSize, _pos.y - maskY * ScaledSize, _pos.z - maskZ * ScaledSize, _pos.w + 1); Block45OctNode newRoot = Block45OctNode.CreateNode(newRootPos, OnCreateNode); this._parent = newRoot; newRoot.Split(thisOctant, this); return(newRoot.RerootToContainPos(pos)); } return(this); }
public static void SplitAt(Block45OctNode root, IntVector3 atpos, int lod) { // calculate the index of the child in which the split will happen. int ind = 0; Block45OctNode cur = root; int nodeCenterX = 0; int nodeCenterY = 0; int nodeCenterZ = 0; for (int i = 0; i < lod; i++) { int centerOfs = Block45Constants.CenterOfs(cur._pos.w); nodeCenterX = cur._pos.x + centerOfs; nodeCenterY = cur._pos.y + centerOfs; nodeCenterZ = cur._pos.z + centerOfs; ind = ((atpos.x > nodeCenterX) ? 1 : 0) | ((atpos.y > nodeCenterY) ? 2 : 0) | ((atpos.z > nodeCenterZ) ? 4 : 0); if (cur.IsLeaf) { cur.Split(); } cur = cur._children[ind]; } }
void GetNodesToGenCol1(IntVector3 boundPos, IntVector3 boundSize, Block45OctNode root, ref List <Block45OctNode> outNodesList) // ignore y to improve performance { if (root._pos.w == 0) { if (root.IsWholeInside(boundPos, boundSize) && root.ChunkGo != null && root.ChunkGo._mc.sharedMesh == null) { outNodesList.Add(root); } } else if (!root.IsLeaf) { if (root.IsWholeInside(boundPos, boundSize)) { AddChildrenNodesToGenCol(root, ref outNodesList); } else if (root.IsOverlapped(boundPos, boundSize)) { for (int i = 0; i < 8; i++) { GetNodesToGenCol1(boundPos, boundSize, root._children [i], ref outNodesList); } } } }
void AddNodeToBuildList(Block45OctNode node) { if (node.LOD == 0) { _octNodesToBuild.Add(node); } }
public void OnRecycle() { gameObject.SetActive(false); if (_mc.sharedMesh != null) { try { Block45Man.self.OnBlock45ColDestroy(this); } catch (System.Exception e) { Debug.LogError("Exception OnBlock45ColDestroy:" + e); } } //Note: mesh.Clear() will cause rebuilding MeshCollider which cause spike; // Destroy do not destroy it until the end of this frame, which cause FillMesh may fill the willDestroy mesh // So use DestroyImmediate instead. //DestroyImmediate(_mf.mesh); DestroyImmediate(_mf.sharedMesh); name = "b45Chnk_"; if (transform.parent != _defParent) { gameObject.layer = _defLayer; transform.parent = _defParent; } _data = null; }
public static Block45OctNode GetNodeRW(IntVector4 poslod, ref Block45OctNode root) // Write new if null { // Note: if req's w > root.w, root would be returned root = root.RerootToContainPos(poslod); int ind = 0; int nodeCenterX = 0; int nodeCenterY = 0; int nodeCenterZ = 0; Block45OctNode cur = root; while (cur._pos.w > poslod.w) { if (cur.IsLeaf) { cur.Split(); } int centerOfs = Block45Constants.CenterOfs(cur._pos.w); nodeCenterX = cur._pos.x + centerOfs; nodeCenterY = cur._pos.y + centerOfs; nodeCenterZ = cur._pos.z + centerOfs; ind = ((poslod.x >= nodeCenterX) ? 1 : 0) | ((poslod.y >= nodeCenterY) ? 2 : 0) | ((poslod.z >= nodeCenterZ) ? 4 : 0); cur = cur._children[ind]; } return(cur); }
// clear public void Clear() { if (_octRoot != null) { Block45OctNode.Clear(_octRoot); Block45OctNode.Merge(_octRoot); } }
public static void MakeCubeRec(Block45OctNode node) { node.MakeCube(); if (!node.IsLeaf) { for (int i = 0; i < 8; i++) { MakeCubeRec(node._children[i]); } } }
public void RebuildMesh() { if (SurfExtractorsMan.B45BuildSurfExtractor != null) { for (int i = 0; i < _octNodesToBuild.Count; i++) { Block45OctNode octNode = _octNodesToBuild [i]; SurfExtractorsMan.B45BuildSurfExtractor.AddSurfExtractReq(SurfExtractReqB45.Get(octNode.GetStamp(), octNode, ChunkProcPostGenMesh)); } } }
public static SurfExtractReqB45 Get(int chunkStamp, Block45OctNode chunkData, Action <SurfExtractReqB45> finHandler, int nVertsPerMesh = SurfExtractorsMan.c_vertsCntMax) { //SurfExtractReqB45 req = new SurfExtractReqB45 (); SurfExtractReqB45 req = s_reqPool.Get(); req._chunkStamp = chunkStamp; req._chunkData = chunkData; req._nVertsPerMesh = nVertsPerMesh; req._finHandler = finHandler; return(req); }
void FixedUpdate() { if (LodMan != null && LodMan.Observer != null && _frameCnt != Time.frameCount && _dataSource.RootNode != null) { _frameCnt = Time.frameCount; _lstBlock45Datas.Clear(); if (_bBuildColliderAsync) // cur pos has the highest priority { _lodCenterPos.x = Mathf.FloorToInt(LodMan.LastRefreshPos.x); _lodCenterPos.y = Mathf.FloorToInt(LodMan.LastRefreshPos.y); _lodCenterPos.z = Mathf.FloorToInt(LodMan.LastRefreshPos.z); _lodCenterPos.w = 0; Block45OctNode node = Block45OctNode.GetNodeRO(_lodCenterPos, _dataSource.RootNode); if (node != null) { if (node.NodeData != null) { node = node.NodeData.PickNodeToSetCol(); if (node != null) { _lstBlock45Datas.Add(node); } } } } if (_lstBlock45Datas.Count <= 0) { _boundPos = LodMan._Lod0ViewBounds.min; GetNodesToGenCol0(_boundPos, _boundSize, _dataSource.RootNode, ref _lstBlock45Datas); } int n = _lstBlock45Datas.Count; for (int i = 0; i < n; i++) { Block45OctNode node = _lstBlock45Datas [i]; if (node == null || node.ChunkGo == null) // { continue; } colliderBuilding = true; node.ChunkGo.OnSetCollider(); if (node.NodeData != null && node.NodeData.IsAllOctNodeReady()) { SceneChunkDependence.Instance.ValidListAdd(node.NodeData.ChunkPosLod, EDependChunkType.ChunkBlkCol); } if (_bBuildColliderAsync) { return; } } colliderBuilding = false; } }
public void Split(int octant = -1, Block45OctNode node = null) { if (NodeData != null) { lock (this.NodeData) { DoSplit(octant, node); } } else { DoSplit(octant, node); } }
public static Block45OctNode CreateNode(IntVector4 atpos, Action <Block45OctNode> onCreateNode) // root node { Block45OctNode node = new Block45OctNode(); node._pos = atpos; node._parent = null; node.OnCreateNode = onCreateNode; if (node.OnCreateNode != null) { node.OnCreateNode(node); } return(node); }
public static void Merge(Block45OctNode node) { if (!node.IsLeaf) { for (int i = 0; i < 8; i++) { if (node._children[i] != null) { Merge(node._children[i]); } node._children[i] = null; } } node._children = null; }
public void AddOctNode(Block45OctNode octNode) { if (_lstBlock45Datas == null) { _lstBlock45Datas = new List <Block45OctNode>(); _lstBlock45DatasStatus = new List <int>(); } _lstBlock45Datas.Add(octNode); _lstBlock45DatasStatus.Add(Block45OctNodeStatus_Idle); if (IsInReq && octNode.VecData != null) { BuildStep = BuildStep_StartGoCreating; _lstBlock45DatasStatus[_lstBlock45DatasStatus.Count - 1] = Block45OctNodeStatus_InBuild; _helperProc.SurfExtractor.AddSurfExtractReq(SurfExtractReqB45.Get(octNode.GetStamp(), octNode, _helperProc.ChunkProcPostGenMesh, SurfExtractorsMan.c_vertsCntMax)); } }
public static Block45OctNode CreateNode(IntVector4 atpos, Block45OctNode parent) { Block45OctNode node = new Block45OctNode(); node._pos = atpos; node._parent = parent; if (parent != null) { node.OnCreateNode = parent.OnCreateNode; } if (node.OnCreateNode != null) { node.OnCreateNode(node); } return(node); }
public B45Block Read(int x, int y, int z, int lod = 0) { IntVector4 poslod = Block45Constants.ToWorldUnitPos(x, y, z, lod); Block45OctNode curNode = Block45OctNode.GetNodeRO(poslod, _octRoot); if (curNode == null) { return(new B45Block(0, 0)); } int vx = (x >> lod) & Block45Constants._mask; int vy = (y >> lod) & Block45Constants._mask; int vz = (z >> lod) & Block45Constants._mask; return(curNode.Read(vx, vy, vz)); }
void AddChildrenNodesToGenCol(Block45OctNode root, ref List <Block45OctNode> outNodesList) { if (root._pos.w == 0) { if (root.ChunkGo != null && root.ChunkGo._mc.sharedMesh == null) { outNodesList.Add(root); } } else if (!root.IsLeaf) { for (int i = 0; i < 8; i++) { AddChildrenNodesToGenCol(root._children [i], ref outNodesList); } } }
public void AddToBuildList(Block45OctNode octNode) // need test { if (_lstBlock45Datas != null) { int n = _lstBlock45Datas.Count; for (int i = 0; i < n; i++) { if (_lstBlock45Datas[i] == octNode) { _lstBlock45DatasStatus[i] = Block45OctNodeStatus_InBuild; BuildStep = BuildStep_StartGoCreating; break; } } } _helperProc.SurfExtractor.AddSurfExtractReq(SurfExtractReqB45.Get(octNode.GetStamp(), octNode, _helperProc.ChunkProcPostGenMesh, SurfExtractorsMan.c_vertsCntMax)); }
public void ChunkProcPreLoadData(ILODNodeData nData) { if (_dataSource == null || _dataSource.RootNode == null) { return; } Block45LODNodeData b45NodeData = nData as Block45LODNodeData; int size = 1 << (LODOctreeMan.Lod0NodeShift + b45NodeData.ChunkPosLod.w); _tmpBoundPos.x = b45NodeData.ChunkPosLod.x << VoxelTerrainConstants._shift; _tmpBoundPos.y = b45NodeData.ChunkPosLod.y << VoxelTerrainConstants._shift; _tmpBoundPos.z = b45NodeData.ChunkPosLod.z << VoxelTerrainConstants._shift; _tmpLstBlock45Datas.Clear(); lock (b45NodeData) { Block45OctNode.FindNodesCenterInside(_tmpBoundPos, size, b45NodeData.LOD, _dataSource.RootNode, ref _tmpLstBlock45Datas); b45NodeData.SetBlock45Datas(_tmpLstBlock45Datas); } }
// append all children(inclusive) with lod recursively for savedata private static int AppendToWrite(Block45OctNode node, BinaryWriter bw, int lod) { int count = 0; if (node._pos.w == lod) { List <BlockVec> vecData = node.VecData; if (vecData != null) { IntVector4 blockUnitPos = Block45Constants.ToBlockUnitPos(node._pos.x, node._pos.y, node._pos.z, node._pos.w); int n = vecData.Count; for (int i = 0; i < n; i++) { BlockVec bv = vecData[i]; int x = bv.x - Block45Constants._numVoxelsPrefix; int y = bv.y - Block45Constants._numVoxelsPrefix; int z = bv.z - Block45Constants._numVoxelsPrefix; if (x < 0 || x >= Block45Constants._numVoxelsPerAxis || y < 0 || y >= Block45Constants._numVoxelsPerAxis || z < 0 || z >= Block45Constants._numVoxelsPerAxis) { continue; } bw.Write(blockUnitPos.x + x); bw.Write(blockUnitPos.y + y); bw.Write(blockUnitPos.z + z); bw.Write(bv._byte0); bw.Write(bv._byte1); count++; } } } else if (node._pos.w > lod && node._children != null) { for (int i = 0; i < 8; i++) { count += AppendToWrite(node._children[i], bw, lod); } } return(count); }
public Block45OctNode RerootToLOD(int lod) { if (LOD < lod) { int posMask = (1 << (Block45Constants._scaledShift + _pos.w + 1)) - 1; int maskX = (_pos.x & posMask) != 0 ? 1 : 0; int maskY = (_pos.y & posMask) != 0 ? 1 : 0; int maskZ = (_pos.z & posMask) != 0 ? 1 : 0; int thisOctant = maskX + (maskY << 1) + (maskZ << 2); // righttop to leftbottom IntVector4 newRootPos = new IntVector4(_pos.x - maskX * ScaledSize, _pos.y - maskY * ScaledSize, _pos.z - maskZ * ScaledSize, _pos.w + 1); Block45OctNode newRoot = Block45OctNode.CreateNode(newRootPos, OnCreateNode); this._parent = newRoot; newRoot.Split(thisOctant, this); return(newRoot.RerootToLOD(lod)); } return(this); }
// strategy 0: check center inside // strategy 1: check whole inside void GetNodesToGenCol0(IntVector3 boundPos, IntVector3 boundSize, Block45OctNode root, ref List <Block45OctNode> outNodesList) { if (root._pos.w == 0) { if (root.IsCenterInside(boundPos, boundSize) && root.ChunkGo != null && root.ChunkGo._mc != null && root.ChunkGo._mc.sharedMesh == null) { outNodesList.Add(root); } } else if (!root.IsLeaf) { if (root.IsOverlapped(boundPos, boundSize) && null != root._children) { for (int i = 0; i < 8; i++) { GetNodesToGenCol0(boundPos, boundSize, root._children [i], ref outNodesList); } } } }
public static void Clear(Block45OctNode node) { if (node._vecData != null) { node._vecData = null; } node.FreeChkData(); if (node._goChunk != null) { VFGoPool <Block45ChunkGo> .FreeGo(node._goChunk); node._goChunk = null; } if (!node.IsLeaf) { for (int i = 0; i < 8; i++) { Clear(node._children[i]); } } }
private void DoSplit(int octant, Block45OctNode node) { _children = new Block45OctNode[8]; int lod = _pos.w; int childScaledSize = ScaledSize >> 1; for (int i = 0; i < 8; i++) { if (i == octant) { _children [octant] = node; continue; } IntVector4 apos = new IntVector4(_pos); apos.w = lod - 1; apos.x += (i & 1) * childScaledSize; apos.y += ((i >> 1) & 1) * childScaledSize; apos.z += ((i >> 2) & 1) * childScaledSize; _children [i] = Block45OctNode.CreateNode(apos, this); } }
public static Block45OctNode GetNodeRO(IntVector4 poslod /*w unused*/, Block45OctNode root) // Read only { if (root == null || !root.Covers(poslod)) { return(null); } if (root._pos.w < poslod.w) { return(null); } if (root._pos.w == poslod.w) { return(root); } int ind = 0; int nodeCenterX = 0; int nodeCenterY = 0; int nodeCenterZ = 0; Block45OctNode cur = root; while (cur._pos.w > poslod.w) { if (cur.IsLeaf) { return(null); } int centerOfs = Block45Constants.CenterOfs(cur._pos.w); nodeCenterX = cur._pos.x + centerOfs; nodeCenterY = cur._pos.y + centerOfs; nodeCenterZ = cur._pos.z + centerOfs; ind = ((poslod.x >= nodeCenterX) ? 1 : 0) | ((poslod.y >= nodeCenterY) ? 2 : 0) | ((poslod.z >= nodeCenterZ) ? 4 : 0); cur = cur._children[ind]; } return(cur); }
public void EndUpdateOctNode(Block45OctNode octNode) { if (_lstBlock45Datas != null) { int n = _lstBlock45Datas.Count; for (int i = 0; i < n; i++) { if (_lstBlock45Datas[i] == octNode) { _lstBlock45DatasStatus[i] = Block45OctNodeStatus_Idle; break; } } for (int i = 0; i < n; i++) { if (_lstBlock45DatasStatus[i] != Block45OctNodeStatus_Idle) { return; } } } BuildStep = BuildStep_NotInBuild; EndUpdateNodeData(); }
public int Write(B45Block voxel, int x, int y, int z, int lod = 0) // logic pos { int vx = (x >> lod) & Block45Constants._mask; int vy = (y >> lod) & Block45Constants._mask; int vz = (z >> lod) & Block45Constants._mask; //Debug.LogWarning("[BlockWrite]:"+x+","+y+","+z+","+voxel.blockType+","+voxel.materialType); IntVector4 poslod; Block45OctNode curNode; if (_octRoot == null) { poslod = Block45Constants.ToWorldUnitPos(x & ~Block45Constants._mask, y & ~Block45Constants._mask, z & ~Block45Constants._mask, lod); IntVector4 rootPosLod = new IntVector4(poslod); curNode = _octRoot = Block45OctNode.CreateNode(rootPosLod, _onCreateNode); //Extend root node if root.lod < VoxelTerrainConstans.MaxLOD _octRoot = _octRoot.RerootToLOD(LODOctreeMan._maxLod); } else { poslod = Block45Constants.ToWorldUnitPos(x, y, z, lod); curNode = Block45OctNode.GetNodeRW(poslod, ref _octRoot); } curNode.Write(vx, vy, vz, voxel.blockType, voxel.materialType); // Write neighbour int fx = 0, fy = 0, fz = 0; int dirtyMask = 0x80; // 0,1,2 bit for xyz dirty mask;4,5,6 bit for sign(neg->1);7 bit for current pos(now not used) // If write one edge's voxel may cause the other edge being modified if (vx < Block45OctNode.S_MinNoDirtyIdx) { fx = -1; dirtyMask |= 0x11; } else if (vx >= Block45OctNode.S_MaxNoDirtyIdx) { fx = 1; dirtyMask |= 0x01; } if (vy < Block45OctNode.S_MinNoDirtyIdx) { fy = -1; dirtyMask |= 0x22; } else if (vy >= Block45OctNode.S_MaxNoDirtyIdx) { fy = 1; dirtyMask |= 0x02; } if (vz < Block45OctNode.S_MinNoDirtyIdx) { fz = -1; dirtyMask |= 0x44; } else if (vz >= Block45OctNode.S_MaxNoDirtyIdx) { fz = 1; dirtyMask |= 0x04; } if (dirtyMask != 0x80) { int _shift = Block45Constants._shift; int cxlod = (x >> (lod + _shift)); int cylod = (y >> (lod + _shift)); int czlod = (z >> (lod + _shift)); int cxround; int cyround; int czround; for (int i = 1; i < 8; i++) { if ((dirtyMask & i) == i) { int dx = fx * Block45OctNode.S_NearNodeOfs[i, 0], dy = fy * Block45OctNode.S_NearNodeOfs[i, 1], dz = fz * Block45OctNode.S_NearNodeOfs[i, 2]; cxround = (cxlod + dx); cyround = (cylod + dy); czround = (czlod + dz); poslod.x = cxround << (Block45Constants._scaledShift + lod); poslod.y = cyround << (Block45Constants._scaledShift + lod); poslod.z = czround << (Block45Constants._scaledShift + lod); Block45OctNode nearNode = Block45OctNode.GetNodeRW(poslod, ref _octRoot); nearNode.Write(vx - dx * Block45Constants._numVoxelsPerAxis, vy - dy * Block45Constants._numVoxelsPerAxis, vz - dz * Block45Constants._numVoxelsPerAxis, voxel.blockType, voxel.materialType); } } } return(dirtyMask); }
public static void FindNodesCenterInside(IntVector3 boundPos, int boundSize, int lod, Block45OctNode root, ref List <Block45OctNode> outNodesList) { if (root._pos.w == lod) { if (root.IsCenterInside(boundPos, boundSize)) { outNodesList.Add(root); } return; } else if (root._pos.w > lod) { if (!root.IsLeaf) { for (int i = 0; i < 8; i++) { FindNodesCenterInside(boundPos, boundSize, lod, root._children [i], ref outNodesList); } } } }