public void PerFrameProcessing(Vector3 cameraLocation) { // free the passes from last frame if there are any if (framePageDecalInfos != null) { FreePasses(framePageDecalInfos); framePageDecalInfos = null; } // compute the camera page PageCoord lastCameraPage = cameraPage; cameraPage = new PageCoord(cameraLocation, TerrainManager.Instance.PageSize); // update the decals Update(cameraLocation.x, cameraLocation.z); // build the per-page data structures framePageDecalInfos = BuildPageInfos(); // if there are any visible decals, then build the material passes for all affected pages if (framePageDecalInfos != null) { BuildPasses(framePageDecalInfos); } }
private void ComputeTouchedPages() { Debug.Assert(closed); // compute the min and max page coord of the pages that this boundary may intersect with boundsMinPage = new PageCoord(bounds.Minimum, pageSize); boundsMaxPage = new PageCoord(bounds.Maximum, pageSize); touchedPages.Clear(); // iterate over the pages and see which intersect with the boundary, and add // those to the list for (int x = boundsMinPage.X; x <= boundsMaxPage.X; x++) { for (int z = boundsMinPage.Z; z <= boundsMaxPage.Z; z++) { PageCoord pc = new PageCoord(x, z); if (IntersectSquare(pc.WorldLocation(pageSize), pageSize)) { touchedPages.Add(pc); } } } Console.WriteLine("boundary {0} touches pages:", name); foreach (PageCoord tp in touchedPages) { Console.WriteLine(" {0}", tp.ToString()); } }
private byte[] newMask(PageCoord pc) { // allocate the new mask byte[] mask = new byte[pageSize * pageSize]; // add it to the dictionary pages.Add(pc, mask); // update bounds if (pc.X < minPageX) { minPageX = pc.X; } if (pc.X > maxPageX) { maxPageX = pc.X; } if (pc.Z < minPageZ) { minPageZ = pc.Z; } if (pc.Z > maxPageZ) { maxPageZ = pc.Z; } return(mask); }
private void SetPageHilights(bool value) { PageCoord minVis = TerrainManager.Instance.MinVisiblePage; PageCoord maxVis = TerrainManager.Instance.MaxVisiblePage; foreach (PageCoord tp in touchedPages) { if (tp.X >= minVis.X && tp.X <= maxVis.X && tp.Z >= minVis.Z && tp.Z <= maxVis.Z) { // tp page is visible visible = true; PageCoord pageOff = tp - minVis; Page page = TerrainManager.Instance.LookupPage(pageOff.X, pageOff.Z); if (value) { page.TerrainPage.HilightMask = PageMaskTexture(tp); page.TerrainPage.HilightType = TerrainPage.PageHilightType.Colorized; } else { page.TerrainPage.HilightType = TerrainPage.PageHilightType.None; // if there is an existing hilight mask, make sure we free it properly Texture t = page.TerrainPage.HilightMask; if (t != null) { page.TerrainPage.HilightMask = null; t.Dispose(); } } } } }
/// <summary> /// Find the tile for a given location /// </summary> /// <param name="location"></param> /// <returns>Returns the tile. Will raise an array bounds exception if the location is not in this page</returns> public Tile LookupTile(Vector3 location) { PageCoord locPageCoord = new PageCoord(location, size / numTiles); PageCoord tilePageCoord = new PageCoord(Location, size / numTiles); PageCoord tileOffset = locPageCoord - tilePageCoord; return(tiles[tileOffset.X, tileOffset.Z]); }
private Texture PageMaskTexture(PageCoord pc) { Image i = BuildPageMask(pc.WorldLocation(pageSize)); String texName = String.Format("{0}-{1}", name, pc.ToString()); Texture t = TextureManager.Instance.LoadImage(texName, i); return(t); }
// Get the mask for the given PageCoord. Returns null if no mask is available public byte[] GetMask(PageCoord pc) { byte[] rawMask; if (!pages.TryGetValue(pc, out rawMask)) { rawMask = null; } return(rawMask); }
protected Technique FindPageTechnique(PageCoord coord) { Page page = TerrainManager.Instance.LookupPage(coord); Technique t = null; if (page != null) { Material mat = page.TerrainPage.Material; t = mat.GetBestTechnique(); } return(t); }
public bool Intersects(PageCoord pc) { bool ret = false; // do bounds intersection first if ((pc.X >= minPageX) && (pc.X <= maxPageX) && (pc.Z >= minPageZ) && (pc.Z <= maxPageZ)) { byte[] mask; // if bounds intersection succeeds, then look up in the dictionary ret = pages.TryGetValue(pc, out mask); } return(ret); }
public PlantRenderable(IndexData ind, VertexData vert, AxisAlignedBox bbox, PageCoord pc, SceneNode parent, Vector3 blockLoc) { indexData = ind; vertexData = vert; material = MaterialManager.Instance.GetByName("Multiverse/DetailVeg"); box = bbox; pageCoord = pc; parentSceneNode = parent; sceneNode = parentSceneNode.CreateChildSceneNode(string.Format("DetailVeg-{0}", pageCoord)); sceneNode.AttachObject(this); sceneNode.Position = new Vector3(blockLoc.x, 0, blockLoc.z); this.ShowBoundingBox = false; CastShadows = true; }
private void SetRoadMask(TerrainPage terrainPage) { // generate a texture from the mask PageCoord pc = new PageCoord(terrainPage.Location, TerrainManager.Instance.PageSize); byte[] byteMask = mask.GetMask(pc); if (byteMask != null) { Image maskImage = Image.FromDynamicImage(byteMask, mask.PageSize, mask.PageSize, PixelFormat.A8); String texName = String.Format("RoadMask-{0}", pc.ToString()); Texture texImage = TextureManager.Instance.LoadImage(texName, maskImage); terrainPage.HilightMask = texImage; terrainPage.HilightType = TerrainPage.PageHilightType.EdgeSharpBlend; } }
/// <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; } } }
public TerrainPage(Vector3 location, Page page) { this.location = location; pageCoord = new PageCoord(location, TerrainManager.Instance.PageSize); terrainMaterial = TerrainManager.Instance.TerrainMaterialConfig.NewTerrainMaterial(pageCoord.X, pageCoord.Z); currentPage = page; Debug.Assert(location == currentPage.Location, "creating TerrainPage with page at different location"); numTiles = currentPage.NumTiles; patchSize = TerrainManager.Instance.PageSize / numTiles; // set up the page height maps for this page of terrain subPageSize = TerrainManager.Instance.SubPageSize; int subPagesPerPage = TerrainManager.Instance.PageSize / subPageSize; pageHeightMap = new PageHeightMap(subPagesPerPage, TerrainManager.Instance.PageSize, TerrainManager.Instance.MaxMetersPerSample, TerrainManager.Instance.MinMetersPerSample); pageHeightMap.Location = location; // create and position a scene node for this terrain page string nodeName = String.Format("TerrainPage[{0},{1}]", (int)(location.x / TerrainManager.oneMeter), (int)(location.z / TerrainManager.oneMeter)); // DEBUG - Console.WriteLine("Creating {0}", name); sceneNode = TerrainManager.Instance.WorldRootSceneNode.CreateChildSceneNode(nodeName); sceneNode.Position = location; sceneNode.AttachObject(this); // create the render operation renderOp = new RenderOperation(); renderOp.operationType = OperationType.TriangleList; renderOp.useIndices = true; CreatePatches(); SetCastShadows(); UpdateBounds(); TerrainManager.Instance.ShadowConfig.ShadowTechniqueChange += ShadowTechniqueChangeHandler; }
public bool IntersectPage(PageCoord pc) { // check if page intersects bounds first if (pc.X < boundsMinPage.X || pc.X > boundsMaxPage.X || pc.Z < boundsMinPage.Z || pc.Z > boundsMaxPage.Z) { return(false); } foreach (PageCoord tp in touchedPages) { if (tp == pc) { return(true); } } return(false); }
// // Iterate page masks, only returning those in the given page range // public void IterateMasks(ReturnMask retDelegate, PageCoord minPage, PageCoord maxPage) { // get out quick if our bounds don't overlap the requested page range if ((minPageX > maxPage.X) || (maxPageX < minPage.X) || (minPageZ > maxPage.Z) || (maxPageZ < minPage.Z)) { return; } foreach (KeyValuePair <PageCoord, byte[]> kvp in pages) { PageCoord pc = kvp.Key; // only call delegate if current page overlaps with requested page range if ((pc.X >= minPage.X) && (pc.X <= maxPage.X) && (pc.Z >= minPage.Z) && (pc.Z <= maxPage.Z)) { retDelegate(pc, kvp.Value); } } }
internal VegetationTile(SceneNode parentSceneNode, List <VegetationSemantic> vegetationBoundaries, int x, int z, PageCoord newPage, int blockSize, float roadClearRadius, MVImageSet imageSet, Random rand) { this.roadClearRadius = roadClearRadius; plantTypes = new List <PlantType>(); PageCoord tmpPage = new PageCoord(x + newPage.X - 1, z + newPage.Z - 1); pc = tmpPage; Vector3 blockLoc = tmpPage.WorldLocation(blockSize); Vector2 blockMin = new Vector2(blockLoc.x, blockLoc.z); Vector2 blockMax = new Vector2(blockMin.x + blockSize * TerrainManager.oneMeter, blockMin.y + blockSize * TerrainManager.oneMeter); List <Vector2> roadSegments = TerrainManager.Instance.Roads.IntersectBlock(blockMin, blockMax); foreach (VegetationSemantic vegetationBoundary in vegetationBoundaries) { Boundary boundary = vegetationBoundary.BoundaryObject; if (boundary.IntersectSquare(new Vector3(blockMin.x, 0f, blockMin.y), blockSize)) { foreach (PlantType boundaryPlantType in vegetationBoundary.PlantTypes) { PlantType plantType = boundaryPlantType.Clone(); plantType.MaybeUseImageSet(imageSet); plantTypes.Add(plantType); totalInstances += plantType.AddPlantInstances(boundary, blockMin, blockSize, rand); } } } if (totalInstances > 0) { BuildIndexBuffer(); AxisAlignedBox bounds; VertexData vertexData = BuildVertexData(blockLoc, blockSize, roadSegments, out bounds); plantRenderable = new PlantRenderable(indexData, vertexData, bounds, tmpPage, parentSceneNode, blockLoc); } }
private void NewCameraPage(PageCoord newPage) { if (enabled && TerrainManager.Instance.CameraSet) { // free the old vegetation tiles VegetationTile[,] newVegetationTiles = new VegetationTile[3, 3]; if (vegetationTiles != null) { foreach (VegetationTile tile in vegetationTiles) { PageCoord pc = tile.pc; int x = pc.X - (newPage.X - 1); int z = pc.Z - (newPage.Z - 1); if ((x >= 0) && (x < 3) && (z >= 0) && (z < 3)) { newVegetationTiles[x, z] = tile; } else { FreeVegetationTile(tile); } } } vegetationTiles = newVegetationTiles; for (int x = 0; x < 3; x++) { for (int z = 0; z < 3; z++) { if (vegetationTiles[x, z] == null) { vegetationTiles[x, z] = new VegetationTile(parentSceneNode, vegetationBoundaries, x, z, newPage, blockSize, roadClearRadius, detailVegImageSet, rand); } } } cameraPage = newPage; } }
private void UpdateVisibility() { PageCoord minVis = TerrainManager.Instance.MinVisiblePage; PageCoord maxVis = TerrainManager.Instance.MaxVisiblePage; visible = false; if (maxVis.X < boundsMinPage.X || minVis.X > boundsMaxPage.X || maxVis.Z < boundsMinPage.Z || minVis.Z > boundsMaxPage.Z) { // this boundary doesn't overlap with the visible area around the camera. return; } foreach (PageCoord tp in touchedPages) { if (tp.X >= minVis.X && tp.X <= maxVis.X && tp.Z >= minVis.Z && tp.Z <= maxVis.Z) { // tp page is visible visible = true; } } }
public void SetPoint(int x, int z, byte value) { // compute pagecoord of the page containing this point PageCoord pc = new PageCoord(new Vector3(x * TerrainManager.oneMeter, 0, z * TerrainManager.oneMeter), pageSize); // PageCoord pc = new PageCoord(x / pageSize, z / pageSize); byte[] rawMask; // lookup the mask. If it is not found, then make a new empty mask and add it to the dictionary if (!pages.TryGetValue(pc, out rawMask)) { rawMask = newMask(pc); } // compute x and z coords of base of page int pagex = pc.X * pageSize; int pagez = pc.Z * pageSize; // compute x and z offsets within page int xoff = x - pagex; int zoff = z - pagez; rawMask[(zoff * pageSize) + xoff] = value; }
/// <summary> /// Compute the "distance" between two pages. Returns the axis aligned /// distance along X or Z (whichever is greater). /// </summary> /// <param name="c2">coordinate to compare to this</param> /// <returns></returns> public int Distance(PageCoord c2) { int xDiff = c2.X - X; int zDiff = c2.Z - Z; if (xDiff < 0) { xDiff = -xDiff; } if (zDiff < 0) { zDiff = -zDiff; } if (xDiff > zDiff) { return(xDiff); } else { return(zDiff); } }
private void ShiftPageHeightMaps(PageCoord pc) { ValidatePageArray(); int dx = pc.X; int dz = pc.Z; // make sure we are actually moving Debug.Assert((dx != 0) || (dz != 0)); int copyStartX = 0; int copyEndX = pageArraySize; int copyIncrX = 1; int copyStartZ = 0; int copyEndZ = pageArraySize; int copyIncrZ = 1; // keep track of the bounds of the area we keep after shifting int clearStartX = 0; int clearEndX = 0; int keepStartZ = 0; int keepEndZ = pageArraySize; int maxMove = pageArraySize - 1; // set to true if we are moving the camera far enough that all of the current heightmaps // move out of view bool bigMove = false; if ((dx > maxMove) || (dx < -maxMove) || (dz > maxMove) || (dz < -maxMove)) { bigMove = true; } if (!bigMove) { // compute move params for the X axis if (dx > 0) { copyStartX = pageArraySize - dx - 1; copyEndX = -1; copyIncrX = -1; clearStartX = 0; clearEndX = dx; } else if (dx < 0) { copyStartX = -dx; copyEndX = pageArraySize; copyIncrX = 1; clearStartX = pageArraySize + dx; clearEndX = pageArraySize; } // compute move params for the Z axis if (dz > 0) { copyStartZ = pageArraySize - dz - 1; copyEndZ = -1; copyIncrZ = -1; keepStartZ = dz; keepEndZ = pageArraySize; } else if (dz < 0) { copyStartZ = -dz; copyEndZ = pageArraySize; copyIncrZ = 1; keepStartZ = 0; keepEndZ = pageArraySize + dz; } long startTick = Root.Instance.Timer.Milliseconds; // copy all height maps that we are keeping for (int z = copyStartZ; z != copyEndZ; z += copyIncrZ) { for (int x = copyStartX; x != copyEndX; x += copyIncrX) { // move the heightmap to its new page, and set its page property // dispose of the old terrain page int destX = x + dx; int destZ = z + dz; if (pages[destX, destZ].TerrainPage != null) { pages[destX, destZ].TerrainPage.Dispose(); } // move the terrainPage, and set its CurrentPage to the new page pages[destX, destZ].TerrainPage = pages[x, z].TerrainPage; pages[destX, destZ].TerrainPage.CurrentPage = pages[destX, destZ]; // clear out the old reference to the TerrainPage we just moved pages[x, z].TerrainPage = null; } } long middleTick = Root.Instance.Timer.Milliseconds; // Perform processing on all pages that are newly revealed after the shift // Set locations on the pageHeightMaps so that they get rebuilt at their new // locations. // Clear and reinitialize the terrain patches of all these pages int newPages = 0; for (int z = 0; z < pageArraySize; z++) { if ((z < keepStartZ) || (z >= keepEndZ)) { // this row does not overlap the keep area, so reainitialize all pages for (int x = 0; x < pageArraySize; x++) { // dispose of the old terrainPage if (pages[x, z].TerrainPage != null) { FreeTerrainPage(pages[x, z]); } pages[x, z].TerrainPage = NewTerrainPage(pages[x, z]); newPages++; } } else // this row overlaps the keep area { for (int x = clearStartX; x < clearEndX; x++) { // dispose of the old terrainPage if (pages[x, z].TerrainPage != null) { FreeTerrainPage(pages[x, z]); } pages[x, z].TerrainPage = NewTerrainPage(pages[x, z]); newPages++; } } } long finalTick = Root.Instance.Timer.Milliseconds; LogManager.Instance.Write("ShiftPageHeightMaps: Shift: {0}", middleTick - startTick); LogManager.Instance.Write("ShiftPageHeightMaps: Clear/Create: {0}", finalTick - middleTick); LogManager.Instance.Write("ShiftPageHeightMaps: dx = {0}, dz = {1}, newPages = {2}", dx, dz, newPages); } else // bigmove { long startTick = Root.Instance.Timer.Milliseconds; InitTerrainPages(); long finalTick = Root.Instance.Timer.Milliseconds; LogManager.Instance.Write("ShiftPageHeightMaps: BigMove: {0}", finalTick - startTick); } ValidatePageArray(); }
public TouchedPage(PageCoord coord, Texture mask) { this.coord = coord; this.mask = mask; }
public bool Update(float cameraX, float cameraZ) { float time = TerrainManager.Instance.Time; bool deleteMe = false; if (firstUpdate) { timeAlive = 0; firstUpdate = false; dirty = true; } if (deleteRadius != 0) { // compute distance from camera float dx = posX - cameraX; float dz = posZ - cameraZ; float dxsq = dx * dx; float dzsq = dz * dz; if ((dxsq + dzsq) > (deleteRadius * deleteRadius)) { // if distance from the camera is greater than deleteRadius, then delete this element deleteMe = true; } } float deltaT = time - lastUpdateTime; timeAlive += deltaT; if ((lifetime != 0) && (timeAlive > lifetime)) { // time has run out, so delete this element deleteMe = true; } lastUpdateTime = time; if (dirty) { float halfx = sizeX / 2f; float halfz = sizeZ / 2f; // compute area possibly touched by the decal if (rot != 0) { float theta = MathUtil.DegreesToRadians(rot); float cos = MathLib.MathUtil.Cos(theta); float sin = MathLib.MathUtil.Sin(theta); float x1 = halfx * cos - halfz * sin; float z1 = halfx * sin + halfz * cos; float x2 = -halfx * cos - halfz * sin; float z2 = -halfx * sin + halfz * cos; float x3 = halfx * cos + halfz * sin; float z3 = halfx * sin - halfz * cos; float x4 = -halfx * cos + halfz * sin; float z4 = -halfx * sin - halfz * cos; maxX = Math.Max(Math.Max(x1, x2), Math.Max(x3, x4)); maxZ = Math.Max(Math.Max(z1, z2), Math.Max(z3, z4)); } else { maxX = halfx; maxZ = halfz; } float worldX1 = posX - maxX; float worldX2 = posX + maxX; float worldZ1 = posZ - maxZ; float worldZ2 = posZ + maxZ; minPC = new PageCoord(new Vector3(worldX1, 0, worldZ1), TerrainManager.Instance.PageSize); maxPC = new PageCoord(new Vector3(worldX2, 0, worldZ2), TerrainManager.Instance.PageSize); } return(deleteMe); }
public PageDecalInfo(PageCoord coord) { this.coord = coord; decals = new List<DecalElement>(); passes = new List<Pass>(); }
/// <summary> /// Used when a PageCoord is added to another PageCoord. /// </summary> /// <param name="left"></param> /// <param name="right"></param> /// <returns></returns> public static PageCoord Add(PageCoord left, PageCoord right) { return(left + right); }
// Get the mask for the given PageCoord. Returns null if no mask is available public byte[] GetMask(PageCoord pc) { byte[] rawMask; if (!pages.TryGetValue(pc, out rawMask)) { rawMask = null; } return rawMask; }
public bool WithinVisibleArea(Vector3 location) { PageCoord locPage = new PageCoord(location, pageSize); PageCoord pageOffset = locPage - cameraPage + new PageCoord(visPageRadius, visPageRadius); if ( pageOffset.X < 0 || pageOffset.X >= pageArraySize || pageOffset.Z < 0 || pageOffset.Z >= pageArraySize ) { return false; } return true; }
/// <summary> /// Find the tile for a given location /// </summary> /// <param name="location"></param> /// <returns>Returns the tile. Will raise an array bounds exception if the location is not in this page</returns> public Tile LookupTile(Vector3 location) { PageCoord locPageCoord = new PageCoord(location, size / numTiles); PageCoord tilePageCoord = new PageCoord(Location, size / numTiles); PageCoord tileOffset = locPageCoord - tilePageCoord; return tiles[tileOffset.X, tileOffset.Z]; }
/// <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; } } }
public float GetAreaHeight(Vector3[] points) { if (!cameraSet) { return float.MinValue; } // compute axis aligned bounding box of points float fx1 = points[0].x; float fx2 = points[0].x; float fz1 = points[0].z; float fz2 = points[0].z; for (int i = 1; i < points.Length; i++) { if (points[i].x < fx1) { fx1 = points[i].x; } else if (points[i].x > fx2) { fx2 = points[i].x; } if (points[i].z < fz1) { fz1 = points[i].z; } else if (points[i].z > fz2) { fz2 = points[i].z; } } PageCoord minPage = new PageCoord(new Vector3(fx1, 0, fz1), pageSize); PageCoord maxPage = new PageCoord(new Vector3(fx2, 0, fz2), pageSize); PageCoord minPageOffset = minPage - cameraPage + new PageCoord(visPageRadius, visPageRadius); PageCoord maxPageOffset = maxPage - cameraPage + new PageCoord(visPageRadius, visPageRadius); // if we are outside the visible area around the camera, get out now if ((minPageOffset.X < 0) || (minPageOffset.Z < 0) || (maxPageOffset.X > pages.GetUpperBound(0)) || (maxPageOffset.Z > pages.GetUpperBound(1))) { return float.MinValue; } float height = float.MinValue; for (int pageX = minPageOffset.X; pageX <= maxPageOffset.X; pageX++) { for (int pageZ = minPageOffset.Z; pageZ <= maxPageOffset.Z; pageZ++) { Page p = LookupPage(pageX, pageZ); float pageHeight = p.TerrainPage.PageHeightMap.GetAreaHeight(fx1, fx2, fz1, fz2); if (pageHeight > height) { height = pageHeight; } } } return height; }
private byte[] newMask(PageCoord pc) { // allocate the new mask byte[] mask = new byte[pageSize * pageSize]; // add it to the dictionary pages.Add(pc, mask); // update bounds if (pc.X < minPageX) { minPageX = pc.X; } if (pc.X > maxPageX) { maxPageX = pc.X; } if (pc.Z < minPageZ) { minPageZ = pc.Z; } if (pc.Z > maxPageZ) { maxPageZ = pc.Z; } return mask; }
protected Technique FindPageTechnique(PageCoord coord) { Page page = TerrainManager.Instance.LookupPage(coord); Technique t = null; if (page != null) { Material mat = page.TerrainPage.Material; t = mat.GetBestTechnique(); } return t; }
public Page LookupPage(PageCoord locPage) { Debug.Assert(cameraSet, "Camera not set in LookupPage"); PageCoord pageOffset = locPage - cameraPage + new PageCoord(visPageRadius, visPageRadius); if ( pageOffset.X < 0 || pageOffset.X >= pageArraySize || pageOffset.Z < 0 || pageOffset.Z >= pageArraySize ) { return null; } return pages[pageOffset.X, pageOffset.Z]; }
/// <summary> /// Used to subtract a PageCoord from another PageCoord. /// </summary> /// <param name="left"></param> /// <param name="right"></param> /// <returns></returns> public static PageCoord Subtract(PageCoord left, PageCoord right) { return(left - right); }
/// <summary> /// Compute the "distance" between two pages. Returns the axis aligned /// distance along X or Z (whichever is greater). /// </summary> /// <param name="c2">coordinate to compare to this</param> /// <returns></returns> public int Distance(PageCoord c2) { int xDiff = c2.X - X; int zDiff = c2.Z - Z; if ( xDiff < 0 ) { xDiff = -xDiff; } if ( zDiff < 0 ) { zDiff = -zDiff; } if ( xDiff > zDiff ) { return xDiff; } else { return zDiff; } }
public PageDecalInfo(PageCoord coord) { this.coord = coord; decals = new List <DecalElement>(); passes = new List <Pass>(); }
/// <summary> /// Used to negate the elements of a PageCoord. /// </summary> /// <param name="left"></param> /// <returns></returns> public static PageCoord Negate(PageCoord left) { return(-left); }
/// <summary> /// Find the page for a given location /// </summary> /// <param name="location"></param> /// <returns>Returns the page, or null if that page is not currently loaded</returns> public Page LookupPage(Vector3 location) { PageCoord locPage = new PageCoord(location, pageSize); return LookupPage(locPage); }
/// <summary> /// Used to negate the elements of a PageCoord. /// </summary> /// <param name="left"></param> /// <returns></returns> public static PageCoord Negate(PageCoord left) { return -left; }
/// <summary> /// Used to subtract a PageCoord from another PageCoord. /// </summary> /// <param name="left"></param> /// <param name="right"></param> /// <returns></returns> public static PageCoord Subtract(PageCoord left, PageCoord right) { return left - right; }
public bool Intersects(PageCoord pc) { bool ret = false; // do bounds intersection first if ((pc.X >= minPageX) && (pc.X <= maxPageX) && (pc.Z >= minPageZ) && (pc.Z <= maxPageZ)) { byte[] mask; // if bounds intersection succeeds, then look up in the dictionary ret = pages.TryGetValue(pc, out mask); } return ret; }
private Texture PageMaskTexture(PageCoord pc) { Image i = BuildPageMask(pc.WorldLocation(pageSize)); String texName = String.Format("{0}-{1}", name, pc.ToString()); Texture t = TextureManager.Instance.LoadImage(texName, i); return t; }
// // Iterate page masks, only returning those in the given page range // public void IterateMasks(ReturnMask retDelegate, PageCoord minPage, PageCoord maxPage) { // get out quick if our bounds don't overlap the requested page range if ((minPageX > maxPage.X) || (maxPageX < minPage.X) || (minPageZ > maxPage.Z) || (maxPageZ < minPage.Z)) { return; } foreach (KeyValuePair<PageCoord, byte[]> kvp in pages) { PageCoord pc = kvp.Key; // only call delegate if current page overlaps with requested page range if ((pc.X >= minPage.X) && (pc.X <= maxPage.X) && (pc.Z >= minPage.Z) && (pc.Z <= maxPage.Z)) { retDelegate(pc, kvp.Value); } } }
public bool IntersectPage(PageCoord pc) { // check if page intersects bounds first if (pc.X < boundsMinPage.X || pc.X > boundsMaxPage.X || pc.Z < boundsMinPage.Z || pc.Z > boundsMaxPage.Z) { return false; } foreach (PageCoord tp in touchedPages) { if (tp == pc) { return true; } } return false; }
/// <summary> /// return the location of the page origin of the page containing the given location /// </summary> /// <param name="location"></param> /// <returns></returns> private Vector3 PageOrigin(Vector3 location) { PageCoord locPage = new PageCoord(location, pageSize); return locPage.WorldLocation(pageSize); }
/// <summary> /// Used when a PageCoord is added to another PageCoord. /// </summary> /// <param name="left"></param> /// <param name="right"></param> /// <returns></returns> public static PageCoord Add(PageCoord left, PageCoord right) { return left + right; }