source: 2014/24/EemeliK/Zombieland/Jypeli/Physics2DDotNet/Body.cs @ 5974

Revision 5974, 33.3 KB checked in by empaheik, 5 years ago (diff)
Line 
1#region MIT License
2/*
3 * Copyright (c) 2005-2008 Jonathan Mark Porter. http://physics2d.googlepages.com/
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#endregion
23
24
25
26
27#if UseDouble
28using Scalar = System.Double;
29#else
30using Scalar = System.Single;
31#endif
32using System;
33using System.Collections.Generic;
34using System.Collections.ObjectModel;
35using AdvanceMath;
36using AdvanceMath.Geometry2D;
37using Physics2DDotNet.Shapes;
38using Physics2DDotNet.Joints;
39using Physics2DDotNet.Ignorers;
40
41
42namespace Physics2DDotNet
43{
44    /// <summary>
45    /// This is the Physical Body that collides in the engine.
46    /// </summary>
47#if !(WINDOWS_PHONE || XBOX)
48    [Serializable]
49#endif
50    public sealed class Body : IPhysicsEntity, IDuplicateable<Body>
51    {
52        #region static methods
53        internal static MassInfo GetMassInfo(Scalar mass, IShape shape)
54        {
55            if (shape == null) { throw new ArgumentNullException("shape"); }
56            return new MassInfo(mass, shape.Inertia * mass);
57        }
58        public static bool CanCollide(Body body1, Body body2)
59        {
60            if (body1 == null) { throw new ArgumentNullException("body1"); }
61            if (body2 == null) { throw new ArgumentNullException("body2"); }
62            return
63                body1.isCollidable &&
64                body2.isCollidable &&
65                (body1.collisionIgnorer == null ||
66                (Ignorer.CanCollide(body1, body2, body1.collisionIgnorer, body2.collisionIgnorer)))
67                &&
68                (body2.collisionIgnorer == null ||
69                !body2.collisionIgnorer.BothNeeded ||
70                (Ignorer.CanCollide(body2, body1, body2.collisionIgnorer, body1.collisionIgnorer)));
71        }
72
73        internal static void CreateProxy(Body body1, Body body2, Matrix2x2 transformation)
74        {
75            AddProxyList(body1, body2, transformation);
76            AddProxyList(body2, body1, transformation.Inverted);
77            AddProxySingle(body1, body2, transformation);
78        }
79        private static void AddProxyList(Body body1, Body body2, Matrix2x2 transformation)
80        {
81            for (LinkedListNode<BodyProxy> node = body2.proxies.First;
82                  node != null;
83                  node = node.Next)
84            {
85                BodyProxy proxyT = node.Value;
86                AddProxySingle(body1, proxyT.Body2,
87                    transformation * proxyT.transformation);
88            }
89        }
90        private static void AddProxySingle(Body body1, Body body2, Matrix2x2 transformation)
91        {
92            BodyProxy proxy1 = new BodyProxy(body2,body1, transformation.Inverted);
93            BodyProxy proxy2 = new BodyProxy(body1,body2, transformation);
94            proxy1.invertedTwin = proxy2;
95            proxy2.invertedTwin = proxy1;
96            body1.proxies.AddLast(proxy2.node);
97            body2.proxies.AddLast(proxy1.node);
98        }
99
100        #endregion
101        #region events
102        /// <summary>
103        /// Raised when the Lifetime property has been Changed.
104        /// </summary>
105        public event EventHandler LifetimeChanged;
106        /// <summary>
107        /// Raised when the Shape of the Body has been Changed.
108        /// </summary>
109        public event EventHandler ShapeChanged;
110        /// <summary>
111        /// Raised when the object is Added to the engine but is not yet part of the update process.
112        /// </summary>
113        public event EventHandler Pending;
114        /// <summary>
115        /// Raised when the object is added to a Physics Engine.
116        /// </summary>
117        public event EventHandler Added;
118        /// <summary>
119        /// Raised when the object is Removed from a Physics Engine.
120        /// </summary>
121        public event EventHandler<RemovedEventArgs> Removed;
122        /// <summary>
123        /// Raised when the Position has been Changed.
124        /// Raised by either the Solver or a call to ApplyMatrix.
125        /// </summary>
126        public event EventHandler PositionChanged;
127        /// <summary>
128        /// Raised when the Body has been updated to a change in time.
129        /// </summary>
130        public event EventHandler<UpdatedEventArgs> Updated;
131        /// <summary>
132        /// Raised when the Body collides with another.
133        /// </summary>
134        public event EventHandler<CollisionEventArgs> Collided;
135        /// <summary>
136        /// Raised constantly when the Body is colliding with another.
137        /// </summary>
138        public event EventHandler<CollisionEventArgs> Colliding;
139        /// <summary>
140        /// Raised when a joint is added that affects this body.
141        /// </summary>
142        public event EventHandler<BodyJointEventArgs> JointAdded;
143        /// <summary>
144        /// Raised when a joint is removed that affects this body.
145        /// </summary>
146        public event EventHandler<BodyJointEventArgs> JointRemoved;
147
148        #endregion
149        #region fields
150        Dictionary<string, object> tags;
151       
152        internal LinkedList<BodyProxy> proxies;
153        private List<Joint> joints;
154        private PhysicsEngine engine;
155        private IShape shape;
156        private PhysicsState state;
157        private Matrices matrices;
158        private MassInfo massInfo;
159        private Coefficients coefficients;
160        private Matrix2x3 transformation;
161        private BoundingRectangle rectangle;
162        private Lifespan lifetime;
163        private Ignorer eventIgnorer;
164        private Ignorer collisionIgnorer;
165
166        private ALVector2D lastPosition;
167        private Scalar linearDamping;
168        private Scalar angularDamping;
169        private int id;
170        internal int idleCount;
171
172        internal bool isChecked;
173        private bool ignoreVertexes;
174        private bool ignoresGravity;
175        private bool ignoresPhysicsLogics;
176        private bool ignoresCollisionResponce;
177        private bool isAdded;
178        private bool isCollidable;
179        private bool isTransformed;
180        private bool isEventable;
181        private bool isBroadPhaseOnly;
182        private bool transformChanged;
183        private bool isFrozen;
184
185        private object tag;
186        private object solverTag;
187        private object detectorTag;
188        #endregion
189        #region constructors
190        /// <summary>
191        /// Creates a new Body Instance.
192        /// </summary>
193        /// <param name="state">The State of the Body.</param>
194        /// <param name="shape">The Shape of the Body.</param>
195        /// <param name="mass">The mass of the Body The inertia will be aquired from the Shape.</param>
196        /// <param name="coefficients">A object containing coefficients.</param>
197        /// <param name="lifeTime">A object Describing how long the object will be in the engine.</param>
198        public Body(
199            PhysicsState state,
200            IShape shape,
201            Scalar mass,
202            Coefficients coefficients,
203            Lifespan lifetime)
204            : this(
205                state, shape,
206                GetMassInfo(mass, shape),
207                coefficients, lifetime) { }
208        /// <summary>
209        /// Creates a new Body Instance.
210        /// </summary>
211        /// <param name="state">The State of the Body.</param>
212        /// <param name="shape">The Shape of the Body.</param>
213        /// <param name="massInfo">A object describing the mass and inertia of the Body.</param>
214        /// <param name="coefficients">A object containing coefficients.</param>
215        /// <param name="lifeTime">A object Describing how long the object will be in the engine.</param>
216        public Body(
217            PhysicsState state,
218            IShape shape,
219            MassInfo massInfo,
220            Coefficients coefficients,
221            Lifespan lifetime)
222        {
223            if (state == null) { throw new ArgumentNullException("state"); }
224            if (shape == null) { throw new ArgumentNullException("shape"); }
225            if (massInfo == null) { throw new ArgumentNullException("massInfo"); }
226            if (coefficients == null) { throw new ArgumentNullException("coefficients"); }
227            if (lifetime == null) { throw new ArgumentNullException("lifetime"); }
228            Initialize();
229            this.matrices = new Matrices();
230            this.transformation = Matrix2x3.Identity;
231
232            this.state = new PhysicsState(state);
233            this.Shape = shape;
234            this.massInfo = massInfo;
235            this.coefficients = coefficients;
236            this.lifetime = lifetime;
237            this.linearDamping = 1;
238            this.angularDamping = 1;
239            this.isCollidable = true;
240            this.isEventable = true;
241            this.ApplyPosition();
242        }
243
244        private Body(Body copy)
245        {
246            Initialize();
247            this.ignoresCollisionResponce = copy.ignoresCollisionResponce;
248            this.shape = copy.shape;
249            this.massInfo = copy.massInfo;
250            this.coefficients = copy.coefficients;
251            this.collisionIgnorer = copy.collisionIgnorer;
252            this.matrices = copy.matrices.Duplicate();
253            this.state = copy.state.Duplicate();
254            this.lifetime = copy.lifetime.Duplicate();
255
256            this.transformation = copy.transformation;
257            this.linearDamping = copy.linearDamping;
258            this.angularDamping = copy.angularDamping;
259
260            this.ignoresCollisionResponce = copy.ignoresCollisionResponce;
261            this.ignoresGravity = copy.ignoresGravity;
262            this.ignoresPhysicsLogics = copy.ignoresPhysicsLogics;
263            this.isTransformed = copy.isTransformed;
264            this.isCollidable = copy.isCollidable;
265            this.isEventable = copy.isEventable;
266
267            this.tag = copy.tag;
268        }
269
270        private void Initialize()
271        {
272            this.id = -1;
273            this.joints = new List<Joint>();
274            this.proxies = new LinkedList<BodyProxy>();
275        }
276        #endregion
277        #region properties
278        public Dictionary<string, object> Tags
279        {
280            get { if (tags == null) { new Dictionary<string, object>(); } return tags; }
281        }
282
283        public bool IsFrozen
284        {
285            get { return isFrozen; }
286            internal set 
287            {
288                if (!value && 
289                    massInfo.MassInv == 0 && 
290                    massInfo.MomentOfInertiaInv == 0 && 
291                    state.Velocity == ALVector2D.Zero)
292                {
293                    return;
294                }
295               
296                isFrozen = value; }
297        }
298
299        /// <summary>
300        /// This is the Baunding rectangle It is calculated on the call to apply matrix.
301        /// </summary>
302        public BoundingRectangle Rectangle
303        {
304            get { return rectangle; }
305        }
306        /// <summary>
307        /// The Matrices that are tranfroming this bodies Shape.
308        /// </summary>
309        public Matrices Matrices
310        {
311            get { return matrices; }
312        }
313        /// <summary>
314        /// Gets and Sets The value represents how much Linear velocity is kept each time step.
315        /// This Dampens the Body's Linear velocity a little per time step. Valid values are zero exclusive to one inclusive. 
316        /// </summary>
317        public Scalar LinearDamping
318        {
319            get { return linearDamping; }
320            set
321            {
322                if (value <= 0 || value > 1) { 
323                    throw new ArgumentOutOfRangeException("value"); }
324                linearDamping = value;
325            }
326        }
327        /// <summary>
328        /// Gets and Sets The value represents how much Angular velocity is kept each time step.
329        /// This Dampens the Body's Angular velocity a little per time step. Valid values are zero exclusive to one inclusive. 
330        /// </summary>
331        public Scalar AngularDamping
332        {
333            get { return angularDamping; }
334            set
335            {
336                if (value <= 0 || value > 1) { throw new ArgumentOutOfRangeException("value"); }
337                angularDamping = value;
338            }
339        }
340        /// <summary>
341        /// These are bodies that are mirrors of this body.
342        /// It's useful for bodies that are being teleported.
343        /// </summary>
344        public IEnumerable<BodyProxy> Proxies
345        {
346            get
347            {
348                for (LinkedListNode<BodyProxy> node = proxies.First;
349                    node != null;
350                    node = node.Next)
351                {
352                    yield return node.Value;
353                }
354            }
355        }
356        /// <summary>
357        /// The number of proxies that this body has.
358        /// </summary>
359        public int ProxiesCount { get { return proxies.Count; } }
360        /// <summary>
361        /// Unique ID of a PhysicsEntity in the PhysicsEngine
362        /// Assigned on being Added.
363        /// </summary>
364        public int ID
365        {
366            get { return id; }
367            internal set { id = value; }
368        }
369        /// <summary>
370        /// Gets The PhysicsEngine the object is currently in. Null if it is in none.
371        /// </summary>
372        public PhysicsEngine Engine
373        {
374            get { return engine; }
375        }
376        /// <summary>
377        /// Gets The current State of the object IE Velocity
378        /// </summary>
379        public PhysicsState State
380        {
381            get { return state; }
382        }
383        /// <summary>
384        /// Gets and Sets the Shape of the Body.
385        /// If setting the shape to a shape another body has it will duplicate the shape.
386        /// </summary>
387        public IShape Shape
388        {
389            set
390            {
391                if (value == null) { throw new ArgumentNullException("value"); }
392                if (value != this.shape)
393                {
394                    this.shape = value;
395                    if (ShapeChanged != null) { ShapeChanged(this, EventArgs.Empty); }
396                }
397            }
398            get { return shape; }
399        }
400        /// <summary>
401        /// Gets The MassInfo of the body.
402        /// </summary>
403        public MassInfo Mass
404        {
405            get { return massInfo; }
406            set { massInfo = value; }
407        }
408        /// <summary>
409        /// Gets and Sets the Ignore object that decides what collisons to ignore.
410        /// </summary>
411        public Ignorer CollisionIgnorer
412        {
413            get { return collisionIgnorer; }
414            set { collisionIgnorer = value; }
415        }
416        /// <summary>
417        /// Gets and Sets the Ignore object that decides what collison events to ignore.
418        /// </summary>
419        public Ignorer EventIgnorer
420        {
421            get { return eventIgnorer; }
422            set { eventIgnorer = value; }
423        }
424        /// <summary>
425        /// Gets and Sets the Coefficients for the class.
426        /// </summary>
427        public Coefficients Coefficients
428        {
429            get { return coefficients; }
430            set
431            {
432                if (value == null) { throw new ArgumentNullException("value"); }
433                coefficients = value;
434            }
435        }
436        /// <summary>
437        /// Gets and Sets the LifeTime of the object. The object will be removed from the engine when it is Expired.
438        /// </summary>
439        public Lifespan Lifetime
440        {
441            get
442            {
443                return lifetime;
444            }
445            set
446            {
447                if (value == null) { throw new ArgumentNullException("value"); }
448                if (this.lifetime != value)
449                {
450                    lifetime = value;
451                    if (LifetimeChanged != null) { LifetimeChanged(this, EventArgs.Empty); }
452                }
453            }
454        }
455        /// <summary>
456        /// Gets and Sets a User defined object.
457        /// </summary>
458        public object Tag
459        {
460            get
461            {
462                return tag;
463            }
464            set
465            {
466                tag = value;
467            }
468        }
469        /// <summary>
470        /// Gets a Solver Defined object.
471        /// </summary>
472        public object SolverTag
473        {
474            get { return solverTag; }
475            internal set { solverTag = value; }
476        }
477        /// <summary>
478        /// Gets a Detector Defined object.
479        /// </summary>
480        public object DetectorTag
481        {
482            get { return detectorTag; }
483            internal set { detectorTag = value; }
484        }
485        /// <summary>
486        /// Gets the Joints attached to this body.
487        /// </summary>
488        public ReadOnlyCollection<Joint> Joints { get { return new ReadOnlyCollection<Joint>(joints); } }
489        /// <summary>
490        /// Gets and Sets if the Body will ignore Gravity.
491        /// </summary>
492        public bool IgnoresGravity
493        {
494            get { return ignoresGravity; }
495            set { ignoresGravity = value; }
496        }
497        /// <summary>
498        /// Gets and Sets if the Body will Ignore all Physics Logics
499        /// </summary>
500        public bool IgnoresPhysicsLogics
501        {
502            get { return ignoresPhysicsLogics; }
503            set { ignoresPhysicsLogics = value; }
504        }
505        /// <summary>
506        /// Gets and Sets if the Object will ignore the collison Responce but still generate the Collision event.
507        /// </summary>
508        public bool IgnoresCollisionResponse
509        {
510            get { return ignoresCollisionResponce; }
511            set { ignoresCollisionResponce = value; }
512        }
513        /// <summary>
514        /// Gets and Sets if this body's shape's Vertexes will be used in collision detection.
515        /// </summary>
516        public bool IgnoreVertexes
517        {
518            get { return ignoreVertexes; }
519            set { ignoreVertexes = value; }
520        }
521        /// <summary>
522        /// Gets if it has been added the the Engine's PendingQueue, but not yet added to the engine.
523        /// </summary>
524        public bool IsPending
525        {
526            get { return engine != null && !isAdded; }
527        }
528        /// <summary>
529        /// Gets if the object has been added to the engine.
530        /// </summary>
531        public bool IsAdded
532        {
533            get
534            {
535                return isAdded;
536            }
537        }
538        /// <summary>
539        /// gets and sets if the body will have any collision detection ran on it.
540        /// </summary>
541        public bool IsCollidable
542        {
543            get { return isCollidable; }
544            set { isCollidable = value; }
545        }
546        /// <summary>
547        /// Gets and Sets if other objects will have their collided
548        /// event raised when colliding with this body
549        /// </summary>
550        public bool IsEventable
551        {
552            get { return isEventable; }
553            set { isEventable = value; }
554        }
555        /// <summary>
556        /// Gets and Sets if the Body will trigger the Collided event at the broadphase level
557        /// </summary>
558        public bool IsBroadPhaseOnly
559        {
560            get { return isBroadPhaseOnly; }
561            set { isBroadPhaseOnly = value; }
562        }
563        /// <summary>
564        /// Gets the Total Kinetic Energy of the Body.
565        /// </summary>
566        public Scalar KineticEnergy
567        {
568            get
569            {
570                Scalar velocityMag;
571                Vector2D.GetMagnitude(ref state.Velocity.Linear,out velocityMag);
572                return
573                    .5f * (velocityMag * velocityMag * massInfo.Mass +
574                    state.Velocity.Angular * state.Velocity.Angular * massInfo.MomentOfInertia);
575            }
576        }
577        /// <summary>
578        /// Gets and Sets the Matrix2x3 that transforms the Shape belonging to the Body.
579        /// </summary>
580        public Matrix2x3 Transformation
581        {
582            get { return transformation; }
583            set
584            {
585                transformation = value;
586                isTransformed = value != Matrix2x3.Identity;
587                transformChanged = true;
588            }
589        }
590        public bool IsTransformed{ get { return isTransformed; } }
591        #endregion
592        #region methods
593        internal void AddJoint(Joint joint)
594        {
595            this.joints.Add(joint);
596            if (JointAdded != null) { JointAdded(this, new BodyJointEventArgs(joint)); }
597        }
598        internal void RemoveJoint(Joint joint)
599        {
600            if (this.joints.Remove(joint))
601            {
602                if (JointRemoved != null) { JointRemoved(this, new BodyJointEventArgs(joint)); }
603            }
604        }
605        /// <summary>
606        /// This applys the proxy.
607        /// This will cause all other bodies in the proxy list to have their velocity set
608        /// to this body’s.
609        /// With the appropriate transformations applied.
610        /// </summary>
611        public void ApplyProxy()
612        {
613            if (proxies.Count == 0) { return; }
614            for (LinkedListNode<BodyProxy> node = proxies.First;
615                node != null;
616                node = node.Next)
617            {
618                BodyProxy proxy = node.Value;
619                PhysicsState state = proxy.Body2.state;
620                state.Velocity.Angular = this.state.Velocity.Angular;
621                Vector2D.Transform(
622                    ref proxy.transformation,
623                    ref this.state.Velocity.Linear,
624                    out state.Velocity.Linear);
625            }
626        }
627        /// <summary>
628        /// This will remove this body from any proxy list it is a part of.
629        /// </summary>
630        private void RemoveFromProxy()
631        {
632            if (proxies.Count == 0) { return; }
633            for (LinkedListNode<BodyProxy> node = proxies.First;
634                node != null;
635                node = node.Next)
636            {
637                BodyProxy proxy = node.Value.invertedTwin;
638                proxy.node.List.Remove(proxy.node);
639            }
640            proxies.Clear();
641        }
642
643        public void UpdatePosition(TimeStep step)
644        {
645            state.Position.Linear.X += state.Velocity.Linear.X * step.Dt;
646            state.Position.Linear.Y += state.Velocity.Linear.Y * step.Dt;
647            state.Position.Angular += state.Velocity.Angular * step.Dt;
648        }
649        public void UpdatePosition(TimeStep step, ALVector2D extraVelocity)
650        {
651            UpdatePosition(step, ref extraVelocity);
652        }
653        [CLSCompliant(false)]
654        public void UpdatePosition(TimeStep step, ref ALVector2D extraVelocity)
655        {
656            state.Position.Linear.X += (state.Velocity.Linear.X + extraVelocity.Linear.X) * step.Dt;
657            state.Position.Linear.Y += (state.Velocity.Linear.Y + extraVelocity.Linear.Y) * step.Dt;
658            state.Position.Angular += (state.Velocity.Angular + extraVelocity.Angular) * step.Dt;
659        }
660        public void UpdateVelocity(TimeStep step)
661        {
662            if (!isFrozen)
663            {
664                if (massInfo.MassInv != 0)
665                {
666                    UpdateAcceleration(ref state.Acceleration, ref state.ForceAccumulator);
667                }
668                UpdateVelocity(ref state.Velocity, ref state.Acceleration, step.Dt);
669            }
670            if (proxies.Count != 0)
671            {
672                ApplyProxy();
673            }
674        }
675        void UpdateAcceleration(ref ALVector2D acceleration, ref ALVector2D forceAccumulator)
676        {
677            Scalar proxDamping = 1.0f / (proxies.Count + 1);
678            acceleration.Linear.X = acceleration.Linear.X * proxDamping + forceAccumulator.Linear.X * massInfo.MassInv;
679            acceleration.Linear.Y = acceleration.Linear.Y * proxDamping + forceAccumulator.Linear.Y * massInfo.MassInv;
680            acceleration.Angular += forceAccumulator.Angular * massInfo.MomentOfInertiaInv;
681        }
682        void UpdateVelocity(ref ALVector2D velocity, ref ALVector2D acceleration, Scalar dt)
683        {
684            velocity.Linear.X = velocity.Linear.X * linearDamping + acceleration.Linear.X * dt;
685            velocity.Linear.Y = velocity.Linear.Y * linearDamping + acceleration.Linear.Y * dt;
686            velocity.Angular = velocity.Angular * angularDamping + acceleration.Angular * dt;
687        }
688
689        internal void UpdateTime(TimeStep step)
690        {
691            lifetime.Update(step);
692            if (collisionIgnorer != null) { collisionIgnorer.UpdateTime(step); }
693            if (Updated != null) { Updated(this, new UpdatedEventArgs(step)); }
694        }
695        /// <summary>
696        /// Updates all the values caluclated from the State.Position.
697        /// Re-calculates the Matrices property the re-calculates the Rectangle property
698        /// from that.
699        /// </summary>
700        public void ApplyPosition()
701        {
702            MathHelper.ClampAngle(ref state.Position.Angular);
703            Matrix2x3 matrix;
704            ALVector2D.ToMatrix2x3(ref state.Position, out matrix);
705            Matrix2x3.Multiply(ref matrix, ref transformation, out matrix);
706            matrices.SetToWorld(ref matrix);
707            shape.CalcBoundingRectangle(ref matrix, out rectangle);
708            if (engine == null || !engine.inUpdate)
709            {
710                OnPositionChanged();
711            }
712        }
713
714        /// <summary>
715        /// Sets Acceleration and ForceAccumulator to Zero.
716        /// </summary>
717        public void ClearForces()
718        {
719            this.state.Acceleration = ALVector2D.Zero;
720            this.state.ForceAccumulator = ALVector2D.Zero;
721        }
722
723        /// <summary>
724        /// Applys a Force
725        /// </summary>
726        /// <param name="force">The direction and magnitude of the force</param>
727        public void ApplyForce(Vector2D force)
728        {
729            Vector2D.Add(ref state.ForceAccumulator.Linear, ref force, out state.ForceAccumulator.Linear);
730        }
731        /// <summary>
732        /// Applys a Force
733        /// </summary>
734        /// <param name="force">The direction and magnitude of the force</param>
735        [CLSCompliant(false)]
736        public void ApplyForce(ref Vector2D force)
737        {
738            Vector2D.Add(ref state.ForceAccumulator.Linear, ref force, out state.ForceAccumulator.Linear);
739        }
740        /// <summary>
741        /// Applys a Force
742        /// </summary>
743        /// <param name="force">The direction and magnitude of the force</param>
744        /// <param name="position">The Location where the force will be applied (Offset: Body Rotation: World) </param>
745        public void ApplyForce(Vector2D force, Vector2D position)
746        {
747            Scalar torque;
748            Vector2D.Add(ref state.ForceAccumulator.Linear, ref force, out state.ForceAccumulator.Linear);
749            Vector2D.ZCross(ref position, ref force, out torque);
750            state.ForceAccumulator.Angular += torque;
751        }
752        /// <summary>
753        /// Applys a Force
754        /// </summary>
755        /// <param name="force">The direction and magnitude of the force</param>
756        /// <param name="position">The Location where the force will be applied (Offset: Body Rotation: World) </param>
757        [CLSCompliant(false)]
758        public void ApplyForce(ref Vector2D force, ref Vector2D position)
759        {
760            Scalar torque;
761            Vector2D.Add(ref state.ForceAccumulator.Linear, ref force, out state.ForceAccumulator.Linear);
762            Vector2D.ZCross(ref position, ref force, out torque);
763            state.ForceAccumulator.Angular += torque;
764        }
765        /// <summary>
766        /// Applys Torque
767        /// </summary>
768        /// <param name="torque">The direction and magnitude of the torque</param>
769        public void ApplyTorque(Scalar torque)
770        {
771            state.ForceAccumulator.Angular += torque;
772        }
773
774        /// <summary>
775        /// Applys Impulse
776        /// </summary>
777        /// <param name="impulse">The direction and magnitude of the impulse</param>
778        public void ApplyImpulse(Vector2D impulse)
779        {
780            ApplyImpulse(ref impulse);
781        }
782        /// <summary>
783        /// Applys Impulse
784        /// </summary>
785        /// <param name="impulse">The direction and magnitude of the impulse.</param>
786        [CLSCompliant(false)]
787        public void ApplyImpulse(ref Vector2D impulse)
788        {
789            Scalar massInv = massInfo.MassInv;
790            state.Velocity.Linear.X += impulse.X * massInv;
791            state.Velocity.Linear.Y += impulse.Y * massInv;
792        }
793        /// <summary>
794        /// Applys Impulse
795        /// </summary>
796        /// <param name="impulse">The direction and magnitude of the impulse.</param>
797        /// <param name="position">The Location where the impulse will be applied (Offset: Body Rotation: World)</param>
798        public void ApplyImpulse(Vector2D impulse, Vector2D position)
799        {
800            ApplyImpulse(ref impulse, ref position);
801        }
802        /// <summary>
803        /// Applys Impulse
804        /// </summary>
805        /// <param name="impulse">The direction and magnitude of the impulse.</param>
806        /// <param name="position">The Location where the impulse will be applied (Offset: Body Rotation: World)</param>
807        [CLSCompliant(false)]
808        public void ApplyImpulse(ref Vector2D impulse, ref Vector2D position)
809        {
810            Scalar massInv = massInfo.MassInv;
811            Scalar IInv = massInfo.MomentOfInertiaInv;
812            PhysicsHelper.AddImpulse(ref state.Velocity, ref impulse, ref position, ref massInv, ref IInv);
813        }
814
815
816        public Body Duplicate()
817        {
818            return new Body(this);
819        }
820        public object Clone()
821        {
822            return Duplicate();
823        }
824
825        internal void OnCollision(TimeStep step, Body other, IContact contact)
826        {
827            if (Collided != null &&
828                other.IsEventable &&
829                (eventIgnorer == null ||
830                Ignorer.CanCollide(this,other, eventIgnorer,other.eventIgnorer)))
831            {
832                Collided(this, new CollisionEventArgs(step, other, contact));
833            }
834        }
835        internal void OnCollision(TimeStep step, Body other, object customIntersectionInfo)
836        {
837            if (Collided != null &&
838                other.IsEventable &&
839                (eventIgnorer == null ||
840                Ignorer.CanCollide(this, other, eventIgnorer, other.eventIgnorer)))
841            {
842                Collided(this, new CollisionEventArgs(step, other, customIntersectionInfo));
843            }
844        }
845
846        internal void OnColliding( TimeStep step, Body other, IContact contact )
847        {
848            if ( Colliding != null &&
849                other.IsEventable &&
850                ( eventIgnorer == null ||
851                Ignorer.CanCollide( this, other, eventIgnorer, other.eventIgnorer ) ) )
852            {
853                Colliding( this, new CollisionEventArgs( step, other, contact ) );
854            }
855        }
856
857        internal void OnPositionChanged()
858        {
859            if (PositionChanged != null &&
860                (transformChanged ||
861                !ALVector2D.Equals(ref lastPosition, ref state.Position)))
862            {
863                PositionChanged(this, EventArgs.Empty);
864                lastPosition = state.Position;
865                transformChanged = false;
866            }
867        }
868        internal void OnPending(PhysicsEngine engine)
869        {
870            this.isChecked = false;
871            this.engine = engine;
872            if (Pending != null) { Pending(this, EventArgs.Empty); }
873        }
874        internal void OnAdded()
875        {
876            this.isAdded = true;
877            if (Added != null) { Added(this, EventArgs.Empty); }
878        }
879        internal void OnRemoved()
880        {
881            bool wasPending = this.IsPending;
882            PhysicsEngine engine = this.engine;
883            this.engine = null;
884            this.id = -1;
885            this.isAdded = false;
886            this.RemoveFromProxy();
887            if (Removed != null) { Removed(this, new RemovedEventArgs(engine, wasPending)); }
888        }
889        #endregion
890    }
891}
Note: See TracBrowser for help on using the repository browser.