source: 2013/30/MiskaK/MW2(My Warfare 2)/Paranneltu Jypeli/Physics2DDotNet/PhysicsLogics/GlobalFluidLogic.cs @ 4507

Revision 4507, 6.4 KB checked in by anlakane, 6 years ago (diff)

Talletus.

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#if UseDouble
26using Scalar = System.Double;
27#else
28using Scalar = System.Single;
29#endif
30using System;
31using System.Collections.Generic;
32
33using AdvanceMath;
34using AdvanceMath.Geometry2D;
35using Physics2DDotNet.Shapes;
36
37namespace Physics2DDotNet.PhysicsLogics
38{
39    /// <summary>
40    /// Applys drag and buoyancy to all items in the engine.
41    /// </summary>
42    public sealed class GlobalFluidLogic : PhysicsLogic
43    {
44        sealed class Wrapper : IDisposable
45        {
46            public Body body;
47            public IGlobalFluidAffectable affectable;
48            public Wrapper(Body body)
49            {
50                this.body = body;
51                this.body.ShapeChanged += OnShapeChanged;
52                this.Calculate();
53            }
54            void Calculate()
55            {
56                affectable = body.Shape as IGlobalFluidAffectable;
57            }
58            void OnShapeChanged(object sender, EventArgs e)
59            {
60                Calculate();
61            }
62            public void Dispose()
63            {
64                this.body.ShapeChanged -= OnShapeChanged;
65            }
66        }
67        static bool IsRemoved(Wrapper wrapper)
68        {
69            if (!wrapper.body.IsAdded)
70            {
71                wrapper.Dispose();
72                return true;
73            }
74            return false;
75        }
76
77        Scalar dragCoefficient;
78        Scalar density;
79        Vector2D fluidVelocity;
80
81
82        List<Wrapper> items;
83
84        public GlobalFluidLogic(
85            Scalar dragCoefficient,
86            Scalar density,
87            Vector2D fluidVelocity,
88            Lifespan lifetime)
89            : base(lifetime)
90        {
91            this.dragCoefficient = dragCoefficient;
92            this.density = density;
93            this.fluidVelocity = fluidVelocity;
94            this.items = new List<Wrapper>();
95            this.Order = 1;
96        }
97
98        public Scalar DragCoefficient
99        {
100            get { return dragCoefficient; }
101            set { dragCoefficient = value; }
102        }
103        public Scalar Density
104        {
105            get { return density; }
106            set { density = value; }
107        }
108        public Vector2D FluidVelocity
109        {
110            get { return fluidVelocity; }
111            set { fluidVelocity = value; }
112        }
113
114        protected internal override void RunLogic(TimeStep step)
115        {
116            for (int index = 0; index < items.Count; ++index)
117            {
118                Wrapper wrapper = items[index];
119                Body body = wrapper.body;
120                if (wrapper.affectable == null ||
121                    body.IgnoresPhysicsLogics ||
122                   Scalar.IsPositiveInfinity(body.Mass.Mass))
123                {
124                    continue;
125                }
126
127                Vector2D centroid = wrapper.body.Matrices.ToWorldNormal * wrapper.affectable.Centroid;
128                Vector2D buoyancyForce = body.State.Acceleration.Linear * wrapper.affectable.Area * -Density;
129                wrapper.body.ApplyForce(buoyancyForce, centroid);
130
131                Vector2D relativeVelocity = body.State.Velocity.Linear - FluidVelocity;
132                Vector2D velocityDirection = relativeVelocity.Normalized;
133                if (velocityDirection == Vector2D.Zero) { continue; }
134                Vector2D dragDirection = body.Matrices.ToBodyNormal * velocityDirection.LeftHandNormal;
135                DragInfo dragInfo = wrapper.affectable.GetFluidInfo(dragDirection);
136                if (dragInfo.DragArea < .01f) { continue; }
137                Scalar speedSq = relativeVelocity.MagnitudeSq;
138                Scalar dragForceMag = -.5f * Density * speedSq * dragInfo.DragArea * DragCoefficient;
139                Scalar maxDrag = -MathHelper.Sqrt(speedSq) * body.Mass.Mass * step.DtInv;
140                if (dragForceMag < maxDrag)
141                {
142                    dragForceMag = maxDrag;
143                }
144
145                Vector2D dragForce = dragForceMag * velocityDirection;
146                wrapper.body.ApplyForce(dragForce, body.Matrices.ToWorldNormal * dragInfo.DragCenter);
147
148                wrapper.body.ApplyTorque(
149                   -body.Mass.MomentOfInertia *
150                   (body.Coefficients.DynamicFriction + Density + DragCoefficient) *
151                   body.State.Velocity.Angular);
152            }
153        }
154        protected internal override void RemoveExpiredBodies()
155        {
156            items.RemoveAll(IsRemoved);
157        }
158        protected internal override void AddBodyRange(List<Body> collection)
159        {
160            int newCapacity = collection.Count + items.Count;
161            if (items.Capacity < newCapacity)
162            {
163                items.Capacity = newCapacity;
164            }
165            for (int index = 0; index < collection.Count; ++index)
166            {
167                items.Add(new Wrapper(collection[index]));
168            }
169        }
170        protected internal override void Clear()
171        {
172            for(int index = 0; index < items.Count;++index)
173            {
174                items[index].Dispose();
175            }
176            items.Clear();
177        }
178    }
179}
Note: See TracBrowser for help on using the repository browser.