public override void OnDraw(GraphicsDevice graphicsDevice, GridQuad bounds, double DownSample, BasicEffect basicEffect) { WebAnnotation.Objects.StructureTypeObj obj = Viking.UI.State.SelectedObject as WebAnnotation.Objects.StructureTypeObj; // Debug.Assert(obj == null, "This command should be inactive if Selected Object isn't a StructureTypeObj"); if(obj == null) return; Parent.fonts.Begin(); string title = obj.Code; if(this.Parent.fonts != null && this.oldMouse != null) { Vector2 offset = Parent.fontArial.MeasureString(title); offset.X /= 2; offset.Y /= 2; Parent.fonts.DrawString(Parent.fontArial, title, new Vector2((float)this.oldMouse.X - offset.X, (float)this.oldMouse.Y - offset.Y), new Microsoft.Xna.Framework.Graphics.Color(obj.Color.R, obj.Color.G, obj.Color.B, 196)); } Parent.fonts.End(); return; }
public override TilePyramid VisibleTiles(GridRectangle VisibleBounds, double DownSample) { int roundedDownsample = NearestAvailableLevel(DownSample); GridQuad VisibleQuad = null; //Add any corners of the VisibleBounds that we can transform to the list of points List<MappingGridVector2> VisiblePoints = VisibleBoundsCorners(VolumeTransform, VisibleBounds); if (VisiblePoints.Count != 4) { //If we can't map all four corners then add all the points from the transform falling inside the visible rectangle or //connected to those points by an edge List<MappingGridVector2> listTransformPoints = this.VolumeTransform.IntersectingControlRectangle(VisibleBounds, true); VisiblePoints.AddRange(listTransformPoints); } else { VisiblePoints.Sort(new MappingGridVector2SortByMapPoints()); VisibleQuad = new GridQuad(VisiblePoints[0].MappedPoint, VisiblePoints[1].MappedPoint, VisiblePoints[2].MappedPoint, VisiblePoints[3].MappedPoint); } //OK, transform all points falling inside the section border //Starting with low-res tiles, add tiles to the list until we reach desired resolution //List<Tile> TilesToDraw = new List<Tile>(); TilePyramid TilesToDraw = new TilePyramid(VisibleBounds); if (VisiblePoints.Count < 3) return TilesToDraw; GridRectangle SectionBorder = MappingGridVector2.CalculateMappedBounds(VisiblePoints.ToArray()); int iLevel = AvailableLevels.Length - 1; int level = AvailableLevels[iLevel]; do { List<Tile> newTiles = RecursiveVisibleTiles(VisibleBounds, SectionBorder, VisibleQuad, level //PORT: AsynchTextureLoad ); //Insert at the beginning so we overwrite earlier tiles with poorer resolution TilesToDraw.AddTiles(level, newTiles.ToArray()); iLevel--; if (iLevel >= 0) level = AvailableLevels[iLevel]; } while (level >= roundedDownsample && iLevel >= 0); // Trace.WriteLine("Drawing " + TilesToDraw.Count.ToString() + " Tiles", "VolumeModel"); return TilesToDraw; }
public static Node CreateNode(Vector3 pos, Vector3 angles, GridQuad grid) //Creates a basic node where none was { //Add node to list Node node = new Node(); node.pos = pos; xa.uIds++; node.uId = xa.uIds; node.lines = new List <Lines.Line>(); node.connections = new List <Node>(); node.angles = angles; node.grid = grid; GameObject go = Instantiate(Defines.self.gridNodePrefab); go.transform.position = pos; //Debug.DrawLine(pos, new Vector3(0, 2, 0), Color.blue, 100); nodes.Add(node); //Debug.Log("Nodes count: " + nodes.Count); return(node); }
public override TilePyramid VisibleTiles(GridRectangle VisibleBounds, double DownSample) { if (VolumeTransform != null) { GridQuad VisibleQuad = null; //Add any corners of the VisibleBounds that we can transform to the list of points List<MappingGridVector2> VisiblePoints = VisibleBoundsCorners(VolumeTransform, VisibleBounds); if (VisiblePoints.Count == 4) { VisiblePoints.Sort(new MappingGridVector2SortByMapPoints()); VisibleQuad = new GridQuad(VisiblePoints[0].MappedPoint, VisiblePoints[1].MappedPoint, VisiblePoints[2].MappedPoint, VisiblePoints[3].MappedPoint); } return VisibleTiles(VisibleBounds, VisibleQuad, DownSample); } else { return new TilePyramid(VisibleBounds); } }
private List<Tile> RecursiveVisibleTiles( GridRectangle VolumeVisibleBounds, GridRectangle SectionVisibleBounds, GridQuad VisibleQuad, int roundedDownsample) { GridInfo gridInfo = LevelToGridInfo[roundedDownsample]; int ScaledTileSizeX = this.TileSizeX * roundedDownsample; int ScaledTileSizeY = this.TileSizeX * roundedDownsample; //Figure out which grid locations are visible int iMinX = (int)Math.Floor(SectionVisibleBounds.Left / ScaledTileSizeX); int iMinY = (int)Math.Floor(SectionVisibleBounds.Bottom / ScaledTileSizeY); int iMaxX = (int)Math.Ceiling(SectionVisibleBounds.Right / ScaledTileSizeX); int iMaxY = (int)Math.Ceiling(SectionVisibleBounds.Top / ScaledTileSizeY); iMinX = iMinX < 0 ? 0 : iMinX; iMinY = iMinY < 0 ? 0 : iMinY; iMaxX = iMaxX > gridInfo.GridXDim ? gridInfo.GridXDim : iMaxX; iMaxY = iMaxY > gridInfo.GridYDim ? gridInfo.GridYDim : iMaxY; int ExpectedTileCount = (iMaxX - iMinX) * (iMaxY - iMinY); List<Tile> TilesToDraw = new List<Tile>(ExpectedTileCount); for (int iX = iMinX; iX < iMaxX; iX++) { for (int iY = iMinY; iY < iMaxY; iY++) { //Figure out if the tile would be visible GridRectangle tileBorder = TileBorder(iX, iY, roundedDownsample); if (tileBorder.Intersects(SectionVisibleBounds) == false) continue; //If we have a visble quad see if the tile intersects that too if (VisibleQuad != null) { if (VisibleQuad.Contains(tileBorder) == false) continue; } string UniqueID = Tile.CreateUniqueKey(Section.Number, "Grid to Volume", Name, roundedDownsample, this.TileTextureFileName(iX, iY)); // Trace.WriteLine(TextureFileName, "VolumeModel"); Tile tile = Global.TileCache.Fetch(UniqueID); if (tile == null) { //First create a new tile int MipMapLevels = 1; //No mip maps if (roundedDownsample == this.AvailableLevels[AvailableLevels.Length - 1]) MipMapLevels = 0; //Generate mipmaps for lowest res texture //PORT: string TextureCacheFileName = TileCacheName(iX, iY, roundedDownsample); int[] edges; // Trace.WriteLine(TextureFileName, "VolumeModel"); PositionNormalTextureVertex[] verticies = CalculateVerticies(iX, iY, roundedDownsample, out edges); string TextureFileName = TileFullPath(iX, iY, roundedDownsample); tile = Global.TileCache.ConstructTile(UniqueID, verticies, edges, TextureFileName, this.TileTextureCacheFileName(roundedDownsample, iX, iY), //PORT: TextureCacheFileName, this.Name, roundedDownsample, MipMapLevels); } TilesToDraw.Add(tile); } } return TilesToDraw; }
protected virtual TilePyramid VisibleTiles(GridRectangle VisibleBounds, GridQuad SectionVisibleBounds, double DownSample) { TilePyramid VisibleTiles = new TilePyramid(VisibleBounds); //Setup a larger boundary outside of which we release textures GridRectangle releaseBounds = VisibleBounds; //Tiles outside this quad will have textures released GridRectangle loadBounds = VisibleBounds; //Tiles inside this quad will have textures loaded GridRectangle abortBounds = VisibleBounds; //Tiles outside this quad will have HTTP requests aborted releaseBounds.Scale(1.25 * DownSample); loadBounds.Scale(1.1f); abortBounds.Scale(1.20f * DownSample); //Get ready by loading a smaller texture in case the user scrolls this direction //Once we have smaller textures then increase the quality // int predictiveDownsample = DownSample * 4 > 64 ? 64 : (int)DownSample * 4; int roundedDownsample = NearestAvailableLevel(DownSample); ReferencePointBasedTransform[] Tranforms = this.TileTransforms; if (TileTransforms == null) return VisibleTiles; int ExpectedTileCount = Tranforms.Length; List<Tile> TilesToDraw = new List<Tile>(ExpectedTileCount); // List<Tile> TilesToLoad = new List<Tile>(ExpectedTileCount); foreach (TriangulationTransform T in Tranforms) { //If this tile has been transformed out of existence then skip it if (T.MapPoints.Length < 3) continue; if (VisibleBounds.Intersects(T.ControlBounds)) { // bool LoadOnly = false; TileTransformInfo info = T.Info as TileTransformInfo; string name = TileFileName(info.TileFileName, roundedDownsample); /* if (SectionVisibleBounds != null) { GridRectangle MosaicPosition = new GridRectangle(T.mapPoints[0].ControlPoint, T.ImageWidth, T.ImageHeight); if (SectionVisibleBounds.Contains(MosaicPosition) == false) { name = TileFileName(T.Number,predictiveDownsample); LoadOnly = true; continue; } } */ string UniqueID = Tile.CreateUniqueKey(Section.Number, Name, CurrentPyramid.Name, roundedDownsample, info.TileFileName); Tile tile = Global.TileCache.Fetch(UniqueID); if(tile == null) { int MipMapLevels = 1; //No mip maps if (roundedDownsample == this.AvailableLevels[AvailableLevels.Length - 1]) MipMapLevels = 0; //Generate mipmaps for lowest res texture //First create a new tile PositionNormalTextureVertex[] verticies = Tile.CalculateVerticies(T, info); if(T.TriangleIndicies != null) { tile = Global.TileCache.ConstructTile(UniqueID, verticies, T.TriangleIndicies, this.TilePath + '/' + name, name, //PORT: TileCacheName(T.Number, roundedDownsample), this.Name, roundedDownsample, MipMapLevels);//T.ImageHeight * T.ImageWidth / roundedDownsample); } } if(tile != null) VisibleTiles.AddTile(roundedDownsample, tile); /* if (LoadOnly) { TilesToLoad.Add(tile); continue; } */ //I used to call draw here, but when exporting frames I want to have all tiles launch threads to load thier textures and then wait. //It is much faster than doing one texture at a time //PORT: Removed //tile.GetTexture(graphicsDevice, true); TilesToDraw.Add(tile); //PORT: Modified to return all tiles of lower resolution /* //See if any tiles of alternate resolution are already loaded //Use them if the correct resolution doesn't have a texture, otherwise abort any requests bool TextureFound = tile.HasTexture; foreach(int testLevel in UI.State.DownsampleLevels) { if(testLevel == roundedDownsample) continue; string altResName = TileFileName(T.Number, testLevel); Tile altResTile = Global.TileCache.GetTile(altResName, this.Name); if (altResTile != null) { //Stop the network request if we've already got a texture //TODO: Once we have a list of textures to draw, send it to TextureConstructor //and have it abort textures not in the list if (TextureFound) altResTile.AbortRequest(); else { if (altResTile.HasTexture) { TilesToDraw.Add(altResTile); TextureFound = true; } } } } */ } /*PORT We no longer handle tiles to be loaded and the aborting tiles here else { if (loadBounds.Intersects(T.CachedControlBounds)) { string name = TileFileName(T.Number, predictiveDownsample); Tile tile = Global.TileCache.GetTile(name, this.Name); if(tile == null) { //First create a new tile int MipMapLevels = 1; //No mip maps if (roundedDownsample == this.AvailableLevels[AvailableLevels.Length - 1]) MipMapLevels = 0; //Generate mipmaps for lowest res texture VertexPositionNormalTexture[] verticies = Tile.CalculateVerticies(T); tile = Global.TileCache.ConstructTile(verticies, T.TriangleIndicies, name, TileCacheName(T.Number, predictiveDownsample), this.Name, roundedDownsample, MipMapLevels, T.ImageHeight * T.ImageWidth / predictiveDownsample); } TilesToLoad.Add(tile); } //Sometimes tiles can overlap both zones, so else if is used else if (abortBounds.Intersects(T.CachedControlBounds) == false) { foreach (int testLevel in UI.State.DownsampleLevels) { string AbortTileName = TileFileName(T.Number, testLevel); Tile tile = Global.TileCache.GetTile(AbortTileName, this.Name); if (tile != null) { tile.AbortRequest(); } } } } */ } /*PORT Model does not load textures foreach (Tile tile in TilesToLoad) { //We are asking for a lower quality texture, but tile will keep any existing higher quality textures if (AsynchTextureLoad) tile.GetTexture(graphicsDevice, true); } //TODO: Give a list of tiles to the TileConstructor that are OK to have outstanding load requests. //All other tiles will be aborted List<Tile> SafeTiles = new List<Tile>(TilesToLoad.Count + TilesToDraw.Count); SafeTiles.AddRange(TilesToLoad); SafeTiles.AddRange(TilesToDraw); Trace.WriteLine("Drawing " + TilesToDraw.Count.ToString() + " Tiles", "VolumeModel"); return TilesToDraw.ToArray(); */ return VisibleTiles; }
public static void InitNodes() { nodes = new List <Node>(); grids = new List <GridQuad>(); //Find gridQuads GameObject[] objsWithTag = GameObject.FindGameObjectsWithTag("GridQuad"); for (int i = 0; i < objsWithTag.Length; i++) { GridQuad grid = new GridQuad(); grid.go = objsWithTag[i]; grid.scale = objsWithTag[i].GetComponentInChildren <GridQuadScript>().GetScale(); xa.uIds++; grid.uId = xa.uIds; grids.Add(grid); } //Create nodes for all gridQuads for (int i = 0; i < grids.Count; i++) { xa.emptyGO.transform.parent = grids[i].go.transform; xa.emptyGO.transform.localPosition = Vector3.zero; xa.emptyGO.transform.localEulerAngles = Vector3.zero; xa.emptyGO.transform.localPosition = new Vector3(-grids[i].scale.x * 0.5f, 0, -grids[i].scale.z * 0.5f); Debug.Log("Starting grid. " + grids[i].go.transform.position + ", " + xa.emptyGO.transform.localPosition); //Now create the nodes int xScale = (int)grids[i].scale.x; int zScale = (int)grids[i].scale.z; for (float x = 0; x <= xScale; x += (1 / xa.gridScale)) { for (float z = 0; z <= zScale; z += (1 / xa.gridScale)) { Vector3 spawnPos = xa.emptyGO.transform.position; xa.emptyGO.transform.LocalSetY(0.02f); spawnPos = xa.emptyGO.transform.position; CreateNode(spawnPos, grids[i].go.GetComponent <Info>().lineAngle, grids[i]); xa.emptyGO.transform.LocalSetY(0); xa.emptyGO.transform.LocalAddZ((1 / xa.gridScale)); } xa.emptyGO.transform.LocalSetZ(-grids[i].scale.z * 0.5f); xa.emptyGO.transform.LocalAddX((1 / xa.gridScale)); } } //Connect all nodes within X dist of each other for (int a = 0; a < nodes.Count; a++) { //do a distance check with all other nodes for (int b = 0; b < nodes.Count; b++) { if (nodes[a].uId != nodes[b].uId) { //do a distance check if (Vector3.Distance(nodes[a].pos, nodes[b].pos) < connectionDist) { //Then connect them nodes[a].connections.Add(nodes[b]); nodes[b].connections.Add(nodes[a]); } } } } //Fill relCon grid for (int a = 0; a < nodes.Count; a++) { for (int b = 0; b < nodes[a].connections.Count; b++) { //Loop through all of this node's connections, and store their relCon dist Vector3 pos = nodes[a].connections[b].pos; Vector3 relPos = pos - nodes[a].pos; //Debug.Log("NodePos: " + nodes[a].pos + ", NodeB: " + nodes[a].connections[b].pos + ", RelPos: " + relPos); RelCon relCon = new RelCon(); relCon.x = Mathf.RoundToInt(relPos.x * xa.gridScale); relCon.y = Mathf.RoundToInt(relPos.y * xa.gridScale); //So I can store & check the relPos as ints, not floats relCon.z = Mathf.RoundToInt(relPos.z * xa.gridScale); relCon.node = nodes[a].connections[b]; nodes[a].relCons.Add(relCon); // nodes[a].relCon } } }