private void BuildImpl()
{
int nextUnusedNode = 1;
m_BuildStack.Push(0);
m_BuildStack.Push(m_ObjectNum);
m_BuildStack.Push(0);
while (m_BuildStack.Count >= 3) {
int begin = m_BuildStack.Pop();
int end = m_BuildStack.Pop();
int node = m_BuildStack.Pop();
KdTreeObject obj0 = m_Objects[begin];
float minX = obj0.MinX;
float maxX = obj0.MaxX;
float minZ = obj0.MinZ;
float maxZ = obj0.MaxZ;
for (int i = begin + 1; i < end; ++i) {
KdTreeObject obj = m_Objects[i];
float newMaxX = obj.MaxX;
float newMinX = obj.MinX;
float newMaxZ = obj.MaxZ;
float newMinZ = obj.MinZ;
if (minX > newMinX) minX = newMinX;
if (maxX < newMaxX) maxX = newMaxX;
if (minZ > newMinZ) minZ = newMinZ;
if (maxZ < newMaxZ) maxZ = newMaxZ;
}
m_KdTree[node].m_MinX = minX;
m_KdTree[node].m_MaxX = maxX;
m_KdTree[node].m_MinZ = minZ;
m_KdTree[node].m_MaxZ = maxZ;
if (end - begin > c_MaxLeafSize) {
m_KdTree[node].m_Left = nextUnusedNode;
++nextUnusedNode;
m_KdTree[node].m_Right = nextUnusedNode;
++nextUnusedNode;
bool isVertical = (maxX - minX > maxZ - minZ);
float splitValue = (isVertical ? 0.5f * (maxX + minX) : 0.5f * (maxZ + minZ));
int begin0 = begin;
int left = begin;
int right = end;
bool canSplit = false;
while (left < right) {
while (left < right) {
KdTreeObject obj = m_Objects[left];
if ((isVertical ? obj.MaxX : obj.MaxZ) < splitValue) {
++left;
canSplit = true;
} else if ((isVertical ? obj.MinX : obj.MinZ) < splitValue) {
obj.Indexed = true;
break;
} else {
break;
}
}
while (left < right) {
KdTreeObject obj = m_Objects[right - 1];
if ((isVertical ? obj.MinX : obj.MinZ) >= splitValue) {
--right;
} else if ((isVertical ? obj.MaxX : obj.MaxZ) >= splitValue) {
obj.Indexed = true;
break;
} else {
break;
}
}
if (left < right) {
if (m_Objects[left].Indexed || m_Objects[right - 1].Indexed) {
if (m_Objects[left].Indexed) {
KdTreeObject tmp = m_Objects[begin];
m_Objects[begin] = m_Objects[left];
m_Objects[left] = tmp;
++begin;
++left;
canSplit = true;
}
if (left < right && m_Objects[right - 1].Indexed) {
KdTreeObject tmp = m_Objects[begin];
m_Objects[begin] = m_Objects[right - 1];
m_Objects[right - 1] = tmp;
++begin;
if (begin >= left) {
++left;
canSplit = true;
}
}
} else {
KdTreeObject tmp = m_Objects[left];
m_Objects[left] = m_Objects[right - 1];
m_Objects[right - 1] = tmp;
++left;
--right;
canSplit = true;
}
}
}
if (canSplit) {
m_KdTree[node].m_Begin = begin0;
m_KdTree[node].m_End = begin;
if (left > begin) {
m_BuildStack.Push(m_KdTree[node].m_Left);
m_BuildStack.Push(left);
m_BuildStack.Push(begin);
}
if (end > left) {
m_BuildStack.Push(m_KdTree[node].m_Right);
m_BuildStack.Push(end);
m_BuildStack.Push(left);
}
} else {
m_KdTree[node].m_Begin = begin0;
m_KdTree[node].m_End = begin0;
m_KdTree[node].m_Left = 0;
m_KdTree[node].m_Right = 0;
nextUnusedNode -= 2;
}
} else {
m_KdTree[node].m_Begin = begin;
m_KdTree[node].m_End = end;
m_KdTree[node].m_Left = 0;
m_KdTree[node].m_Right = 0;
}
}
}