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;
}