public Intersection(int index1, int index2, double avgSize1, double avgSize2, CollisionHull.IntersectionPoint[] intersections)
 {
     this.Index1 = index1;
     this.Index2 = index2;
     this.AvgSize1 = avgSize1;
     this.AvgSize2 = avgSize2;
     this.Intersections = intersections;
 }
Exemple #2
0
        //NOTE: Taking in token was added so that if a body needs to change size, a new one can be built using
        //the same token.  In general, always pass null to guarantee unique tokens for each body
        public Body(CollisionHull hull, Matrix3D offsetMatrix, double mass, Visual3D[] visuals = null, long?token = null)
        {
            _world       = hull.World;
            _worldHandle = _world.Handle;
            this.Visuals = visuals;

            //NOTE:  The collision hull can take a null offset matrix, but the body can't
            _handle = Newton.NewtonCreateBody(_worldHandle, hull.Handle, new NewtonMatrix(offsetMatrix).Matrix);

            IntPtr hullHandlePost = Newton.NewtonBodyGetCollision(_handle);

            if (hullHandlePost != hull.Handle)
            {
                // For some reason, this is coming back with a new handle for compound collision hulls.  So store this second one as well
                ObjectStorage.Instance.AddCollisionHull(hullHandlePost, hull.Clone(hullHandlePost));

                // Testing shows the old one to still be out there.  I should probably clone the hull with this new handle using a special overload of
                // the constructor.  But as long as the user doesn't manipulate hulls after they are bound to a body, everything should be fine
                //int test = Newton.NewtonCollisionIsTriggerVolume(hull.Handle);
            }

            // Listen to the move event (the invoke method is a newton callback that converts the newton stuff into c# friendly stuff)
            _newtonBodyMoved = new Newton.NewtonSetTransform(InvokeBodyMoved);
            Newton.NewtonBodySetTransformCallback(_handle, _newtonBodyMoved);
            this.OffsetMatrix = offsetMatrix;           // calling this explicitly, because it call OnBodyMoved (making sure the visual is synced)

            // Store the default mass matrix
            this.Mass = mass;           // letting the property set build the mass matrix

            if (token == null)
            {
                this.Token = TokenGenerator.NextToken();
            }
            else
            {
                this.Token = token.Value;
            }

            ObjectStorage.Instance.AddBody(_handle, this);

            _world.BodyCreated(this);
        }
        public static CollisionHull CreateCompoundCollision(WorldBase world, int shapeID, CollisionHull[] hulls)
        {
            IntPtr[] handles = new IntPtr[hulls.Length];
            for (int cntr = 0; cntr < hulls.Length; cntr++)
            {
                handles[cntr] = hulls[cntr].Handle;
            }

            IntPtr handle = Newton.NewtonCreateCompoundCollision(world.Handle, hulls.Length, handles, shapeID);

            return new CollisionHull(handle, world, null, CollisionShapeType.Compound);
        }
        /// <summary>
        /// This finds intersections between all the hulls
        /// </summary>
        private static Intersection[] GetIntersections(PartSeparator_Part[] parts, CollisionHull[] hulls, bool[] hasMoved, World world)
        {
            List<Intersection> retVal = new List<Intersection>();

            // Compare each hull to the others
            for (int outer = 0; outer < hulls.Length - 1; outer++)
            {
                double? sizeOuter = null;

                for (int inner = outer + 1; inner < hulls.Length; inner++)
                {
                    // Rebuild hulls if nessessary
                    if (hasMoved[outer])
                    {
                        hulls[outer].Dispose();
                        hulls[outer] = parts[outer].CreateCollisionHull(world);
                        hasMoved[outer] = false;
                    }

                    if (hasMoved[inner])
                    {
                        hulls[inner].Dispose();
                        hulls[inner] = parts[inner].CreateCollisionHull(world);
                        hasMoved[inner] = false;
                    }

                    // Get intersecting points
                    CollisionHull.IntersectionPoint[] points = hulls[outer].GetIntersectingPoints_HullToHull(100, hulls[inner], 0);

                    if (points != null && points.Length > 0)
                    {
                        sizeOuter = sizeOuter ?? (parts[outer].Size.X + parts[outer].Size.X + parts[outer].Size.X) / 3d;
                        double sizeInner = (parts[inner].Size.X + parts[inner].Size.X + parts[inner].Size.X) / 3d;

                        double sumSize = sizeOuter.Value + sizeInner;
                        double minSize = sumSize * IGNOREDEPTHPERCENT;

                        // Filter out the shallow penetrations
                        //TODO: May need to add the lost distance to the remaining intersections
                        points = points.Where(o => o.PenetrationDistance > minSize).ToArray();

                        if (points != null && points.Length > 0)
                        {
                            retVal.Add(new Intersection(outer, inner, sizeOuter.Value, sizeInner, points));
                        }
                    }
                }
            }

            // Exit Function
            return retVal.ToArray();
        }
Exemple #5
0
        public bool GetNearestPoint_HullToHull(out Point3D?contactPointThis, out Point3D?contactPointOther, out Vector3D?normal, CollisionHull otherHull, int threadIndex, Transform3D thisTransform, Transform3D otherTransform)
        {
            float[] finalOffsetThis  = thisTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(thisTransform.Value).Matrix;               // not including the member's offset, because newton is already accounting for it.
            float[] finalOffsetOther = thisTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(otherTransform.Value).Matrix;

            NewtonVector3 contactANewt = new NewtonVector3();
            NewtonVector3 contactBNewt = new NewtonVector3();
            NewtonVector3 normalNewt   = new NewtonVector3();

            int retVal = Newton.NewtonCollisionClosestPoint(_world.Handle, _handle, finalOffsetThis, otherHull.Handle, finalOffsetOther, contactANewt.Vector, contactBNewt.Vector, normalNewt.Vector, threadIndex);

            // Exit Function
            if (retVal == 1)
            {
                contactPointThis  = contactANewt.ToPointWPF();
                contactPointOther = contactBNewt.ToPointWPF();
                normal            = normalNewt.ToVectorWPF();
                return(true);
            }
            else
            {
                contactPointThis  = null;
                contactPointOther = null;
                normal            = null;
                return(false);
            }
        }
Exemple #6
0
 public CollisionHullDestroyedArgs(WorldBase world, CollisionHull collisionHull)
 {
     this.World = world;
     this.CollisionHull = collisionHull;
 }
 /// <summary>
 /// This returns the intersection points and time of impact between two hulls within a window of time
 /// NOTE:  The hulls need to start out not touching, and collide within the timestep passed in
 /// </summary>
 /// <param name="maxReturnCount">The maximum number of points to return</param>
 /// <param name="timestep">Maximum time interval consided for the collision calculation</param>
 public IntersectionPoint[] GetIntersectingPoints_HullToHull(int maxReturnCount, double timestep, Vector3D velocity, Vector3D angularVelocity, CollisionHull otherHull, Vector3D otherVelocity, Vector3D otherAngularVelocity, int threadIndex)
 {
     return GetIntersectingPoints_HullToHull(maxReturnCount, timestep, velocity, angularVelocity, otherHull, otherVelocity, otherAngularVelocity, threadIndex, null, null);
 }
 /// <summary>
 /// This returns intersection points between the two hulls (won't return anything if the hulls aren't touching)
 /// NOTE:  This overload is a snapshot in time, the other overload does collision calculations within a window of time
 /// </summary>
 /// <param name="maxReturnCount">The maximum number of points to return</param>
 public IntersectionPoint[] GetIntersectingPoints_HullToHull(int maxReturnCount, CollisionHull otherHull, int threadIndex)
 {
     return GetIntersectingPoints_HullToHull(maxReturnCount, otherHull, threadIndex, null, null);
 }
            /// <summary>
            /// This finds intersections between all the hulls
            /// </summary>
            private static Tuple<int, int, CollisionHull.IntersectionPoint[]>[] GetIntersections(out SortedList<int, double> sizes, CollisionHull[] hulls, double ignoreDepthPercent)
            {
                List<Tuple<int, int, CollisionHull.IntersectionPoint[]>> retVal = new List<Tuple<int, int, CollisionHull.IntersectionPoint[]>>();

                sizes = new SortedList<int, double>();

                // Compare each hull to the others
                for (int outer = 0; outer < hulls.Length - 1; outer++)
                {
                    for (int inner = outer + 1; inner < hulls.Length; inner++)
                    {



                        //TODO: Use the overload that takes offsets
                        CollisionHull.IntersectionPoint[] points = hulls[outer].GetIntersectingPoints_HullToHull(100, hulls[inner], 0);
                        //CollisionHull.IntersectionPoint[] points = hulls[inner].GetIntersectingPoints_HullToHull(100, hulls[outer], 0);		// the normals seem to be the same when colliding from the other direction


                        if (points != null && points.Length > 0)
                        {
                            double sumSize = GetIntersectionsSprtSize(sizes, hulls, outer) + GetIntersectionsSprtSize(sizes, hulls, inner);
                            double minSize = sumSize * ignoreDepthPercent;

                            // Filter out the shallow penetrations
                            //TODO: May need to add the lost distance to the remaining intersections
                            points = points.Where(o => o.PenetrationDistance > minSize).ToArray();

                            if (points != null && points.Length > 0)
                            {
                                retVal.Add(Tuple.Create(outer, inner, points));
                            }
                        }
                    }
                }

                // Exit Function
                return retVal.ToArray();
            }
            /// <summary>
            /// This will move/rotate parts until they aren't intersecting
            /// </summary>
            /// <remarks>
            /// To save some processing, the final collision hulls are returned (so the caller doesn't have to recreate them)
            /// </remarks>
            public static CollisionHull[] Separate(out CollisionHull.IntersectionPoint[] allIntersections, PartBase[] parts, World world, double ignoreDepthPercent)
            {
                // Get collision hulls for all the parts
                CollisionHull[] retVal = parts.Select(o => o.CreateCollisionHull(world)).ToArray();

                List<CollisionHull.IntersectionPoint> all = new List<CollisionHull.IntersectionPoint>();
                List<int> changedParts = new List<int>();

                while (true)
                {
                    // See which parts are colliding
                    SortedList<int, double> sizes;
                    var intersections = GetIntersections(out sizes, retVal, ignoreDepthPercent);
                    if (intersections.Length == 0)
                    {
                        break;
                    }

                    all.AddRange(intersections.SelectMany(o => o.Item3));

                    DoStep1(parts, retVal, intersections, changedParts);
                    //DoStep2(parts, retVal, intersections, changedParts, sizes);		//Attempt2 is flawed.  Newton is returning collision normals that don't seem to be right.  They are perpendicular to part1's face, but don't seem to make sense with part2

                    //Maybe attempt3 should do some kind of jostling.  Do translations in the direction that attempt1 is using, but choose a couple random rotations to see if the parts can be separated without going the full translation distance (seems very inneficient though)


                    //TODO: Remove this when the intersections start taking in offsets
                    break;
                }

                // Recreate the final hulls for parts that changed
                foreach (int index in changedParts.Distinct())
                {
                    //TODO: Attempt a dispose on the old hull (newton reuses and shares hulls when the values are the same, so it's dangerous to dispose hulls, but not disposing will permanently consume memory)
                    //retVal[index].Dispose();
                    retVal[index] = parts[index].CreateCollisionHull(world);
                }

                // Exit Function
                allIntersections = all.ToArray();
                return retVal;
            }
Exemple #11
0
        public IntersectionPoint[] GetIntersectingPoints_HullToHull(int maxReturnCount, double timestep, Vector3D velocity, Vector3D angularVelocity, CollisionHull otherHull, Vector3D otherVelocity, Vector3D otherAngularVelocity, int threadIndex, Transform3D thisTransform, Transform3D otherTransform)
        {
            float[] finalOffsetThis  = thisTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(thisTransform.Value).Matrix;               // not including the member's offset, because newton is already accounting for it.
            float[] finalOffsetOther = thisTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(otherTransform.Value).Matrix;

            // Prep some arrays to hold the return values
            float[] contacts             = new float[3 * maxReturnCount];
            float[] normals              = new float[3 * maxReturnCount];
            float[] penetrationDistances = new float[maxReturnCount];
            float[] timesOfImpact        = new float[maxReturnCount];

            // Call Newton
            int pointCount = Newton.NewtonCollisionCollideContinue(_world.Handle, maxReturnCount, Convert.ToSingle(timestep),
                                                                   _handle, finalOffsetThis, new NewtonVector3(velocity).Vector, new NewtonVector3(angularVelocity).Vector,
                                                                   otherHull.Handle, finalOffsetOther, new NewtonVector3(otherVelocity).Vector, new NewtonVector3(otherAngularVelocity).Vector,
                                                                   timesOfImpact, contacts, normals, penetrationDistances,
                                                                   threadIndex);

            // Convert to c#
            List <IntersectionPoint> retVal = new List <IntersectionPoint>();

            for (int cntr = 0; cntr < pointCount; cntr++)
            {
                int offset = cntr * 3;

                IntersectionPoint point;
                point.ContactPoint        = new NewtonVector3(contacts[offset], contacts[offset + 1], contacts[offset + 2]).ToPointWPF();
                point.Normal              = new NewtonVector3(normals[offset], normals[offset + 1], normals[offset + 2]).ToVectorWPF();
                point.PenetrationDistance = penetrationDistances[cntr];
                point.TimeOfImpact        = timesOfImpact[cntr];

                retVal.Add(point);
            }

            // Exit Function
            return(retVal.ToArray());
        }
Exemple #12
0
 /// <summary>
 /// This returns the intersection points and time of impact between two hulls within a window of time
 /// NOTE:  The hulls need to start out not touching, and collide within the timestep passed in
 /// </summary>
 /// <param name="maxReturnCount">The maximum number of points to return</param>
 /// <param name="timestep">Maximum time interval consided for the collision calculation</param>
 public IntersectionPoint[] GetIntersectingPoints_HullToHull(int maxReturnCount, double timestep, Vector3D velocity, Vector3D angularVelocity, CollisionHull otherHull, Vector3D otherVelocity, Vector3D otherAngularVelocity, int threadIndex)
 {
     return(GetIntersectingPoints_HullToHull(maxReturnCount, timestep, velocity, angularVelocity, otherHull, otherVelocity, otherAngularVelocity, threadIndex, null, null));
 }
Exemple #13
0
        public IntersectionPoint[] GetIntersectingPoints_HullToHull(int maxReturnCount, CollisionHull otherHull, int threadIndex, Transform3D thisTransform, Transform3D otherTransform)
        {
            float[] finalOffsetThis  = thisTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(thisTransform.Value).Matrix;               // not including the member's offset, because newton is already accounting for it.
            float[] finalOffsetOther = otherTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(otherTransform.Value).Matrix;

            if (_handle == otherHull._handle && thisTransform == null && otherTransform == null)
            {
                // Newton throws an exception if trying to collide the same hull
                return(new IntersectionPoint[0]);
            }

            // Prep some arrays to hold the return values
            float[] contacts             = new float[3 * maxReturnCount];
            float[] normals              = new float[3 * maxReturnCount];
            float[] penetrationDistances = new float[maxReturnCount];

            // Call Newton
            int pointCount = Newton.NewtonCollisionCollide(_world.Handle, maxReturnCount, _handle, finalOffsetThis, otherHull.Handle, finalOffsetOther, contacts, normals, penetrationDistances, threadIndex);

            // Convert to c#
            List <IntersectionPoint> retVal = new List <IntersectionPoint>();

            for (int cntr = 0; cntr < pointCount; cntr++)
            {
                int offset = cntr * 3;

                IntersectionPoint point;
                point.ContactPoint        = new NewtonVector3(contacts[offset], contacts[offset + 1], contacts[offset + 2]).ToPointWPF();
                point.Normal              = new NewtonVector3(normals[offset], normals[offset + 1], normals[offset + 2]).ToVectorWPF();
                point.PenetrationDistance = penetrationDistances[cntr];
                point.TimeOfImpact        = 0;  // time of impact has no meaning for this method (I'm just reusing the same structure between two methods)

                retVal.Add(point);
            }

            // Exit Function
            return(retVal.ToArray());
        }
Exemple #14
0
 /// <summary>
 /// This returns intersection points between the two hulls (won't return anything if the hulls aren't touching)
 /// NOTE:  This overload is a snapshot in time, the other overload does collision calculations within a window of time
 /// </summary>
 /// <param name="maxReturnCount">The maximum number of points to return</param>
 public IntersectionPoint[] GetIntersectingPoints_HullToHull(int maxReturnCount, CollisionHull otherHull, int threadIndex)
 {
     return(GetIntersectingPoints_HullToHull(maxReturnCount, otherHull, threadIndex, null, null));
 }
 /// <summary>
 /// Returns the closest points along the surface of the two hulls (null if the hulls intersect each other)
 /// </summary>
 public bool GetNearestPoint_HullToHull(out Point3D? contactPointThis, out Point3D? contactPointOther, out Vector3D? normal, CollisionHull otherHull, int threadIndex)
 {
     return GetNearestPoint_HullToHull(out contactPointThis, out contactPointOther, out normal, otherHull, threadIndex, null, null);
 }
            //Attempt2: Include rotation
            private static void DoStep2(PartBase[] parts, CollisionHull[] hulls, Tuple<int, int, CollisionHull.IntersectionPoint[]>[] intersections, List<int> changedParts, SortedList<int, double> sizes)
            {
                SortedList<int, List<Tuple<Vector3D?, Quaternion?>>> moves = new SortedList<int, List<Tuple<Vector3D?, Quaternion?>>>();

                // Shoot through all the part pairs
                foreach (var intersection in intersections)
                {
                    double mass1 = parts[intersection.Item1].TotalMass;
                    double mass2 = parts[intersection.Item2].TotalMass;
                    double totalMass = mass1 + mass2;

                    double sumPenetration = intersection.Item3.Sum(o => o.PenetrationDistance);
                    double avgPenetration = sumPenetration / Convert.ToDouble(intersection.Item3.Length);

                    // Shoot through the intersecting points between these two parts
                    foreach (var intersectPoint in intersection.Item3)
                    {
                        // The sum of scaledDistance needs to add up to avgPenetration
                        double percentDistance = intersectPoint.PenetrationDistance / sumPenetration;
                        double scaledDistance = avgPenetration * percentDistance;

                        double distance1 = scaledDistance * ((totalMass - mass1) / totalMass);
                        double distance2 = scaledDistance * ((totalMass - mass2) / totalMass);


                        // Normal is pointing away from the first and toward the second
                        Vector3D normalUnit = intersectPoint.Normal.ToUnit();

                        Vector3D translation, torque;
                        Math3D.SplitForceIntoTranslationAndTorque(out translation, out torque, intersectPoint.ContactPoint - parts[intersection.Item1].Position, normalUnit * (-1d * distance1));
                        DoStepSprtAddForce(moves, intersection.Item1, translation, DoStep2SprtRotate(torque, sizes[intersection.Item1]));


                        Math3D.SplitForceIntoTranslationAndTorque(out translation, out torque, intersectPoint.ContactPoint - parts[intersection.Item2].Position, normalUnit * distance2);
                        DoStepSprtAddForce(moves, intersection.Item2, translation, DoStep2SprtRotate(torque, sizes[intersection.Item2]));


                    }
                }

                // Apply the movements
                DoStepSprtMove(parts, moves);

                // Remember which parts were modified (the list will be deduped later)
                changedParts.AddRange(moves.Keys);
            }
        public bool GetNearestPoint_HullToHull(out Point3D? contactPointThis, out Point3D? contactPointOther, out Vector3D? normal, CollisionHull otherHull, int threadIndex, Transform3D thisTransform, Transform3D otherTransform)
        {
            float[] finalOffsetThis = thisTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(thisTransform.Value).Matrix;		// not including the member's offset, because newton is already accounting for it.
            float[] finalOffsetOther = thisTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(otherTransform.Value).Matrix;

            NewtonVector3 contactANewt = new NewtonVector3();
            NewtonVector3 contactBNewt = new NewtonVector3();
            NewtonVector3 normalNewt = new NewtonVector3();

            int retVal = Newton.NewtonCollisionClosestPoint(_world.Handle, _handle, finalOffsetThis, otherHull.Handle, finalOffsetOther, contactANewt.Vector, contactBNewt.Vector, normalNewt.Vector, threadIndex);

            // Exit Function
            if (retVal == 1)
            {
                contactPointThis = contactANewt.ToPointWPF();
                contactPointOther = contactBNewt.ToPointWPF();
                normal = normalNewt.ToVectorWPF();
                return true;
            }
            else
            {
                contactPointThis = null;
                contactPointOther = null;
                normal = null;
                return false;
            }
        }
        private ModelVisual3D GetWPFModel(out CollisionHull hull, out Transform3DGroup transform, out Quaternion rotation, out DiffuseMaterial bodyMaterial, CollisionShapeType shape, Color color, Color reflectionColor, double reflectionIntensity, Vector3D size, Point3D position, DoubleVector directionFacing, bool createHull)
        {
            // Material
            MaterialGroup materials = new MaterialGroup();
            bodyMaterial = new DiffuseMaterial(new SolidColorBrush(color));
            materials.Children.Add(bodyMaterial);
            materials.Children.Add(new SpecularMaterial(new SolidColorBrush(reflectionColor), reflectionIntensity));

            // Geometry Model
            GeometryModel3D geometry = new GeometryModel3D();
            geometry.Material = materials;
            geometry.BackMaterial = materials;

            hull = null;

            switch (shape)
            {
                case CollisionShapeType.Box:
                    Vector3D halfSize = size / 2d;
                    geometry.Geometry = UtilityWPF.GetCube_IndependentFaces(new Point3D(-halfSize.X, -halfSize.Y, -halfSize.Z), new Point3D(halfSize.X, halfSize.Y, halfSize.Z));
                    if (createHull)
                    {
                        hull = CollisionHull.CreateBox(_world, 0, size, null);
                    }
                    break;

                case CollisionShapeType.Sphere:
                    geometry.Geometry = UtilityWPF.GetSphere_LatLon(5, size.X, size.Y, size.Z);
                    if (createHull)
                    {
                        hull = CollisionHull.CreateSphere(_world, 0, size, null);
                    }
                    break;

                case CollisionShapeType.Cylinder:
                    geometry.Geometry = UtilityWPF.GetCylinder_AlongX(20, size.X, size.Y);
                    if (createHull)
                    {
                        hull = CollisionHull.CreateCylinder(_world, 0, size.X, size.Y, null);
                    }
                    break;

                case CollisionShapeType.Cone:
                    geometry.Geometry = UtilityWPF.GetCone_AlongX(20, size.X, size.Y);
                    if (createHull)
                    {
                        hull = CollisionHull.CreateCone(_world, 0, size.X, size.Y, null);
                    }
                    break;

                default:
                    throw new ApplicationException("Unexpected CollisionShapeType: " + shape.ToString());
            }

            // Transform
            transform = new Transform3DGroup();		// rotate needs to be added before translate



            //rotation = _defaultDirectionFacing.GetAngleAroundAxis(directionFacing);		// can't use double vector, it over rotates (not anymore, but this is still isn't rotating correctly)

            rotation = Math3D.GetRotation(_defaultDirectionFacing.Standard, directionFacing.Standard);



            transform.Children.Add(new RotateTransform3D(new QuaternionRotation3D(rotation)));
            transform.Children.Add(new TranslateTransform3D(position.ToVector()));

            // Model Visual
            ModelVisual3D retVal = new ModelVisual3D();
            retVal.Content = geometry;
            retVal.Transform = transform;

            // Exit Function
            return retVal;
        }
        public IntersectionPoint[] GetIntersectingPoints_HullToHull(int maxReturnCount, CollisionHull otherHull, int threadIndex, Transform3D thisTransform, Transform3D otherTransform)
        {
            float[] finalOffsetThis = thisTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(thisTransform.Value).Matrix;		// not including the member's offset, because newton is already accounting for it.
            float[] finalOffsetOther = otherTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(otherTransform.Value).Matrix;

            if (_handle == otherHull._handle && thisTransform == null && otherTransform == null)
            {
                // Newton throws an exception if trying to collide the same hull
                return new IntersectionPoint[0];
            }

            // Prep some arrays to hold the return values
            float[] contacts = new float[3 * maxReturnCount];
            float[] normals = new float[3 * maxReturnCount];
            float[] penetrationDistances = new float[maxReturnCount];

            // Call Newton
            int pointCount = Newton.NewtonCollisionCollide(_world.Handle, maxReturnCount, _handle, finalOffsetThis, otherHull.Handle, finalOffsetOther, contacts, normals, penetrationDistances, threadIndex);

            // Convert to c#
            List<IntersectionPoint> retVal = new List<IntersectionPoint>();

            for (int cntr = 0; cntr < pointCount; cntr++)
            {
                int offset = cntr * 3;

                IntersectionPoint point;
                point.ContactPoint = new NewtonVector3(contacts[offset], contacts[offset + 1], contacts[offset + 2]).ToPointWPF();
                point.Normal = new NewtonVector3(normals[offset], normals[offset + 1], normals[offset + 2]).ToVectorWPF();
                point.PenetrationDistance = penetrationDistances[cntr];
                point.TimeOfImpact = 0;		// time of impact has no meaning for this method (I'm just reusing the same structure between two methods)

                retVal.Add(point);
            }

            // Exit Function
            return retVal.ToArray();


        }
            private static double GetIntersectionsSprtSize(SortedList<int, double> sizes, CollisionHull[] hulls, int index)
            {
                if (sizes.ContainsKey(index))
                {
                    return sizes[index];
                }

                //NOTE: The returned AABB will be bigger than the actual object
                Point3D min, max;
                hulls[index].CalculateAproximateAABB(out min, out max);

                // Just get the average size of this box
                double size = ((max.X - min.X) + (max.Y - min.Y) + (max.Z - min.Z)) / 3d;

                sizes.Add(index, size);

                return size;
            }
        public IntersectionPoint[] GetIntersectingPoints_HullToHull(int maxReturnCount, double timestep, Vector3D velocity, Vector3D angularVelocity, CollisionHull otherHull, Vector3D otherVelocity, Vector3D otherAngularVelocity, int threadIndex, Transform3D thisTransform, Transform3D otherTransform)
        {
            float[] finalOffsetThis = thisTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(thisTransform.Value).Matrix;		// not including the member's offset, because newton is already accounting for it.
            float[] finalOffsetOther = thisTransform == null ? new NewtonMatrix(Matrix3D.Identity).Matrix : new NewtonMatrix(otherTransform.Value).Matrix;

            // Prep some arrays to hold the return values
            float[] contacts = new float[3 * maxReturnCount];
            float[] normals = new float[3 * maxReturnCount];
            float[] penetrationDistances = new float[maxReturnCount];
            float[] timesOfImpact = new float[maxReturnCount];

            // Call Newton
            int pointCount = Newton.NewtonCollisionCollideContinue(_world.Handle, maxReturnCount, Convert.ToSingle(timestep),
                                                                                                                _handle, finalOffsetThis, new NewtonVector3(velocity).Vector, new NewtonVector3(angularVelocity).Vector,
                                                                                                                otherHull.Handle, finalOffsetOther, new NewtonVector3(otherVelocity).Vector, new NewtonVector3(otherAngularVelocity).Vector,
                                                                                                                timesOfImpact, contacts, normals, penetrationDistances,
                                                                                                                threadIndex);

            // Convert to c#
            List<IntersectionPoint> retVal = new List<IntersectionPoint>();

            for (int cntr = 0; cntr < pointCount; cntr++)
            {
                int offset = cntr * 3;

                IntersectionPoint point;
                point.ContactPoint = new NewtonVector3(contacts[offset], contacts[offset + 1], contacts[offset + 2]).ToPointWPF();
                point.Normal = new NewtonVector3(normals[offset], normals[offset + 1], normals[offset + 2]).ToVectorWPF();
                point.PenetrationDistance = penetrationDistances[cntr];
                point.TimeOfImpact = timesOfImpact[cntr];

                retVal.Add(point);
            }

            // Exit Function
            return retVal.ToArray();
        }
            /// <summary>
            /// This returns collision hulls that are offset where the parts are (only recreates hulls for parts that have moved)
            /// </summary>
            public CollisionHull[] GetCollisionHulls()
            {
                CollisionHull[] retVal = new CollisionHull[_parts.Length];

                for (int cntr = 0; cntr < _parts.Length; cntr++)
                {
                    if (_hasMoved[cntr])
                    {
                        retVal[cntr].Dispose();
                        retVal[cntr] = _parts[cntr].CreateCollisionHull(_world);
                        _hasMoved[cntr] = false;
                    }
                    else
                    {
                        retVal[cntr] = _hulls[cntr];
                    }
                }

                return retVal;
            }
        private void btnBodyPropellerPlates_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                RemoveCurrentBody();

                _world.Pause();

                // Material
                MaterialGroup materials = new MaterialGroup();
                materials.Children.Add(new DiffuseMaterial(new SolidColorBrush(_colors.HullFace)));
                materials.Children.Add(_colors.HullFaceSpecular);

                #region Templates

                // These positions are transformed for each blade
                Point3D[] bladePositions = new Point3D[2];
                bladePositions[0] = new Point3D(-1d, -.25d, -.05d);
                bladePositions[1] = new Point3D(1d, .25d, .05d);

                // This tranform is throw away.  It's just used to transform points
                Transform3DGroup transform = new Transform3DGroup();
                transform.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(1, 0, 0), 90d + 15d)));		// rotar tilt (the flow defaults to -x, so face them into the wind)
                transform.Children.Add(new TranslateTransform3D(new Vector3D(1d + .5d, 0, 0)));		// pull away from the center a bit
                transform.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 0, 1), 90)));		// I don't want it along X, I want it along Y

                #endregion

                // Blades
                MeshGeometry3D[] meshBlades = new MeshGeometry3D[StaticRandom.Next(1, 8)];
                CollisionHull[] collisionBlades = new CollisionHull[meshBlades.Length];
                Transform3D[] transformBlades = new Transform3D[meshBlades.Length];
                GeometryModel3D[] geometryBlades = new GeometryModel3D[meshBlades.Length];
                ModelVisual3D[] modelBlades = new ModelVisual3D[meshBlades.Length];

                for (int cntr = 0; cntr < meshBlades.Length; cntr++)
                {
                    meshBlades[cntr] = UtilityWPF.GetCube_IndependentFaces(bladePositions[0], bladePositions[1]);
                    collisionBlades[cntr] = CollisionHull.CreateBox(_world, 0, bladePositions[1] - bladePositions[0], transform.Value);
                    transformBlades[cntr] = transform.Clone();

                    geometryBlades[cntr] = new GeometryModel3D();
                    geometryBlades[cntr].Material = materials;
                    geometryBlades[cntr].BackMaterial = materials;
                    geometryBlades[cntr].Geometry = meshBlades[cntr];
                    geometryBlades[cntr].Transform = transformBlades[cntr];

                    modelBlades[cntr] = new ModelVisual3D();
                    modelBlades[cntr].Content = geometryBlades[cntr];
                    modelBlades[cntr].Transform = _modelOrientationTrackball.Transform;

                    // Prep for the next blade
                    transform.Children.Add(new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(1, 0, 0), 360d / meshBlades.Length)));
                }

                // Body
                CollisionHull collisionHull = CollisionHull.CreateCompoundCollision(_world, 0, collisionBlades);

                _body = new Body(collisionHull, _modelOrientationTrackball.Transform.Value, 1, null);
                collisionHull.Dispose();
                foreach (CollisionHull hull in collisionBlades)
                {
                    hull.Dispose();
                }

                _fluidHull = new FluidHull();
                _fluidHull.Triangles = FluidHull.FluidTriangle.GetTrianglesFromMesh(meshBlades, transformBlades);
                _fluidHull.IsClosedConvexInUniformField = false;
                _fluidHull.Transform = _modelOrientationTrackball.Transform;
                _fluidHull.Field = _field;
                _fluidHull.Body = _body;

                // Wireframe
                ScreenSpaceLines3D modelWireframe = GetModelWireframe(_fluidHull);
                modelWireframe.Transform = _modelOrientationTrackball.Transform;
                _viewport.Children.Add(modelWireframe);

                // Rope
                Point3D bodyAttachPoint = _modelOrientationTrackball.Transform.Transform(new Point3D(.25, 0, 0));
                Point3D anchorPoint = _modelOrientationTrackball.Transform.Transform(new Point3D(3, 0, 0));
                AddRope(bodyAttachPoint, anchorPoint, Math1D.DegreesToRadians(1d));

                // Add to the viewport
                foreach (ModelVisual3D model in modelBlades)
                {
                    _viewport.Children.Add(model);
                }

                // Finish setting up the body
                Visual3D[] visuals = new Visual3D[meshBlades.Length + 1];
                for (int cntr = 0; cntr < meshBlades.Length; cntr++)
                {
                    visuals[cntr] = modelBlades[cntr];
                }
                visuals[visuals.Length - 1] = modelWireframe;

                _body.Visuals = visuals;
                _body.ApplyForceAndTorque += new EventHandler<BodyApplyForceAndTorqueArgs>(Body_ApplyForceAndTorque);
                _body.BodyMoved += new EventHandler(Body_BodyMoved);

                _world.UnPause();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Exemple #24
0
 /// <summary>
 /// Returns the closest points along the surface of the two hulls (null if the hulls intersect each other)
 /// </summary>
 public bool GetNearestPoint_HullToHull(out Point3D?contactPointThis, out Point3D?contactPointOther, out Vector3D?normal, CollisionHull otherHull, int threadIndex)
 {
     return(GetNearestPoint_HullToHull(out contactPointThis, out contactPointOther, out normal, otherHull, threadIndex, null, null));
 }