public TerrainQuadTreeNode( Terrain terrain, TerrainQuadTreeNode parent, ushort xOff, ushort yOff, ushort size, ushort lod, ushort depth, ushort quadrant ) : base() { this.mTerrain = terrain; this.mParent = parent; this.mOffsetX = xOff; this.mOffsetY = yOff; this.mBoundaryX = (ushort)( xOff + size ); this.mBoundaryY = (ushort)( yOff + size ); this.mSize = size; this.mBaseLod = lod; this.mDepth = depth; this.mQuadrant = quadrant; this.mBoundingRadius = 0; this.mCurrentLod = -1; this.mMaterialLodIndex = 0; this.mLodTransition = 0; this.mChildWithMaxHeightDelta = null; this.mSelfOrChildRendered = false; this.mNodeWithVertexData = null; this.mAABB = new AxisAlignedBox(); if ( this.mTerrain.MaxBatchSize < size ) { var childSize = (ushort)( ( ( size - 1 )*0.5f ) + 1 ); var childOff = (ushort)( childSize - 1 ); var childLod = (ushort)( lod - 1 ); // LOD levels decrease down the tree (higher detail) var childDepth = (ushort)( depth + 1 ); // create children this.mChildren[ 0 ] = new TerrainQuadTreeNode( this.mTerrain, this, xOff, yOff, childSize, childLod, childDepth, 0 ); this.mChildren[ 1 ] = new TerrainQuadTreeNode( this.mTerrain, this, (ushort)( xOff + childOff ), yOff, childSize, childLod, childDepth, 1 ); this.mChildren[ 2 ] = new TerrainQuadTreeNode( this.mTerrain, this, xOff, (ushort)( yOff + childOff ), childSize, childLod, childDepth, 2 ); this.mChildren[ 3 ] = new TerrainQuadTreeNode( this.mTerrain, this, (ushort)( xOff + childOff ), (ushort)( yOff + childOff ), childSize, childLod, childDepth, 3 ); var ll = new LodLevel(); // non-leaf nodes always render with minBatchSize vertices ll.BatchSize = this.mTerrain.MinBatchSize; ll.MaxHeightDelta = 0; ll.CalcMaxHeightDelta = 0; this.mLodLevels.Add( ll ); } else { //no children Array.Clear( this.mChildren, 0, this.mChildren.Length ); // this is a leaf node and may have internal LODs of its own var ownLod = this.mTerrain.NumLodLevelsPerLeaf; Debug.Assert( lod == ( ownLod - 1 ), "The lod passed in should reflect the number of lods in a leaf" ); // leaf nodes always have a base LOD of 0, because they're always handling // the highest level of detail this.mBaseLod = 0; var sz = this.mTerrain.MaxBatchSize; while ( ownLod-- != 0 ) { var ll = new LodLevel(); ll.BatchSize = sz; ll.MaxHeightDelta = 0; ll.CalcMaxHeightDelta = 0; this.mLodLevels.Add( ll ); if ( ownLod != 0 ) { sz = (ushort)( ( ( sz - 1 )*0.5 ) + 1 ); } } Debug.Assert( sz == this.mTerrain.MinBatchSize ); } // local centre calculation // because of pow2 +1 there is always a middle point var midoffset = (ushort)( ( size - 1 )/2 ); var midpointX = (ushort)( this.mOffsetX + midoffset ); var midpointY = (ushort)( this.mOffsetY + midoffset ); //derive the local centry, but give it a height if 0 //TODO: - what if we actually centred this at the terrain height at this point? //would this be better? this.mTerrain.GetPoint( midpointX, midpointY, 0, ref this.mLocalCentre ); this.mMovable = new Movable( this ); this.mRend = new Rend( this ); }
/// <summary> /// Default constructor. /// </summary> /// <param name="terrain">The ultimate parent terrain</param> /// <param name="parent">ptional parent node (in which case xoff, yoff are 0 and size must be entire terrain)</param> /// <param name="xOff">Offsets from the start of the terrain data in 2D</param> /// <param name="yOff">Offsets from the start of the terrain data in 2D</param> /// <param name="size">The size of the node in vertices at the highest LOD</param> /// <param name="lod">The base LOD level</param> /// <param name="depth">The depth that this node is at in the tree (or convenience)</param> /// <param name="quadrant">The index of the quadrant (0, 1, 2, 3)</param> public TerrainQuadTreeNode(Terrain terrain, TerrainQuadTreeNode parent, ushort xOff, ushort yOff, ushort size, ushort lod, ushort depth, ushort quadrant) { mTerrain = terrain; mParent = parent; mOffsetX = xOff; mOffsetY = yOff; mBoundaryX = (ushort)(xOff + size); mBoundaryY = (ushort)(yOff + size); mSize = size; mBaseLod = lod; mDepth = depth; mQuadrant = quadrant; mBoundingRadius = 0; mCurrentLod = -1; mMaterialLodIndex = 0; mLodTransition = 0; mChildWithMaxHeightDelta = null; mSelfOrChildRendered = false; mNodeWithVertexData = null; // mMovable = null; mRend = null; mAABB = new AxisAlignedBox(); if (mTerrain.MaxBatchSize < size) { ushort childSize = (ushort)(((size - 1) * 0.5f) + 1); ushort childOff = (ushort)(childSize - 1); ushort childLod = (ushort)(lod - 1); ushort childDepth = (ushort)(depth + 1); mChildren[0] = new TerrainQuadTreeNode(mTerrain, this, xOff, yOff, childSize, childLod, childDepth, 0); mChildren[1] = new TerrainQuadTreeNode(mTerrain, this, (ushort)(xOff + childOff), yOff, childSize, childLod, childDepth, 1); mChildren[2] = new TerrainQuadTreeNode(mTerrain, this, xOff, (ushort)(yOff + childOff), childSize, childLod, childDepth, 2); mChildren[3] = new TerrainQuadTreeNode(mTerrain, this, (ushort)(xOff + childOff), (ushort)(yOff + childOff), childSize, childLod, childDepth, 3); LodLevel ll = new LodLevel(); // non-leaf nodes always render with minBatchSize vertices ll.BatchSize = mTerrain.MinBatchSize; ll.MaxHeightDelta = 0; ll.CalcMaxHeightDelta = 0; mLodLevels.Add(ll); } else { //no children Array.Clear(mChildren, 0, mChildren.Length); // this is a leaf node and may have internal LODs of its own ushort ownLod = mTerrain.LodLevelsPerLeafCount; Debug.Assert(lod == (ownLod - 1), "The lod passed in should reflect the number of lods in a leaf"); // leaf nodes always have a base LOD of 0, because they're always handling // the highest level of detail mBaseLod = 0; ushort sz = mTerrain.MaxBatchSize; while (ownLod-- != 0) { LodLevel ll = new LodLevel(); ll.BatchSize = sz; ll.MaxHeightDelta = 0; ll.CalcMaxHeightDelta = 0; mLodLevels.Add(ll); if(ownLod != 0) sz = (ushort)(((sz - 1) * 0.5) + 1); } Debug.Assert(sz == mTerrain.MinBatchSize); } // local centre calculation // because of pow2 +1 there is always a middle point ushort midoffset = (ushort)((size - 1) / 2); ushort midpointX = (ushort)(mOffsetX + midoffset); ushort midpointY = (ushort)(mOffsetY + midoffset); //derive the local centry, but give it a height if 0 //TODO: - what if we actually centred this at the terrain height at this point? //would this be better? mTerrain.GetPoint(midpointX, midpointY, 0, ref mLocalCentre); /*mRend = new Rend(this); mMovable = new Movable(this,mRend);*/ mRend= new TerrainRendable(this); SceneNode sn = mTerrain.RootSceneNode.CreateChildSceneNode(mLocalCentre); sn.AttachObject(mRend); // sn.AttachObject(mRend); }