public bool Select(Selection selection, bool parentCompletelyInFrustum, bool ignoreVisibilityCheck)
{
BoundingBox boundingBox;
GetBoundingBox(ref selection.TerrainOffset, selection.PatchScale, selection.HeightScale, out boundingBox);
ContainmentType containmentType = ContainmentType.Contains;
if (!parentCompletelyInFrustum)
{
selection.Frustum.Contains(ref boundingBox, out containmentType);
}
BoundingSphere sphere;
bool intersected = true;
if (!ignoreVisibilityCheck)
{
selection.GetVisibilitySphere(level, out sphere);
boundingBox.Intersects(ref sphere, out intersected);
if (!intersected)
return false;
}
if (level == 0)
{
// we reach a leaf node.
if (containmentType != ContainmentType.Disjoint)
selection.AddSelectedNode(this);
return true;
}
// If this node is out of the next visibility, we do not need to check children.
selection.GetVisibilitySphere(level - 1, out sphere);
boundingBox.Intersects(ref sphere, out intersected);
if (!intersected)
{
if (containmentType != ContainmentType.Disjoint)
selection.AddSelectedNode(this);
return true;
}
bool weAreCompletelyInFrustum = (containmentType == ContainmentType.Contains);
// Check a child node's visibility on ahead.
var someChildrenSelected = false;
someChildrenSelected |= childTopLeft.PreSelect(selection, weAreCompletelyInFrustum);
if (childTopRight != null)
someChildrenSelected |= childTopRight.PreSelect(selection, weAreCompletelyInFrustum);
if (childBottomLeft != null)
someChildrenSelected |= childBottomLeft.PreSelect(selection, weAreCompletelyInFrustum);
if (childBottomRight != null)
someChildrenSelected |= childBottomRight.PreSelect(selection, weAreCompletelyInFrustum);
if (someChildrenSelected)
{
// Select all children to avoid T-junctions by ignoring a visibiliy range check
// if can select at least one.
// The original code tries to select finer nodes as far as possible,
// and hides parts of a coaser node overlapped by them at render time.
// But using HW instancing, we must use a same mesh, so can not use such a overlap.
childTopLeft.Select(selection, weAreCompletelyInFrustum, true);
if (childTopRight != null)
childTopRight.Select(selection, weAreCompletelyInFrustum, true);
if (childBottomLeft != null)
childBottomLeft.Select(selection, weAreCompletelyInFrustum, true);
if (childBottomRight != null)
childBottomRight.Select(selection, weAreCompletelyInFrustum, true);
}
else
{
if (containmentType != ContainmentType.Disjoint)
selection.AddSelectedNode(this);
}
return true;
}