/// <summary> /// Find all the quads in a terrain that need to be drawn. If a quad is a leaf and is visible it should /// be drawn. If that quads tile is not ready the first ready parent is drawn /// NOTE - because of the current set up all task are run on the frame they are generated so /// the leaf quads will always have tiles that are ready to be drawn /// </summary> private void FindDrawableQuads(TerrainQuad quad, List <TileSampler> samplers) { quad.Drawable = false; if (!quad.IsVisible) { quad.Drawable = true; return; } if (quad.IsLeaf) { for (int i = 0; i < samplers.Count; ++i) { TileProducer p = samplers[i].Producer; int l = quad.Level; int tx = quad.Tx; int ty = quad.Ty; if (p.HasTile(l, tx, ty) && p.FindTile(l, tx, ty, false, true) == null) { return; } } } else { int nDrawable = 0; for (int i = 0; i < 4; ++i) { FindDrawableQuads(quad.GetChild(i), samplers); if (quad.GetChild(i).Drawable) { ++nDrawable; } } if (nDrawable < 4) { for (int i = 0; i < samplers.Count; ++i) { TileProducer p = samplers[i].Producer; int l = quad.Level; int tx = quad.Tx; int ty = quad.Ty; if (p.HasTile(l, tx, ty) && p.FindTile(l, tx, ty, false, true) == null) { return; } } } } quad.Drawable = true; }
/// <summary> /// Updates the internal quadtree to make it identical to the given terrain /// quadtree.Collects the tasks necessary to create the missing texture /// tiles, corresponding to newly created quads. /// </summary> protected virtual void GetTiles(QuadTree parent, ref QuadTree tree, TerrainQuad quad) { //if tree not created, create a new tree and check if its tile is needed if (tree == null) { tree = new QuadTree(parent); tree.NeedTile = NeedTile(quad); } //If this trees tile is needed get a tile and add its task to the schedular if the task is not already done if (tree.NeedTile && tree.Tile == null) { tree.Tile = Producer.GetTile(quad.Level, quad.Tx, quad.Ty); if (!tree.Tile.IsDone) { tree.Tile.CreateTile(); } } if (!quad.IsLeaf && Producer.HasChildren(quad.Level, quad.Tx, quad.Ty)) { for (int i = 0; i < 4; ++i) { GetTiles(tree, ref tree.Children[i], quad.GetChild(i)); } } }
/// <summary> /// Updates the internal quadtree to make it identical to the given terrain /// quadtree.This method releases the texture tiles corresponding to /// deleted quads. /// </summary> protected virtual void PutTiles(QuadTree tree, TerrainQuad quad) { if (tree == null) { return; } //Check if this tile is needed, if not put tile. tree.NeedTile = NeedTile(quad); if (!tree.NeedTile && tree.Tile != null) { Producer.PutTile(tree.Tile); tree.Tile = null; } //If this qiad is a leaf then all children of the tree are not needed if (quad.IsLeaf) { if (!tree.IsLeaf) { tree.RecursiveDeleteChildren(this); } } else if (Producer.HasChildren(quad.Level, quad.Tx, quad.Ty)) { for (int i = 0; i < 4; ++i) { PutTiles(tree.Children[i], quad.GetChild(i)); } } }
private void DrawQuad(TerrainNode node, TerrainQuad quad, List <TileSampler> samplers) { if (!quad.IsVisible) { return; } if (!quad.Drawable) { return; } if (quad.IsLeaf) { m_propertyBlock.Clear(); //Set the unifroms needed to draw the texture for this sampler for (int i = 0; i < samplers.Count; ++i) { samplers[i].SetTile(m_propertyBlock, quad.Level, quad.Tx, quad.Ty); } //Set the uniforms unique to each quad node.SetPerQuadUniforms(quad, m_propertyBlock); //Draw the mesh Graphics.DrawMesh(m_quadMesh, Matrix4x4.identity, node.Material, 0, Camera.main, 0, m_propertyBlock); } else { //draw quads in a order based on distance to camera int[] order = new int[4]; double ox = node.LocalCameraPos.x; double oy = node.LocalCameraPos.y; double cx = quad.Ox + quad.Length / 2.0; double cy = quad.Oy + quad.Length / 2.0; if (oy < cy) { if (ox < cx) { order[0] = 0; order[1] = 1; order[2] = 2; order[3] = 3; } else { order[0] = 1; order[1] = 0; order[2] = 3; order[3] = 2; } } else { if (ox < cx) { order[0] = 2; order[1] = 0; order[2] = 3; order[3] = 1; } else { order[0] = 3; order[1] = 1; order[2] = 2; order[3] = 0; } } int done = 0; for (int i = 0; i < 4; ++i) { if (quad.GetChild(order[i]).Visible == FRUSTUM_VISIBILTY.INVISIBLE) { done |= (1 << order[i]); } else if (quad.GetChild(order[i]).Drawable) { DrawQuad(node, quad.GetChild(order[i]), samplers); done |= (1 << order[i]); } } if (done < 15) { //If a leaf quad needs to be drawn but its tiles are not ready then this //will draw the next parent tile instead that is ready. //Because of the current set up all tiles always have there tasks run on the frame they are generated //so this section of code is never reached m_propertyBlock.Clear(); //Set the unifroms needed to draw the texture for this sampler for (int i = 0; i < samplers.Count; ++i) { samplers[i].SetTile(m_propertyBlock, quad.Level, quad.Tx, quad.Ty); } //Set the uniforms unique to each quad node.SetPerQuadUniforms(quad, m_propertyBlock); //Draw the mesh. Graphics.DrawMesh(m_quadMesh, Matrix4x4.identity, node.Material, 0, Camera.main, 0, m_propertyBlock); } } }