public void UpdateQuadtreeClipmaps(LodOctreeNode node, Vector3 cameraPosition, int minNodeSize) { var center = (Vector3)node.LowerLeft.ToVector3() + new Vector3(1) * node.size * 0.5f; var dist = Vector3.Distance(cameraPosition, center); // Should take into account the fact that if minNodeSize changes, the quality of far away nodes changes so the threshold maybe should change too if (dist > node.size * 1.2f) { // This is a valid node size at this distance, so remove all children Merge(node); } else { if (node.Children == null) { Split(node, false, minNodeSize); } if (node.Children == null) { return; // Minlevel } for (int i = 0; i < 8; i++) { UpdateQuadtreeClipmaps(node.Children[i], cameraPosition, minNodeSize); } } }
public void UpdateCanRenderWithoutHoles(LodOctreeNode node) { if (node.Children == null) { node.CanRenderWithoutHoles = node.Mesh != null; /*if (!node.CanRenderWithoutHoles) { TW.Graphics.LineManager3D.WorldMatrix = Matrix.Identity; tree.DrawSingleNode(node, TW.Graphics.LineManager3D, Color.Orange); }*/ return; } var canRenderChildrenWithoutHoles = true; for (int i = 0; i < 8; i++) { var child = node.Children[i]; UpdateCanRenderWithoutHoles(child); if (!child.CanRenderWithoutHoles) canRenderChildrenWithoutHoles = false; } // only render when children cant and i have mesh node.CanRenderWithoutHoles = canRenderChildrenWithoutHoles || node.Mesh != null; }
public DeferredMeshElement CreateRenderElementForNode(LodOctreeNode node, int minNodeSize, IMesh mesh) { var el = TW.Graphics.AcquireRenderer().CreateMeshElement(mesh); float setApart = 1.1f; setApart = 1; // Disable spacing between cells el.WorldMatrix = Matrix.Scaling(new Vector3(node.size / minNodeSize)) * Matrix.Translation(node.LowerLeft.ToVector3() * setApart); return(el); }
private void DestroyMeshElementRecursive(LodOctreeNode node) { DestroyMeshElement(node); if (node.Children == null) return; for (int i = 0; i < 8; i++) { DestroyMeshElementRecursive(node.Children[i]); } }
public LodOctreeNode Create(int size, int leafCellSize, int depth = 0, Point3 pos = new Point3()) { var ret = new LodOctreeNode(size, depth, pos); if (size <= leafCellSize) { return(ret); // Finest detail } Split(ret, true, leafCellSize); return(ret); }
public void DrawLines(LodOctreeNode node, LineManager3D lm) { DrawSingleNode(node, lm, Color.Black); if (node.Children == null) { return; } for (int i = 0; i < 8; i++) { DrawLines(node.Children[i], lm); } }
public void Merge(LodOctreeNode node) { if (node.Children == null) { return; } for (int i = 0; i < 8; i++) { node.Children[i].Destroy(); } node.Children = null; }
public void VisitDepthFirst(LodOctreeNode rootNode, Action <LodOctreeNode> action) { action(rootNode); if (rootNode.Children == null) { return; } for (int i = 0; i < 8; i++) { VisitDepthFirst(rootNode.Children[i], action); } }
private void ensureMeshElementCreated(LodOctreeNode node) { visibleMeshes++; /*TW.Graphics.LineManager3D.WorldMatrix = Matrix.Identity; tree.DrawSingleNode(node, TW.Graphics.LineManager3D, Color.Red);*/ var mesh = node.Mesh; if (mesh == null) throw new InvalidOperationException("Cannot ensure!"); if (node.RenderElement == null) { node.RenderElement = meshBuilder.CreateRenderElementForNode(node, minNodeSize, mesh); node.RenderElement.WorldMatrix = (Matrix)node.RenderElement.WorldMatrix * Matrix.Scaling(new Vector3(globalScaling)); } }
public IMesh CalculateNodeMesh(LodOctreeNode node, int minNodeSize, Func <Vector3, float> density) { var grid = getGrid(node, minNodeSize, density); var mesh = meshBuilder.buildMesh(grid); if (mesh.GetCoreData().Parts.Count > 0) { mesh.GetCoreData().Parts[0].MeshMaterial = new MeshCoreData.Material() { ColoredMaterial = true, DiffuseColor = colors[node.depth % colors.Length].xna() } } ; return(mesh); }
public void ListMeshLessNodes(LodOctreeNode n, List <LodOctreeNode> list) { if (n.Mesh == null) { list.Add(n); } if (n.Children == null) { return; } for (int i = 0; i < 8; i++) { ListMeshLessNodes(n.Children[i], list); } }
public void DrawLines(LodOctreeNode node, LineManager3D lm, Func <LodOctreeNode, bool> isVisible, Func <LodOctreeNode, Color> getColor) { if (isVisible(node)) { DrawSingleNode(node, lm, getColor(node)); } if (node.Children == null) { return; } for (int i = 0; i < 8; i++) { DrawLines(node.Children[i], lm, isVisible, getColor); } }
public void UpdateMeshElements(LodOctreeNode node) { if (node.Children == null) { if (node.Mesh != null) ensureMeshElementCreated(node); return; } if (node.CanRenderWithoutHoles) { var canRenderChildrenWithoutHoles = true; for (int i = 0; i < 8; i++) { var child = node.Children[i]; UpdateCanRenderWithoutHoles(child); if (!child.CanRenderWithoutHoles) canRenderChildrenWithoutHoles = false; } if (canRenderChildrenWithoutHoles) { //Render children DestroyMeshElement(node); for (int i = 0; i < 8; i++) { UpdateMeshElements(node.Children[i]); } } else { ensureMeshElementCreated(node); if (node.Children != null) for (int i = 0; i < 8; i++) DestroyMeshElementRecursive(node.Children[i]); } } else { DestroyMeshElementRecursive(node); /*DestroyMeshElement(node); if (node.Children != null) for (int i = 0; i < 8; i++) UpdateMeshElements(node.Children[i]);*/ } }
public void Split(LodOctreeNode ret, bool recurse = false, int minSize = 1) { if (ret.Children != null) { throw new InvalidOperationException(); } var childSize = ret.size / 2; if (childSize < minSize) { return; } ret.Children = new LodOctreeNode[8]; for (int i = 0; i < 8; i++) { ret.Children[i] = new LodOctreeNode(childSize, ret.depth + 1, ret.LowerLeft + ChildOffsets[i] * childSize); } }
private HermiteDataGrid getGrid(LodOctreeNode node, int minNodeSize, Func <Vector3, float> density) { var nId = new NodeIdentifier(node); if (cachedGrids.ContainsKey(nId)) { return(cachedGrids[nId]); } var currScaling = node.size / minNodeSize; // Then we add another +1 to be able to connect the gaps between the hermite grids //TODO: do lod stitching here var gridSize = minNodeSize + 1; var grid = HermiteDataGrid.CopyGrid( new DensityFunctionHermiteGrid(v => density(v * currScaling + (Vector3)node.LowerLeft.ToVector3()), new Point3(gridSize, gridSize, gridSize))); cachedGrids[nId] = grid; return(grid); }
public TerrainLodEnvironment() { tree = new LodOctree(); var size = 32 * (1 << 10); rootNode = tree.Create(size, size); //octreeOffset = new Vector3(0, size, 0); octreeOffset = new Vector3(0, 0, 0); density = VoxelTerrainGenerationTest.createDensityFunction5Perlin(17, size / 2); //density = v => DensityHermiteGridTest.SineXzDensityFunction(v, 1/5f, size/2, 3); density = densityFunction; densityGrid = new DensityFunctionHermiteGrid(density, new Point3(size, size, size)); minNodeSize = 32; }
public NodeIdentifier(LodOctreeNode node) { this.Pos = node.LowerLeft; this.Size = node.size; }
public void DrawSingleNode(LodOctreeNode node, LineManager3D lm, Color col) { lm.AddBox(new BoundingBox(node.LowerLeft.ToVector3(), (Vector3)node.LowerLeft.ToVector3() + node.size * new Vector3(1)), col); }
private static void DestroyMeshElement(LodOctreeNode node) { if (node.RenderElement != null) node.RenderElement.Delete(); node.RenderElement = null; }