public OctreeNode(OctreeNodeType _type) { Type = _type; drawInfo = new OctreeDrawInfo(); Children = new OctreeNode[8]; for (int i = 0; i < 8; i++) { Children[i] = null; } }
public int Build(Vector3 min, int size, float threshold, List <VertexPositionColorNormal> vertices, int grid_size) { this.position = min; this.size = size; this.type = OctreeNodeType.Internal; int v_index = 0; ConstructNodes(vertices, grid_size, 1); Simplify(threshold, false); return(v_index); }
public OctreeNode() { Type = OctreeNodeType.Node_None; drawInfo = new OctreeDrawInfo(); Children = new OctreeNode[8]; for (int i = 0; i < 8; i++) { Children[i] = null; } }
public OctreeNode(OctreeNodeType _type) { Type = _type; min = Vec3.Zero; size = 0; drawInfo = new OctreeDrawInfo(); children = new OctreeNode[8]; for (var i = 0; i < 8; i++) { children[i] = null; } }
public OctreeNode() { Type = OctreeNodeType.Node_None; min = Vector3.zero; size = 0; drawInfo = new OctreeDrawInfo(); children = new OctreeNode[8]; for (int i = 0; i < 8; i++) { children[i] = null; } }
public OctreeNode(OctreeNodeType _type) { type = _type; min = Vector3.zero; size = 0; drawInfo = null; children = new OctreeNode[8]; for (int i = 0; i < 8; i++) { children[i] = null; } }
public void Simplify(float threshold, bool randomize = false) { if (type != OctreeNodeType.Internal) { return; } int[] signs = { -1, -1, -1, -1, -1, -1, -1, -1 }; int mid_sign = -1; bool is_collapsible = true; //QEF3D qef = new QEF3D(); QEFProper.QEFSolver qef = new QEFProper.QEFSolver(); Random rnd = new Random(); float t = threshold; for (int i = 0; i < 8; i++) { if (children[i] == null) { continue; } if (randomize) { t = (float)rnd.NextDouble() * (float)rnd.NextDouble() * 20.0f; } children[i].Simplify(t); OctreeNode child = children[i]; if (child.type == OctreeNodeType.Internal) { is_collapsible = false; } else { //qef.Add(child.draw_info.position, child.draw_info.averageNormal); //if (child.draw_info.qef != null) qef.Add(ref child.draw_info.qef.data); mid_sign = (child.draw_info.corners >> (7 - i)) & 1; signs[i] = (child.draw_info.corners >> i) & 1; } } if (size == 16) { } if (!is_collapsible) { return; } //Vector3 pos = qef.Solve2(0, 0, 0); Vector3 pos = qef.Solve(1e-6f, 4, 1e-6f); float error = qef.GetError(); if (error > threshold) { return; } OctreeDrawInfo draw_info = new OctreeDrawInfo(); for (int i = 0; i < 8; i++) { if (signs[i] == -1) { draw_info.corners |= mid_sign << i; } else { draw_info.corners |= signs[i] << i; } } Vector3 normal = new Vector3(); for (int i = 0; i < 8; i++) { if (children[i] != null) { OctreeNode child = children[i]; if (child.type == OctreeNodeType.Pseudo || child.type == OctreeNodeType.Leaf) { normal += child.draw_info.averageNormal; } } } normal.Normalize(); draw_info.averageNormal = normal; draw_info.position = pos; draw_info.qef = qef; for (int i = 0; i < 8; i++) { children[i] = null; } type = OctreeNodeType.Pseudo; this.draw_info = draw_info; }
/* The following code is more or less a copy/paste cleanup of the C++ implementation * It's not clean, or efficient, but it works and is fairly straightforward */ public bool ConstructLeaf(List <VertexPositionColorNormal> vertices, int grid_size) { if (size != 1) { return(false); } int corners = 0; float[, ,] samples = new float[2, 2, 2]; for (int i = 0; i < 8; i++) { if ((samples[i / 4, i % 4 / 2, i % 2] = Sampler.Sample(position + new Vector3(i / 4, i % 4 / 2, i % 2))) < 0) { corners |= 1 << i; } } if (corners == 0 || corners == 255) { return(false); } //type = OctreeNodeType.Leaf; //return true; QEF3D qef = new QEF3D(); QEFProper.QEFSolver qefp = new QEFProper.QEFSolver(); Vector3 average_normal = Vector3.Zero; for (int i = 0; i < 12; i++) { int c1 = edgevmap[i, 0]; int c2 = edgevmap[i, 1]; int m1 = (corners >> c1) & 1; int m2 = (corners >> c2) & 1; if (m1 == m2) { continue; } float d1 = samples[c1 / 4, c1 % 4 / 2, c1 % 2]; float d2 = samples[c2 / 4, c2 % 4 / 2, c2 % 2]; Vector3 p1 = new Vector3((float)((c1 / 4)), (float)((c1 % 4 / 2)), (float)((c1 % 2))); Vector3 p2 = new Vector3((float)((c2 / 4)), (float)((c2 % 4 / 2)), (float)((c2 % 2))); Vector3 intersection = Sampler.GetIntersection(p1, p2, d1, d2) + position; Vector3 normal = Sampler.GetNormal(intersection); //GetNormal(x, y); average_normal += normal; qef.Add(intersection, normal); qefp.Add(intersection, normal); } Vector3 n = average_normal / (float)qef.Intersections.Count; n.Normalize(); draw_info = new OctreeDrawInfo(); //draw_info.position = position + qef.Solve2(0, 0, 0); draw_info.position = qefp.Solve(1e-6f, 4, 1e-6f); draw_info.corners = corners; draw_info.averageNormal = n; draw_info.qef = qefp; //vertices.Add(new VertexPositionColorNormal(position + draw_info.position, Color.LightGreen, n)); type = OctreeNodeType.Leaf; return(true); }
public void Simplify(float threshold, bool randomize = false) { if (type != OctreeNodeType.Internal) return; int[] signs = { -1, -1, -1, -1, -1, -1, -1, -1 }; int mid_sign = -1; bool is_collapsible = true; //QEF3D qef = new QEF3D(); QEFProper.QEFSolver qef = new QEFProper.QEFSolver(); Random rnd = new Random(); float t = threshold; for (int i = 0; i < 8; i++) { if (children[i] == null) continue; if (randomize) t = (float)rnd.NextDouble() * (float)rnd.NextDouble() * 20.0f; children[i].Simplify(t); OctreeNode child = children[i]; if (child.type == OctreeNodeType.Internal) is_collapsible = false; else { //qef.Add(child.draw_info.position, child.draw_info.averageNormal); //if (child.draw_info.qef != null) qef.Add(ref child.draw_info.qef.data); mid_sign = (child.draw_info.corners >> (7 - i)) & 1; signs[i] = (child.draw_info.corners >> i) & 1; } } if (size == 16) { } if (!is_collapsible) return; //Vector3 pos = qef.Solve2(0, 0, 0); Vector3 pos = qef.Solve(1e-6f, 4, 1e-6f); float error = qef.GetError(); if (error > threshold) return; OctreeDrawInfo draw_info = new OctreeDrawInfo(); for (int i = 0; i < 8; i++) { if (signs[i] == -1) draw_info.corners |= mid_sign << i; else draw_info.corners |= signs[i] << i; } Vector3 normal = new Vector3(); for (int i = 0; i < 8; i++) { if (children[i] != null) { OctreeNode child = children[i]; if (child.type == OctreeNodeType.Pseudo || child.type == OctreeNodeType.Leaf) normal += child.draw_info.averageNormal; } } normal.Normalize(); draw_info.averageNormal = normal; draw_info.position = pos; draw_info.qef = qef; for (int i = 0; i < 8; i++) { children[i] = null; } type = OctreeNodeType.Pseudo; this.draw_info = draw_info; }
/* The following code is more or less a copy/paste cleanup of the C++ implementation * It's not clean, or efficient, but it works and is fairly straightforward */ public bool ConstructLeaf(List<VertexPositionColorNormal> vertices, int grid_size) { if (size != 1) return false; int corners = 0; float[, ,] samples = new float[2, 2, 2]; for (int i = 0; i < 8; i++) { if ((samples[i / 4, i % 4 / 2, i % 2] = Sampler.Sample(position + new Vector3(i / 4, i % 4 / 2, i % 2))) < 0) corners |= 1 << i; } if (corners == 0 || corners == 255) return false; //type = OctreeNodeType.Leaf; //return true; QEF3D qef = new QEF3D(); QEFProper.QEFSolver qefp = new QEFProper.QEFSolver(); Vector3 average_normal = Vector3.Zero; for (int i = 0; i < 12; i++) { int c1 = edgevmap[i, 0]; int c2 = edgevmap[i, 1]; int m1 = (corners >> c1) & 1; int m2 = (corners >> c2) & 1; if (m1 == m2) continue; float d1 = samples[c1 / 4, c1 % 4 / 2, c1 % 2]; float d2 = samples[c2 / 4, c2 % 4 / 2, c2 % 2]; Vector3 p1 = new Vector3((float)((c1 / 4)), (float)((c1 % 4 / 2)), (float)((c1 % 2))); Vector3 p2 = new Vector3((float)((c2 / 4)), (float)((c2 % 4 / 2)), (float)((c2 % 2))); Vector3 intersection = Sampler.GetIntersection(p1, p2, d1, d2) + position; Vector3 normal = Sampler.GetNormal(intersection);//GetNormal(x, y); average_normal += normal; qef.Add(intersection, normal); qefp.Add(intersection, normal); } Vector3 n = average_normal / (float)qef.Intersections.Count; n.Normalize(); draw_info = new OctreeDrawInfo(); //draw_info.position = position + qef.Solve2(0, 0, 0); draw_info.position = qefp.Solve(1e-6f, 4, 1e-6f); draw_info.corners = corners; draw_info.averageNormal = n; draw_info.qef = qefp; //vertices.Add(new VertexPositionColorNormal(position + draw_info.position, Color.LightGreen, n)); type = OctreeNodeType.Leaf; return true; }
public int Build(Vector3 min, int size, float threshold, List<VertexPositionColorNormal> vertices, int grid_size) { this.position = min; this.size = size; this.type = OctreeNodeType.Internal; int v_index = 0; ConstructNodes(vertices, grid_size, 1); Simplify(threshold, false); return v_index; }
public OctreeNode() { type = OctreeNodeType.None; position = Vector3.Zero; size = 0; children = new OctreeNode[8]; draw_info = null; }
public OctreeNode() { type = OctreeNodeType.NODE_NONE; position = Vector3.zero; size = 1; }