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 );
		}
Example #2
0
        /// <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);

        }