示例#1
0
        public RayCastResult CastRay(Point3D position, Vector3D direction, double rayLength, BodyFilterType filterType, params Body[] bodies)
        {

            //TODO:  If the ray starts outside the boundries, then this method will fail.  Fix that here, so the user doesn't
            // have to worry about it.  Also, if the ray length would cause an endpoint outside the bounds
            //
            // Also, if I fixed the start distance, then I need to add that back into the result, so it's transparent to the caller


            CBody[] bodyHandles = null;
            if (bodies.Length > 0)
            {
                // make a list of newton handles
                bodyHandles = new CBody[bodies.Length];
                for (int i = 0; i < bodies.Length; i++)
                {
                    bodyHandles[i] = bodies[i].NewtonBody;
                }
            }

            //TODO:  Always skip the boundry terrains

            EventHandler<CWorldRayPreFilterEventArgs> preFilterHandler = null;
            if (bodyHandles != null)
            {
                // This artificial method gets called from within NewtonWorld.WorldRayCast
                preFilterHandler = delegate(object sender, CWorldRayPreFilterEventArgs preFilterArgs)
                {
                    switch (filterType)
                    {
                        case BodyFilterType.ExcludeBodies:
                            preFilterArgs.Skip = (Array.IndexOf(bodyHandles, preFilterArgs.Body)) >= 0;
                            break;
                        case BodyFilterType.IncludeBodies:
                            preFilterArgs.Skip = (Array.IndexOf(bodyHandles, preFilterArgs.Body)) < 0;
                            break;
                    }
                };
            }

            List<CWorldRayFilterEventArgs> hitTestResults = new List<CWorldRayFilterEventArgs>();

            Vector3D posAsVector = position.ToVector();		// newt wants a vector instead of a point3d

            // Ask newton to do the hit test (it will invoke the filter delegate, whose implementation is above)
            this.NewtonWorld.WorldRayCast(posAsVector, posAsVector + (direction * rayLength),
                delegate(object sender, CWorldRayFilterEventArgs filterArgs)
                {
                    hitTestResults.Add(filterArgs);
                },
                null, preFilterHandler);

            if (hitTestResults.Count > 0)
            {
                // Find the closest one
                CWorldRayFilterEventArgs hitTestResult = null;
                double distance = double.MaxValue;
                for (int i = 0; i < hitTestResults.Count; i++)
                {
                    double d = (hitTestResults[i].IntersetParam * rayLength);
                    if (d < distance)
                    {
                        distance = d;
                        hitTestResult = hitTestResults[i];
                    }
                }

                Body resultBody = UtilityNewt.GetBodyFromUserData(hitTestResult.Body);
                if (resultBody == null)
                {
                    throw new ApplicationException("Couldn't get the Body from the CBody.UserData");
                }

                // Exit Function
                return new RayCastResult(resultBody, distance, hitTestResult.HitNormal, hitTestResult.IntersetParam);
            }
            else
            {
                // Nothing found
                return null;
            }
        }
示例#2
0
        /// <summary>
        /// NOTE: The ray must be added to the viewport, or this overload won't work
        /// NOTE: Taking in a ray instead of simply taking two Point3D's seems overly complex.  Why the need for the ray to be added to the viewport?  Newton doesn't need that...
        /// </summary>
        public RayCastResult CastRay(Ray ray, BodyFilterType filterType, params Body[] bodies)
        {
            Matrix3D localToWorld = MathUtils.GetTransformToWorld(ray);

            Vector3D direction;
            if (ray.DirectionOrigin == ObjectOrigin.Local)
            {
                direction = localToWorld.Transform(ray.Direction);
            }
            else
            {
                direction = ray.Direction;
            }

            Point3D position = localToWorld.Transform(new Point3D());

            // Call my overload
            return CastRay(position, direction, ray.RayLength, filterType, bodies);
        }