public void TrySplit(int min_size, float threshold, int grid_size, List <VertexPositionColorNormal> vertices) { // This part taken from http://www.volume-gfx.com/ as a listed optimization, though it's disabled right now by setting the value to 1000 float minSplitDistanceDiagonalFactor = 1000.0f; if (Sampler.Sample(position + Vector2.One * size * 0.5f) > size * (float)Math.Sqrt(2) * minSplitDistanceDiagonalFactor || size <= min_size || GetError(threshold) < threshold) { dualgrid_pos = 0.5f * size * Vector2.One; isovalue = Sampler.Sample(dualgrid_pos); normal = Sampler.GetNormal(dualgrid_pos); vertex_index = vertices.Count; leaf = true; Color n_c = new Color(210, 220, 210); vertices.Add(new VertexPositionColorNormal(new Vector3(position * grid_size + dualgrid_pos * grid_size, 0), n_c, new Vector3(normal, 0))); return; } for (int i = 0; i < 4; i++) { children[i] = new QuadtreeNode(); children[i].index = i; children[i].position = position + (float)(size / 2) * new Vector2(i / 2, i % 2); children[i].size = size / 2; children[i].TrySplit(min_size, threshold, grid_size, vertices); } }
public QuadtreeNode() { //type = QuadtreeNodeType.None; position = Vector2.Zero; size = 0; children = new QuadtreeNode[4]; vertex_index = -1; //draw_info = new QuadtreeDrawInfo(); }
public void ConstructTreeGrid(QuadtreeNode node) { if (node == null) { return; } VertexPositionColor[] vs = new VertexPositionColor[16]; int x = (int)node.position.X * this.Size; int y = (int)node.position.Y * this.Size; Color c = Color.LightSteelBlue; Color v = Color.LightSalmon; float size = node.size * this.Size; vs[0] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, 0), c); vs[1] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, 0), c); vs[2] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, 0), c); vs[3] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, 0), c); vs[4] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, 0), c); vs[5] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, 0), c); vs[6] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, 0), c); vs[7] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, 0), c); OutlineBuffer.SetData <VertexPositionColor>(OutlineLocation * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 8, VertexPositionColor.VertexDeclaration.VertexStride); OutlineLocation += 8; if (node.leaf && false) { x += (int)(node.dualgrid_pos.X * (float)this.Size); y += (int)(node.dualgrid_pos.Y * (float)this.Size); float r = 2; vs[8] = new VertexPositionColor(new Vector3(x - r, y - r, 0), v); vs[9] = new VertexPositionColor(new Vector3(x + r, y - r, 0), v); vs[10] = new VertexPositionColor(new Vector3(x + r, y - r, 0), v); vs[11] = new VertexPositionColor(new Vector3(x + r, y + r, 0), v); vs[12] = new VertexPositionColor(new Vector3(x + r, y + r, 0), v); vs[13] = new VertexPositionColor(new Vector3(x - r, y + r, 0), v); vs[14] = new VertexPositionColor(new Vector3(x - r, y + r, 0), v); vs[15] = new VertexPositionColor(new Vector3(x - r, y - r, 0), v); OutlineBuffer.SetData <VertexPositionColor>(OutlineLocation * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 16, VertexPositionColor.VertexDeclaration.VertexStride); OutlineLocation += 16; } for (int i = 0; i < 4; i++) { ConstructTreeGrid(node.children[i]); } }
public static void ProcessEdge(QuadtreeNode q1, QuadtreeNode q2, int edge, List<int> indices, List<Cell> cells) { if (q1.leaf && q2.leaf) return; for (int i = 0; i < 2; i++) { QuadtreeNode n1 = (q1.leaf ? q1 : q1.children[edge_children[edge, i, 0]]); QuadtreeNode n2 = (q2.leaf ? q2 : q2.children[edge_children[edge, i, 1]]); ProcessEdge(n1, n2, edge, indices, cells); } if (edge == 0) ProcessVertices((q1.leaf ? q1 : q1.children[vertex_children[edge, 0, 0]]), (q1.leaf ? q1 : q1.children[vertex_children[edge, 0, 1]]), (q2.leaf ? q2 : q2.children[vertex_children[edge, 1, 0]]), (q2.leaf ? q2 : q2.children[vertex_children[edge, 1, 1]]), indices, cells); else ProcessVertices((q1.leaf ? q1 : q1.children[vertex_children[edge, 0, 0]]), (q2.leaf ? q2 : q2.children[vertex_children[edge, 1, 0]]), (q1.leaf ? q1 : q1.children[vertex_children[edge, 0, 1]]), (q2.leaf ? q2 : q2.children[vertex_children[edge, 1, 1]]), indices, cells); }
public static void ProcessVertices(QuadtreeNode q1, QuadtreeNode q2, QuadtreeNode q3, QuadtreeNode q4, List <int> indices, List <Cell> cells) { if (q1 == null || q2 == null || q3 == null || q4 == null) { return; } QuadtreeNode[] children = { q1, q2, q3, q4 }; QuadtreeNode[] leafs = new QuadtreeNode[4]; if (!children[0].leaf || !children[1].leaf || !children[2].leaf || !children[3].leaf) { for (int i = 0; i < 4; i++) { if (children[i] == null) //shouldn't happen { return; } if (children[i].leaf) { leafs[i] = children[i]; } else { leafs[i] = children[i].children[middle_points[i]]; } } ProcessVertices(leafs[0], leafs[1], leafs[2], leafs[3], indices, cells); } else { Cell c = new Cell(); for (int i = 0; i < 4; i++) { indices.Add(children[connect_points[i]].vertex_index); indices.Add(children[connect_points[(i + 1) % 4]].vertex_index); c.Positions[i] = children[i].dualgrid_pos + children[i].position; c.Values[i] = children[i].isovalue; c.Normals[i] = children[i].normal; } cells.Add(c); } }
/* The following functions generate the dual grid */ public static void ProcessFace(QuadtreeNode q1, List <int> indices, List <Cell> cells) { if (q1 == null || q1.leaf) { return; } for (int i = 0; i < 4; i++) { ProcessFace(q1.children[i], indices, cells); } for (int i = 0; i < 4; i++) { QuadtreeNode c1 = q1.children[edges[i, 0]]; QuadtreeNode c2 = q1.children[edges[i, 1]]; ProcessEdge(c1, c2, i / 2, indices, cells); } ProcessVertices(q1.children[0], q1.children[1], q1.children[2], q1.children[3], indices, cells); }
public static void ProcessEdge(QuadtreeNode q1, QuadtreeNode q2, int edge, List <int> indices, List <Cell> cells) { if (q1.leaf && q2.leaf) { return; } for (int i = 0; i < 2; i++) { QuadtreeNode n1 = (q1.leaf ? q1 : q1.children[edge_children[edge, i, 0]]); QuadtreeNode n2 = (q2.leaf ? q2 : q2.children[edge_children[edge, i, 1]]); ProcessEdge(n1, n2, edge, indices, cells); } if (edge == 0) { ProcessVertices((q1.leaf ? q1 : q1.children[vertex_children[edge, 0, 0]]), (q1.leaf ? q1 : q1.children[vertex_children[edge, 0, 1]]), (q2.leaf ? q2 : q2.children[vertex_children[edge, 1, 0]]), (q2.leaf ? q2 : q2.children[vertex_children[edge, 1, 1]]), indices, cells); } else { ProcessVertices((q1.leaf ? q1 : q1.children[vertex_children[edge, 0, 0]]), (q2.leaf ? q2 : q2.children[vertex_children[edge, 1, 0]]), (q1.leaf ? q1 : q1.children[vertex_children[edge, 0, 1]]), (q2.leaf ? q2 : q2.children[vertex_children[edge, 1, 1]]), indices, cells); } }
public override long Contour(float threshold) { Stopwatch watch = new Stopwatch(); Vertices.Clear(); Tree = new QuadtreeNode(); OutlineLocation = 0; watch.Start(); Tree.Build(Resolution, 1, threshold, this.Size, Vertices); DualGridCount = Vertices.Count; if (DualGridCount > 0) { DualGridBuffer.SetData <VertexPositionColorNormal>(Vertices.ToArray()); } CalculateIndexes(); watch.Stop(); ConstructTreeGrid(Tree); return(watch.ElapsedMilliseconds); }
public void CalculateIndexes() { List <int> indexes = new List <int>(); Cells.Clear(); QuadtreeNode.ProcessFace(Tree, indexes, Cells); IndexCount = indexes.Count; if (indexes.Count != 0) { IndexBuffer.SetData <int>(indexes.ToArray()); } Vertices.Clear(); foreach (Cell c in Cells) { c.Polygonize(Vertices, Size); } VertexCount = Vertices.Count; if (VertexCount > 0) { VertexBuffer.SetData <VertexPositionColorNormal>(Vertices.ToArray()); } }
/* The following functions generate the dual grid */ public static void ProcessFace(QuadtreeNode q1, List<int> indices, List<Cell> cells) { if (q1 == null || q1.leaf) return; for (int i = 0; i < 4; i++) { ProcessFace(q1.children[i], indices, cells); } for (int i = 0; i < 4; i++) { QuadtreeNode c1 = q1.children[edges[i, 0]]; QuadtreeNode c2 = q1.children[edges[i, 1]]; ProcessEdge(c1, c2, i / 2, indices, cells); } ProcessVertices(q1.children[0], q1.children[1], q1.children[2], q1.children[3], indices, cells); }
public void TrySplit(int min_size, float threshold, int grid_size, List<VertexPositionColorNormal> vertices) { // This part taken from http://www.volume-gfx.com/ as a listed optimization, though it's disabled right now by setting the value to 1000 float minSplitDistanceDiagonalFactor = 1000.0f; if (Sampler.Sample(position + Vector2.One * size * 0.5f) > size * (float)Math.Sqrt(2) * minSplitDistanceDiagonalFactor || size <= min_size || GetError(threshold) < threshold) { dualgrid_pos = 0.5f * size * Vector2.One; isovalue = Sampler.Sample(dualgrid_pos); normal = Sampler.GetNormal(dualgrid_pos); vertex_index = vertices.Count; leaf = true; Color n_c = new Color(210, 220, 210); vertices.Add(new VertexPositionColorNormal(new Vector3(position * grid_size + dualgrid_pos * grid_size, 0), n_c, new Vector3(normal, 0))); return; } for (int i = 0; i < 4; i++) { children[i] = new QuadtreeNode(); children[i].index = i; children[i].position = position + (float)(size / 2) * new Vector2(i / 2, i % 2); children[i].size = size / 2; children[i].TrySplit(min_size, threshold, grid_size, vertices); } }
public static void ProcessVertices(QuadtreeNode q1, QuadtreeNode q2, QuadtreeNode q3, QuadtreeNode q4, List<int> indices, List<Cell> cells) { if (q1 == null || q2 == null || q3 == null || q4 == null) return; QuadtreeNode[] children = { q1, q2, q3, q4 }; QuadtreeNode[] leafs = new QuadtreeNode[4]; if (!children[0].leaf || !children[1].leaf || !children[2].leaf || !children[3].leaf) { for (int i = 0; i < 4; i++) { if (children[i] == null) //shouldn't happen return; if (children[i].leaf) leafs[i] = children[i]; else leafs[i] = children[i].children[middle_points[i]]; } ProcessVertices(leafs[0], leafs[1], leafs[2], leafs[3], indices, cells); } else { Cell c = new Cell(); for (int i = 0; i < 4; i++) { indices.Add(children[connect_points[i]].vertex_index); indices.Add(children[connect_points[(i + 1) % 4]].vertex_index); c.Positions[i] = children[i].dualgrid_pos + children[i].position; c.Values[i] = children[i].isovalue; c.Normals[i] = children[i].normal; } cells.Add(c); } }
public void ConstructTreeGrid(QuadtreeNode node) { if (node == null) return; VertexPositionColor[] vs = new VertexPositionColor[16]; int x = (int)node.position.X * this.Size; int y = (int)node.position.Y * this.Size; Color c = Color.LightSteelBlue; Color v = Color.LightSalmon; float size = node.size * this.Size; vs[0] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, 0), c); vs[1] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, 0), c); vs[2] = new VertexPositionColor(new Vector3(x + 1 * size, y + 0 * size, 0), c); vs[3] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, 0), c); vs[4] = new VertexPositionColor(new Vector3(x + 1 * size, y + 1 * size, 0), c); vs[5] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, 0), c); vs[6] = new VertexPositionColor(new Vector3(x + 0 * size, y + 1 * size, 0), c); vs[7] = new VertexPositionColor(new Vector3(x + 0 * size, y + 0 * size, 0), c); OutlineBuffer.SetData<VertexPositionColor>(OutlineLocation * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 8, VertexPositionColor.VertexDeclaration.VertexStride); OutlineLocation += 8; if (node.leaf && false) { x += (int)(node.dualgrid_pos.X * (float)this.Size); y += (int)(node.dualgrid_pos.Y * (float)this.Size); float r = 2; vs[8] = new VertexPositionColor(new Vector3(x - r, y - r, 0), v); vs[9] = new VertexPositionColor(new Vector3(x + r, y - r, 0), v); vs[10] = new VertexPositionColor(new Vector3(x + r, y - r, 0), v); vs[11] = new VertexPositionColor(new Vector3(x + r, y + r, 0), v); vs[12] = new VertexPositionColor(new Vector3(x + r, y + r, 0), v); vs[13] = new VertexPositionColor(new Vector3(x - r, y + r, 0), v); vs[14] = new VertexPositionColor(new Vector3(x - r, y + r, 0), v); vs[15] = new VertexPositionColor(new Vector3(x - r, y - r, 0), v); OutlineBuffer.SetData<VertexPositionColor>(OutlineLocation * VertexPositionColor.VertexDeclaration.VertexStride, vs, 0, 16, VertexPositionColor.VertexDeclaration.VertexStride); OutlineLocation += 16; } for (int i = 0; i < 4; i++) { ConstructTreeGrid(node.children[i]); } }
public override long Contour(float threshold) { Stopwatch watch = new Stopwatch(); Vertices.Clear(); Tree = new QuadtreeNode(); OutlineLocation = 0; watch.Start(); Tree.Build(Resolution, 1, threshold, this.Size, Vertices); DualGridCount = Vertices.Count; if (DualGridCount > 0) DualGridBuffer.SetData<VertexPositionColorNormal>(Vertices.ToArray()); CalculateIndexes(); watch.Stop(); ConstructTreeGrid(Tree); return watch.ElapsedMilliseconds; }