/// <summary> /// Release the pickable object held if any. /// </summary> protected virtual void StopPicking() { if (IsHolding) { if (!PickedObj.Equals(null) && PickedObj.Picker == this) { PickedObj.OnReleased(this); } IsHolding = false; PickedObj = null; Debug.Log("Stop picking."); } }
/// <summary> /// This function will be called in FixedUpdate cycle. It calls the pickable object's /// OnPickedUpdate function. /// </summary> protected virtual void PickingFixedUpdate() { // Check if PickedObj has been destroyed if (PickedObj == null || PickedObj.Equals(null)) { PickedObj = null; IsHolding = false; return; } if (IsHolding) { PickedObj.OnPickedUpdate(this); } }
/// <summary> /// Recursive function used to pick the object in the scene based on the projected near point and far point of the ray corresponding to a mouse click on the screen /// </summary> private PickedObj PickRayCast(object SceneGraphNode, Vector3 nearPoint, Vector3 farPoint) { if (SceneGraphNode == null) { return null; } Vector3 Direction = (farPoint - nearPoint); float MinDistance = -1.0f; float DistanceOfIntersection; GeometryNode ClosestGeometryNode = null; if (SceneGraphNode.GetType() == typeof(GeometryNode)) { if ((DistanceOfIntersection = RaySphereIntersectionTest((GeometryNode)SceneGraphNode, nearPoint, farPoint)) > 0.0) { if (((GeometryNode)SceneGraphNode).BoundingVolume.Center.Length() > 0.0) { MinDistance = DistanceOfIntersection; ClosestGeometryNode = (GeometryNode)SceneGraphNode; } } } try { Type nodeType = SceneGraphNode.GetType(); PropertyInfo[] nodeProperties = nodeType.GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (PropertyInfo nodeProperty in nodeProperties) { if (nodeProperty.PropertyType.IsGenericType) { Type nodePropertyType = nodeProperty.ReflectedType; IList<GoblinXNA.SceneGraph.Node> NodeCollection; if (nodePropertyType == typeof(BranchNode) || nodePropertyType == typeof(TransformNode) || nodePropertyType == typeof(GeometryNode) || nodePropertyType == typeof(MarkerNode)) { NodeCollection = (IList<GoblinXNA.SceneGraph.Node>)nodeProperty.GetValue(SceneGraphNode, null); PickedObj ChildPickedObj; foreach (object ChildGraphNode in NodeCollection) { ChildPickedObj = PickRayCast(ChildGraphNode, nearPoint, farPoint); if (ChildPickedObj != null && (MinDistance < 0.0 || ChildPickedObj.DistanceOfRay < MinDistance)) { MinDistance = ChildPickedObj.DistanceOfRay; ClosestGeometryNode = ChildPickedObj.PickedNode; } } } } } } catch (Exception) { return null; } if (MinDistance > 0.0) { PickedObj returnObj = new PickedObj(ClosestGeometryNode, MinDistance); return returnObj; } return null; }