public HeightField(Tile t) : base() { tile = t; Init(WorldManager.Instance.MetersPerSample(tile.Location)); // generate the height map WorldManager.Instance.TerrainGenerator.GenerateHeightField(location, Size, metersPerSample, heightMap, out minHeight, out maxHeight); UpdateBounds(); }
/// <summary> /// Create a new heightField that is (equal or) lower LOD than the four sources, /// Height points are copied from the four sources. /// </summary> /// <param name="t"></param> /// <param name="srcNW"></param> /// <param name="srcNE"></param> /// <param name="srcSW"></param> /// <param name="srcSE"></param> public HeightField(Tile t, HeightField srcNW, HeightField srcNE, HeightField srcSW, HeightField srcSE ) : base() { tile = t; Init(WorldManager.Instance.MetersPerSample(tile.Location)); // copy from the source heightMap int halfSamples = numSamples/2; CopyHeightFieldScaleDown(srcSW.heightMap, metersPerSample / srcSW.metersPerSample, srcSW.numSamples, 0, halfSamples); CopyHeightFieldScaleDown(srcSE.heightMap, metersPerSample / srcSE.metersPerSample, srcSE.numSamples, halfSamples, halfSamples); CopyHeightFieldScaleDown(srcNW.heightMap, metersPerSample / srcNW.metersPerSample, srcNW.numSamples, 0, 0); CopyHeightFieldScaleDown(srcNE.heightMap, metersPerSample / srcNE.metersPerSample, srcNE.numSamples, halfSamples, 0); // update minHeight and maxHeight by taking the most extreme from the 4 sources. // this could result in a bounding box slightly larger than necessary, but its // not enough of an issue to warrant scanning the entire heightField looking for // the true min and max. minHeight = srcSW.minHeight; if ( srcSE.minHeight < minHeight ) { minHeight = srcSE.minHeight; } if ( srcNW.minHeight < minHeight ) { minHeight = srcNW.minHeight; } if ( srcNE.minHeight < minHeight ) { minHeight = srcNE.minHeight; } maxHeight = srcSW.maxHeight; if ( srcSE.maxHeight > maxHeight ) { maxHeight = srcSE.maxHeight; } if ( srcNW.maxHeight > maxHeight ) { maxHeight = srcNW.maxHeight; } if ( srcNE.maxHeight > maxHeight ) { maxHeight = srcNE.maxHeight; } UpdateBounds(); }
/// <summary> /// Page Constructor /// </summary> /// <param name="relativeLocation">The location of the page in world space, relative to the page containing the camera</param> /// <param name="indexX">index into the TerrainManager's page array</param> /// <param name="indexZ">index into the TerrainManager's page array</param> public Page(Vector3 relativeLocation, int indexX, int indexZ) { size = TerrainManager.Instance.PageSize; this.relativeLocation = relativeLocation; this.indexX = indexX; this.indexZ = indexZ; // Figure out which page the camera is in PageCoord cameraPageCoord = new PageCoord(TerrainManager.Instance.VisPageRadius, TerrainManager.Instance.VisPageRadius); // compute the distance (in pages) from this page to the camera page pagesFromCamera = cameraPageCoord.Distance(new PageCoord(indexX, indexZ)); // create a scene node for this page String nodeName = String.Format("Page[{0},{1}]", indexX, indexZ); sceneNode = TerrainManager.Instance.WorldRootSceneNode.CreateChildSceneNode(nodeName); sceneNode.Position = relativeLocation; // ask the world manager how many tiles we need in this page based on the distance from the camera numTiles = TerrainManager.Instance.TilesPerPage(pagesFromCamera); // compute size of a tile in sample space tileSize = size / numTiles; // allocate the array of tiles tiles = new Tile[numTiles,numTiles]; // this is the size of the tile in "world space" float tileWorldSize = tileSize * TerrainManager.oneMeter; // create the tiles for this page for ( int tilex = 0; tilex < numTiles; tilex++ ) { float tileWorldX = tilex * tileWorldSize + relativeLocation.x; for ( int tilez = 0; tilez < numTiles; tilez++ ) { float tileWorldZ = tilez * tileWorldSize + relativeLocation.z; Tile t = new Tile(new Vector3(tileWorldX, 0, tileWorldZ), tileSize, this, tilex, tilez); tiles[tilex, tilez] = t; } } }
/// <summary> /// create a new heightField that has the same LOD as the source, /// and 1/4 the area of the source. Height points are copied from one /// quadrant of the source. /// If the heightField needs to be higher LOD, it will be adjusted /// later and the required points will be generated. /// </summary> /// <param name="t"></param> /// <param name="src"></param> /// <param name="quad"></param> public HeightField(Tile t, HeightField src, Quadrant quad) : base() { tile = t; // in this case we will make the new heightField have the same LOD as // the source. The LOD will be adjusted upward later if necessary. Init(src.metersPerSample); Debug.Assert((numSamples * metersPerSample * 2) == ( src.metersPerSample * src.numSamples), "creating heightfield from source that is not next lower LOD"); int xoff = 0; int zoff = 0; switch ( quad ) { case Quadrant.Northeast: xoff = src.numSamples / 2; zoff = 0; break; case Quadrant.Northwest: xoff = 0; zoff = 0; break; case Quadrant.Southeast: xoff = src.numSamples / 2; zoff = src.numSamples / 2; break; case Quadrant.Southwest: xoff = 0; zoff = src.numSamples / 2; break; } // copy from the source heightMap this.CopyHeightFieldScaleUp(src.heightMap, 1, xoff, zoff, src.numSamples); // compute the min and max extents of this heightField, since nobody else is // going to do it. // XXX - do we need to do this? minHeight = float.MaxValue; maxHeight = float.MinValue; foreach ( float h in heightMap ) { if ( h < minHeight ) { minHeight = h; } if ( h > maxHeight ) { maxHeight = h; } } // generate the height points that were not filled in above //WorldManager.Instance.TerrainGenerator.GenerateHeightField(location, Size, metersPerSample, // heightMap, out minHeight, out maxHeight, src.metersPerSample); UpdateBounds(); }
public void AttachNeighbors() { // Find Western neighbor if ( indexX == 0 ) { Page nextPage = page.FindNeighbor(Direction.West); if ( nextPage == null ) { neighborWest1 = null; neighborWest2 = null; } else { if ( nextPage.NumTiles == page.NumTiles ) { neighborWest1 = nextPage.LookupTile(nextPage.NumTiles - 1, indexZ); neighborWest2 = null; } else if ( nextPage.NumTiles < page.NumTiles ) { Debug.Assert(((nextPage.NumTiles * 2) == page.NumTiles), "Adjacent page numtiles not half"); neighborWest1 = nextPage.LookupTile(nextPage.NumTiles - 1, indexZ / 2); neighborWest2 = null; } else { Debug.Assert((nextPage.NumTiles == ( page.NumTiles * 2)), "Adjacent page numtiles not double"); neighborWest1 = nextPage.LookupTile(nextPage.NumTiles - 1, indexZ * 2); neighborWest2 = nextPage.LookupTile(nextPage.NumTiles - 1, ( indexZ * 2 ) + 1); } } } else { neighborWest1 = page.LookupTile(indexX - 1, indexZ); neighborWest2 = null; } // Find Eastern neighbor if ( indexX == ( page.NumTiles - 1 ) ) { Page nextPage = page.FindNeighbor(Direction.East); if ( nextPage == null ) { neighborEast1 = null; neighborEast2 = null; } else { if ( nextPage.NumTiles == page.NumTiles ) { neighborEast1 = nextPage.LookupTile(0, indexZ); neighborEast2 = null; } else if ( nextPage.NumTiles < page.NumTiles ) { Debug.Assert(((nextPage.NumTiles * 2) == page.NumTiles), "Adjacent page numtiles not half"); neighborEast1 = nextPage.LookupTile(0, indexZ / 2); neighborEast2 = null; } else { Debug.Assert((nextPage.NumTiles == ( page.NumTiles * 2)), "Adjacent page numtiles not double"); neighborEast1 = nextPage.LookupTile(0, indexZ * 2); neighborEast2 = nextPage.LookupTile(0, ( indexZ * 2 ) + 1); } } } else { neighborEast1 = page.LookupTile(indexX + 1, indexZ); neighborEast2 = null; } // Find Northern neighbor if ( indexZ == 0 ) { Page nextPage = page.FindNeighbor(Direction.North); if ( nextPage == null ) { neighborNorth1 = null; neighborNorth2 = null; } else { if ( nextPage.NumTiles == page.NumTiles ) { neighborNorth1 = nextPage.LookupTile(indexX, nextPage.NumTiles - 1); neighborNorth2 = null; } else if ( nextPage.NumTiles < page.NumTiles ) { Debug.Assert(((nextPage.NumTiles * 2) == page.NumTiles), "Adjacent page numtiles not half"); neighborNorth1 = nextPage.LookupTile(indexX / 2, nextPage.NumTiles - 1); neighborNorth2 = null; } else { Debug.Assert((nextPage.NumTiles == ( page.NumTiles * 2)), "Adjacent page numtiles not double"); neighborNorth1 = nextPage.LookupTile(indexX * 2, nextPage.NumTiles - 1); neighborNorth2 = nextPage.LookupTile( ( indexX * 2 ) + 1, nextPage.NumTiles - 1); } } } else { neighborNorth1 = page.LookupTile(indexX, indexZ - 1); neighborNorth2 = null; } // Find Southern neighbor if ( indexZ == ( page.NumTiles - 1 ) ) { Page nextPage = page.FindNeighbor(Direction.South); if ( nextPage == null ) { neighborSouth1 = null; neighborSouth2 = null; } else { if ( nextPage.NumTiles == page.NumTiles ) { neighborSouth1 = nextPage.LookupTile(indexX, 0); neighborSouth2 = null; } else if ( nextPage.NumTiles < page.NumTiles ) { Debug.Assert(((nextPage.NumTiles * 2) == page.NumTiles), "Adjacent page numtiles not half"); neighborSouth1 = nextPage.LookupTile(indexX / 2, 0); neighborSouth2 = null; } else { Debug.Assert((nextPage.NumTiles == ( page.NumTiles * 2)), "Adjacent page numtiles not double"); neighborSouth1 = nextPage.LookupTile(indexX * 2, 0); neighborSouth2 = nextPage.LookupTile(( indexX * 2 ) + 1, 0); } } } else { neighborSouth1 = page.LookupTile(indexX, indexZ + 1); neighborSouth2 = null; } }