예제 #1
0
        public static HydroTimeSeries GetMissingValuesHydro(ITimeSeries ts, DateTime start, DateTime end, TimeStep step)
        {
            HydroTimeSeries missingTs = new HydroTimeSeries(start, end);
            List<int> breakIx = GetDataBreaks(ts);

            //TODO missing points before series start
            foreach (int begIndex in breakIx)
            {
                if (begIndex < ts.Count - 1)
                {
                    DateTime begDate = DateTime.FromOADate(ts[begIndex].X);
                    DateTime endDate = DateTime.FromOADate(ts[begIndex + 1].X);
                    if (step == TimeStep.Day)
                    {
                        int nd = (int)endDate.Subtract(begDate).TotalDays;
                        for (int i = 0; i < nd; i++)
                        {
                            DateTime newTime = begDate.AddDays(i);
                            missingTs.AddUnknownValue(newTime);
                        }
                    }
                    else
                    {
                        int nh = (int)endDate.Subtract(begDate).TotalHours;
                        for (int i = 0; i < nh; i++)
                        {
                            DateTime newTime = begDate.AddHours(i);
                            missingTs.AddUnknownValue(newTime);
                        }
                    }
                }
            }
            return missingTs;
        }
예제 #2
0
        /// <summary>
        /// Creates a new regular-spaced list and sets all values to initialValue
        /// </summary>
        /// <param name="period"></param>
        /// <param name="step"></param>
        /// <param name="initialValue"></param>
        /// <returns></returns>
        public TimeValueList(TimeInterval period, TimeStep step, double initialValue)
        {
            _timeStepFactor = (step == TimeStep.Hour) ? 24 : 1;
            _start = period.Start.ToOADate();

            switch(TimeStep)
            {
                case TimeStep.Hour:
                    _data = new double[(int) period.Length.TotalHours];
                    break;
                case TimeStep.Day:
                    _data = new double[(int) period.Length.TotalDays];
                    break;
                default:
                    throw new ArgumentException("'step' parameter must be 'Hour' or 'Day'");
            }

            if (initialValue != 0.0)
            {
                // initialize array values...
                for (int i = 0; i < _data.Length; ++i)
                {
                    _data[i] = initialValue;
                }
            }
        }
예제 #3
0
 /// <summary>
 /// Fills the data gaps inside the time-series by setting them to 'no data' vals
 /// </summary>
 /// <param name="ts"></param>
 public static ITimeSeries FillDataGaps(ITimeSeries ts, TimeStep step)
 {
     ITimeSeries myTs = MakeRegularTimeSeries(ts.Start, ts.End, step);
     if (step == TimeStep.Day)
     {
         double tStart = myTs[0].X;
         for (int i = 0; i < ts.Count - 1; i++)
         {
             double index = (ts[i].X - tStart);
             int ix = (int)index;
             myTs[ix].Y = ts[i].Y;
         }
     }
     else
     {
         double tStart = myTs[0].X * 24;
         for (int i = 0; i < ts.Count - 1; i++)
         {
             double index = (ts[i].X * 24 - tStart);
             int ix = (int)index;
             myTs[ix].Y = ts[i].Y;
         }
     }
     return myTs;
 }
예제 #4
0
 public ServiceRate(string serviceName,TimeStep timeStep,DateTime stamp,int rate)
 {
     this.ServiceName = serviceName;
     this.RateTimeStep = timeStep;
     this.TimeStamp = stamp;
     this.Rate = rate;
 }
 public override void Step(TimeStep step)
 {
     if (_bodyList == null) return;
     if (useWorldGravity)
     {
         gravity = _world.Gravity;
     }
     for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
     {
         Body body = i.body;
         if (body.IsSleeping())
         {
             //Buoyancy force is just a function of position,
             //so unlike most forces, it is safe to ignore sleeping bodes
             continue;
         }
         Vec2 areac = new Vec2(0, 0);
         Vec2 massc = new Vec2(0, 0);
         float area = 0;
         float mass = 0;
         for (Shape shape = body.GetShapeList(); shape != null; shape = shape.GetNext())
         {
             Vec2 sc;
             float sarea = shape.ComputeSubmergedArea(normal, offset, body.GetXForm(), out sc);
             area += sarea;
             areac.X += sarea * sc.X;
             areac.Y += sarea * sc.Y;
             float shapeDensity = 0;
             if (useDensity)
             {
                 //TODO: Expose density publicly
                 shapeDensity = shape.Density;
             }
             else
             {
                 shapeDensity = 1;
             }
             mass += sarea * shapeDensity;
             massc.X += sarea * sc.X * shapeDensity;
             massc.Y += sarea * sc.Y * shapeDensity;
         }
         areac.X /= area;
         areac.Y /= area;
         massc.X /= mass;
         massc.Y /= mass;
         if (area < Box2DX.Common.Settings.FLT_EPSILON)
             continue;
         //Buoyancy
         Vec2 buoyancyForce = -density * area * gravity;
         body.ApplyForce(buoyancyForce, massc);
         //Linear drag
         Vec2 dragForce = body.GetLinearVelocityFromWorldPoint(areac) - velocity;
         dragForce *= -linearDrag * area;
         body.ApplyForce(dragForce, areac);
         //Angular drag
         //TODO: Something that makes more physical sense?
         body.ApplyTorque(-body.GetInertia() / body.GetMass() * area * body.GetAngularVelocity() * angularDrag);
     }
 }
예제 #6
0
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            _jointError = BodyA.Sweep.A - TargetAngle;

            _bias = -BiasFactor * step.inv_dt * _jointError;

            _massFactor = (1 - Softness) / (BodyA.InvI);
        }
 public override void Step(TimeStep step)
 {
     for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
     {
         Body body = i.body;
         if (body.IsSleeping())
             continue;
         body.SetLinearVelocity(body.GetLinearVelocity() + step.Dt * A);
     }
 }
예제 #8
0
 public override void Step(TimeStep step)
 {
     //B2_NOT_USED(step);
     for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
     {
         Body body = i.body;
         if (body.IsSleeping())
             continue;
         body.ApplyForce(F, body.GetWorldCenter());
     }
 }
예제 #9
0
 public static void ReadBinaryFile(string fileName, DateTime startTime, DateTime endTime, TimeStep timeStep, 
     bool includeNA, IObservationList observations)
 {
     if (timeStep == TimeStep.Day)
     {
         ReadBinaryFileDaily(fileName, startTime, endTime, includeNA, observations);
     }
     else
     {
         ReadBinaryFileHourly(fileName, startTime, endTime, includeNA, observations);
     }
 }
예제 #10
0
        protected internal override void RunLogic(TimeStep step)
        {
            foreach (Body e in this.Bodies)
            {
                if (e.IgnoresGravity ||
                    e.IgnoresPhysicsLogics)
                {
                    continue;
                }
                Vector2D.Add(ref e.State.Acceleration.Linear, ref gravity, out e.State.Acceleration.Linear);

            }
        }
예제 #11
0
        protected internal override void RunLogic(TimeStep step)
        {
            foreach (Body e in this.Bodies)
            {
                if (e.IgnoresGravity ||
                    e.IgnoresPhysicsLogics)
                {
                    continue;
                }
                Vector2D vect;
                Vector2D.Subtract(ref location, ref e.State.Position.Linear, out vect);
                Vector2D.Normalize(ref vect, out vect);
                Vector2D.Multiply(ref vect, ref gravity, out vect);
                Vector2D.Add(ref e.State.Acceleration.Linear, ref vect, out e.State.Acceleration.Linear);

            }
        }
예제 #12
0
        public override void Step(TimeStep step)
        {
            float timestep = step.Dt;
            if (timestep <= Settings.FLT_EPSILON)
                return;
            if (timestep > MaxTimestep && MaxTimestep > 0)
                timestep = MaxTimestep;
            for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
            {
                Body body = i.body;
                if (body.IsSleeping())
                    continue;

                Vec2 damping = body.GetWorldVector(Math.Mul(T, body.GetLocalVector(body.GetLinearVelocity())));
                body.SetLinearVelocity(body.GetLinearVelocity() + timestep*damping);
            }
        }
 public override void Detect(TimeStep step)
 {
     for (int index1 = 0; index1 < this.Bodies.Count; index1++)
     {
         Body body1 = this.Bodies[index1];
         for (int index2 = index1 + 1; index2 < this.Bodies.Count; index2++)
         {
             Body body2 = this.Bodies[index2];
             if ((body1.Mass.MassInv != 0 || body2.Mass.MassInv != 0) &&
                     Body.CanCollide(body1, body2) &&
                     body1.Rectangle.Intersects(body2.Rectangle))
             {
                 OnCollision(step, body1, body2);
             }
         }
     }
 }
예제 #14
0
 protected internal override void RunLogic(TimeStep step)
 {
     foreach (Body e in Bodies)
     {
         if (e == body ||
             e.IgnoresGravity ||
             e.IgnoresPhysicsLogics)
         {
             continue;
         }
         Scalar magnitude;
         Vector2D gravity;
         Vector2D.Subtract(ref body.State.Position.Linear, ref e.State.Position.Linear, out gravity);
         Vector2D.Normalize(ref gravity, out magnitude, out gravity);
         magnitude = (body.Mass.AccelerationDueToGravity /
                 (magnitude * magnitude * metersPerDistanceUnit * metersPerDistanceUnit));
         Vector2D.Multiply(ref gravity, ref magnitude, out gravity);
         Vector2D.Add(ref e.State.Acceleration.Linear, ref gravity, out e.State.Acceleration.Linear);
     }
 }
예제 #15
0
        /// <summary>
        /// Retrieves a time series of discharge observations from the database
        /// (only measured, non-zero values are retrieved)
        /// </summary>
        /// <param name="stationId"></param>
        /// <param name="variableId"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="scaleFactor"></param>
        /// <param name="observations"></param>
        public static void LoadObservationsDischarge(int stationId, int variableId, DateTime start, DateTime end,
            TimeStep step, IObservationList observations)
        {
            //observations.Clear();
            SqlCommand cmd = DataUtils.CreateCommand();
            cmd.CommandText = "plaveninycz.new_query_observations";

            cmd.CommandType = CommandType.StoredProcedure;
            SetCmdParameters(cmd, stationId, variableId, start, end, step);
            SqlDataReader rdr;
            double val;
            DateTime t;

            try
            {
                cmd.Connection.Open();
                rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                while (rdr.Read())
                {
                    if (!rdr.IsDBNull(1))
                    {
                        t = Convert.ToDateTime(rdr[0]);
                        val = Convert.ToDouble(rdr[1]);
                        //val = Math.Pow(2.0, (val / 1000.0));
                        if (val > 0)
                        {
                            observations.AddObservation(t, val);
                        }
                        else
                        {
                            observations.AddUnknownValue(t);
                        }
                    }
                }
                rdr.Close();
            }
            finally
            {
                cmd.Connection.Close();
            }
        }
        public override void Step(TimeStep step)
        {
            //B2_NOT_USED(step);
            if (InvSqr)
            {
                for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
                {
                    Body body1 = i.body;
                    for (ControllerEdge j = _bodyList; j != i; j = j.nextBody)
                    {
                        Body body2 = j.body;
                        Vector2 d = body2.GetWorldCenter() - body1.GetWorldCenter();
                        float r2 = d.sqrMagnitude;
                        if (r2 < Settings.FLT_EPSILON)
                            continue;

                        Vector2 f = G / r2 / Math.Sqrt(r2) * body1.GetMass() * body2.GetMass() * d;
                        body1.ApplyForce(f, body1.GetWorldCenter());
                        body2.ApplyForce(-1.0f * f, body2.GetWorldCenter());
                    }
                }
            }
            else
            {
                for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
                {
                    Body body1 = i.body;
                    for (ControllerEdge j = _bodyList; j != i; j = j.nextBody)
                    {
                        Body body2 = j.body;
                        Vector2 d = body2.GetWorldCenter() - body1.GetWorldCenter();
                        float r2 = d.sqrMagnitude;
                        if (r2 < Settings.FLT_EPSILON)
                            continue;
                        Vector2 f = G / r2 * body1.GetMass() * body2.GetMass() * d;
                        body1.ApplyForce(f, body1.GetWorldCenter());
                        body2.ApplyForce(-1.0f * f, body2.GetWorldCenter());
                    }
                }
            }
        }
예제 #17
0
 protected internal override void RunLogic(TimeStep step)
 {
     foreach (Body e in Bodies)
     {
         if (e.IgnoresPhysicsLogics) { continue; }
         Scalar velocity;
         Vector2D.GetMagnitude(ref e.State.Velocity.Linear, out velocity);
         if (velocity > maxLinearVelocity)
         {
             velocity = maxLinearVelocity / velocity;
             Vector2D.Multiply(ref e.State.Velocity.Linear, ref velocity, out e.State.Velocity.Linear);
         }
         if (e.State.Velocity.Angular > maxAngularVelocity)
         {
             e.State.Velocity.Angular = maxAngularVelocity;
         }
         else if (e.State.Velocity.Angular < -maxAngularVelocity)
         {
             e.State.Velocity.Angular = -maxAngularVelocity;
         }
     }
 }
        private void Run([NotNull] CalcLoadTypeDto dstLoadType,
                         [NotNull][ItemNotNull] List <OnlineEnergyFileRow> energyFileRows,
                         [NotNull] IFileFactoryAndTracker fft,
                         [NotNull] EnergyFileColumns efc,
                         [NotNull] Dictionary <CalcLoadTypeDto, Dictionary <StrGuid, double> > loadTypeTodeviceIDToAverageLookup,
                         [ItemNotNull][NotNull] List <DeviceTaggingSetInformation> deviceTaggingSets,
                         [NotNull] Dictionary <string, string> deviceNameToCategory,
                         [NotNull] Dictionary <string, double> deviceEnergyDict,
                         [NotNull] HouseholdKey key)
        {
            if (!efc.ColumnEntriesByColumn.ContainsKey(dstLoadType))
            {
                //for this load type for this house there are no column, so nothing to do
                return;
            }
            var calcParameters = Repository.CalcParameters;
            var rowlength      = energyFileRows[0].EnergyEntries.Count;
            var ts             = new TimeStep(0, 0, true);
            var sum            = new OnlineEnergyFileRow(ts, new List <double>(new double[rowlength]), dstLoadType);
            var curDate        = calcParameters.OfficialStartTime;
            var sumsPerMonth   = MakeSumsPerMonth(dstLoadType, energyFileRows, curDate, sum, rowlength);

            /*
             * if (Config.IsInUnitTesting && Config.ExtraUnitTestChecking) {
             *  if (!double.IsNaN(previousTotal) && Math.Abs(sum.SumFresh - previousTotal) > 0.000001) {
             *      throw new LPGException("Unknown bug while generating the device totals. Sums don't match.");
             *  }
             * }*/
            var sumPerMonthPerDeviceID = MakeSumPerMonthPerDeviceID(dstLoadType, efc, sumsPerMonth, out var columns);

            var sumsPerDeviceID  = new Dictionary <StrGuid, double>();
            var deviceNamesPerID = new Dictionary <StrGuid, string>();
            var sumPerDeviceName = new Dictionary <string, double>();

            foreach (var pair in columns)
            {
                var ce = pair.Value;
                if (!sumsPerDeviceID.ContainsKey(ce.DeviceGuid))
                {
                    sumsPerDeviceID.Add(ce.DeviceGuid, 0);
                    deviceNamesPerID.Add(ce.DeviceGuid, ce.Name);
                }

                if (!sumPerDeviceName.ContainsKey(ce.Name))
                {
                    sumPerDeviceName.Add(ce.Name, 0);
                }

                sumPerDeviceName[ce.Name]      += sum.EnergyEntries[pair.Key];
                sumsPerDeviceID[ce.DeviceGuid] += sum.EnergyEntries[pair.Key];
            }

            MakeTotalsPerDeviceTaggingSet(fft, dstLoadType, deviceTaggingSets, deviceEnergyDict, key);
            var builder = new StringBuilder();

            foreach (var calcDeviceTaggingSet in deviceTaggingSets)
            {
                if (calcDeviceTaggingSet.LoadTypesForThisSet.Any(x => x.Name == dstLoadType.Name))
                {
                    builder.Append(calcDeviceTaggingSet.Name).Append(calcParameters.CSVCharacter);
                }
            }

            var taggingsetHeader = builder.ToString();
            var devicesums       = fft.MakeFile <StreamWriter>("DeviceSums." + dstLoadType.Name + "." + key.Key + ".csv",
                                                               "Summed up " + dstLoadType.Name + " use per device and comparison with statistical values",
                                                               true,
                                                               ResultFileID.DeviceSums,
                                                               key,
                                                               TargetDirectory.Reports,
                                                               calcParameters.InternalStepsize, CalcOption.TotalsPerDevice,
                                                               dstLoadType.ConvertToLoadTypeInformation());
            var calcDuration  = calcParameters.OfficialEndTime - calcParameters.OfficialStartTime;
            var amountofYears = calcDuration.TotalDays / 365.0;
            var sb            = new StringBuilder();

            sb.Append("Device name");
            sb.Append(calcParameters.CSVCharacter);
            sb.Append("Usage sum in this simulation [").Append(dstLoadType.UnitOfSum).Append("]");
            sb.Append(calcParameters.CSVCharacter);
            sb.Append("Usage sum in this simulation linear extrapolated to 1 year [").Append(dstLoadType.UnitOfSum).Append("]");
            sb.Append(calcParameters.CSVCharacter);

            sb.Append("Comparison Value from the device entry [").Append(dstLoadType.UnitOfSum).Append("]");
            sb.Append(calcParameters.CSVCharacter);
            sb.Append("Percentage of the comparison value [1 = 100%]");
            sb.Append(calcParameters.CSVCharacter);
            sb.Append("Device Category");
            sb.Append(calcParameters.CSVCharacter);
            sb.Append(taggingsetHeader);

            devicesums.WriteLine(sb);
            double devicesum           = 0;
            double extrapolatedSum     = 0;
            double comparsionvaluessum = 0;

            foreach (var keyValuePair in sumsPerDeviceID)
            {
                var s = string.Empty;
                s += deviceNamesPerID[keyValuePair.Key];

                s         += calcParameters.CSVCharacter;
                s         += keyValuePair.Value * dstLoadType.ConversionFactor;
                devicesum += keyValuePair.Value;

                //deviceSums.AddDeviceSum(deviceNamesPerID[keyValuePair.Key],devicesum,dstLoadType);

                s += calcParameters.CSVCharacter;
                var extrapolatedValue = keyValuePair.Value * dstLoadType.ConversionFactor / amountofYears;
                s += extrapolatedValue;
                extrapolatedSum += keyValuePair.Value / amountofYears;

                s += calcParameters.CSVCharacter;
                double defaultvalue = 0;
                if (loadTypeTodeviceIDToAverageLookup.ContainsKey(dstLoadType))
                {
                    if (loadTypeTodeviceIDToAverageLookup[dstLoadType].ContainsKey(keyValuePair.Key))
                    {
                        defaultvalue = loadTypeTodeviceIDToAverageLookup[dstLoadType][keyValuePair.Key];
                    }
                }

                s += defaultvalue;
                comparsionvaluessum += defaultvalue;
                s += calcParameters.CSVCharacter;
                if (Math.Abs(defaultvalue) > Constants.Ebsilon)
                {
                    s += extrapolatedValue / defaultvalue;
                }
                else
                {
                    s += 0;
                }

                s += calcParameters.CSVCharacter;
                var devicename     = deviceNamesPerID[keyValuePair.Key];
                var deviceCategory = "(no category)";
                if (deviceNameToCategory.ContainsKey(devicename))
                {
                    deviceCategory = deviceNameToCategory[devicename];
                }

                s += deviceCategory;
                s += calcParameters.CSVCharacter;
                var tags = string.Empty;
                foreach (var calcDeviceTaggingSet in deviceTaggingSets)
                {
                    if (calcDeviceTaggingSet.LoadTypesForThisSet.Any(x => x.Name == dstLoadType.Name))
                    {
                        var deviceName = deviceNamesPerID[keyValuePair.Key];
                        if (calcDeviceTaggingSet.TagByDeviceName.ContainsKey(deviceName))
                        {
                            tags += calcDeviceTaggingSet.TagByDeviceName[deviceName] + calcParameters.CSVCharacter;
                        }
                        else
                        {
                            tags += Constants.UnknownTag + calcParameters.CSVCharacter;
                        }
                    }
                }

                devicesums.WriteLine(s + tags);
            }

            var sumstr = "Sums";

            sumstr += calcParameters.CSVCharacter;
            sumstr += devicesum * dstLoadType.ConversionFactor;
            sumstr += calcParameters.CSVCharacter;
            sumstr += extrapolatedSum * dstLoadType.ConversionFactor;
            sumstr += calcParameters.CSVCharacter;
            sumstr += comparsionvaluessum;
            devicesums.WriteLine(sumstr);
            devicesums.Flush();
            WriteMonthlyDeviceSums(fft, dstLoadType, sumPerMonthPerDeviceID, deviceNamesPerID, key);
        }
예제 #19
0
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            float K = 0.0f;

            _J.SetZero();

            if (_revolute1 != null || _fixedRevolute1 != null)
            {
                _J.AngularA = -1.0f;
                K          += b1.InvI;
            }
            else
            {
                Vector2 ug;
                if (_prismatic1 != null)
                {
                    ug = _prismatic1.LocalXAxis1; // MathUtils.Multiply(ref xfg1.R, _prismatic1.LocalXAxis1);
                }
                else
                {
                    ug = _fixedPrismatic1.LocalXAxis1; // MathUtils.Multiply(ref xfg1.R, _prismatic1.LocalXAxis1);
                }
                Transform xf1 /*, xfg1*/;
                b1.GetTransform(out xf1);
                //g1.GetTransform(out xfg1);

                Vector2 r    = MathUtils.Multiply(ref xf1.R, LocalAnchor1 - b1.LocalCenter);
                float   crug = MathUtils.Cross(r, ug);
                _J.LinearA  = -ug;
                _J.AngularA = -crug;
                K          += b1.InvMass + b1.InvI * crug * crug;
            }

            if (_revolute2 != null || _fixedRevolute2 != null)
            {
                _J.AngularB = -Ratio;
                K          += Ratio * Ratio * b2.InvI;
            }
            else
            {
                Vector2 ug;
                if (_prismatic2 != null)
                {
                    ug = _prismatic2.LocalXAxis1; // MathUtils.Multiply(ref xfg1.R, _prismatic1.LocalXAxis1);
                }
                else
                {
                    ug = _fixedPrismatic2.LocalXAxis1; // MathUtils.Multiply(ref xfg1.R, _prismatic1.LocalXAxis1);
                }
                Transform /*xfg1,*/ xf2;
                //g1.GetTransform(out xfg1);
                b2.GetTransform(out xf2);

                Vector2 r    = MathUtils.Multiply(ref xf2.R, LocalAnchor2 - b2.LocalCenter);
                float   crug = MathUtils.Cross(r, ug);
                _J.LinearB  = -Ratio * ug;
                _J.AngularB = -Ratio * crug;
                K          += Ratio * Ratio * (b2.InvMass + b2.InvI * crug * crug);
            }

            // Compute effective mass.
            Debug.Assert(K > 0.0f);
            _mass = K > 0.0f ? 1.0f / K : 0.0f;

            if (Settings.EnableWarmstarting)
            {
                // Warm starting.
                b1.LinearVelocityInternal  += b1.InvMass * _impulse * _J.LinearA;
                b1.AngularVelocityInternal += b1.InvI * _impulse * _J.AngularA;
                b2.LinearVelocityInternal  += b2.InvMass * _impulse * _J.LinearB;
                b2.AngularVelocityInternal += b2.InvI * _impulse * _J.AngularB;
            }
            else
            {
                _impulse = 0.0f;
            }
        }
예제 #20
0
        internal void Reset(ref TimeStep step, int count, Contact[] contacts, SolverPosition[] positions, SolverVelocity[] velocities,
                            int[] locks, int velocityConstraintsMultithreadThreshold, int positionConstraintsMultithreadThreshold)
        {
            _count      = count;
            _positions  = positions;
            _velocities = velocities;
            _locks      = locks;
            _contacts   = contacts;
            _velocityConstraintsMultithreadThreshold = velocityConstraintsMultithreadThreshold;
            _positionConstraintsMultithreadThreshold = positionConstraintsMultithreadThreshold;

            // grow the array
            if (_velocityConstraints == null || _velocityConstraints.Length < count)
            {
                int newBufferCount = Math.Max(count, 32);
                newBufferCount = newBufferCount + (newBufferCount * 2 >> 4); // grow by x1.125f
                newBufferCount = (newBufferCount + 31) & (~31);              // grow in chunks of 32.
                int oldBufferCount = (_velocityConstraints == null) ? 0 : _velocityConstraints.Length;
                Array.Resize(ref _velocityConstraints, newBufferCount);
                Array.Resize(ref _positionConstraints, newBufferCount);

                for (int i = oldBufferCount; i < newBufferCount; i++)
                {
                    _velocityConstraints[i] = new ContactVelocityConstraint();
                    _positionConstraints[i] = new ContactPositionConstraint();
                }
            }

            // Initialize position independent portions of the constraints.
            for (int i = 0; i < _count; ++i)
            {
                Contact contact = contacts[i];

                Fixture  fixtureA = contact.FixtureA;
                Fixture  fixtureB = contact.FixtureB;
                Shape    shapeA   = fixtureA.Shape;
                Shape    shapeB   = fixtureB.Shape;
                float    radiusA  = shapeA.Radius;
                float    radiusB  = shapeB.Radius;
                Body     bodyA    = fixtureA.Body;
                Body     bodyB    = fixtureB.Body;
                Manifold manifold = contact.Manifold;

                int pointCount = manifold.PointCount;
                Debug.Assert(pointCount > 0);

                ContactVelocityConstraint vc = _velocityConstraints[i];
                vc.friction     = contact.Friction;
                vc.restitution  = contact.Restitution;
                vc.tangentSpeed = contact.TangentSpeed;
                vc.indexA       = bodyA.IslandIndex;
                vc.indexB       = bodyB.IslandIndex;
                vc.invMassA     = bodyA._invMass;
                vc.invMassB     = bodyB._invMass;
                vc.invIA        = bodyA._invI;
                vc.invIB        = bodyB._invI;
                vc.contactIndex = i;
                vc.pointCount   = pointCount;
                vc.K.SetZero();
                vc.normalMass.SetZero();

                ContactPositionConstraint pc = _positionConstraints[i];
                pc.indexA       = bodyA.IslandIndex;
                pc.indexB       = bodyB.IslandIndex;
                pc.invMassA     = bodyA._invMass;
                pc.invMassB     = bodyB._invMass;
                pc.localCenterA = bodyA._sweep.LocalCenter;
                pc.localCenterB = bodyB._sweep.LocalCenter;
                pc.invIA        = bodyA._invI;
                pc.invIB        = bodyB._invI;
                pc.localNormal  = manifold.LocalNormal;
                pc.localPoint   = manifold.LocalPoint;
                pc.pointCount   = pointCount;
                pc.radiusA      = radiusA;
                pc.radiusB      = radiusB;
                pc.type         = manifold.Type;

                for (int j = 0; j < pointCount; ++j)
                {
                    ManifoldPoint           cp  = manifold.Points[j];
                    VelocityConstraintPoint vcp = vc.points[j];

                    if (step.warmStarting)
                    {
                        vcp.normalImpulse  = step.dtRatio * cp.NormalImpulse;
                        vcp.tangentImpulse = step.dtRatio * cp.TangentImpulse;
                    }
                    else
                    {
                        vcp.normalImpulse  = 0.0f;
                        vcp.tangentImpulse = 0.0f;
                    }

                    vcp.rA           = Vector2.Zero;
                    vcp.rB           = Vector2.Zero;
                    vcp.normalMass   = 0.0f;
                    vcp.tangentMass  = 0.0f;
                    vcp.velocityBias = 0.0f;

                    pc.localPoints[j] = cp.LocalPoint;
                }
            }
        }
예제 #21
0
        internal override void SolveVelocityConstraints(ref TimeStep step)
        {
            Body b = BodyA;

            Transform xf1;
            b.GetTransform(out xf1);

            Vector2 r = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b.LocalCenter);

            // Cdot = v + cross(w, r)
            Vector2 Cdot = b.LinearVelocityInternal + MathUtils.Cross(b.AngularVelocityInternal, r);
            Vector2 impulse = MathUtils.Multiply(ref _mass, -(Cdot + _beta*_C + _gamma*_impulse));

            Vector2 oldImpulse = _impulse;
            _impulse += impulse;
            float maxImpulse = step.dt*MaxForce;
            if (_impulse.LengthSquared() > maxImpulse*maxImpulse)
            {
                _impulse *= maxImpulse/_impulse.Length();
            }
            impulse = _impulse - oldImpulse;

            b.LinearVelocityInternal += b.InvMass*impulse;
            b.AngularVelocityInternal += b.InvI*MathUtils.Cross(r, impulse);
        }
예제 #22
0
 private bool PassedFirstRepairTime(DateTime start, TimeStep step) =>
 step.Prev - start < FirstRepairTime && step.Now - start >= FirstRepairTime;
예제 #23
0
        internal override void InitVelocityConstraints(TimeStep step)
        {
            Body b1 = _body1;
            Body b2 = _body2;

            if (_enableMotor || _enableLimit)
            {
                // You cannot create a rotation limit between bodies that
                // both have fixed rotation.
                Box2DNetDebug.Assert(b1._invI > 0.0f || b2._invI > 0.0f);
            }

            // Compute the effective mass matrix.
            Vector2 r1 = b1.GetTransform().TransformDirection(_localAnchor1 - b1.GetLocalCenter());
            Vector2 r2 = b2.GetTransform().TransformDirection(_localAnchor2 - b2.GetLocalCenter());

            // J = [-I -r1_skew I r2_skew]
            //     [ 0       -1 0       1]
            // r_skew = [-ry; rx]

            // Matlab
            // K = [ m1+r1y^2*i1+m2+r2y^2*i2,  -r1y*i1*r1x-r2y*i2*r2x,          -r1y*i1-r2y*i2]
            //     [  -r1y*i1*r1x-r2y*i2*r2x, m1+r1x^2*i1+m2+r2x^2*i2,           r1x*i1+r2x*i2]
            //     [          -r1y*i1-r2y*i2,           r1x*i1+r2x*i2,                   i1+i2]

            float m1 = b1._invMass, m2 = b2._invMass;
            float i1 = b1._invI, i2 = b2._invI;

            _mass.Col1.X = m1 + m2 + r1.Y * r1.Y * i1 + r2.Y * r2.Y * i2;
            _mass.Col2.X = -r1.Y * r1.X * i1 - r2.Y * r2.X * i2;
            _mass.Col3.X = -r1.Y * i1 - r2.Y * i2;
            _mass.Col1.Y = _mass.Col2.X;
            _mass.Col2.Y = m1 + m2 + r1.X * r1.X * i1 + r2.X * r2.X * i2;
            _mass.Col3.Y = r1.X * i1 + r2.Y * i2;
            _mass.Col1.Z = _mass.Col3.X;
            _mass.Col2.Z = _mass.Col3.Y;
            _mass.Col3.Z = i1 + i2;

            _motorMass = 1.0f / (i1 + i2);

            if (_enableMotor == false)
            {
                _motorImpulse = 0.0f;
            }

            if (_enableLimit)
            {
                float jointAngle = b2._sweep.A - b1._sweep.A - _referenceAngle;
                if (Box2DNetMath.Abs(_upperAngle - _lowerAngle) < 2.0f * Settings.AngularSlop)
                {
                    _limitState = LimitState.EqualLimits;
                }
                else if (jointAngle <= _lowerAngle)
                {
                    if (_limitState != LimitState.AtLowerLimit)
                    {
                        _impulse.Z = 0.0f;
                    }
                    _limitState = LimitState.AtLowerLimit;
                }
                else if (jointAngle >= _upperAngle)
                {
                    if (_limitState != LimitState.AtUpperLimit)
                    {
                        _impulse.Z = 0.0f;
                    }
                    _limitState = LimitState.AtUpperLimit;
                }
                else
                {
                    _limitState = LimitState.InactiveLimit;
                    _impulse.Z  = 0.0f;
                }
            }
            else
            {
                _limitState = LimitState.InactiveLimit;
            }

            if (step.WarmStarting)
            {
                // Scale impulses to support a variable time step.
                _impulse      *= step.DtRatio;
                _motorImpulse *= step.DtRatio;

                Vector2 P = _impulse.ToVector2();

                b1._linearVelocity  -= m1 * P;
                b1._angularVelocity -= i1 * (r1.Cross(P) + _motorImpulse + _impulse.Z);

                b2._linearVelocity  += m2 * P;
                b2._angularVelocity += i2 * (r2.Cross(P) + _motorImpulse + _impulse.Z);
            }
            else
            {
                _impulse      = Vector3.Zero;
                _motorImpulse = 0.0f;
            }
        }
        internal override void SolveVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            Transform xf1, xf2;
            b1.GetTransform(out xf1);
            b2.GetTransform(out xf2);

            Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b1.LocalCenter);
            Vector2 r2 = MathUtils.Multiply(ref xf2.R, LocalAnchorB - b2.LocalCenter);

            // Cdot = dot(u, v + cross(w, r))
            MathUtils.Cross(b1.AngularVelocityInternal, ref r1, out _tmpVector1);
            Vector2 v1 = b1.LinearVelocityInternal + _tmpVector1;
            MathUtils.Cross(b2.AngularVelocityInternal, ref r2, out _tmpVector1);
            Vector2 v2 = b2.LinearVelocityInternal + _tmpVector1;
            float Cdot = Vector2.Dot(_u, v2 - v1);

            float impulse = -_mass * (Cdot + _bias + _gamma * _impulse);
            _impulse += impulse;

            Vector2 P = impulse * _u;
            b1.LinearVelocityInternal -= b1.InvMass * P;
            MathUtils.Cross(ref r1, ref P, out _tmpFloat1);
            b1.AngularVelocityInternal -= b1.InvI * _tmpFloat1;
            b2.LinearVelocityInternal += b2.InvMass * P;
            MathUtils.Cross(ref r2, ref P, out _tmpFloat1);
            b2.AngularVelocityInternal += b2.InvI * _tmpFloat1;
        }
예제 #25
0
        internal override void SolveVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            Vector2 v1 = b1.LinearVelocityInternal;
            float   w1 = b1.AngularVelocityInternal;
            Vector2 v2 = b2.LinearVelocityInternal;
            float   w2 = b2.AngularVelocityInternal;

            // Solve linear motor constraint.
            if (_enableMotor && _limitState != LimitState.Equal)
            {
                float Cdot       = Vector2.Dot(_axis, v2 - v1) + _a2 * w2 - _a1 * w1;
                float impulse    = _motorMass * (_motorSpeed - Cdot);
                float oldImpulse = _motorImpulse;
                float maxImpulse = step.dt * _maxMotorForce;
                _motorImpulse = MathHelper.Clamp(_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse       = _motorImpulse - oldImpulse;

                Vector2 P  = impulse * _axis;
                float   L1 = impulse * _a1;
                float   L2 = impulse * _a2;

                v1 -= InvMassA * P;
                w1 -= InvIA * L1;

                v2 += InvMassB * P;
                w2 += InvIB * L2;
            }

            Vector2 Cdot1 = new Vector2(Vector2.Dot(_perp, v2 - v1) + _s2 * w2 - _s1 * w1, w2 - w1);

            if (_enableLimit && _limitState != LimitState.Inactive)
            {
                // Solve prismatic and limit constraint in block form.
                float   Cdot2 = Vector2.Dot(_axis, v2 - v1) + _a2 * w2 - _a1 * w1;
                Vector3 Cdot  = new Vector3(Cdot1.X, Cdot1.Y, Cdot2);

                Vector3 f1 = _impulse;
                Vector3 df = _K.Solve33(-Cdot);
                _impulse += df;

                if (_limitState == LimitState.AtLower)
                {
                    _impulse.Z = Math.Max(_impulse.Z, 0.0f);
                }
                else if (_limitState == LimitState.AtUpper)
                {
                    _impulse.Z = Math.Min(_impulse.Z, 0.0f);
                }

                // f2(1:2) = invK(1:2,1:2) * (-Cdot(1:2) - K(1:2,3) * (f2(3) - f1(3))) + f1(1:2)
                Vector2 b   = -Cdot1 - (_impulse.Z - f1.Z) * new Vector2(_K.Col3.X, _K.Col3.Y);
                Vector2 f2r = _K.Solve22(b) + new Vector2(f1.X, f1.Y);
                _impulse.X = f2r.X;
                _impulse.Y = f2r.Y;

                df = _impulse - f1;

                Vector2 P  = df.X * _perp + df.Z * _axis;
                float   L1 = df.X * _s1 + df.Y + df.Z * _a1;
                float   L2 = df.X * _s2 + df.Y + df.Z * _a2;

                v1 -= InvMassA * P;
                w1 -= InvIA * L1;

                v2 += InvMassB * P;
                w2 += InvIB * L2;
            }
            else
            {
                // Limit is inactive, just solve the prismatic constraint in block form.
                Vector2 df = _K.Solve22(-Cdot1);
                _impulse.X += df.X;
                _impulse.Y += df.Y;

                Vector2 P  = df.X * _perp;
                float   L1 = df.X * _s1 + df.Y;
                float   L2 = df.X * _s2 + df.Y;

                v1 -= InvMassA * P;
                w1 -= InvIA * L1;

                v2 += InvMassB * P;
                w2 += InvIB * L2;
            }

            b1.LinearVelocityInternal  = v1;
            b1.AngularVelocityInternal = w1;
            b2.LinearVelocityInternal  = v2;
            b2.AngularVelocityInternal = w2;
        }
예제 #26
0
        /// <summary>
        /// Updates the physics bodies and resolves all forces.
        /// </summary>
        private void Update(TimeStep timeStep)
        {
            ResolveMassiveBodyParents();
            _spaceCraftManager.ResolveGravitionalParents(_massiveBodies);
            AdjustSpeedForBurns(timeStep);

            double targetDt = _isPaused ? 0 : timeStep.Dt;

            // Update all bodies according to the timestep
            for (int i = 0; i < timeStep.UpdateLoops; i++)
            {
                // Resolve n body massive body forces
                foreach (IMassiveBody bodyA in _massiveBodies)
                {
                    bodyA.ResetAccelerations();

                    foreach (IMassiveBody bodyB in _massiveBodies)
                    {
                        if (bodyA == bodyB)
                        {
                            continue;
                        }

                        bodyA.ResolveGravitation(bodyB);
                    }
                }

                _spaceCraftManager.ResolveForces(_massiveBodies);
                _spaceCraftManager.Update(timeStep, targetDt);

                // Update bodies
                foreach (IGravitationalBody gravitationalBody in _gravitationalBodies)
                {
                    gravitationalBody.Update(targetDt);
                }

                _totalElapsedSeconds += targetDt;
            }

            _camera.Update(TimeStep.RealTimeDt);
            _pipCam.Update(TimeStep.RealTimeDt);
            _eventManager.Update(TimeStep.RealTimeDt);

            // Fixed update all gravitational bodies
            foreach (IGravitationalBody body in _gravitationalBodies)
            {
                body.FixedUpdate(timeStep);
            }

            var targetSpaceCraft = _gravitationalBodies[_targetIndex] as ISpaceCraft;

            if (targetSpaceCraft != null)
            {
                if (targetSpaceCraft.Controller.IsPrograde)
                {
                    _progradeButton.Enable();
                }
                else
                {
                    _progradeButton.Disable();
                }

                if (targetSpaceCraft.Controller.IsRetrograde)
                {
                    _retrogradeButton.Enable();
                }
                else
                {
                    _retrogradeButton.Disable();
                }
            }

            _scrollRate = MathHelper.Lerp(_scrollRate, _targetScrollRate, 0.1f);

            _targetScrollRate = MathHelper.Lerp(_targetScrollRate, 0, 0.1f);

            if (_camera.Zoom > 1)
            {
                double scroll = Math.Pow(_camera.Zoom, 1.05f) * _scrollRate;

                _camera.ChangeZoom(scroll);
            }
            else
            {
                _camera.ChangeZoom(_scrollRate);
            }

            SetCameraRotation();
        }
예제 #27
0
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            Body bB = BodyB;

            LocalCenterA = Vector2.Zero;
            LocalCenterB = bB.LocalCenter;

            Transform xfB;

            bB.GetTransform(out xfB);

            // Compute the effective masses.
            Vector2 rA = LocalAnchorA;
            Vector2 rB = MathUtils.Multiply(ref xfB.R, LocalAnchorB - LocalCenterB);
            Vector2 d  = bB.Sweep.C + rB - rA;

            InvMassA = 0.0f;
            InvIA    = 0.0f;
            InvMassB = bB.InvMass;
            InvIB    = bB.InvI;

            // Point to line constraint
            {
                _ay  = _localYAxisA;
                _sAy = MathUtils.Cross(d + rA, _ay);
                _sBy = MathUtils.Cross(rB, _ay);

                _mass = InvMassA + InvMassB + InvIA * _sAy * _sAy + InvIB * _sBy * _sBy;

                if (_mass > 0.0f)
                {
                    _mass = 1.0f / _mass;
                }
            }

            // Spring constraint
            _springMass = 0.0f;
            if (Frequency > 0.0f)
            {
                _ax  = LocalXAxis;
                _sAx = MathUtils.Cross(d + rA, _ax);
                _sBx = MathUtils.Cross(rB, _ax);

                float invMass = InvMassA + InvMassB + InvIA * _sAx * _sAx + InvIB * _sBx * _sBx;

                if (invMass > 0.0f)
                {
                    _springMass = 1.0f / invMass;

                    float C = Vector2.Dot(d, _ax);

                    // Frequency
                    float omega = 2.0f * Settings.Pi * Frequency;

                    // Damping coefficient
                    float da = 2.0f * _springMass * DampingRatio * omega;

                    // Spring stiffness
                    float k = _springMass * omega * omega;

                    // magic formulas
                    _gamma = step.dt * (da + step.dt * k);
                    if (_gamma > 0.0f)
                    {
                        _gamma = 1.0f / _gamma;
                    }

                    _bias = C * step.dt * k * _gamma;

                    _springMass = invMass + _gamma;
                    if (_springMass > 0.0f)
                    {
                        _springMass = 1.0f / _springMass;
                    }
                }
            }
            else
            {
                _springImpulse = 0.0f;
                _springMass    = 0.0f;
            }

            // Rotational motor
            if (_enableMotor)
            {
                _motorMass = InvIA + InvIB;
                if (_motorMass > 0.0f)
                {
                    _motorMass = 1.0f / _motorMass;
                }
            }
            else
            {
                _motorMass    = 0.0f;
                _motorImpulse = 0.0f;
            }

            if (Settings.EnableWarmstarting)
            {
                // Account for variable time step.
                _impulse       *= step.dtRatio;
                _springImpulse *= step.dtRatio;
                _motorImpulse  *= step.dtRatio;

                Vector2 P  = _impulse * _ay + _springImpulse * _ax;
                float   LB = _impulse * _sBy + _springImpulse * _sBx + _motorImpulse;

                bB.LinearVelocityInternal  += InvMassB * P;
                bB.AngularVelocityInternal += InvIB * LB;
            }
            else
            {
                _impulse       = 0.0f;
                _springImpulse = 0.0f;
                _motorImpulse  = 0.0f;
            }
        }
예제 #28
0
        public void Reset(TimeStep step, int count, Contact[] contacts, Position[] positions, Velocity[] velocities, bool warmstarting = Settings.EnableWarmstarting)
        {
            _step       = step;
            _count      = count;
            _positions  = positions;
            _velocities = velocities;
            _contacts   = contacts;

            // grow the array
            if (_velocityConstraints == null || _velocityConstraints.Length < count)
            {
                _velocityConstraints = new ContactVelocityConstraint[count * 2];
                _positionConstraints = new ContactPositionConstraint[count * 2];

                for (int i = 0; i < _velocityConstraints.Length; i++)
                {
                    _velocityConstraints[i] = new ContactVelocityConstraint();
                }

                for (int i = 0; i < _positionConstraints.Length; i++)
                {
                    _positionConstraints[i] = new ContactPositionConstraint();
                }
            }

            // Initialize position independent portions of the constraints.
            for (int i = 0; i < _count; ++i)
            {
                Contact contact = contacts[i];

                Fixture  fixtureA = contact.FixtureA;
                Fixture  fixtureB = contact.FixtureB;
                Shape    shapeA   = fixtureA.Shape;
                Shape    shapeB   = fixtureB.Shape;
                float    radiusA  = shapeA.Radius;
                float    radiusB  = shapeB.Radius;
                Body     bodyA    = fixtureA.Body;
                Body     bodyB    = fixtureB.Body;
                Manifold manifold = contact.Manifold;

                int pointCount = manifold.PointCount;
                Debug.Assert(pointCount > 0);

                ContactVelocityConstraint vc = _velocityConstraints[i];
                vc.friction     = contact.Friction;
                vc.restitution  = contact.Restitution;
                vc.tangentSpeed = contact.TangentSpeed;
                vc.indexA       = bodyA.IslandIndex;
                vc.indexB       = bodyB.IslandIndex;
                vc.invMassA     = bodyA._invMass;
                vc.invMassB     = bodyB._invMass;
                vc.invIA        = bodyA._invI;
                vc.invIB        = bodyB._invI;
                vc.contactIndex = i;
                vc.pointCount   = pointCount;
                vc.K.SetZero();
                vc.normalMass.SetZero();

                ContactPositionConstraint pc = _positionConstraints[i];
                pc.indexA       = bodyA.IslandIndex;
                pc.indexB       = bodyB.IslandIndex;
                pc.invMassA     = bodyA._invMass;
                pc.invMassB     = bodyB._invMass;
                pc.localCenterA = bodyA._sweep.LocalCenter;
                pc.localCenterB = bodyB._sweep.LocalCenter;
                pc.invIA        = bodyA._invI;
                pc.invIB        = bodyB._invI;
                pc.localNormal  = manifold.LocalNormal;
                pc.localPoint   = manifold.LocalPoint;
                pc.pointCount   = pointCount;
                pc.radiusA      = radiusA;
                pc.radiusB      = radiusB;
                pc.type         = manifold.Type;

                for (int j = 0; j < pointCount; ++j)
                {
                    ManifoldPoint           cp  = manifold.Points[j];
                    VelocityConstraintPoint vcp = vc.points[j];

                    if (Settings.EnableWarmstarting)
                    {
                        vcp.normalImpulse  = _step.dtRatio * cp.NormalImpulse;
                        vcp.tangentImpulse = _step.dtRatio * cp.TangentImpulse;
                    }
                    else
                    {
                        vcp.normalImpulse  = 0.0f;
                        vcp.tangentImpulse = 0.0f;
                    }

                    vcp.rA           = Vector2.Zero;
                    vcp.rB           = Vector2.Zero;
                    vcp.normalMass   = 0.0f;
                    vcp.tangentMass  = 0.0f;
                    vcp.velocityBias = 0.0f;

                    pc.localPoints[j] = cp.LocalPoint;
                }
            }
        }
예제 #29
0
        internal override void InitVelocityConstraints(TimeStep step)
        {
            Body b1 = _body1;
            Body b2 = _body2;

            Vector2 r1 = b1.GetTransform().TransformDirection(_localAnchor1 - b1.GetLocalCenter());
            Vector2 r2 = b2.GetTransform().TransformDirection(_localAnchor2 - b2.GetLocalCenter());

            Vector2 p1 = b1._sweep.C + r1;
            Vector2 p2 = b2._sweep.C + r2;

            Vector2 s1 = _ground.GetTransform().position + _groundAnchor1;
            Vector2 s2 = _ground.GetTransform().position + _groundAnchor2;

            // Get the pulley axes.
            _u1 = p1 - s1;
            _u2 = p2 - s2;

            float length1 = _u1.Length();
            float length2 = _u2.Length();

            if (length1 > Settings.LinearSlop)
            {
                _u1 *= 1.0f / length1;
            }
            else
            {
                _u1 = Vector2.Zero;
            }

            if (length2 > Settings.LinearSlop)
            {
                _u2 *= 1.0f / length2;
            }
            else
            {
                _u2 = Vector2.Zero;
            }

            float C = _constant - length1 - _ratio * length2;

            if (C > 0.0f)
            {
                _state   = LimitState.InactiveLimit;
                _impulse = 0.0f;
            }
            else
            {
                _state = LimitState.AtUpperLimit;
            }

            if (length1 < _maxLength1)
            {
                _limitState1   = LimitState.InactiveLimit;
                _limitImpulse1 = 0.0f;
            }
            else
            {
                _limitState1 = LimitState.AtUpperLimit;
            }

            if (length2 < _maxLength2)
            {
                _limitState2   = LimitState.InactiveLimit;
                _limitImpulse2 = 0.0f;
            }
            else
            {
                _limitState2 = LimitState.AtUpperLimit;
            }

            // Compute effective mass.
            float cr1u1 = r1.Cross(_u1);
            float cr2u2 = r2.Cross(_u2);

            _limitMass1 = b1._invMass + b1._invI * cr1u1 * cr1u1;
            _limitMass2 = b2._invMass + b2._invI * cr2u2 * cr2u2;
            _pulleyMass = _limitMass1 + _ratio * _ratio * _limitMass2;
            Box2DNetDebug.Assert(_limitMass1 > Settings.FLT_EPSILON);
            Box2DNetDebug.Assert(_limitMass2 > Settings.FLT_EPSILON);
            Box2DNetDebug.Assert(_pulleyMass > Settings.FLT_EPSILON);
            _limitMass1 = 1.0f / _limitMass1;
            _limitMass2 = 1.0f / _limitMass2;
            _pulleyMass = 1.0f / _pulleyMass;

            if (step.WarmStarting)
            {
                // Scale impulses to support variable time steps.
                _impulse       *= step.DtRatio;
                _limitImpulse1 *= step.DtRatio;
                _limitImpulse2 *= step.DtRatio;

                // Warm starting.
                Vector2 P1 = -(_impulse + _limitImpulse1) * _u1;
                Vector2 P2 = (-_ratio * _impulse - _limitImpulse2) * _u2;
                b1._linearVelocity  += b1._invMass * P1;
                b1._angularVelocity += b1._invI * r1.Cross(P1);
                b2._linearVelocity  += b2._invMass * P2;
                b2._angularVelocity += b2._invI * r2.Cross(P2);
            }
            else
            {
                _impulse       = 0.0f;
                _limitImpulse1 = 0.0f;
                _limitImpulse2 = 0.0f;
            }
        }
예제 #30
0
        internal override void SolveVelocityConstraints(TimeStep step)
        {
            Body b1 = _body1;
            Body b2 = _body2;

            Vector2 v1 = b1._linearVelocity;
            float   w1 = b1._angularVelocity;
            Vector2 v2 = b2._linearVelocity;
            float   w2 = b2._angularVelocity;

            float m1 = b1._invMass, m2 = b2._invMass;
            float i1 = b1._invI, i2 = b2._invI;

            //Solve motor constraint.
            if (_enableMotor && _limitState != LimitState.EqualLimits)
            {
                float Cdot       = w2 - w1 - _motorSpeed;
                float impulse    = _motorMass * (-Cdot);
                float oldImpulse = _motorImpulse;
                float maxImpulse = step.Dt * _maxMotorTorque;
                _motorImpulse = Box2DNet.Common.Math.Clamp(_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse       = _motorImpulse - oldImpulse;

                w1 -= i1 * impulse;
                w2 += i2 * impulse;
            }

            //Solve limit constraint.
            if (_enableLimit && _limitState != LimitState.InactiveLimit)
            {
                Vector2 r1 = b1.GetTransform().TransformDirection(_localAnchor1 - b1.GetLocalCenter());
                Vector2 r2 = b2.GetTransform().TransformDirection(_localAnchor2 - b2.GetLocalCenter());

                // Solve point-to-point constraint
                Vector2 Cdot1 = v2 + r2.CrossScalarPreMultiply(w2) - v1 - r1.CrossScalarPreMultiply(w1);
                float   Cdot2 = w2 - w1;
                Vector3 Cdot  = new Vector3(Cdot1.X, Cdot1.Y, Cdot2);

                Vector3 impulse = _mass.Solve33(-Cdot);

                if (_limitState == LimitState.EqualLimits)
                {
                    _impulse += impulse;
                }
                else if (_limitState == LimitState.AtLowerLimit)
                {
                    float newImpulse = _impulse.Z + impulse.Z;
                    if (newImpulse < 0.0f)
                    {
                        Vector2 reduced = _mass.Solve22(-Cdot1);
                        impulse.X   = reduced.X;
                        impulse.Y   = reduced.Y;
                        impulse.Z   = -_impulse.Z;
                        _impulse.X += reduced.X;
                        _impulse.Y += reduced.Y;
                        _impulse.Z  = 0.0f;
                    }
                }
                else if (_limitState == LimitState.AtUpperLimit)
                {
                    float newImpulse = _impulse.Z + impulse.Z;
                    if (newImpulse > 0.0f)
                    {
                        Vector2 reduced = _mass.Solve22(-Cdot1);
                        impulse.X   = reduced.X;
                        impulse.Y   = reduced.Y;
                        impulse.Z   = -_impulse.Z;
                        _impulse.X += reduced.X;
                        _impulse.Y += reduced.Y;
                        _impulse.Z  = 0.0f;
                    }
                }

                Vector2 P = impulse.ToVector2();

                v1 -= m1 * P;
                w1 -= i1 * (r1.Cross(P) + impulse.Z);

                v2 += m2 * P;
                w2 += i2 * (r2.Cross(P) + impulse.Z);
            }
            else
            {
                Vector2 r1 = b1.GetTransform().TransformDirection(_localAnchor1 - b1.GetLocalCenter());
                Vector2 r2 = b2.GetTransform().TransformDirection(_localAnchor2 - b2.GetLocalCenter());

                // Solve point-to-point constraint
                Vector2 Cdot    = v2 + r2.CrossScalarPreMultiply(w2) - v1 - r1.CrossScalarPreMultiply(w1);
                Vector2 impulse = _mass.Solve22(-Cdot);

                _impulse.X += impulse.X;
                _impulse.Y += impulse.Y;

                v1 -= m1 * impulse;
                w1 -= i1 * r1.Cross(impulse);

                v2 += m2 * impulse;
                w2 += i2 * r2.Cross(impulse);
            }

            b1._linearVelocity  = v1;
            b1._angularVelocity = w1;
            b2._linearVelocity  = v2;
            b2._angularVelocity = w2;
        }
예제 #31
0
        // djm pooling

        public void init(ContactSolverDef def)
        {
            // System.out.println("Initializing contact solver");
            m_step  = def.step;
            m_count = def.count;

            if (m_positionConstraints.Length < m_count)
            {
                ContactPositionConstraint[] old = m_positionConstraints;
                m_positionConstraints = new ContactPositionConstraint[MathUtils.max(old.Length * 2, m_count)];
                ArrayHelper.Copy(old, 0, m_positionConstraints, 0, old.Length);
                for (int i = old.Length; i < m_positionConstraints.Length; i++)
                {
                    m_positionConstraints[i] = new ContactPositionConstraint();
                }
            }

            if (m_velocityConstraints.Length < m_count)
            {
                ContactVelocityConstraint[] old = m_velocityConstraints;
                m_velocityConstraints = new ContactVelocityConstraint[MathUtils.max(old.Length * 2, m_count)];
                ArrayHelper.Copy(old, 0, m_velocityConstraints, 0, old.Length);
                for (int i = old.Length; i < m_velocityConstraints.Length; i++)
                {
                    m_velocityConstraints[i] = new ContactVelocityConstraint();
                }
            }

            m_positions  = def.positions;
            m_velocities = def.velocities;
            m_contacts   = def.contacts;

            for (int i = 0; i < m_count; ++i)
            {
                // System.out.println("contacts: " + m_count);
                Contact contact = m_contacts[i];

                Fixture  fixtureA = contact.m_fixtureA;
                Fixture  fixtureB = contact.m_fixtureB;
                Shape    shapeA   = fixtureA.getShape();
                Shape    shapeB   = fixtureB.getShape();
                double   radiusA  = shapeA.m_radius;
                double   radiusB  = shapeB.m_radius;
                Body     bodyA    = fixtureA.getBody();
                Body     bodyB    = fixtureB.getBody();
                Manifold manifold = contact.getManifold();

                int pointCount = manifold.pointCount;

                ContactVelocityConstraint vc = m_velocityConstraints[i];
                vc.friction     = contact.m_friction;
                vc.restitution  = contact.m_restitution;
                vc.tangentSpeed = contact.m_tangentSpeed;
                vc.indexA       = bodyA.m_islandIndex;
                vc.indexB       = bodyB.m_islandIndex;
                vc.invMassA     = bodyA.m_invMass;
                vc.invMassB     = bodyB.m_invMass;
                vc.invIA        = bodyA.m_invI;
                vc.invIB        = bodyB.m_invI;
                vc.contactIndex = i;
                vc.pointCount   = pointCount;
                vc.K.setZero();
                vc.normalMass.setZero();

                ContactPositionConstraint pc = m_positionConstraints[i];
                pc.indexA   = bodyA.m_islandIndex;
                pc.indexB   = bodyB.m_islandIndex;
                pc.invMassA = bodyA.m_invMass;
                pc.invMassB = bodyB.m_invMass;
                pc.localCenterA.set(bodyA.m_sweep.localCenter);
                pc.localCenterB.set(bodyB.m_sweep.localCenter);
                pc.invIA = bodyA.m_invI;
                pc.invIB = bodyB.m_invI;
                pc.localNormal.set(manifold.localNormal);
                pc.localPoint.set(manifold.localPoint);
                pc.pointCount = pointCount;
                pc.radiusA    = radiusA;
                pc.radiusB    = radiusB;
                pc.type       = manifold.type;

                // System.out.println("contact point count: " + pointCount);
                for (int j = 0; j < pointCount; j++)
                {
                    ManifoldPoint           cp  = manifold.points[j];
                    VelocityConstraintPoint vcp = vc.points[j];

                    if (m_step.warmStarting)
                    {
                        // assert(cp.normalImpulse == 0);
                        // System.out.println("contact normal impulse: " + cp.normalImpulse);
                        vcp.normalImpulse  = m_step.dtRatio * cp.normalImpulse;
                        vcp.tangentImpulse = m_step.dtRatio * cp.tangentImpulse;
                    }
                    else
                    {
                        vcp.normalImpulse  = 0;
                        vcp.tangentImpulse = 0;
                    }

                    vcp.rA.setZero();
                    vcp.rB.setZero();
                    vcp.normalMass      = 0;
                    vcp.tangentMass     = 0;
                    vcp.velocityBias    = 0;
                    pc.localPoints[j].x = cp.localPoint.x;
                    pc.localPoints[j].y = cp.localPoint.y;
                }
            }
        }
예제 #32
0
 public override void Detect(TimeStep step)
 {
     this.step = step;
     this.Run();
 }
예제 #33
0
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            LocalCenterA = b1.LocalCenter;
            LocalCenterB = b2.LocalCenter;

            Transform xf1, xf2;

            b1.GetTransform(out xf1);
            b2.GetTransform(out xf2);

            // Compute the effective masses.
            Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - LocalCenterA);
            Vector2 r2 = MathUtils.Multiply(ref xf2.R, LocalAnchorB - LocalCenterB);
            Vector2 d  = b2.Sweep.C + r2 - b1.Sweep.C - r1;

            InvMassA = b1.InvMass;
            InvIA    = b1.InvI;
            InvMassB = b2.InvMass;
            InvIB    = b2.InvI;

            // Compute motor Jacobian and effective mass.
            {
                _axis = MathUtils.Multiply(ref xf1.R, _localXAxis1);
                _a1   = MathUtils.Cross(d + r1, _axis);
                _a2   = MathUtils.Cross(r2, _axis);

                _motorMass = InvMassA + InvMassB + InvIA * _a1 * _a1 + InvIB * _a2 * _a2;

                if (_motorMass > Settings.Epsilon)
                {
                    _motorMass = 1.0f / _motorMass;
                }
            }

            // Prismatic constraint.
            {
                _perp = MathUtils.Multiply(ref xf1.R, _localYAxis1);

                _s1 = MathUtils.Cross(d + r1, _perp);
                _s2 = MathUtils.Cross(r2, _perp);

                float m1 = InvMassA, m2 = InvMassB;
                float i1 = InvIA, i2 = InvIB;

                float k11 = m1 + m2 + i1 * _s1 * _s1 + i2 * _s2 * _s2;
                float k12 = i1 * _s1 + i2 * _s2;
                float k13 = i1 * _s1 * _a1 + i2 * _s2 * _a2;
                float k22 = i1 + i2;
                float k23 = i1 * _a1 + i2 * _a2;
                float k33 = m1 + m2 + i1 * _a1 * _a1 + i2 * _a2 * _a2;

                _K.Col1 = new Vector3(k11, k12, k13);
                _K.Col2 = new Vector3(k12, k22, k23);
                _K.Col3 = new Vector3(k13, k23, k33);
            }

            // Compute motor and limit terms.
            if (_enableLimit)
            {
                float jointTranslation = Vector2.Dot(_axis, d);
                if (Math.Abs(_upperTranslation - _lowerTranslation) < 2.0f * Settings.LinearSlop)
                {
                    _limitState = LimitState.Equal;
                }
                else if (jointTranslation <= _lowerTranslation)
                {
                    if (_limitState != LimitState.AtLower)
                    {
                        _limitState = LimitState.AtLower;
                        _impulse.Z  = 0.0f;
                    }
                }
                else if (jointTranslation >= _upperTranslation)
                {
                    if (_limitState != LimitState.AtUpper)
                    {
                        _limitState = LimitState.AtUpper;
                        _impulse.Z  = 0.0f;
                    }
                }
                else
                {
                    _limitState = LimitState.Inactive;
                    _impulse.Z  = 0.0f;
                }
            }
            else
            {
                _limitState = LimitState.Inactive;
            }

            if (_enableMotor == false)
            {
                _motorImpulse = 0.0f;
            }

            if (Settings.EnableWarmstarting)
            {
                // Account for variable time step.
                _impulse      *= step.dtRatio;
                _motorImpulse *= step.dtRatio;

                Vector2 P  = _impulse.X * _perp + (_motorImpulse + _impulse.Z) * _axis;
                float   L1 = _impulse.X * _s1 + _impulse.Y + (_motorImpulse + _impulse.Z) * _a1;
                float   L2 = _impulse.X * _s2 + _impulse.Y + (_motorImpulse + _impulse.Z) * _a2;

                b1.LinearVelocityInternal  -= InvMassA * P;
                b1.AngularVelocityInternal -= InvIA * L1;

                b2.LinearVelocityInternal  += InvMassB * P;
                b2.AngularVelocityInternal += InvIB * L2;
            }
            else
            {
                _impulse      = Vector3.Zero;
                _motorImpulse = 0.0f;
            }
        }
예제 #34
0
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            Transform xf1, xf2;

            b1.GetTransform(out xf1);
            b2.GetTransform(out xf2);

            // Compute the effective mass matrix.
            Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b1.LocalCenter);
            Vector2 r2 = MathUtils.Multiply(ref xf2.R, LocalAnchorB - b2.LocalCenter);

            _u = b2.Sweep.C + r2 - b1.Sweep.C - r1;

            // Handle singularity.
            float length = _u.Length();

            if (length < MaxLength && length > MinLength)
            {
                return;
            }

            if (length > Settings.LinearSlop)
            {
                _u *= 1.0f / length;
            }
            else
            {
                _u = Vector2.Zero;
            }

            float cr1u    = MathUtils.Cross(r1, _u);
            float cr2u    = MathUtils.Cross(r2, _u);
            float invMass = b1.InvMass + b1.InvI * cr1u * cr1u + b2.InvMass + b2.InvI * cr2u * cr2u;

            Debug.Assert(invMass > Settings.Epsilon);
            _mass = invMass != 0.0f ? 1.0f / invMass : 0.0f;

            if (Frequency > 0.0f)
            {
                float C = length - MaxLength;

                // Frequency
                float omega = 2.0f * Settings.Pi * Frequency;

                // Damping coefficient
                float d = 2.0f * _mass * DampingRatio * omega;

                // Spring stiffness
                float k = _mass * omega * omega;

                // magic formulas
                _gamma = step.dt * (d + step.dt * k);
                _gamma = _gamma != 0.0f ? 1.0f / _gamma : 0.0f;
                _bias  = C * step.dt * k * _gamma;

                _mass = invMass + _gamma;
                _mass = _mass != 0.0f ? 1.0f / _mass : 0.0f;
            }

            if (Settings.EnableWarmstarting)
            {
                // Scale the impulse to support a variable time step.
                _impulse *= step.dtRatio;

                Vector2 P = _impulse * _u;
                b1.LinearVelocityInternal  -= b1.InvMass * P;
                b1.AngularVelocityInternal -= b1.InvI * MathUtils.Cross(r1, P);
                b2.LinearVelocityInternal  += b2.InvMass * P;
                b2.AngularVelocityInternal += b2.InvI * MathUtils.Cross(r2, P);
            }
            else
            {
                _impulse = 0.0f;
            }
        }
        public void RunOneStep(TimeStep timestep, DateTime now, bool runProcessing)
        {
            /*if (_allProfiles == null) {
             *  throw new LPGException("all profiles was null");
             * }*/

            if (_households == null)
            {
                throw new LPGException("households was null");
            }

            if (_autoDevs == null)
            {
                throw new LPGException("_autoDevs was null");
            }

            if (_transformationDevices == null)
            {
                throw new LPGException("_transformationDevices was null");
            }

            if (_energyStorages == null)
            {
                throw new LPGException("_energyStorages was null");
            }

            if (_generators == null)
            {
                throw new LPGException("_generators was null");
            }

            foreach (var household in _households)
            {
                household.RunOneStep(timestep, now, false);
            }

            if (_calcSpaceHeating != null)
            {
                if (!_calcSpaceHeating.IsBusyDuringTimespan(timestep, 1, 1, _calcSpaceHeating.Loads[0].LoadType))
                {
                    _calcSpaceHeating.Activate(timestep, now);
                }
            }

            if (_calcAirConditioning?.IsBusyDuringTimespan(timestep, 1, 1,
                                                           _calcAirConditioning.Loads[0].LoadType) == false)
            {
                _calcAirConditioning.Activate(timestep, now);
            }

            foreach (var calcAutoDev in _autoDevs)
            {
                if (!calcAutoDev.IsBusyDuringTimespan(timestep, 1, 1, calcAutoDev.LoadType))
                {
                    calcAutoDev.Activate(timestep);
                }
            }

            var runAgain       = true;
            var energyFileRows = _calcRepo.Odap.ProcessOneTimestep(timestep);

            var           repetitioncount = 0;
            List <string> log             = null;

            while (runAgain)
            {
                runAgain = false;
                repetitioncount++;
                if (repetitioncount == 98)
                {
                    log = new List <string>();
                }

                if (repetitioncount > 100)
                {
                    var builder = new StringBuilder();
                    foreach (var transformationDevice in _transformationDevices)
                    {
                        builder.Append(transformationDevice.Name).Append(Environment.NewLine);
                    }

                    foreach (var dev in _energyStorages)
                    {
                        builder.Append(dev.Name).Append(Environment.NewLine);
                    }

                    foreach (var dev in _generators)
                    {
                        builder.Append(dev.Name).Append(Environment.NewLine);
                    }

                    var protocol = string.Empty;
                    if (log != null)
                    {
                        foreach (var s1 in log)
                        {
                            protocol += s1 + Environment.NewLine;
                        }
                    }

                    throw new DataIntegrityException(
                              "Did more than 100 tries while trying to calculate the transformation devices in the house " +
                              Name + " without reaching a solution. " +
                              "This most likely means you have a transformation device loop which is not permitted. " +
                              "A loop might be device A makes water from electricity and device B makes electricty from water. " +
                              "The devices are:" + Environment.NewLine + builder +
                              Environment.NewLine + Environment.NewLine + "The last actions were:" + Environment.NewLine +
                              protocol);
                }

                foreach (var transformationDevice in _transformationDevices)
                {
                    if (transformationDevice.ProcessOneTimestep(energyFileRows, log))
                    {
                        runAgain = true;
                    }
                }

                foreach (var energyStorage in _energyStorages)
                {
                    if (energyStorage.ProcessOneTimestep(energyFileRows, timestep, log))
                    {
                        runAgain = true;
                    }
                }

                foreach (var calcGenerator in _generators)
                {
                    if (calcGenerator.ProcessOneTimestep(energyFileRows, timestep, log))
                    {
                        runAgain = true;
                    }
                }
            }

            foreach (var fileRow in energyFileRows)
            {
                if (_calcRepo.CalcParameters.IsSet(CalcOption.DetailedDatFiles))
                {
                    fileRow.Save(_calcRepo.Odap.BinaryOutStreams[fileRow.LoadType]);
                }

                if (_calcRepo.CalcParameters.IsSet(CalcOption.OverallDats))
                {
                    fileRow.SaveSum(_calcRepo.Odap.SumBinaryOutStreams[fileRow.LoadType]);
                }
            }
        }
예제 #36
0
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            Body bA = BodyA;
            Body bB = BodyB;

            Transform xfA, xfB;

            bA.GetTransform(out xfA);
            bB.GetTransform(out xfB);

            // Compute the effective mass matrix.
            Vector2 rA = MathUtils.Multiply(ref xfA.R, LocalAnchorA - bA.LocalCenter);
            Vector2 rB = MathUtils.Multiply(ref xfB.R, LocalAnchorB - bB.LocalCenter);

            // J = [-I -r1_skew I r2_skew]
            //     [ 0       -1 0       1]
            // r_skew = [-ry; rx]

            // Matlab
            // K = [ mA+r1y^2*iA+mB+r2y^2*iB,  -r1y*iA*r1x-r2y*iB*r2x,          -r1y*iA-r2y*iB]
            //     [  -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB,           r1x*iA+r2x*iB]
            //     [          -r1y*iA-r2y*iB,           r1x*iA+r2x*iB,                   iA+iB]

            float mA = bA.InvMass, mB = bB.InvMass;
            float iA = bA.InvI, iB = bB.InvI;

            Mat22 K1 = new Mat22();

            K1.Col1.X = mA + mB;
            K1.Col2.X = 0.0f;
            K1.Col1.Y = 0.0f;
            K1.Col2.Y = mA + mB;

            Mat22 K2 = new Mat22();

            K2.Col1.X = iA * rA.Y * rA.Y;
            K2.Col2.X = -iA * rA.X * rA.Y;
            K2.Col1.Y = -iA * rA.X * rA.Y;
            K2.Col2.Y = iA * rA.X * rA.X;

            Mat22 K3 = new Mat22();

            K3.Col1.X = iB * rB.Y * rB.Y;
            K3.Col2.X = -iB * rB.X * rB.Y;
            K3.Col1.Y = -iB * rB.X * rB.Y;
            K3.Col2.Y = iB * rB.X * rB.X;

            Mat22 K12;

            Mat22.Add(ref K1, ref K2, out K12);

            Mat22 K;

            Mat22.Add(ref K12, ref K3, out K);

            _linearMass = K.Inverse;

            _angularMass = iA + iB;
            if (_angularMass > 0.0f)
            {
                _angularMass = 1.0f / _angularMass;
            }

            if (Settings.EnableWarmstarting)
            {
                // Scale impulses to support a variable time step.
                _linearImpulse  *= step.dtRatio;
                _angularImpulse *= step.dtRatio;

                Vector2 P = new Vector2(_linearImpulse.X, _linearImpulse.Y);

                bA.LinearVelocityInternal  -= mA * P;
                bA.AngularVelocityInternal -= iA * (MathUtils.Cross(rA, P) + _angularImpulse);

                bB.LinearVelocityInternal  += mB * P;
                bB.AngularVelocityInternal += iB * (MathUtils.Cross(rB, P) + _angularImpulse);
            }
            else
            {
                _linearImpulse  = Vector2.Zero;
                _angularImpulse = 0.0f;
            }
        }
예제 #37
0
 public SharedDesireValue(decimal currentValue, [CanBeNull] TimeStep lastDecay)
 {
     CurrentValue = currentValue;
     LastDecay    = lastDecay;
 }
예제 #38
0
        internal override void SolveVelocityConstraints(ref TimeStep step)
        {
            Body bA = BodyA;
            Body bB = BodyB;

            Vector2 vA = bA.LinearVelocityInternal;
            float   wA = bA.AngularVelocityInternal;
            Vector2 vB = bB.LinearVelocityInternal;
            float   wB = bB.AngularVelocityInternal;

            float mA = bA.InvMass, mB = bB.InvMass;
            float iA = bA.InvI, iB = bB.InvI;

            Transform xfA, xfB;

            bA.GetTransform(out xfA);
            bB.GetTransform(out xfB);

            Vector2 rA = MathUtils.Multiply(ref xfA.R, LocalAnchorA - bA.LocalCenter);
            Vector2 rB = MathUtils.Multiply(ref xfB.R, LocalAnchorB - bB.LocalCenter);

            // Solve angular friction
            {
                float Cdot    = wB - wA;
                float impulse = -_angularMass * Cdot;

                float oldImpulse = _angularImpulse;
                float maxImpulse = step.dt * MaxTorque;
                _angularImpulse = MathUtils.Clamp(_angularImpulse + impulse, -maxImpulse, maxImpulse);
                impulse         = _angularImpulse - oldImpulse;

                wA -= iA * impulse;
                wB += iB * impulse;
            }

            // Solve linear friction
            {
                Vector2 Cdot = vB + MathUtils.Cross(wB, rB) - vA - MathUtils.Cross(wA, rA);

                Vector2 impulse    = -MathUtils.Multiply(ref _linearMass, Cdot);
                Vector2 oldImpulse = _linearImpulse;
                _linearImpulse += impulse;

                float maxImpulse = step.dt * MaxForce;

                if (_linearImpulse.LengthSquared() > maxImpulse * maxImpulse)
                {
                    _linearImpulse.Normalize();
                    _linearImpulse *= maxImpulse;
                }

                impulse = _linearImpulse - oldImpulse;

                vA -= mA * impulse;
                wA -= iA * MathUtils.Cross(rA, impulse);

                vB += mB * impulse;
                wB += iB * MathUtils.Cross(rB, impulse);
            }

            bA.LinearVelocityInternal  = vA;
            bA.AngularVelocityInternal = wA;
            bB.LinearVelocityInternal  = vB;
            bB.AngularVelocityInternal = wB;
        }
예제 #39
0
        internal override void SolveVelocityConstraints(ref TimeStep step)
        {
            Body bA = BodyA;
            Body bB = BodyB;

            Vector2 vA = bA.LinearVelocityInternal;
            float wA = bA.AngularVelocityInternal;
            Vector2 vB = bB.LinearVelocityInternal;
            float wB = bB.AngularVelocityInternal;

            float mA = bA.InvMass, mB = bB.InvMass;
            float iA = bA.InvI, iB = bB.InvI;

            Transform xfA, xfB;
            bA.GetTransform(out xfA);
            bB.GetTransform(out xfB);

            Vector2 rA = MathUtils.Multiply(ref xfA.R, LocalAnchorA - bA.LocalCenter);
            Vector2 rB = MathUtils.Multiply(ref xfB.R, LocalAnchorB - bB.LocalCenter);

            //  Solve point-to-point constraint
            Vector2 Cdot1 = vB + MathUtils.Cross(wB, rB) - vA - MathUtils.Cross(wA, rA);
            float Cdot2 = wB - wA;
            Vector3 Cdot = new Vector3(Cdot1.X, Cdot1.Y, Cdot2);

            Vector3 impulse = _mass.Solve33(-Cdot);
            _impulse += impulse;

            Vector2 P = new Vector2(impulse.X, impulse.Y);

            vA -= mA * P;
            wA -= iA * (MathUtils.Cross(rA, P) + impulse.Z);

            vB += mB * P;
            wB += iB * (MathUtils.Cross(rB, P) + impulse.Z);

            bA.LinearVelocityInternal = vA;
            bA.AngularVelocityInternal = wA;
            bB.LinearVelocityInternal = vB;
            bB.AngularVelocityInternal = wB;
        }
예제 #40
0
 public override void FixedUpdate(TimeStep timeStep)
 {
     OrbitHelper.TraceMassiveBody(this, OrbitTrace);
 }
        internal override void SolveVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;

            Transform xf1;
            b1.GetTransform(out xf1);

            Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b1.LocalCenter);

            // Cdot = dot(u, v + cross(w, r))
            Vector2 v1 = b1.LinearVelocityInternal + MathUtils.Cross(b1.AngularVelocityInternal, r1);
            Vector2 v2 = new Vector2(0, 0);
            float Cdot = Vector2.Dot(_u, v2 - v1);

            float impulse = -_mass * (Cdot + _bias + _gamma * _impulse);
            _impulse += impulse;

            Vector2 P = impulse * _u;
            b1.LinearVelocityInternal -= b1.InvMass * P;
            b1.AngularVelocityInternal -= b1.InvI * MathUtils.Cross(r1, P);
        }
예제 #42
0
 protected internal virtual void UpdateTime(TimeStep step)
 {
     this.lifetime.Update(step);
 }
예제 #43
0
        /// <summary>
        /// Fills a cell with appropriate brush based on its data, and writes variable names if under variable control.
        /// </summary>
        private void refreshCell(Graphics g, Point p)
        {
            DigitalDataPoint dp = cellPointToDigitalDataPoint(p);

            Pen outlinePen = normalOutlinePen;

            /* if (dp != null)
             * {
             *   if (dp.usesPulse())
             *   {
             *       outlinePen = pulseOutlintPen;
             *   }
             *   else
             *   {
             *       outlinePen = normalOutlinePen;
             *   }
             * }*/


            if (dp == null)
            {
                paintCell(g, p, nullBrush, outlinePen);
                return;
            }

            if (dp.variable == null)
            {
                Brush br;
                if (dp.DigitalContinue)
                {
                    int stepID    = cellPointToTimeStepId(p);
                    int channelID = cellPointToChannelID(p);
                    if (stepID == -1 || channelID == -1)
                    {
                        return;
                    }
                    TimeStep step          = Storage.sequenceData.TimeSteps[stepID];
                    bool     continueValue = step.getDigitalValue(channelID,
                                                                  Storage.sequenceData.TimeSteps,
                                                                  stepID);

                    br = continueBrush(p.Y, continueValue);
                }
                else if (dp.ManualValue)
                {
                    br = trueBrush(p.Y);
                    // paintCell(g, p, trueBrush(p.Y), outlinePen);
                }
                else
                {
                    br = falseBrush;
                    // paintCell(g, p, falseBrush, outlinePen);
                    //painCellRectInternal(g, p, new Pen(trueBrush(p.Y)));
                    //drawCellTopAndBottomInternalLines(g, p, new Pen(trueBrush(p.Y)));
                }
                paintCell(g, p, br, outlinePen);
            }
            else
            {
                // this will probably never get used. Though there is functionality for having a variable value for a digital
                // this does not get set anywhere. Probably this is superseeded by pulse capability
                paintCell(g, p, variableBrush, outlinePen);
                g.DrawString(dp.variable.ToString(), variableFont, Brushes.Black, new RectangleF(p.X * colWidth, p.Y * rowHeight, colWidth, rowHeight));
            }

            if (dp.DigitalPulse != null)
            {
                p = paintPulse(g, p, dp);
            }

            if (WordGenerator.MainClientForm.instance.studentEdition)
            {
                paintCell(g, p, seb, null);
            }
        }
예제 #44
0
        internal override void SolveVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            Transform xf1, xf2;
            b1.GetTransform(out xf1);
            b2.GetTransform(out xf2);

            Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b1.LocalCenter);
            Vector2 r2 = MathUtils.Multiply(ref xf2.R, LocalAnchorB - b2.LocalCenter);

            if (_state == LimitState.AtUpper)
            {
                Vector2 v1 = b1.LinearVelocityInternal + MathUtils.Cross(b1.AngularVelocityInternal, r1);
                Vector2 v2 = b2.LinearVelocityInternal + MathUtils.Cross(b2.AngularVelocityInternal, r2);

                float Cdot = -Vector2.Dot(_u1, v1) - Ratio * Vector2.Dot(_u2, v2);
                float impulse = _pulleyMass * (-Cdot);
                float oldImpulse = _impulse;
                _impulse = Math.Max(0.0f, _impulse + impulse);
                impulse = _impulse - oldImpulse;

                Vector2 P1 = -impulse * _u1;
                Vector2 P2 = -Ratio * impulse * _u2;
                b1.LinearVelocityInternal += b1.InvMass * P1;
                b1.AngularVelocityInternal += b1.InvI * MathUtils.Cross(r1, P1);
                b2.LinearVelocityInternal += b2.InvMass * P2;
                b2.AngularVelocityInternal += b2.InvI * MathUtils.Cross(r2, P2);
            }

            if (_limitState1 == LimitState.AtUpper)
            {
                Vector2 v1 = b1.LinearVelocityInternal + MathUtils.Cross(b1.AngularVelocityInternal, r1);

                float Cdot = -Vector2.Dot(_u1, v1);
                float impulse = -_limitMass1 * Cdot;
                float oldImpulse = _limitImpulse1;
                _limitImpulse1 = Math.Max(0.0f, _limitImpulse1 + impulse);
                impulse = _limitImpulse1 - oldImpulse;

                Vector2 P1 = -impulse * _u1;
                b1.LinearVelocityInternal += b1.InvMass * P1;
                b1.AngularVelocityInternal += b1.InvI * MathUtils.Cross(r1, P1);
            }

            if (_limitState2 == LimitState.AtUpper)
            {
                Vector2 v2 = b2.LinearVelocityInternal + MathUtils.Cross(b2.AngularVelocityInternal, r2);

                float Cdot = -Vector2.Dot(_u2, v2);
                float impulse = -_limitMass2 * Cdot;
                float oldImpulse = _limitImpulse2;
                _limitImpulse2 = Math.Max(0.0f, _limitImpulse2 + impulse);
                impulse = _limitImpulse2 - oldImpulse;

                Vector2 P2 = -impulse * _u2;
                b2.LinearVelocityInternal += b2.InvMass * P2;
                b2.AngularVelocityInternal += b2.InvI * MathUtils.Cross(r2, P2);
            }
        }
예제 #45
0
        /// <summary>
        /// Draws all the physics bodies and UI elements.
        /// </summary>
        private unsafe void DrawFrame(TimeStep timeStep, FpsManager frameTimer)
        {
            _textDisplay.Clear();

            // check for global events
            _eventManager.CheckForGlobalEvents(this);

            RectangleD cameraBounds = _camera.Bounds;

            IGravitationalBody target = _gravitationalBodies[_targetIndex];
            var targetSpaceCraft      = target as SpaceCraftBase;

            // If openCL is supported render all cl bodies
            if (_renderingType == RenderingType.OpenCLHardware ||
                _renderingType == RenderingType.OpenCLSoftware)
            {
                _gpuClear.RenderCl(_clProxy);

                foreach (MassiveBodyBase renderable in _massiveBodies)
                {
                    if (renderable.Visibility(cameraBounds) > 0)
                    {
                        renderable.RenderCl(_clProxy, _camera, _sun);
                    }
                }

                int[] frameData = _clProxy.ReadIntBuffer("image", RenderUtils.ScreenArea);

                var rect = new Rectangle(0, 0, _imageBitmap.Width, _imageBitmap.Height);

                BitmapData bmpData = _imageBitmap.LockBits(rect, ImageLockMode.WriteOnly,
                                                           PixelFormat.Format32bppArgb);

                Marshal.Copy(frameData, 0, bmpData.Scan0, RenderUtils.ScreenArea);

                var ptr = (byte *)bmpData.Scan0;

                // Hack to force full alpha for now
                for (int i = 0; i < RenderUtils.ScreenArea; i++)
                {
                    ptr[i * 4 + 3] = 255;
                }

                _imageBitmap.UnlockBits(bmpData);
            }
            else
            {
                // Fall back to gdi for cl renderables
                using (var graphics = Graphics.FromImage(_imageBitmap))
                {
                    graphics.Clear(Color.Black);

                    _camera.ApplyScreenRotation(graphics);

                    foreach (MassiveBodyBase renderable in _massiveBodies)
                    {
                        if (renderable.Visibility(cameraBounds) > 0)
                        {
                            renderable.RenderGdiFallback(graphics, _camera, _sun);
                        }
                    }
                }
            }

            // Draw all orbit traces, spacecrafts, and GDI objects
            using (Graphics graphics = RenderUtils.GetContext(false, _imageBitmap))
            {
                _camera.ApplyScreenRotation(graphics);

                // Draw all massive body orbit traces
                foreach (MassiveBodyBase massiveBody in _massiveBodies)
                {
                    if (massiveBody is Sun)
                    {
                        continue;
                    }

                    massiveBody.RenderGdi(graphics, _camera);
                }

                graphics.ResetTransform();

                // Draw structures
                foreach (StructureBase structure in _structures)
                {
                    structure.RenderGdi(graphics, _camera);
                }

                _spaceCraftManager.Render(graphics, _camera);
            }

            // Draw all GUI elements (higher quality)
            using (Graphics graphics = RenderUtils.GetContext(true, _imageBitmap))
            {
                double throttle = 0;

                if (targetSpaceCraft != null)
                {
                    throttle = targetSpaceCraft.Throttle;

                    // TODO: render PIP
                    //int width = RenderUtils.ScreenWidth;
                    //int height = RenderUtils.ScreenHeight;
                    //Rectangle rectPip = new Rectangle(width - 220, 100, 200, height - 300);
                    //graphics.DrawRectangle(Pens.White, rectPip);

                    //_pipCam.ApplyScreenRotation(graphics);
                    //_spaceCraftManager.Render(graphics, _pipCam);
                }

                double pitch           = 0.0;
                double flightPathAngle = 0.0;
                foreach (IGauge gauge in _gauges)
                {
                    if (targetSpaceCraft != null)
                    {
                        if (_targetInOrbit && _rotateInOrbit)
                        {
                            pitch = _gravitationalBodies[_targetIndex].Pitch;
                        }
                        else
                        {
                            pitch = _gravitationalBodies[_targetIndex].GetRelativePitch();
                        }

                        flightPathAngle = pitch - targetSpaceCraft.GetAlpha();
                        gauge.Update(pitch, throttle / 100.0, flightPathAngle);
                    }

                    gauge.Render(graphics, cameraBounds);
                }

                _eventManager.Render(graphics);

                var elapsedTime = TimeSpan.FromSeconds(_totalElapsedSeconds - _clockDelay);

                int elapsedYears = elapsedTime.Days / 365;
                int elapsedDays  = elapsedTime.Days % 365;

                DateTime localTime = _originTime + elapsedTime;

                // Main timing display
                _textDisplay.AddTextBlock(StringAlignment.Near, new List <string>
                {
                    //$"Origin Time: {localTime.ToShortDateString()} {localTime.ToShortTimeString()}",
                    $"Origin Time: {string.Format("{0}-{1}-{2:D2}", localTime.Date.Year, localTime.Date.Month, localTime.Date.Day)} {localTime.ToShortTimeString()}",
                    //$"Elapsed Time: Y:{elapsedYears} D:{elapsedDays} H:{elapsedTime.Hours} M:{elapsedTime.Minutes} S:{Math.Round(elapsedTime.TotalSeconds % 60)}",
                    $"Elapsed Time: Y:{elapsedYears} D:{elapsedDays} H:{elapsedTime.Hours} M:{elapsedTime.Minutes} S:{elapsedTime.Seconds}",
                    $"Update Speed: {timeStep.Multiplier}"
                });

                // Target display
                _textDisplay.AddTextBlock(StringAlignment.Center, string.Format("Target: {0}", target));

                // FPS
                _textDisplay.AddTextBlock(StringAlignment.Far, "FPS: " + frameTimer.CurrentFps);

                double targetVelocity   = target.GetRelativeVelocity().Length();
                double inertialVelocity = target.GetInertialVelocity().Length();

                // Info for altitude
                // double altitude = target.GetRelativeAltitude();
                // double altitude = target.GetRelativeAltitude() + 82.5;    // Starship Mk1
                double altitude     = target.GetRelativeAltitude() - 111.4; // Starship + Super Heavy
                var    altitudeInfo = new List <string> {
                    "Altitude: " + UnitDisplay.Distance(altitude)
                };

                // Add downrange if spacecraft exists
                if (targetSpaceCraft != null)
                {
                    double downrangeDistance = targetSpaceCraft.GetDownrangeDistance(_structures[0].Position);

                    altitudeInfo.Add("Downrange: " + UnitDisplay.Distance(downrangeDistance));
                }

                _textDisplay.AddTextBlock(StringAlignment.Near, altitudeInfo);

                // Info for speed / acceleration
                var movementInfo = new List <string>
                {
                    "Inertial Velocity: " + UnitDisplay.Speed(targetVelocity, useKmh),
                    "Orbital Velocity: " + UnitDisplay.Speed(inertialVelocity, useKmh),
                    "Inertial Acceleration: " + UnitDisplay.Acceleration(target.GetRelativeAcceleration().Length()),
                    "Orbital Acceleration: " + UnitDisplay.Acceleration(target.GetInertialAcceleration().Length())
                };

                double lateralVelocity = target.GetLateralVelocity().Length();
                if (lateralVelocity > 0)
                {
                    double lateralPosition = target.GetLateralPosition().Length();
                    altitudeInfo.Add("Crossrange: " + UnitDisplay.Distance(lateralPosition));

                    movementInfo.Add("Lateral Velocity: " + UnitDisplay.Speed(lateralVelocity, useKmh));
                    movementInfo.Add("Lateral Acceleration: " + UnitDisplay.Acceleration(target.GetLateralAcceleration().Length()));
                }

                // Add angle of attack if it exists
                if (targetSpaceCraft != null)
                {
                    movementInfo.Add("Angle of Attack: " + UnitDisplay.AoA(targetSpaceCraft.GetAlpha()));

                    // calculate the current inclination
                    double G      = 6.67408E-11;
                    double M      = target.GravitationalParent.Mass;
                    double μ      = G * M;
                    double R      = target.GravitationalParent.SurfaceRadius;
                    double apogee = target.Apoapsis;
                    if (initialPerigee == 0)
                    {
                        initialPerigee = target.Periapsis;
                    }
                    double Ra = R + apogee;
                    double Rp = R + initialPerigee;
                    double e  = 1 - 2 / ((Ra / Rp) + 1);
                    double ω  = 0;
                    double f  = 0;

                    // orbital period
                    double a           = (initialPerigee + R * 2 + apogee) / 2;
                    double P           = 2 * Math.PI * Math.Pow(Math.Pow(a, 3) / μ, 0.5);
                    double n           = 2 * Math.PI / P;
                    double Δi          = 2 * Math.Asin(lateralVelocity * (1 + e * Math.Cos(f)) / (Math.Pow(1 - Math.Pow(e, 2), 0.5) * Math.Cos(ω + f) * n * a * 2));
                    double inclination = launchInclination * MathHelper.DegreesToRadians - Δi;
                    movementInfo.Add("Inclination: " + UnitDisplay.Degrees(inclination));

                    double speedOfSound = targetSpaceCraft.GravitationalParent.GetSpeedOfSound(target.GetRelativeAltitude());
                    if (speedOfSound > 0)
                    {
                        double machNumber = targetVelocity / speedOfSound;
                        movementInfo.Add("Mach number: " + UnitDisplay.Mach(machNumber));
                    }
                }

                _textDisplay.AddTextBlock(StringAlignment.Near, movementInfo);

                var forceInfo = new List <string> {
                    "Mass: " + UnitDisplay.Mass(target.Mass)
                };

                // Add additional forces
                if (targetSpaceCraft != null)
                {
                    DVector2 dragForce = targetSpaceCraft.AccelerationD * targetSpaceCraft.Mass;
                    DVector2 liftForce = targetSpaceCraft.AccelerationL * targetSpaceCraft.Mass;
                    if (Settings.Default.UseTheTurnForce)
                    {
                        liftForce *= Math.Cos(targetSpaceCraft.Roll);
                    }

                    forceInfo.Add("Thrust: " + UnitDisplay.Force(targetSpaceCraft.Thrust));
                    forceInfo.Add("Drag: " + UnitDisplay.Force(dragForce.Length()));
                    forceInfo.Add("Lift: " + UnitDisplay.Force(liftForce.Length()));
                }

                _textDisplay.AddTextBlock(StringAlignment.Near, forceInfo);

                // Don't show Apoapsis/Periapsis info for the sun
                if (!(target is Sun) && target.GravitationalParent != null)
                {
                    _textDisplay.AddTextBlock(StringAlignment.Near, new List <string>
                    {
                        $"{target.GravitationalParent.ApoapsisName}: {UnitDisplay.Distance(target.Apoapsis)}",
                        $"{target.GravitationalParent.PeriapsisName}: {UnitDisplay.Distance(target.Periapsis)}",
                    });
                }

                // Add atmospheric info if the spaceship is the target
                if (targetSpaceCraft != null && targetSpaceCraft.GravitationalParent != null)
                {
                    double density         = targetSpaceCraft.GravitationalParent.GetAtmosphericDensity(target.GetRelativeAltitude());
                    double dynamicPressure = 0.5 * density * targetVelocity * targetVelocity;

                    _textDisplay.AddTextBlock(StringAlignment.Near, new List <string>
                    {
                        "Air Density: " + UnitDisplay.Density(density),
                        "Dynamic Pressure: " + UnitDisplay.Pressure(dynamicPressure),
                        "Heat Flux: " + UnitDisplay.Heat(targetSpaceCraft.HeatingRate)
                    });
                }

                _textDisplay.Draw(graphics);
            }
        }
예제 #46
0
        internal override void InitVelocityConstraints(TimeStep step)
        {
            Body b1 = _body1;
            Body b2 = _body2;

            // Compute the effective mass matrix.
            Vector2 r1 = b1.GetTransform().TransformDirection(_localAnchor1 - b1.GetLocalCenter());
            Vector2 r2 = b2.GetTransform().TransformDirection(_localAnchor2 - b2.GetLocalCenter());

            _u = b2._sweep.C + r2 - b1._sweep.C - r1;

            // Handle singularity.
            float length = _u.Length();

            if (length > Settings.LinearSlop)
            {
                _u *= 1.0f / length;
            }
            else
            {
                _u = Vector2.Zero;
            }

            float cr1u    = r1.Cross(_u);
            float cr2u    = r2.Cross(_u);
            float invMass = b1._invMass + b1._invI * cr1u * cr1u + b2._invMass + b2._invI * cr2u * cr2u;

            _mass = 1.0f / invMass;

            if (_frequencyHz > 0.0f)
            {
                float C = length - _length;

                // Frequency
                float omega = 2.0f * Settings.Pi * _frequencyHz;

                // Damping coefficient
                float d = 2.0f * _mass * _dampingRatio * omega;

                // Spring stiffness
                float k = _mass * omega * omega;

                // magic formulas
                _gamma = 1.0f / (step.Dt * (d + step.Dt * k));
                _bias  = C * step.Dt * k * _gamma;

                _mass = 1.0f / (invMass + _gamma);
            }

            if (step.WarmStarting)
            {
                //Scale the inpulse to support a variable timestep.
                _impulse *= step.DtRatio;
                Vector2 P = _impulse * _u;
                b1._linearVelocity  -= b1._invMass * P;
                b1._angularVelocity -= b1._invI * r1.Cross(P);
                b2._linearVelocity  += b2._invMass * P;
                b2._angularVelocity += b2._invI * r2.Cross(P);
            }
            else
            {
                _impulse = 0.0f;
            }
        }
예제 #47
0
        internal override void SolveVelocityConstraints(ref TimeStep step)
        {
            Body bB = BodyB;

            Vector2 vA = Vector2.Zero;
            float wA = 0.0f;
            Vector2 vB = bB.LinearVelocityInternal;
            float wB = bB.AngularVelocityInternal;

            // Solve spring constraint
            {
                float Cdot = Vector2.Dot(_ax, vB - vA) + _sBx * wB - _sAx * wA;
                float impulse = -_springMass * (Cdot + _bias + _gamma * _springImpulse);
                _springImpulse += impulse;

                Vector2 P = impulse * _ax;
                float LA = impulse * _sAx;
                float LB = impulse * _sBx;

                vA -= InvMassA * P;
                wA -= InvIA * LA;

                vB += InvMassB * P;
                wB += InvIB * LB;
            }

            // Solve rotational motor constraint
            {
                float Cdot = wB - wA - _motorSpeed;
                float impulse = -_motorMass * Cdot;

                float oldImpulse = _motorImpulse;
                float maxImpulse = step.dt * _maxMotorTorque;
                _motorImpulse = MathHelper.Clamp(_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse = _motorImpulse - oldImpulse;

                wA -= InvIA * impulse;
                wB += InvIB * impulse;
            }

            // Solve point to line constraint
            {
                float Cdot = Vector2.Dot(_ay, vB - vA) + _sBy * wB - _sAy * wA;
                float impulse = _mass * (-Cdot);
                _impulse += impulse;

                Vector2 P = impulse * _ay;
                float LB = impulse * _sBy;

                vB += InvMassB * P;
                wB += InvIB * LB;
            }

            bB.LinearVelocityInternal = vB;
            bB.AngularVelocityInternal = wB;
        }
예제 #48
0
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;

            if (_enableMotor || _enableLimit)
            {
                // You cannot create a rotation limit between bodies that
                // both have fixed rotation.
                Debug.Assert(b1.InvI > 0.0f /* || b2._invI > 0.0f*/);
            }

            // Compute the effective mass matrix.
            Transform xf1;

            b1.GetTransform(out xf1);

            Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b1.LocalCenter);
            Vector2 r2 = LocalAnchorB; // MathUtils.Multiply(ref xf2.R, LocalAnchorB - b2.LocalCenter);

            // J = [-I -r1_skew I r2_skew]
            // [ 0       -1 0       1]
            // r_skew = [-ry; rx]

            // Matlab
            // K = [ m1+r1y^2*i1+m2+r2y^2*i2,  -r1y*i1*r1x-r2y*i2*r2x,          -r1y*i1-r2y*i2]
            // [  -r1y*i1*r1x-r2y*i2*r2x, m1+r1x^2*i1+m2+r2x^2*i2,           r1x*i1+r2x*i2]
            // [          -r1y*i1-r2y*i2,           r1x*i1+r2x*i2,                   i1+i2]

            float       m1 = b1.InvMass;
            const float m2 = 0;
            float       i1 = b1.InvI;
            const float i2 = 0;

            _mass.col1.X = m1 + m2 + r1.Y * r1.Y * i1 + r2.Y * r2.Y * i2;
            _mass.col2.X = -r1.Y * r1.X * i1 - r2.Y * r2.X * i2;
            _mass.col3.X = -r1.Y * i1 - r2.Y * i2;
            _mass.col1.Y = _mass.col2.X;
            _mass.col2.Y = m1 + m2 + r1.X * r1.X * i1 + r2.X * r2.X * i2;
            _mass.col3.Y = r1.X * i1 + r2.X * i2;
            _mass.col1.Z = _mass.col3.X;
            _mass.col2.Z = _mass.col3.Y;
            _mass.col3.Z = i1 + i2;

            _motorMass = i1 + i2;
            if (_motorMass > 0.0f)
            {
                _motorMass = 1.0f / _motorMass;
            }

            if (_enableMotor == false)
            {
                _motorImpulse = 0.0f;
            }

            if (_enableLimit)
            {
                float jointAngle = 0 - b1.Sweep.a - ReferenceAngle;
                if (Math.Abs(_upperAngle - _lowerAngle) < 2.0f * Settings.AngularSlop)
                {
                    _limitState = LimitState.Equal;
                }
                else if (jointAngle <= _lowerAngle)
                {
                    if (_limitState != LimitState.AtLower)
                    {
                        _impulse.Z = 0.0f;
                    }
                    _limitState = LimitState.AtLower;
                }
                else if (jointAngle >= _upperAngle)
                {
                    if (_limitState != LimitState.AtUpper)
                    {
                        _impulse.Z = 0.0f;
                    }
                    _limitState = LimitState.AtUpper;
                }
                else
                {
                    _limitState = LimitState.Inactive;
                    _impulse.Z  = 0.0f;
                }
            }
            else
            {
                _limitState = LimitState.Inactive;
            }

            if (Settings.EnableWarmstarting)
            {
                // Scale impulses to support a variable time step.
                _impulse      *= step.dtRatio;
                _motorImpulse *= step.dtRatio;

                Vector2 P = new Vector2(_impulse.X, _impulse.Y);

                b1.LinearVelocityInternal  -= m1 * P;
                b1.AngularVelocityInternal -= i1 * (MathUtils.Cross(r1, P) + _motorImpulse + _impulse.Z);
            }
            else
            {
                _impulse      = Vector3.Zero;
                _motorImpulse = 0.0f;
            }
        }
예제 #49
0
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            Body bA = BodyA;
            Body bB = BodyB;

            Transform xfA, xfB;
            bA.GetTransform(out xfA);
            bB.GetTransform(out xfB);

            // Compute the effective mass matrix.
            Vector2 rA = MathUtils.Multiply(ref xfA.R, LocalAnchorA - bA.LocalCenter);
            Vector2 rB = MathUtils.Multiply(ref xfB.R, LocalAnchorB - bB.LocalCenter);

            // J = [-I -r1_skew I r2_skew]
            //     [ 0       -1 0       1]
            // r_skew = [-ry; rx]

            // Matlab
            // K = [ mA+r1y^2*iA+mB+r2y^2*iB,  -r1y*iA*r1x-r2y*iB*r2x,          -r1y*iA-r2y*iB]
            //     [  -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB,           r1x*iA+r2x*iB]
            //     [          -r1y*iA-r2y*iB,           r1x*iA+r2x*iB,                   iA+iB]

            float mA = bA.InvMass, mB = bB.InvMass;
            float iA = bA.InvI, iB = bB.InvI;

            _mass.Col1.X = mA + mB + rA.Y * rA.Y * iA + rB.Y * rB.Y * iB;
            _mass.Col2.X = -rA.Y * rA.X * iA - rB.Y * rB.X * iB;
            _mass.Col3.X = -rA.Y * iA - rB.Y * iB;
            _mass.Col1.Y = _mass.Col2.X;
            _mass.Col2.Y = mA + mB + rA.X * rA.X * iA + rB.X * rB.X * iB;
            _mass.Col3.Y = rA.X * iA + rB.X * iB;
            _mass.Col1.Z = _mass.Col3.X;
            _mass.Col2.Z = _mass.Col3.Y;
            _mass.Col3.Z = iA + iB;

            if (Settings.EnableWarmstarting)
            {
                // Scale impulses to support a variable time step.
                _impulse *= step.dtRatio;

                Vector2 P = new Vector2(_impulse.X, _impulse.Y);

                bA.LinearVelocityInternal -= mA * P;
                bA.AngularVelocityInternal -= iA * (MathUtils.Cross(rA, P) + _impulse.Z);

                bB.LinearVelocityInternal += mB * P;
                bB.AngularVelocityInternal += iB * (MathUtils.Cross(rB, P) + _impulse.Z);
            }
            else
            {
                _impulse = Vector3.Zero;
            }
        }
예제 #50
0
        internal override void SolveVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;

            Vector2     v1 = b1.LinearVelocityInternal;
            float       w1 = b1.AngularVelocityInternal;
            Vector2     v2 = Vector2.Zero;
            const float w2 = 0;

            float m1 = b1.InvMass;
            float i1 = b1.InvI;

            // Solve motor constraint.
            if (_enableMotor && _limitState != LimitState.Equal)
            {
                float Cdot       = w2 - w1 - _motorSpeed;
                float impulse    = _motorMass * (-Cdot);
                float oldImpulse = _motorImpulse;
                float maxImpulse = step.dt * _maxMotorTorque;
                _motorImpulse = MathUtils.Clamp(_motorImpulse + impulse, -maxImpulse, maxImpulse);
                impulse       = _motorImpulse - oldImpulse;

                w1 -= i1 * impulse;
            }

            // Solve limit constraint.
            if (_enableLimit && _limitState != LimitState.Inactive)
            {
                Transform xf1;
                b1.GetTransform(out xf1);

                Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b1.LocalCenter);
                Vector2 r2 = LocalAnchorB;

                // Solve point-to-point constraint
                Vector2 Cdot1 = v2 + MathUtils.Cross(w2, r2) - v1 - MathUtils.Cross(w1, r1);
                float   Cdot2 = w2 - w1;
                Vector3 Cdot  = new Vector3(Cdot1.X, Cdot1.Y, Cdot2);

                Vector3 impulse = _mass.Solve33(-Cdot);

                if (_limitState == LimitState.Equal)
                {
                    _impulse += impulse;
                }
                else if (_limitState == LimitState.AtLower)
                {
                    float newImpulse = _impulse.Z + impulse.Z;
                    if (newImpulse < 0.0f)
                    {
                        Vector2 reduced = _mass.Solve22(-Cdot1);
                        impulse.X   = reduced.X;
                        impulse.Y   = reduced.Y;
                        impulse.Z   = -_impulse.Z;
                        _impulse.X += reduced.X;
                        _impulse.Y += reduced.Y;
                        _impulse.Z  = 0.0f;
                    }
                }
                else if (_limitState == LimitState.AtUpper)
                {
                    float newImpulse = _impulse.Z + impulse.Z;
                    if (newImpulse > 0.0f)
                    {
                        Vector2 reduced = _mass.Solve22(-Cdot1);
                        impulse.X   = reduced.X;
                        impulse.Y   = reduced.Y;
                        impulse.Z   = -_impulse.Z;
                        _impulse.X += reduced.X;
                        _impulse.Y += reduced.Y;
                        _impulse.Z  = 0.0f;
                    }
                }

                Vector2 P = new Vector2(impulse.X, impulse.Y);

                v1 -= m1 * P;
                w1 -= i1 * (MathUtils.Cross(r1, P) + impulse.Z);
            }
            else
            {
                Transform xf1;
                b1.GetTransform(out xf1);

                Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b1.LocalCenter);
                Vector2 r2 = LocalAnchorB;

                // Solve point-to-point constraint
                Vector2 Cdot    = v2 + MathUtils.Cross(w2, r2) - v1 - MathUtils.Cross(w1, r1);
                Vector2 impulse = _mass.Solve22(-Cdot);

                _impulse.X += impulse.X;
                _impulse.Y += impulse.Y;

                v1 -= m1 * impulse;
                w1 -= i1 * MathUtils.Cross(r1, impulse);
            }

            b1.LinearVelocityInternal  = v1;
            b1.AngularVelocityInternal = w1;
        }
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;

            Transform xf1;
            b1.GetTransform(out xf1);

            // Compute the effective mass matrix.
            Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b1.LocalCenter);
            Vector2 r2 = LocalAnchorB;
            _u = r2 - b1.Sweep.c - r1;

            // Handle singularity.
            float length = _u.Length();
            if (length > Settings.LinearSlop)
            {
                _u *= 1.0f / length;
            }
            else
            {
                _u = Vector2.Zero;
            }

            float cr1u = MathUtils.Cross(r1, _u);
            float cr2u = MathUtils.Cross(r2, _u);
            float invMass = b1.InvMass + b1.InvI * cr1u * cr1u + 0 * cr2u * cr2u;
            Debug.Assert(invMass > Settings.Epsilon);
            _mass = invMass != 0.0f ? 1.0f / invMass : 0.0f;

            if (Frequency > 0.0f)
            {
                float C = length - Length;

                // Frequency
                float omega = 2.0f * Settings.Pi * Frequency;

                // Damping coefficient
                float d = 2.0f * _mass * DampingRatio * omega;

                // Spring stiffness
                float k = _mass * omega * omega;

                // magic formulas
                _gamma = step.dt * (d + step.dt * k);
                _gamma = _gamma != 0.0f ? 1.0f / _gamma : 0.0f;
                _bias = C * step.dt * k * _gamma;

                _mass = invMass + _gamma;
                _mass = _mass != 0.0f ? 1.0f / _mass : 0.0f;
            }

            if (Settings.EnableWarmstarting)
            {
                // Scale the impulse to support a variable time step.
                _impulse *= step.dtRatio;

                Vector2 P = _impulse * _u;
                b1.LinearVelocityInternal -= b1.InvMass * P;
                b1.AngularVelocityInternal -= b1.InvI * MathUtils.Cross(r1, P);
            }
            else
            {
                _impulse = 0.0f;
            }
        }
예제 #52
0
        /// <summary>
        ///     Inits the velocity constraints using the specified step
        /// </summary>
        /// <param name="step">The step</param>
        internal override void InitVelocityConstraints(TimeStep step)
        {
            Body body1 = Body1;
            Body body2 = Body2;

            if (IsMotorEnabled || IsLimitEnabled)
            {
                // You cannot create a rotation limit between bodies that
                // both have fixed rotation.
                Box2DxDebug.Assert(body1.InvI > 0.0f || body2.InvI > 0.0f);
            }

            // Compute the effective mass matrix.
            Vec2 mulR1 = Box2DXMath.Mul(body1.GetXForm().R, LocalAnchor1 - body1.GetLocalCenter());
            Vec2 mulR2 = Box2DXMath.Mul(body2.GetXForm().R, LocalAnchor2 - body2.GetLocalCenter());

            // J = [-I -r1_skew I r2_skew]
            //     [ 0       -1 0       1]
            // r_skew = [-ry; rx]

            // Matlab
            // K = [ m1+r1y^2*i1+m2+r2y^2*i2,  -r1y*i1*r1x-r2y*i2*r2x,          -r1y*i1-r2y*i2]
            //     [  -r1y*i1*r1x-r2y*i2*r2x, m1+r1x^2*i1+m2+r2x^2*i2,           r1x*i1+r2x*i2]
            //     [          -r1y*i1-r2y*i2,           r1x*i1+r2x*i2,                   i1+i2]

            float m1 = body1.InvMass, m2 = body2.InvMass;
            float i1 = body1.InvI, i2 = body2.InvI;


            float col1X = m1 + m2 + mulR1.Y * mulR1.Y * i1 + mulR2.Y * mulR2.Y * i2;
            float col2X = -mulR1.Y * mulR1.X * i1 - mulR2.Y * mulR2.X * i2;
            float col3X = -mulR1.Y * i1 - mulR2.Y * i2;

            float col1Y = Mass.Col2.X;
            float col2Y = m1 + m2 + mulR1.X * mulR1.X * i1 + mulR2.X * mulR2.X * i2;
            float col3Y = mulR1.X * i1 + mulR2.X * i2;

            float col1Z = Mass.Col3.X;
            float col2Z = Mass.Col3.Y;
            float col3Z = i1 + i2;

            Mass = new Mat33(new Vec3(col1X, col1Y, col1Z), new Vec3(col2X, col2Y, col2Z),
                             new Vec3(col3X, col3Y, col3Z));

            /*
             *          _mass.Col1.X = m1 + m2 + r1.Y * r1.Y * i1 + r2.Y * r2.Y * i2;
             *          _mass.Col2.X = -r1.Y * r1.X * i1 - r2.Y * r2.X * i2;
             *          _mass.Col3.X = -r1.Y * i1 - r2.Y * i2;
             *          _mass.Col1.Y = _mass.Col2.X;
             *          _mass.Col2.Y = m1 + m2 + r1.X * r1.X * i1 + r2.X * r2.X * i2;
             *          _mass.Col3.Y = r1.X * i1 + r2.X * i2;
             *          _mass.Col1.Z = _mass.Col3.X;
             *          _mass.Col2.Z = _mass.Col3.Y;
             *          _mass.Col3.Z = i1 + i2;
             */
            MotorMass = 1.0f / (i1 + i2);

            if (IsMotorEnabled == false)
            {
                MotorTorque = 0.0f;
            }

            if (IsLimitEnabled)
            {
                float jointAngle = body2.Sweep.A - body1.Sweep.A - ReferenceAngle;
                if (Box2DXMath.Abs(UpperLimit - LowerLimit) < 2.0f * Settings.AngularSlop)
                {
                    State = LimitState.EqualLimits;
                }
                else if (jointAngle <= LowerLimit)
                {
                    if (State != LimitState.AtLowerLimit)
                    {
                        Impulse = new Vec3(Impulse.X, Impulse.Y, 0.0f);
                    }

                    State = LimitState.AtLowerLimit;
                }
                else if (jointAngle >= UpperLimit)
                {
                    if (State != LimitState.AtUpperLimit)
                    {
                        Impulse = new Vec3(Impulse.X, Impulse.Y, 0.0f);
                    }

                    State = LimitState.AtUpperLimit;
                }
                else
                {
                    State   = LimitState.InactiveLimit;
                    Impulse = new Vec3(Impulse.X, Impulse.Y, 0.0f);
                }
            }
            else
            {
                State = LimitState.InactiveLimit;
            }

            if (step.WarmStarting)
            {
                // Scale impulses to support a variable time step.
                Impulse     *= step.DtRatio;
                MotorTorque *= step.DtRatio;

                Vec2 p = new Vec2(Impulse.X, Impulse.Y);

                body1.LinearVelocity  -= m1 * p;
                body1.AngularVelocity -= i1 * (Vec2.Cross(mulR1, p) + MotorTorque + Impulse.Z);

                body2.LinearVelocity  += m2 * p;
                body2.AngularVelocity += i2 * (Vec2.Cross(mulR2, p) + MotorTorque + Impulse.Z);
            }
            else
            {
                Impulse.SetZero();
                MotorTorque = 0.0f;
            }
        }
예제 #53
0
 protected internal abstract void RunLogic(TimeStep step);
예제 #54
0
        /// <summary>
        ///     Solves the velocity constraints using the specified step
        /// </summary>
        /// <param name="step">The step</param>
        internal override void SolveVelocityConstraints(TimeStep step)
        {
            Body b1 = Body1;
            Body b2 = Body2;

            Vec2  v1 = b1.LinearVelocity;
            float w1 = b1.AngularVelocity;
            Vec2  v2 = b2.LinearVelocity;
            float w2 = b2.AngularVelocity;

            float m1 = b1.InvMass, m2 = b2.InvMass;
            float i1 = b1.InvI, i2 = b2.InvI;

            //Solve motor constraint.
            if (IsMotorEnabled && State != LimitState.EqualLimits)
            {
                float cdot       = w2 - w1 - MotorSpeed;
                float impulse    = MotorMass * -cdot;
                float oldImpulse = MotorTorque;
                float maxImpulse = step.Dt * MaxMotorTorque;
                MotorTorque = Box2DXMath.Clamp(MotorTorque + impulse, -maxImpulse, maxImpulse);
                impulse     = MotorTorque - oldImpulse;

                w1 -= i1 * impulse;
                w2 += i2 * impulse;
            }

            //Solve limit constraint.
            if (IsLimitEnabled && State != LimitState.InactiveLimit)
            {
                Vec2 r1 = Box2DXMath.Mul(b1.GetXForm().R, LocalAnchor1 - b1.GetLocalCenter());
                Vec2 r2 = Box2DXMath.Mul(b2.GetXForm().R, LocalAnchor2 - b2.GetLocalCenter());

                // Solve point-to-point constraint
                Vec2  cdot1 = v2 + Vec2.Cross(w2, r2) - v1 - Vec2.Cross(w1, r1);
                float cdot2 = w2 - w1;
                Vec3  cdot  = new Vec3(cdot1.X, cdot1.Y, cdot2);

                Vec3 impulse = Mass.Solve33(-cdot);

                if (State == LimitState.EqualLimits)
                {
                    Impulse += impulse;
                }
                else if (State == LimitState.AtLowerLimit)
                {
                    float newImpulse = Impulse.Z + impulse.Z;
                    if (newImpulse < 0.0f)
                    {
                        Vec2 reduced = Mass.Solve22(-cdot1);
                        impulse.X = reduced.X;
                        impulse.Y = reduced.Y;
                        impulse.Z = -Impulse.Z;
                        Impulse   = new Vec3(reduced.X, reduced.Y, 0.0f);
                    }
                }
                else if (State == LimitState.AtUpperLimit)
                {
                    float newImpulse = Impulse.Z + impulse.Z;
                    if (newImpulse > 0.0f)
                    {
                        Vec2 reduced = Mass.Solve22(-cdot1);
                        impulse.X = reduced.X;
                        impulse.Y = reduced.Y;
                        impulse.Z = -Impulse.Z;
                        Impulse   = new Vec3(reduced.X, reduced.Y, 0.0f);
                    }
                }

                Vec2 p = new Vec2(impulse.X, impulse.Y);

                v1 -= m1 * p;
                w1 -= i1 * (Vec2.Cross(r1, p) + impulse.Z);

                v2 += m2 * p;
                w2 += i2 * (Vec2.Cross(r2, p) + impulse.Z);
            }
            else
            {
                Vec2 r1 = Box2DXMath.Mul(b1.GetXForm().R, LocalAnchor1 - b1.GetLocalCenter());
                Vec2 r2 = Box2DXMath.Mul(b2.GetXForm().R, LocalAnchor2 - b2.GetLocalCenter());

                // Solve point-to-point constraint
                Vec2 cdot    = v2 + Vec2.Cross(w2, r2) - v1 - Vec2.Cross(w1, r1);
                Vec2 impulse = Mass.Solve22(-cdot);

                Impulse = new Vec3(impulse.X, impulse.Y, Impulse.Z);

                v1 -= m1 * impulse;
                w1 -= i1 * Vec2.Cross(r1, impulse);

                v2 += m2 * impulse;
                w2 += i2 * Vec2.Cross(r2, impulse);
            }

            b1.LinearVelocity  = v1;
            b1.AngularVelocity = w1;
            b2.LinearVelocity  = v2;
            b2.AngularVelocity = w2;
        }
예제 #55
0
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            Transform xf1, xf2;
            b1.GetTransform(out xf1);
            b2.GetTransform(out xf2);

            Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b1.LocalCenter);
            Vector2 r2 = MathUtils.Multiply(ref xf2.R, LocalAnchorB - b2.LocalCenter);

            Vector2 p1 = b1.Sweep.c + r1;
            Vector2 p2 = b2.Sweep.c + r2;

            Vector2 s1 = GroundAnchorA;
            Vector2 s2 = GroundAnchorB;

            // Get the pulley axes.
            _u1 = p1 - s1;
            _u2 = p2 - s2;

            float length1 = _u1.Length();
            float length2 = _u2.Length();

            if (length1 > Settings.LinearSlop)
            {
                _u1 *= 1.0f / length1;
            }
            else
            {
                _u1 = Vector2.Zero;
            }

            if (length2 > Settings.LinearSlop)
            {
                _u2 *= 1.0f / length2;
            }
            else
            {
                _u2 = Vector2.Zero;
            }

            float C = _ant - length1 - Ratio * length2;
            if (C > 0.0f)
            {
                _state = LimitState.Inactive;
                _impulse = 0.0f;
            }
            else
            {
                _state = LimitState.AtUpper;
            }

            if (length1 < _maxLengthA)
            {
                _limitState1 = LimitState.Inactive;
                _limitImpulse1 = 0.0f;
            }
            else
            {
                _limitState1 = LimitState.AtUpper;
            }

            if (length2 < _maxLengthB)
            {
                _limitState2 = LimitState.Inactive;
                _limitImpulse2 = 0.0f;
            }
            else
            {
                _limitState2 = LimitState.AtUpper;
            }

            // Compute effective mass.
            float cr1u1 = MathUtils.Cross(r1, _u1);
            float cr2u2 = MathUtils.Cross(r2, _u2);

            _limitMass1 = b1.InvMass + b1.InvI * cr1u1 * cr1u1;
            _limitMass2 = b2.InvMass + b2.InvI * cr2u2 * cr2u2;
            _pulleyMass = _limitMass1 + Ratio * Ratio * _limitMass2;
            Debug.Assert(_limitMass1 > Settings.Epsilon);
            Debug.Assert(_limitMass2 > Settings.Epsilon);
            Debug.Assert(_pulleyMass > Settings.Epsilon);
            _limitMass1 = 1.0f / _limitMass1;
            _limitMass2 = 1.0f / _limitMass2;
            _pulleyMass = 1.0f / _pulleyMass;

            if (Settings.EnableWarmstarting)
            {
                // Scale impulses to support variable time steps.
                _impulse *= step.dtRatio;
                _limitImpulse1 *= step.dtRatio;
                _limitImpulse2 *= step.dtRatio;

                // Warm starting.
                Vector2 P1 = -(_impulse + _limitImpulse1) * _u1;
                Vector2 P2 = (-Ratio * _impulse - _limitImpulse2) * _u2;
                b1.LinearVelocityInternal += b1.InvMass * P1;
                b1.AngularVelocityInternal += b1.InvI * MathUtils.Cross(r1, P1);
                b2.LinearVelocityInternal += b2.InvMass * P2;
                b2.AngularVelocityInternal += b2.InvI * MathUtils.Cross(r2, P2);
            }
            else
            {
                _impulse = 0.0f;
                _limitImpulse1 = 0.0f;
                _limitImpulse2 = 0.0f;
            }
        }
예제 #56
0
        public void Solve(TimeStep step, Vec2 gravity, bool allowSleep)
        {
            // Integrate velocities and apply damping.
            for (int i = 0; i < _bodyCount; ++i)
            {
                Body b = _bodies[i];

                if (b.IsStatic())
                {
                    continue;
                }

                // Integrate velocities.
                b._linearVelocity  += step.Dt * (gravity + b._invMass * b._force);
                b._angularVelocity += step.Dt * b._invI * b._torque;

                // Reset forces.
                b._force.Set(0.0f, 0.0f);
                b._torque = 0.0f;

                // Apply damping.
                // ODE: dv/dt + c * v = 0
                // Solution: v(t) = v0 * exp(-c * t)
                // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt)
                // v2 = exp(-c * dt) * v1
                // Taylor expansion:
                // v2 = (1.0f - c * dt) * v1
                b._linearVelocity  *= Common.MathB2.Clamp(1.0f - step.Dt * b._linearDamping, 0.0f, 1.0f);
                b._angularVelocity *= Common.MathB2.Clamp(1.0f - step.Dt * b._angularDamping, 0.0f, 1.0f);
            }

            ContactSolver contactSolver = new ContactSolver(step, _contacts, _contactCount);

            // Initialize velocity constraints.
            contactSolver.InitVelocityConstraints(step);

            for (int i = 0; i < _jointCount; ++i)
            {
                _joints[i].InitVelocityConstraints(step);
            }

            // Solve velocity constraints.
            for (int i = 0; i < step.VelocityIterations; ++i)
            {
                for (int j = 0; j < _jointCount; ++j)
                {
                    _joints[j].SolveVelocityConstraints(step);
                }
                contactSolver.SolveVelocityConstraints();
            }

            // Post-solve (store impulses for warm starting).
            contactSolver.FinalizeVelocityConstraints();

            // Integrate positions.
            for (int i = 0; i < _bodyCount; ++i)
            {
                Body b = _bodies[i];

                if (b.IsStatic())
                {
                    continue;
                }

                // Check for large velocities.
                Vec2 translation = step.Dt * b._linearVelocity;
                if (Common.Vec2.Dot(translation, translation) > Settings.MaxTranslationSquared)
                {
                    translation.Normalize();
                    b._linearVelocity = (Settings.MaxTranslation * step.Inv_Dt) * translation;
                }

                float rotation = step.Dt * b._angularVelocity;
                if (rotation * rotation > Settings.MaxRotationSquared)
                {
                    if (rotation < 0.0)
                    {
                        b._angularVelocity = -step.Inv_Dt * Settings.MaxRotation;
                    }
                    else
                    {
                        b._angularVelocity = step.Inv_Dt * Settings.MaxRotation;
                    }
                }

                // Store positions for continuous collision.
                b._sweep.C0 = b._sweep.C;
                b._sweep.A0 = b._sweep.A;

                // Integrate
                b._sweep.C += step.Dt * b._linearVelocity;
                b._sweep.A += step.Dt * b._angularVelocity;

                // Compute new transform
                b.SynchronizeTransform();

                // Note: shapes are synchronized later.
            }

            // Iterate over constraints.
            for (int i = 0; i < step.PositionIterations; ++i)
            {
                bool contactsOkay = contactSolver.SolvePositionConstraints(Settings.ContactBaumgarte);

                bool jointsOkay = true;
                for (int j = 0; j < _jointCount; ++j)
                {
                    bool jointOkay = _joints[j].SolvePositionConstraints(Settings.ContactBaumgarte);
                    jointsOkay = jointsOkay && jointOkay;
                }

                if (contactsOkay && jointsOkay)
                {
                    // Exit early if the position errors are small.
                    break;
                }
            }

            Report(contactSolver._constraints);

            if (allowSleep)
            {
                float minSleepTime = Settings.FLT_MAX;

#if !TARGET_FLOAT32_IS_FIXED
                float linTolSqr = Settings.LinearSleepTolerance * Settings.LinearSleepTolerance;
                float angTolSqr = Settings.AngularSleepTolerance * Settings.AngularSleepTolerance;
#endif

                for (int i = 0; i < _bodyCount; ++i)
                {
                    Body b = _bodies[i];
                    if (b._invMass == 0.0f)
                    {
                        continue;
                    }

                    if ((b._flags & Body.BodyFlags.AllowSleep) == 0)
                    {
                        b._sleepTime = 0.0f;
                        minSleepTime = 0.0f;
                    }

                    if ((b._flags & Body.BodyFlags.AllowSleep) == 0 ||
#if TARGET_FLOAT32_IS_FIXED
                        Common.Math.Abs(b._angularVelocity) > Settings.AngularSleepTolerance ||
                        Common.Math.Abs(b._linearVelocity.X) > Settings.LinearSleepTolerance ||
                        Common.Math.Abs(b._linearVelocity.Y) > Settings.LinearSleepTolerance)
#else
                        b._angularVelocity *b._angularVelocity > angTolSqr ||
                        Vec2.Dot(b._linearVelocity, b._linearVelocity) > linTolSqr)
#endif
                    {
                        b._sleepTime = 0.0f;
                        minSleepTime = 0.0f;
                    }
                    else
                    {
                        b._sleepTime += step.Dt;
                        minSleepTime  = Common.MathB2.Min(minSleepTime, b._sleepTime);
                    }
                }
예제 #57
0
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            Body b = BodyA;

            float mass = b.Mass;

            // Frequency
            float omega = 2.0f*Settings.Pi*Frequency;

            // Damping coefficient
            float d = 2.0f*mass*DampingRatio*omega;

            // Spring stiffness
            float k = mass*(omega*omega);

            // magic formulas
            // gamma has units of inverse mass.
            // beta has units of inverse time.
            Debug.Assert(d + step.dt*k > Settings.Epsilon);

            _gamma = step.dt*(d + step.dt*k);
            if (_gamma != 0.0f)
            {
                _gamma = 1.0f/_gamma;
            }

            _beta = step.dt*k*_gamma;

            // Compute the effective mass matrix.
            Transform xf1;
            b.GetTransform(out xf1);
            Vector2 r = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b.LocalCenter);

            // K    = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
            //      = [1/m1+1/m2     0    ] + invI1 * [r1.Y*r1.Y -r1.X*r1.Y] + invI2 * [r1.Y*r1.Y -r1.X*r1.Y]
            //        [    0     1/m1+1/m2]           [-r1.X*r1.Y r1.X*r1.X]           [-r1.X*r1.Y r1.X*r1.X]
            float invMass = b.InvMass;
            float invI = b.InvI;

            Mat22 K1 = new Mat22(new Vector2(invMass, 0.0f), new Vector2(0.0f, invMass));
            Mat22 K2 = new Mat22(new Vector2(invI*r.Y*r.Y, -invI*r.X*r.Y),
                                 new Vector2(-invI*r.X*r.Y, invI*r.X*r.X));

            Mat22 K;
            Mat22.Add(ref K1, ref K2, out K);

            K.Col1.X += _gamma;
            K.Col2.Y += _gamma;

            _mass = K.Inverse;

            _C = b.Sweep.C + r - _worldAnchor;

            // Cheat with some damping
            b.AngularVelocityInternal *= 0.98f;

            // Warm starting.
            _impulse *= step.dtRatio;
            b.LinearVelocityInternal += invMass*_impulse;
            b.AngularVelocityInternal += invI*MathUtils.Cross(r, _impulse);
        }
예제 #58
0
        internal override void InitVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            Transform xf1, xf2;

            b1.GetTransform(out xf1);
            b2.GetTransform(out xf2);

            Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b1.LocalCenter);
            Vector2 r2 = MathUtils.Multiply(ref xf2.R, LocalAnchorB - b2.LocalCenter);

            Vector2 p1 = b1.Sweep.C + r1;
            Vector2 p2 = b2.Sweep.C + r2;

            Vector2 s1 = GroundAnchorA;
            Vector2 s2 = GroundAnchorB;

            // Get the pulley axes.
            _u1 = p1 - s1;
            _u2 = p2 - s2;

            float length1 = _u1.Length();
            float length2 = _u2.Length();

            if (length1 > Settings.LinearSlop)
            {
                _u1 *= 1.0f / length1;
            }
            else
            {
                _u1 = Vector2.Zero;
            }

            if (length2 > Settings.LinearSlop)
            {
                _u2 *= 1.0f / length2;
            }
            else
            {
                _u2 = Vector2.Zero;
            }

            float C = _ant - length1 - Ratio * length2;

            if (C > 0.0f)
            {
                _state   = LimitState.Inactive;
                _impulse = 0.0f;
            }
            else
            {
                _state = LimitState.AtUpper;
            }

            if (length1 < _maxLengthA)
            {
                _limitState1   = LimitState.Inactive;
                _limitImpulse1 = 0.0f;
            }
            else
            {
                _limitState1 = LimitState.AtUpper;
            }

            if (length2 < _maxLengthB)
            {
                _limitState2   = LimitState.Inactive;
                _limitImpulse2 = 0.0f;
            }
            else
            {
                _limitState2 = LimitState.AtUpper;
            }

            // Compute effective mass.
            float cr1u1 = MathUtils.Cross(r1, _u1);
            float cr2u2 = MathUtils.Cross(r2, _u2);

            _limitMass1 = b1.InvMass + b1.InvI * cr1u1 * cr1u1;
            _limitMass2 = b2.InvMass + b2.InvI * cr2u2 * cr2u2;
            _pulleyMass = _limitMass1 + Ratio * Ratio * _limitMass2;
            Debug.Assert(_limitMass1 > Settings.Epsilon);
            Debug.Assert(_limitMass2 > Settings.Epsilon);
            Debug.Assert(_pulleyMass > Settings.Epsilon);
            _limitMass1 = 1.0f / _limitMass1;
            _limitMass2 = 1.0f / _limitMass2;
            _pulleyMass = 1.0f / _pulleyMass;

            if (Settings.EnableWarmstarting)
            {
                // Scale impulses to support variable time steps.
                _impulse       *= step.dtRatio;
                _limitImpulse1 *= step.dtRatio;
                _limitImpulse2 *= step.dtRatio;

                // Warm starting.
                Vector2 P1 = -(_impulse + _limitImpulse1) * _u1;
                Vector2 P2 = (-Ratio * _impulse - _limitImpulse2) * _u2;
                b1.LinearVelocityInternal  += b1.InvMass * P1;
                b1.AngularVelocityInternal += b1.InvI * MathUtils.Cross(r1, P1);
                b2.LinearVelocityInternal  += b2.InvMass * P2;
                b2.AngularVelocityInternal += b2.InvI * MathUtils.Cross(r2, P2);
            }
            else
            {
                _impulse       = 0.0f;
                _limitImpulse1 = 0.0f;
                _limitImpulse2 = 0.0f;
            }
        }
예제 #59
0
        protected internal override void RunLogic(TimeStep step)
        {
            for (int index = 0; index < items.Count; ++index)
            {
                Wrapper wrapper = items[index];
                Body body = wrapper.body;

                if (wrapper.affectable == null ||
                     body.IgnoresPhysicsLogics ||
                   Scalar.IsPositiveInfinity(body.Mass.Mass))
                {
                    continue;
                }
                IShape shape = body.Shape;
                int isInsideCount = 0;
                foreach (Vector2D corner in body.Rectangle.Corners())
                {
                    Scalar distance = line.GetDistance(corner);
                    if (distance <= 0)
                    {
                        isInsideCount++;
                    }
                }
                if (isInsideCount == 0) { continue; }

                if (isInsideCount != 4)
                {
                    Vector2D relativeVelocity = Vector2D.Zero;
                    Vector2D velocityDirection  = Vector2D.Zero;
                    Vector2D dragDirection = Vector2D.Zero;
                    Vector2D centroid = Vector2D.Zero;
                    
                    
                    Line bodyLine;
                    Line.Transform(ref body.Matrices.ToBody, ref line, out bodyLine);


                    GetTangentCallback callback = delegate(Vector2D centTemp)
                    {
                        centroid = body.Matrices.ToWorldNormal * centTemp;
                        PhysicsHelper.GetRelativeVelocity(ref body.State.Velocity, ref centroid, out relativeVelocity);
                        relativeVelocity = FluidVelocity - relativeVelocity;
                        velocityDirection = relativeVelocity.Normalized;
                        dragDirection = body.Matrices.ToBodyNormal * velocityDirection.LeftHandNormal;
                        return dragDirection;
                    };

                    FluidInfo lineInfo = wrapper.affectable.GetFluidInfo(callback, bodyLine);
                    if (lineInfo == null) { continue; }
                  //  Vector2D centTemp = lineInfo.Centroid;
                    Scalar areaTemp = lineInfo.Area;
                  //  Vector2D centroid = body.Matrices.ToWorldNormal * centTemp;
                    Vector2D buoyancyForce = body.State.Acceleration.Linear * areaTemp * -Density;
                    body.ApplyForce(buoyancyForce, centroid);


/*
                    PhysicsHelper.GetRelativeVelocity(ref body.State.Velocity, ref centroid, out relativeVelocity);
                    relativeVelocity =  FluidVelocity-relativeVelocity;
                    velocityDirection = relativeVelocity.Normalized;
                    dragDirection = body.Matrices.ToBodyNormal * velocityDirection.LeftHandNormal;

                    lineInfo = wrapper.affectable.GetFluidInfo(dragDirection, bodyLine);
                    if (lineInfo == null) { continue; }*/

                    Scalar speedSq = relativeVelocity.MagnitudeSq;
                    Scalar dragForceMag = -.5f * Density * speedSq * lineInfo.DragArea * DragCoefficient;
                    Scalar maxDrag = -MathHelper.Sqrt(speedSq) * body.Mass.Mass * step.DtInv;
                    if (dragForceMag < maxDrag)
                    {
                        dragForceMag = maxDrag;
                    }

                    Vector2D dragForce = dragForceMag * velocityDirection;
                    body.ApplyForce(dragForce, body.Matrices.ToWorldNormal * lineInfo.DragCenter);

                    body.ApplyTorque(
                       -body.Mass.MomentOfInertia *
                       (body.Coefficients.DynamicFriction + Density + DragCoefficient) *
                       body.State.Velocity.Angular);
                }
                else
                {

                    Vector2D relativeVelocity = body.State.Velocity.Linear - FluidVelocity;
                    Vector2D velocityDirection = relativeVelocity.Normalized;
                    Vector2D dragDirection = body.Matrices.ToBodyNormal * velocityDirection.LeftHandNormal;

                    Vector2D centroid = wrapper.body.Matrices.ToWorldNormal * wrapper.affectable.Centroid;
                    Vector2D buoyancyForce = body.State.Acceleration.Linear * wrapper.affectable.Area * -Density;
                    wrapper.body.ApplyForce(buoyancyForce, centroid);
                    if (velocityDirection == Vector2D.Zero) { continue; }

                    DragInfo dragInfo = wrapper.affectable.GetFluidInfo(dragDirection);
                    if (dragInfo.DragArea < .01f) { continue; }
                    Scalar speedSq = relativeVelocity.MagnitudeSq;
                    Scalar dragForceMag = -.5f * Density * speedSq * dragInfo.DragArea * DragCoefficient;
                    Scalar maxDrag = -MathHelper.Sqrt(speedSq) * body.Mass.Mass * step.DtInv;
                    if (dragForceMag < maxDrag)
                    {
                        dragForceMag = maxDrag;
                    }

                    Vector2D dragForce = dragForceMag * velocityDirection;
                    wrapper.body.ApplyForce(dragForce, body.Matrices.ToWorldNormal * dragInfo.DragCenter);

                    wrapper.body.ApplyTorque(
                       -body.Mass.MomentOfInertia *
                       (body.Coefficients.DynamicFriction + Density + DragCoefficient) *
                       body.State.Velocity.Angular);
                }
            }
        }
예제 #60
0
        internal override void SolveVelocityConstraints(ref TimeStep step)
        {
            Body b1 = BodyA;
            Body b2 = BodyB;

            Transform xf1, xf2;

            b1.GetTransform(out xf1);
            b2.GetTransform(out xf2);

            Vector2 r1 = MathUtils.Multiply(ref xf1.R, LocalAnchorA - b1.LocalCenter);
            Vector2 r2 = MathUtils.Multiply(ref xf2.R, LocalAnchorB - b2.LocalCenter);

            if (_state == LimitState.AtUpper)
            {
                Vector2 v1 = b1.LinearVelocityInternal + MathUtils.Cross(b1.AngularVelocityInternal, r1);
                Vector2 v2 = b2.LinearVelocityInternal + MathUtils.Cross(b2.AngularVelocityInternal, r2);

                float Cdot       = -Vector2.Dot(_u1, v1) - Ratio * Vector2.Dot(_u2, v2);
                float impulse    = _pulleyMass * (-Cdot);
                float oldImpulse = _impulse;
                _impulse = Math.Max(0.0f, _impulse + impulse);
                impulse  = _impulse - oldImpulse;

                Vector2 P1 = -impulse * _u1;
                Vector2 P2 = -Ratio * impulse * _u2;
                b1.LinearVelocityInternal  += b1.InvMass * P1;
                b1.AngularVelocityInternal += b1.InvI * MathUtils.Cross(r1, P1);
                b2.LinearVelocityInternal  += b2.InvMass * P2;
                b2.AngularVelocityInternal += b2.InvI * MathUtils.Cross(r2, P2);
            }

            if (_limitState1 == LimitState.AtUpper)
            {
                Vector2 v1 = b1.LinearVelocityInternal + MathUtils.Cross(b1.AngularVelocityInternal, r1);

                float Cdot       = -Vector2.Dot(_u1, v1);
                float impulse    = -_limitMass1 * Cdot;
                float oldImpulse = _limitImpulse1;
                _limitImpulse1 = Math.Max(0.0f, _limitImpulse1 + impulse);
                impulse        = _limitImpulse1 - oldImpulse;

                Vector2 P1 = -impulse * _u1;
                b1.LinearVelocityInternal  += b1.InvMass * P1;
                b1.AngularVelocityInternal += b1.InvI * MathUtils.Cross(r1, P1);
            }

            if (_limitState2 == LimitState.AtUpper)
            {
                Vector2 v2 = b2.LinearVelocityInternal + MathUtils.Cross(b2.AngularVelocityInternal, r2);

                float Cdot       = -Vector2.Dot(_u2, v2);
                float impulse    = -_limitMass2 * Cdot;
                float oldImpulse = _limitImpulse2;
                _limitImpulse2 = Math.Max(0.0f, _limitImpulse2 + impulse);
                impulse        = _limitImpulse2 - oldImpulse;

                Vector2 P2 = -impulse * _u2;
                b2.LinearVelocityInternal  += b2.InvMass * P2;
                b2.AngularVelocityInternal += b2.InvI * MathUtils.Cross(r2, P2);
            }
        }