/// <summary> /// Tests pointer against model intersections to /// resolve actual model intersection at face level. /// </summary> private void PointerModelIntersectionsTest() { // Nothing to do if no intersections if (pointerNodeIntersections.Count == 0) { return; } // Sort intersections by distance pointerNodeIntersections.Sort(); // Iterate intersections float?intersection = null; float?closestIntersection = null; Intersection.NodeIntersection closestModelIntersection = null; foreach (var ni in pointerNodeIntersections) { // Ensure node is a ModelNode if (false == (ni.Node is ModelNode)) { continue; } // Get model ModelNode node = (ModelNode)ni.Node; ModelManager.ModelData model = node.Model; // Test model bool insideBoundingSphere; int subMeshResult, planeResult; intersection = Intersection.RayIntersectsDFMesh( pointerRay, node.Matrix, ref model, out insideBoundingSphere, out subMeshResult, out planeResult); if (intersection != null) { if (closestIntersection == null || intersection < closestIntersection) { closestIntersection = intersection; closestModelIntersection = ni; } } } // Store closest intersection if (closestModelIntersection != null) { pointerOverModelNode = (ModelNode)closestModelIntersection.Node; } else { pointerOverModelNode = null; } }
/// <summary> /// Recursively walks scene and batches visible submeshes. /// </summary> /// <param name="node">Start node.</param> /// <param name="pointerIntersects">True if pointer intersects.</param> protected void BatchNode(SceneNode node, bool pointerIntersects) { // Do nothing if not visible if (!node.Visible) { return; } // Test node bounds against camera frustum if (!camera.BoundingFrustum.Intersects(node.TransformedBounds)) { return; } // Test if pointer still intersects at this level float?intersectDistance = null; if (pointerIntersects) { intersectDistance = pointerRay.Intersects(node.TransformedBounds); if (intersectDistance == null) { pointerIntersects = false; } } // Batch children of this node foreach (SceneNode child in node.Children) { BatchNode(child, pointerIntersects); } // Batch node if (node is ModelNode) { BatchModelNode((ModelNode)node); if (pointerIntersects) { Intersection.NodeIntersection ni = new Intersection.NodeIntersection(intersectDistance, node); pointerNodeIntersections.Add(ni); } } else if (node is GroundPlaneNode) { BatchGroundPlaneNode((GroundPlaneNode)node); } else if (node is BillboardNode) { BatchBillboardNode((BillboardNode)node); } else if (node is PointLightNode) { BatchPointLightNode((PointLightNode)node); } }