Esempio n. 1
0
        protected virtual void Set(Part p, ReentrySimulation.SimCurves _simCurves)
        {
            Rigidbody rigidbody = p.rb;

            totalMass = rigidbody == null ? 0 : rigidbody.mass; // TODO : check if we need to use this or the one without the childMass
            shieldedFromAirstream = p.ShieldedFromAirstream;

            noDrag = rigidbody == null && !PhysicsGlobals.ApplyDragToNonPhysicsParts;
            hasLiftModule = p.hasLiftModule;
            bodyLiftMultiplier = p.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier;

            simCurves = _simCurves;

            cubes = new DragCubeList();
            CopyDragCubesList(p.DragCubes, cubes);

            // Rotation to convert the vessel space vesselVelocity to the part space vesselVelocity
            vesselToPart = Quaternion.LookRotation(p.vessel.GetTransform().InverseTransformDirection(p.transform.forward), p.vessel.GetTransform().InverseTransformDirection(p.transform.up)).Inverse();

            //DragCubeMultiplier = PhysicsGlobals.DragCubeMultiplier;
            //DragMultiplier = PhysicsGlobals.DragMultiplier;


            //if (p.dragModel != Part.DragModel.CUBE)
            //    MechJebCore.print(p.name + " " + p.dragModel);

            //oPart = p;

        }
Esempio n. 2
0
        protected virtual void Set(Part p, ReentrySimulation.SimCurves _simCurves)
        {
            Rigidbody rigidbody = p.rb;

            totalMass             = rigidbody == null ? 0 : rigidbody.mass; // TODO : check if we need to use this or the one without the childMass
            shieldedFromAirstream = p.ShieldedFromAirstream;

            noDrag             = rigidbody == null && !PhysicsGlobals.ApplyDragToNonPhysicsParts;
            hasLiftModule      = p.hasLiftModule;
            bodyLiftMultiplier = p.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier;

            simCurves = _simCurves;

            cubes = new DragCubeList();
            CopyDragCubesList(p.DragCubes, cubes);

            // Rotation to convert the vessel space vesselVelocity to the part space vesselVelocity
            vesselToPart = Quaternion.LookRotation(p.vessel.GetTransform().InverseTransformDirection(p.transform.forward), p.vessel.GetTransform().InverseTransformDirection(p.transform.up)).Inverse();

            //DragCubeMultiplier = PhysicsGlobals.DragCubeMultiplier;
            //DragMultiplier = PhysicsGlobals.DragMultiplier;


            //if (p.dragModel != Part.DragModel.CUBE)
            //    MechJebCore.print(p.name + " " + p.dragModel);

            //oPart = p;
        }
Esempio n. 3
0
        //TODO : rewrite the cube calls to only store and update the minimum needed data ( AreaOccluded + WeightedDrag ?)

        protected static void CopyDragCubesList(DragCubeList source, DragCubeList dest)
        {
            dest.ClearCubes();

            dest.None = source.None;

            // Procedural need access to part so things gets bad quick.
            dest.Procedural = false;

            for (int i = 0; i < source.Cubes.Count; i++)
            {
                DragCube c = DragCubePool.Instance.Borrow();
                CopyDragCube(source.Cubes[i], c);
                dest.Cubes.Add(c);
            }

            dest.SetDragWeights();

            for (int i = 0; i < 6; i++)
            {
                dest.WeightedArea[i]  = source.WeightedArea[i];
                dest.WeightedDrag[i]  = source.WeightedDrag[i];
                dest.AreaOccluded[i]  = source.AreaOccluded[i];
                dest.WeightedDepth[i] = source.WeightedDepth[i];
            }

            dest.SetDragWeights();

            // We are missing PostOcclusionArea but it seems to be used in Thermal only
        }
Esempio n. 4
0
 // Unfortunately the DragCubeList SetDrag method is not thread safe
 // so here is a thread safe version
 protected void SetDrag(Vector3d dragVector, float machNumber)
 {
     areaDrag  = 0;
     liftForce = Vector3d.zero;
     if (cubes.None)
     {
         return;
     }
     for (int i = 0; i < 6; i++)
     {
         Vector3d faceDirection = DragCubeList.GetFaceDirection((DragCube.DragFace)i);
         float    dragDot       = (float)Vector3d.Dot(dragVector, faceDirection);
         float    dragValue     = DragCurveValue((dragDot + 1f) * 0.5f, machNumber);
         float    faceAreaDrag  = cubes.AreaOccluded[i] * dragValue;
         areaDrag = areaDrag + faceAreaDrag * cubes.WeightedDrag[i];
         if (dragDot > 0f)
         {
             float lift = simCurves.LiftCurve.Evaluate(dragDot);
             if (!double.IsNaN(lift))
             {
                 liftForce = liftForce - faceDirection * (dragDot * cubes.AreaOccluded[i] * cubes.WeightedDrag[i] * lift);
             }
         }
     }
 }
Esempio n. 5
0
        private void Set(Part p, ReentrySimulation.SimCurves _simCurves)
        {
            totalMass             = p.mass + p.GetResourceMass() + p.GetPhysicslessChildMass();
            shieldedFromAirstream = p.ShieldedFromAirstream;

            noDrag             = p.rb == null && !PhysicsGlobals.ApplyDragToNonPhysicsParts;
            hasLiftModule      = p.hasLiftModule;
            bodyLiftMultiplier = p.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier;

            simCurves = _simCurves;


            // TODO : choose either method :
            // - use the part cube but have the risk that the part change the cubes values (stagging, ...) while we do the sim
            // - use a copy of the cubes but use more mem
            cubes = p.DragCubes;
            //cubes = new DragCubeList();
            //CopyDragCubesList(p.DragCubes, cubes);

            // Rotation to convert the vessel space vesselVelocity to the part space vesselVelocity
            vesselToPart = Quaternion.LookRotation(p.vessel.GetTransform().InverseTransformDirection(p.transform.forward), p.vessel.GetTransform().InverseTransformDirection(p.transform.up)).Inverse();


            //DragCubeMultiplier = PhysicsGlobals.DragCubeMultiplier;
            //DragMultiplier = PhysicsGlobals.DragMultiplier;


            if (p.dragModel != Part.DragModel.CUBE)
            {
                MechJebCore.print(p.name + " " + p.dragModel);
            }

            //oPart = p;
        }
Esempio n. 6
0
        public static void CopyDragCubesList(DragCubeList source, DragCubeList dest)
        {
            dest.ClearCubes();

            dest.None       = source.None;
            dest.Procedural = source.Procedural;

            for (int i = 0; i < source.Cubes.Count; i++)
            {
                DragCube c = new DragCube();
                CopyDragCube(source.Cubes[i], c);
                dest.Cubes.Add(c);
            }

            dest.SetDragWeights();

            for (int i = 0; i < 6; i++)
            {
                dest.WeightedArea[i]  = source.WeightedArea[i];
                dest.WeightedDrag[i]  = source.WeightedDrag[i];
                dest.AreaOccluded[i]  = source.AreaOccluded[i];
                dest.WeightedDepth[i] = source.WeightedDepth[i];
            }

            dest.SetDragWeights();

            // We are missing PostOcclusionArea but it seems to be used in Thermal only
        }
Esempio n. 7
0
 private void BuildCubeData()
 {
     DragCubeList cubes = part.DragCubes;
     XP = $"{cubes.WeightedArea[0]:F2} ({cubes.GetCubeAreaDir(DragCubeList.GetFaceDirection(DragCube.DragFace.XP)):F2})";
     XN = $"{cubes.WeightedArea[1]:F2} ({cubes.GetCubeAreaDir(DragCubeList.GetFaceDirection(DragCube.DragFace.XN)):F2})";
     YP = $"{cubes.WeightedArea[2]:F2} ({cubes.GetCubeAreaDir(DragCubeList.GetFaceDirection(DragCube.DragFace.YP)):F2})";
     YN = $"{cubes.WeightedArea[3]:F2} ({cubes.GetCubeAreaDir(DragCubeList.GetFaceDirection(DragCube.DragFace.YN)):F2})";
     ZP = $"{cubes.WeightedArea[4]:F2} ({cubes.GetCubeAreaDir(DragCubeList.GetFaceDirection(DragCube.DragFace.ZP)):F2})";
     ZN = $"{cubes.WeightedArea[5]:F2} ({cubes.GetCubeAreaDir(DragCubeList.GetFaceDirection(DragCube.DragFace.ZN)):F2})";
 }
Esempio n. 8
0
        protected void CopyDragCubesList(DragCubeList source, DragCubeList dest)
        {
            source.ForceUpdate(true, true);
            source.SetDragWeights();
            source.SetPartOcclusion();

            dest.ClearCubes();

            dest.SetPart(source.Part);

            dest.None = source.None;

            // Procedural need access to part so things gets bad quick.
            dest.Procedural = false;

            for (int i = 0; i < source.Cubes.Count; i++)
            {
                DragCube c;
                lock (DragCubePool.Instance)
                    c = DragCubePool.Instance.Borrow();
                CopyDragCube(source.Cubes[i], c);
                dest.Cubes.Add(c);
            }

            dest.SetDragWeights();

            for (int i = 0; i < 6; i++)
            {
                dest.WeightedArea[i]  = source.WeightedArea[i];
                dest.WeightedDrag[i]  = source.WeightedDrag[i];
                dest.AreaOccluded[i]  = source.AreaOccluded[i];
                dest.WeightedDepth[i] = source.WeightedDepth[i];
            }

            dest.SetDragWeights();

            dest.BodyLiftCurve = new PhysicsGlobals.LiftingSurfaceCurve();
            dest.SurfaceCurves = new PhysicsGlobals.SurfaceCurvesList();

            dest.DragCurveCd         = simCurves.DragCurveCd.Clone();
            dest.DragCurveCdPower    = simCurves.DragCurveCdPower.Clone();
            dest.DragCurveMultiplier = simCurves.DragCurveMultiplier.Clone();

            dest.BodyLiftCurve.liftCurve     = simCurves.LiftCurve.Clone();
            dest.BodyLiftCurve.dragCurve     = simCurves.DragCurve.Clone();
            dest.BodyLiftCurve.dragMachCurve = simCurves.DragMachCurve.Clone();
            dest.BodyLiftCurve.liftMachCurve = simCurves.LiftMachCurve.Clone();

            dest.SurfaceCurves.dragCurveMultiplier = simCurves.DragCurveMultiplier.Clone();
            dest.SurfaceCurves.dragCurveSurface    = simCurves.DragCurveSurface.Clone();
            dest.SurfaceCurves.dragCurveTail       = simCurves.DragCurveTail.Clone();
            dest.SurfaceCurves.dragCurveTip        = simCurves.DragCurveTip.Clone();

            dest.SetPartOcclusion();
        }
Esempio n. 9
0
        public void setup()
        {
            //Get rid of decoupler shroud module if no top node found
            if (destroyShroudIfNoTopNode())
            {
                return;
            }

            starDragCubes = part.DragCubes;
            getTextureNames();

            //Remove copied decoupler shroud when copied
            Transform copiedDecouplerShroud = transform.FindChild("DecouplerShroud");

            if (copiedDecouplerShroud != null)
            {
                Destroy(copiedDecouplerShroud.gameObject);
                shroudCylinders = null;
            }

            //Set up events
            part.OnEditorAttach += partReattached;
            part.OnEditorDetach += partDetached;

            Fields[nameof(shroudEnabled)].OnValueModified  += activeToggled;
            Fields[nameof(autoDetectSize)].OnValueModified += setButtonActive;
            Fields[nameof(autoDetectSize)].OnValueModified += detectSize;

            Fields[nameof(topWidth)].OnValueModified     += updateShroud;
            Fields[nameof(botWidth)].OnValueModified     += updateShroud;
            Fields[nameof(height)].OnValueModified       += updateShroud;
            Fields[nameof(thickness)].OnValueModified    += updateShroud;
            Fields[nameof(vertOffset)].OnValueModified   += updateShroud;
            Fields[nameof(textureIndex)].OnValueModified += updateTexture;

            setButtonActive();

            if (HighLogic.LoadedSceneIsFlight)
            {
                createShroudGO();
                if (GetShroudedPart() != null && shroudEnabled)
                {
                    GetShroudedPart().AddShield(this);
                }
            }
            else
            {
                if (part.isAttached)
                {
                    createShroudGO();
                }
            }
            detectSize();
            setupFinished = true;
        }
Esempio n. 10
0
        static float GetFacingAreaSum(Vector3 direction, float[] faceAreaArray)
        {
            float num = 0;

            for (int i = 0; i < 6; i++)
            {
                float num2 = Mathf.Clamp01(Vector3.Dot(direction, DragCubeList.GetFaceDirection((DragCube.DragFace)i)));
                num += faceAreaArray [i] * num2;
            }
            return(num);
        }
Esempio n. 11
0
        //Retreives an "apparent" diameter from a DragCube
        private float GetApparentDiameter(DragCube cube)
        {
            float area = 0;

            for (int i = 0; i < 6; i++)
            {
                area += cube.Area[i] * cube.Drag[i]
                        * PhysicsGlobals.DragCurveValue((Vector3.Dot(Vector3.up, DragCubeList.GetFaceDirection((DragCube.DragFace)i)) + 1f) * 0.5f, 0);
            }
            return((float)(Math.Max(Math.Round(Math.Sqrt((area * PhysicsGlobals.DragCubeMultiplier * PhysicsGlobals.DragMultiplier) / Math.PI) * 2d, 1, MidpointRounding.AwayFromZero), 0.1)));
        }
Esempio n. 12
0
        public DragCubeList.CubeData AddSurfaceDragDirection(Vector3 direction, float machNumber)
        {
            part.DragCubes.SetDrag(direction, machNumber);
            //var liftCurves = GetPrivate<PhysicsGlobals.LiftingSurfaceCurve>("liftCurves", part.DragCubes);
            var   liftCurves = part.DragCubes.BodyLiftCurve;
            float num        = 0;

            DragCubeList.CubeData result = default(DragCubeList.CubeData);
            result.dragVector = direction;
            for (int i = 0; i < 6; i++)
            {
                Vector3 faceDirection = DragCubeList.GetFaceDirection((DragCube.DragFace)i);
                float   num2          = Vector3.Dot(direction, faceDirection);
                float   dotNormalized = (num2 + 1) * 0.5f;
                float   num3          = PhysicsGlobals.DragCurveValue(PhysicsGlobals.SurfaceCurves, dotNormalized, machNumber);
                float   num4          = this.areaOccluded [i] * num3;
                float   num5          = this.weightedDrag [i];
                float   num6          = num5;
                if (num6 < 1)
                {
                    num6 = PhysicsGlobals.DragCurveCd.Evaluate(num6);
                }
                result.area               += num4;
                result.areaDrag           += num4 * num6;
                result.crossSectionalArea += this.areaOccluded [i] * Mathf.Clamp01(num2);
                if (num5 < 0.01)
                {
                    num5 = 1;
                }
                if (num5 < 1)
                {
                    num5 = 1 / num5;
                }
                result.exposedArea += num4 / PhysicsGlobals.DragCurveMultiplier.Evaluate(machNumber) * num5;
                if (num2 > 0)
                {
                    num += num2;
                    double num7 = (double)liftCurves.liftCurve.Evaluate(num2);
                    if (!double.IsNaN(num7))
                    {
                        result.liftForce += -faceDirection * (num2 * this.areaOccluded [i] * this.weightedDrag [i] * (float)num7);
                    }
                    result.depth     += num2 * this.weightedDepth [i];
                    result.dragCoeff += num2 * num6;
                }
            }
            float num8 = 1 / num;

            result.depth     *= num8;
            result.dragCoeff *= num8;
            return(result);
        }
Esempio n. 13
0
        protected void CopyDragCubesList(DragCubeList source, DragCubeList dest)
        {
            dest.ClearCubes();

            dest.SetPart(source.Part);

            dest.None = source.None;

            // Procedural need access to part so things gets bad quick.
            dest.Procedural = false;

            for (int i = 0; i < source.Cubes.Count; i++)
            {
                DragCube c = DragCubePool.Instance.Borrow();
                CopyDragCube(source.Cubes[i], c);
                dest.Cubes.Add(c);
            }

            dest.SetDragWeights();

            for (int i = 0; i < 6; i++)
            {
                dest.WeightedArea[i]  = source.WeightedArea[i];
                dest.WeightedDrag[i]  = source.WeightedDrag[i];
                dest.AreaOccluded[i]  = source.AreaOccluded[i];
                dest.WeightedDepth[i] = source.WeightedDepth[i];
            }

            dest.SetDragWeights();

            dest.DragCurveCd         = simCurves.DragCurveCd;
            dest.DragCurveCdPower    = simCurves.DragCurveCdPower;
            dest.DragCurveMultiplier = simCurves.DragCurveMultiplier;

            dest.BodyLiftCurve.liftCurve     = simCurves.LiftCurve;
            dest.BodyLiftCurve.dragCurve     = simCurves.DragCurve;
            dest.BodyLiftCurve.dragMachCurve = simCurves.DragMachCurve;
            dest.BodyLiftCurve.liftMachCurve = simCurves.LiftMachCurve;

            dest.SurfaceCurves.dragCurveMultiplier = simCurves.DragCurveMultiplier;
            dest.SurfaceCurves.dragCurveSurface    = simCurves.DragCurveSurface;
            dest.SurfaceCurves.dragCurveTail       = simCurves.DragCurveTail;
            dest.SurfaceCurves.dragCurveTip        = simCurves.DragCurveTip;
        }
Esempio n. 14
0
 void AreaToCubeOperation(Vector3 direction, float area, Func <float, float, float> operation)
 {
     for (int i = 0; i < 6; i++)
     {
         float num = Mathf.Clamp01(Vector3.Dot(direction, DragCubeList.GetFaceDirection((DragCube.DragFace)i)));
         if (num > 0)
         {
             this.areaOccluded[i] = operation(area * num, this.areaOccluded[i]);
             float num2 = this.weightedArea [i] - this.areaOccluded[i];
             if (this.areaOccluded[i] > 0)
             {
                 this.weightedDrag[i] = Mathf.Max(0, (this.weightedDragOrig[i] * this.weightedArea[i] - num2) / this.areaOccluded[i]);
             }
             else
             {
                 this.weightedDrag[i] = 1E-05f;
             }
         }
     }
 }
        //Retrieves an "apparent" diameter from a DragCube
        private static float GetApparentDiameter(DragCube cube)
        {
            float area = 0;

            for (int i = 0; i < 6; i++)
            {
                // TODO 1.2: according to API docs this method should have only 2 arguments but it has 3
                area += cube.Area[i] *
                        cube.Drag[i] *
                        PhysicsGlobals.DragCurveValue(PhysicsGlobals.SurfaceCurves,
                                                      (Vector3.Dot(Vector3.up,
                                                                   DragCubeList
                                                                   .GetFaceDirection((DragCube.DragFace)i)) +
                                                       1) *
                                                      0.5f,
                                                      0);
            }
            return((float)Math.Max(Math.Round(Math.Sqrt(area * 0.1f * PhysicsGlobals.DragMultiplier / Math.PI) * 2,
                                              1,
                                              MidpointRounding.AwayFromZero),
                                   0.1));
        }
        public void setup()
        {
            starDragCubes = part.DragCubes;
            getTextures();

            //Set up events
            part.OnEditorAttach += partReattached;
            part.OnEditorDetach += partDetached;

            Fields[nameof(shroudEnabled)].OnValueModified  += activeToggled;
            Fields[nameof(autoDetectSize)].OnValueModified += setButtonActive;
            Fields[nameof(autoDetectSize)].OnValueModified += detectSize;

            Fields[nameof(topWidth)].OnValueModified     += updateShroud;
            Fields[nameof(botWidth)].OnValueModified     += updateShroud;
            Fields[nameof(height)].OnValueModified       += updateShroud;
            Fields[nameof(thickness)].OnValueModified    += updateShroud;
            Fields[nameof(vertOffset)].OnValueModified   += updateShroud;
            Fields[nameof(textureIndex)].OnValueModified += updateTexture;

            setButtonActive();

            if (HighLogic.LoadedSceneIsFlight)
            {
                createShroudGO();
                if (GetShroudedPart() != null && shroudEnabled)
                {
                    GetShroudedPart().AddShield(this);
                }
            }
            else
            {
                if (part.isAttached)
                {
                    createShroudGO();
                }
            }
            detectSize();
        }
Esempio n. 17
0
                public void update(double curSpeed, double curDensity)
                {
                    maxSpeed      = 0;
                    breakDistance = 0;
                    curDensity    = Math.Max(curDensity, 0.2 * vesselState.mainBody.atmDensityASL);
                    double curSpeedOfSound = Math.Max(vesselState.speedOfSound, vesselState.mainBody.GetSpeedOfSound(0.2 * vesselState.mainBody.atmPressureASL, 0.2 * vesselState.mainBody.atmDensityASL));
                    //create List by descending order of maxSpeed with drag and max chute reaction time
                    SortedList <double, (float, float)> parachuteTypes = new SortedList <double, (float, float)>(Comparer <double> .Create((a, b) => Math.Sign(b - a)));

                    foreach (var p in vesselState.parachutes)
                    {
                        if (p.deploymentState == ModuleParachute.deploymentStates.STOWED)
                        {
                            p.refDensity = curDensity;
                            p.CalcBaseStats();
                            DragCubeList simParachute = new DragCubeList();
                            simParachute.LoadCube(p.part.DragCubes, "DEPLOYED");
                            simParachute.SetPart(p.part);
                            simParachute.SetOcclusionMultiplier(0f);
                            simParachute.ResetCubeWeights();
                            simParachute.SetDragWeights();
                            simParachute.SetPartOcclusion();
                            //Debug.Log(String.Format("ParachuteInfo.update Parchute {0} has up Cube area={1:F1} drag={2:F1} weight={3:F1} AreaOccluded={4:F1}",
                            //    p.part.name, simParachute.Cubes[0].Area[(int) DragCube.DragFace.YP], simParachute.Cubes[0].Drag[(int) DragCube.DragFace.YP],
                            //    simParachute.Cubes[0].Weight, simParachute.AreaOccluded[(int)DragCube.DragFace.YP]));
                            DragCubeList.CubeData simDrag = new DragCubeList.CubeData();
                            simParachute.AddSurfaceDragDirection(Vector3.up, (float)(p.maxSafeSpeedAtRef / curSpeedOfSound), ref simDrag);
                            //Debug.Log(String.Format("ParachuteInfo.update Parchute {0} has areaDrag={1:F1}, crossSectionalArea={2:F1}, exposedArea={3:F1}",
                            //          p.part.name, simDrag.areaDrag, simDrag.crossSectionalArea, simDrag.exposedArea));
                            if (parachuteTypes.ContainsKey(p.maxSafeSpeedAtRef))
                            {
                                parachuteTypes[p.maxSafeSpeedAtRef] = (parachuteTypes[p.maxSafeSpeedAtRef].Item1 + simDrag.areaDrag,
                                                                       Mathf.Max(parachuteTypes[p.maxSafeSpeedAtRef].Item2, p.Anim[p.semiDeployedAnimation].length / p.semiDeploymentSpeed + p.Anim[p.fullyDeployedAnimation].length / p.deploymentSpeed));
                            }
                            else
                            {
                                parachuteTypes.Add(p.maxSafeSpeedAtRef, (simDrag.areaDrag, p.Anim[p.semiDeployedAnimation].length / p.semiDeploymentSpeed + p.Anim[p.fullyDeployedAnimation].length / p.deploymentSpeed));
                            }
                        }
                    }
                    float  totalFriction = 0;
                    double lastSpeed     = 0;

                    foreach (var pt in parachuteTypes)
                    {
                        double effSpeed = Math.Min(curSpeed, pt.Key);
                        // base equation deceleration term + chute reaction term with deceleration taken from moving equations with netwon friction
                        // during reaction time we hardly break, so assume
                        float friction_const = pt.Value.Item1 * 0.0005f * (float)curDensity * PhysicsGlobals.DragMultiplier
                                               * PhysicsGlobals.DragCubeMultiplier * PhysicsGlobals.DragCurvePseudoReynolds.Evaluate((float)(effSpeed * curDensity));
                        if (breakDistance == 0) // first term for highest speed
                        {
                            breakDistance      = (float)vesselState.mass / friction_const * Math.Log(effSpeed) + effSpeed * pt.Value.Item2;
                            undeployedDistance = effSpeed * pt.Value.Item2;// - vesselState.mass / friction_const  ;
                            maxSpeed           = lastSpeed = effSpeed;
                            totalFriction      = friction_const;
                            //Debug.Log(String.Format("ParachuteInfo.update has first chute type with friction={0:F4} and effSpeed={1:F0}, delay={3:F1} results break dist={2:F0}", friction_const, effSpeed, breakDistance, pt.Value.Item2));
                        }
                        else
                        {
                            // calculate slowdown during parachute opening using old friction
                            effSpeed           *= (float)vesselState.mass / (totalFriction * pt.Value.Item2 * effSpeed + vesselState.mass);
                            breakDistance      -= (float)vesselState.mass / (totalFriction + friction_const) * friction_const / totalFriction * Math.Log(effSpeed);
                            undeployedDistance += pt.Value.Item2 * effSpeed;// + vesselState.mass * lastSpeed / (totalFriction * effSpeed) - vesselState.mass / (totalFriction + friction_const);
                            lastSpeed           = effSpeed;
                            totalFriction      += friction_const;
                            //Debug.Log(String.Format("ParachuteInfo.update has next chute type with friction={0:F4} and effSpeed={1:F0}, delay={3:F1} results break dist={2:F0}", friction_const, effSpeed, breakDistance, pt.Value.Item2));
                        }
                    }
                    if (totalFriction > 0)
                    {
                        double terminalSpeed = Math.Sqrt((float)vesselState.mass / totalFriction * vesselState.mainBody.GeeASL * PhysicsGlobals.GravitationalAcceleration);
                        //we are not getting slower than terminal velocity, so substract this as best guess for integration constant v
                        breakDistance -= (float)vesselState.mass / totalFriction * Math.Log(terminalSpeed);
                        //undeployedDistance += vesselState.mass * lastSpeed / (totalFriction * terminalSpeed);
                        //Debug.Log(String.Format("ParachuteInfo.update has terminal velocity term with friction={0:F4} and terminalSpeed={1:F0} results break dist={2:F0}", totalFriction, terminalSpeed, breakDistance));
                    }
                    Debug.Log(String.Format("ParachuteInfo.update for speed={0:F0} gives maxSpeed={1:F0} break dist={2:F0} undeployedDistance={3:F0}", curSpeed, maxSpeed, breakDistance, undeployedDistance));
                }
Esempio n. 18
0
        public override void OnStart(PartModule.StartState state)
        {
            if (!HighLogic.LoadedSceneIsEditor && !HighLogic.LoadedSceneIsFlight)
            {
                return;
            }
            if (!CompatibilityChecker.IsAllCompatible())
            {
                Actions.ForEach(a => a.active = false);
                Events.ForEach(e =>
                {
                    e.active          = false;
                    e.guiActive       = false;
                    e.guiActiveEditor = false;
                });
                Fields["chuteCount"].guiActive = false;
                return;
            }

            //Staging icon
            this.part.stagingIcon = "PARACHUTES";
            InitializeAnimationSystem();

            //First initiation of the part
            if (!this.initiated)
            {
                this.initiated  = true;
                this.armed      = false;
                this.chuteCount = maxSpares;
                this.cap.gameObject.SetActive(true);
            }
            this.part.mass = this.totalMass;
            this.massDelta = 0f;
            if ((object)(this.part.partInfo) != null && (object)(this.part.partInfo.partPrefab) != null)
            {
                this.massDelta = this.part.mass - this.part.partInfo.partPrefab.mass;
            }

            //Flight loading
            if (HighLogic.LoadedSceneIsFlight)
            {
                Random random = new Random();
                this.randomTime = (float)random.NextDouble();
                this.randomX    = (float)(random.NextDouble() * 100);
                this.randomY    = (float)(random.NextDouble() * 100);

                //Hide/show UI event addition
                GameEvents.onHideUI.Add(HideUI);
                GameEvents.onShowUI.Add(ShowUI);

                if (this.canRepack)
                {
                    SetRepack();
                }

                if (this.time != 0)
                {
                    this.dragTimer = new PhysicsWatch(this.time);
                }
                if (this.deploymentState != DeploymentStates.STOWED)
                {
                    this.part.stackIcon.SetIconColor(XKCDColors.Red);
                    this.cap.gameObject.SetActive(false);
                }

                if (this.staged && this.isDeployed)
                {
                    this.parachute.gameObject.SetActive(true);
                    switch (this.deploymentState)
                    {
                    case DeploymentStates.PREDEPLOYED:
                        this.part.SkipToAnimationTime(this.semiDeployedAnimation, this.semiDeploymentSpeed, Mathf.Clamp01(this.time)); break;

                    case DeploymentStates.DEPLOYED:
                        this.part.SkipToAnimationTime(this.fullyDeployedAnimation, this.deploymentSpeed, Mathf.Clamp01(this.time)); break;

                    default:
                        break;
                    }
                }

                DragCubeList cubes = this.part.DragCubes;
                //Set stock cubes to 0
                cubes.SetCubeWeight("PACKED", 0);
                cubes.SetCubeWeight("SEMIDEPLOYED", 0);
                cubes.SetCubeWeight("DEPLOYED", 0);

                //Sets RC cubes
                if (this.deploymentState == DeploymentStates.STOWED)
                {
                    cubes.SetCubeWeight("PACKED", 1);
                    cubes.SetCubeWeight("RCDEPLOYED", 0);
                }
                else
                {
                    cubes.SetCubeWeight("PACKED", 0);
                    cubes.SetCubeWeight("RCDEPLOYED", 1);
                }
            }

            //GUI
            this.window = new Rect(200, 100, 350, 400);
            this.drag   = new Rect(0, 0, 350, 30);
        }
Esempio n. 19
0
        private void Init(IShipconstruct v)
        {
            totalMass        = 0;
            dryMass          = 0;
            CoM              = Vector3.zero;
            CoM_dry          = Vector3.zero;
            relativeWingArea = 0;
            stage            = 0;

            List <Part>          oParts = v.Parts;
            List <SimulatedPart> variableDragParts_ctrls = new List <SimulatedPart>();

            count = oParts.Count;

            if (HighLogic.LoadedSceneIsEditor)
            {
                for (int i = 0; i < v.Parts.Count; i++)
                {
                    Part p = v.Parts[i];
                    if (p.dragModel == Part.DragModel.CUBE && !p.DragCubes.None)
                    {
                        DragCubeList cubes = p.DragCubes;
                        lock (cubes)
                        {
                            DragCubeList.CubeData p_drag_data = new DragCubeList.CubeData();

                            try
                            {
                                cubes.SetDragWeights();
                                cubes.SetPartOcclusion();
                                cubes.AddSurfaceDragDirection(-Vector3.forward, 0, ref p_drag_data);
                            }
                            catch (Exception)
                            {
                                cubes.SetDrag(Vector3.forward, 0);
                                cubes.ForceUpdate(true, true);
                                cubes.SetDragWeights();
                                cubes.SetPartOcclusion();
                                cubes.AddSurfaceDragDirection(-Vector3.forward, 0, ref p_drag_data);
                                //Debug.Log(String.Format("Trajectories: Caught NRE on Drag Initialization.  Should be fixed now.  {0}", e));
                            }
                        }
                    }
                }
            }

            bool lgWarning = false;

            for (int i = 0; i < count; i++)
            {
                if (!lgWarning)
                {
                    ModuleWheels.ModuleWheelDeployment gear = oParts[i].FindModuleImplementing <ModuleWheels.ModuleWheelDeployment>();
                    bool forcedRetract = !oParts[i].ShieldedFromAirstream && gear != null && gear.Position > 0;

                    if (forcedRetract)
                    {
                        lgWarning = true;
                    }
                }
            }

            // Recursively add all parts to collections
            // What a crazy change to make just to accomodate rotating parts!
            partCollection = PartCollection.Borrow(this, oParts[0]);

            CoM     /= totalMass;
            CoM_dry /= dryMass;

            partCollection.origin = CoM;

            if (relativeWingArea == 0)
            {
                // I'm not sure what effect calling ScreenMessages from a background thread will be.
                // Fortunately, anyone using this mod probably has at least one wing.
                ScreenMessages.PostScreenMessage("No wings found, using a reference area of 1.", 5, ScreenMessageStyle.UPPER_CENTER);
                relativeWingArea = 1;
            }

            //if (lgWarning)
            //ScreenMessages.PostScreenMessage("Landing gear deployed, results may not be accurate.", 5, ScreenMessageStyle.UPPER_CENTER);
        }
Esempio n. 20
0
        //TODO : rewrite the cube calls to only store and update the minimum needed data ( AreaOccluded + WeightedDrag ?)

        protected static void CopyDragCubesList(DragCubeList source, DragCubeList dest)
        {
            dest.ClearCubes();

            dest.None = source.None;

            // Procedural need access to part so things gets bad quick.
            dest.Procedural = false;

            for (int i = 0; i < source.Cubes.Count; i++)
            {
                DragCube c = new DragCube();
                CopyDragCube(source.Cubes[i], c);
                dest.Cubes.Add(c);
            }

            dest.SetDragWeights();

            for (int i=0; i<6; i++)
            {
                dest.WeightedArea[i] = source.WeightedArea[i];
                dest.WeightedDrag[i] = source.WeightedDrag[i];
                dest.AreaOccluded[i] = source.AreaOccluded[i];
                dest.WeightedDepth[i] = source.WeightedDepth[i];
            }

            dest.SetDragWeights();

            // We are missing PostOcclusionArea but it seems to be used in Thermal only
        }
        public override void OnStart(StartState startState)
        {
            if (!HighLogic.LoadedSceneIsEditor && !HighLogic.LoadedSceneIsFlight)
            {
                return;
            }
            if (!CompatibilityChecker.IsAllCompatible())
            {
                Actions.ForEach(a => a.active = false);
                Events.ForEach(e =>
                {
                    e.active          = false;
                    e.guiActive       = false;
                    e.guiActiveEditor = false;
                });
                Fields["chuteCount"].guiActive = false;
                return;
            }

            //Staging icon
            part.stagingIcon = "PARACHUTES";
            InitializeAnimationSystem();

            //First initiation of the part
            if (!initiated)
            {
                initiated  = true;
                armed      = false;
                chuteCount = maxSpares;
                cap.gameObject.SetActive(true);
            }

            float tmpPartMass = TotalMass;

            massDelta = 0;
            if (!(part.partInfo?.partPrefab is null))
            {
                massDelta = tmpPartMass - part.partInfo.partPrefab.mass;
            }

            //Flight loading
            if (HighLogic.LoadedSceneIsFlight)
            {
                var random = new Random();
                randomTime = (float)random.NextDouble();
                randomX    = (float)(random.NextDouble() * 100);
                randomY    = (float)(random.NextDouble() * 100);

                //Hide/show UI event addition
                GameEvents.onHideUI.Add(HideUI);
                GameEvents.onShowUI.Add(ShowUI);
                GameEvents.onStageActivate.Add(OnStageActivate);

                if (CanRepack)
                {
                    SetRepack();
                }

                if (!time.NearlyEqual(0))
                {
                    dragTimer = new PhysicsWatch(time);
                }
                if (DeploymentState != DeploymentStates.STOWED)
                {
                    part.stackIcon.SetIconColor(XKCDColors.Red);
                    cap.gameObject.SetActive(false);
                }

                if (staged && IsDeployed)
                {
                    parachute.gameObject.SetActive(true);
                    switch (DeploymentState)
                    {
                    case DeploymentStates.PREDEPLOYED:
                        part.SkipToAnimationTime(semiDeployedAnimation, semiDeploymentSpeed, Mathf.Clamp01(time));
                        break;

                    case DeploymentStates.DEPLOYED:
                        part.SkipToAnimationTime(fullyDeployedAnimation, deploymentSpeed, Mathf.Clamp01(time));
                        break;
                    }
                }

                DragCubeList cubes = part.DragCubes;
                //Set stock cubes to 0
                cubes.SetCubeWeight("PACKED", 0);
                cubes.SetCubeWeight("SEMIDEPLOYED", 0);
                cubes.SetCubeWeight("DEPLOYED", 0);

                //Sets RC cubes
                if (DeploymentState == DeploymentStates.STOWED)
                {
                    cubes.SetCubeWeight("PACKED", 1);
                    cubes.SetCubeWeight("RCDEPLOYED", 0);
                }
                else
                {
                    cubes.SetCubeWeight("PACKED", 0);
                    cubes.SetCubeWeight("RCDEPLOYED", 1);
                }
            }

            //GUI
            window = new Rect(200, 100, 350, 400);
            drag   = new Rect(0, 0, 350, 30);
        }
Esempio n. 22
0
        public static double GetChuteArea(List <Part> parts)
        {
            double RCParameter    = 0;
            bool   realChuteInUse = false;

            try
            {
                foreach (Part p in parts)
                {
                    //Make a list of all the Module Names for easy checking later. This can be avoided, but is convenient.
                    List <string> ModuleNames = new List <string>();
                    foreach (PartModule pm in p.Modules)
                    {
                        ModuleNames.Add(pm.moduleName);
                    }

                    if (ModuleNames.Contains("RealChuteModule"))
                    {
                        if (!realChuteInUse)
                        {
                            RCParameter = 0;
                        }
                        //First off, get the PPMS since we'll need that
                        PartModule realChute = p.Modules["RealChuteModule"];
                        //Assuming that's not somehow null, then we continue
                        if (realChute != null) //Some of this was adopted from DebRefund, as Vendan's method of handling multiple parachutes is better than what I had.
                        {
                            //We make a list of ConfigNodes containing the parachutes (usually 1, but now there can be any number of them)
                            //We get that from the PPMS
                            ConfigNode rcNode = new ConfigNode();
                            realChute.Save(rcNode);

                            //It's existence means that RealChute is installed and in use on the craft (you could have it installed and use stock chutes, so we only check if it's on the craft)
                            realChuteInUse = true;

                            RCParameter += ProcessRealchute(rcNode);
                        }
                    }
                    else if (ModuleNames.Contains("RealChuteFAR")) //RealChute Lite for FAR
                    {
                        if (!realChuteInUse)
                        {
                            RCParameter = 0;
                        }

                        PartModule realChute = p.Modules["RealChuteFAR"];
                        float      diameter  = 0.0F; //realChute.moduleValues.GetValue("deployedDiameter")

                        if (realChute != null)
                        {
                            try
                            {
                                diameter = realChute.Fields.GetValue <float>("deployedDiameter");
                                Log.Info($"[SR] Diameter is {diameter}.");
                            }
                            catch (Exception e)
                            {
                                Debug.LogError("[SR] Exception while finding deployedDiameter for RealChuteFAR module on module.");
                                Debug.LogException(e);
                            }
                        }
                        else
                        {
                            Log.Info("[SR] moduleRef is null, attempting workaround to find diameter.");
                            object dDefault = p.partInfo.partPrefab.Modules["RealChuteFAR"]?.Fields?.GetValue("deployedDiameter"); //requires C# 6
                            if (dDefault != null)
                            {
                                diameter = Convert.ToSingle(dDefault);
                                Log.Info($"[SR] Workaround gave a diameter of {diameter}.");
                            }
                            else
                            {
                                Log.Info("[SR] Couldn't get default value, setting to 0 and calling it a day.");
                                diameter = 0.0F;
                            }
                        }
                        float dragC = 1.0f; //float.Parse(realChute.moduleValues.GetValue("staticCd"));
                        RCParameter += (dragC * Mathf.Pow(diameter, 2) * Math.PI / 4.0);

                        realChuteInUse = true;
                    }
                    else if (!realChuteInUse && ModuleNames.Contains("ModuleParachute"))
                    {
                        //Credit to m4v and RCSBuildAid: https://github.com/m4v/RCSBuildAid/blob/master/Plugin/CoDMarker.cs
                        Part         part      = p ?? p.partInfo.partPrefab; //the part, or the part prefab
                        DragCubeList dragCubes = part.DragCubes;
                        dragCubes.SetCubeWeight("DEPLOYED", 1);
                        dragCubes.SetCubeWeight("SEMIDEPLOYED", 0);
                        dragCubes.SetCubeWeight("PACKED", 0);
                        dragCubes.SetOcclusionMultiplier(0);
                        Quaternion rotation = Quaternion.LookRotation(Vector3d.up);
                        try
                        {
                            rotation = Quaternion.LookRotation(part.partTransform?.InverseTransformDirection(Vector3d.up) ?? Vector3d.up);
                        }
                        catch (Exception e)
                        {
                            Debug.LogException(e);
                        }
                        dragCubes.SetDragVectorRotation(rotation);
                    }
                    if (!realChuteInUse)
                    {
                        Part         part      = p ?? p.partInfo.partPrefab; //the part reference, or the part prefab
                        DragCubeList dragCubes = part.DragCubes;
                        dragCubes.ForceUpdate(false, true);
                        dragCubes.SetDragWeights();
                        dragCubes.SetPartOcclusion();

                        Vector3 dir = Vector3d.up;
                        try
                        {
                            dir = -part.partTransform?.InverseTransformDirection(Vector3d.down) ?? Vector3d.up;
                        }
                        catch (Exception e)
                        {
                            //Debug.LogException(e);
                            Log.Info("[SR] The expected excpetion is still present. " + e.Message);
                        }
                        dragCubes.SetDrag(dir, 0.03f); //mach 0.03, or about 10m/s

                        double dragCoeff = dragCubes.AreaDrag * PhysicsGlobals.DragCubeMultiplier;

                        RCParameter += (dragCoeff * PhysicsGlobals.DragMultiplier);
                    }
                }
            }
            catch (Exception e)
            {
                Debug.LogError("[SR] Error occured while trying to determine total chute area.");
                Debug.LogException(e);
            }
            return(RCParameter);
        }
        private void Init(IShipconstruct v, SimCurves _simCurves)
        {
            totalMass = 0;
            dryMass = 0;
            CoM = Vector3.zero;
            CoM_dry = Vector3.zero;

            List<Part> oParts = v.Parts;
            List<SimulatedPart> variableDragParts_ctrls = new List<SimulatedPart>();
            count = oParts.Count;

            if (HighLogic.LoadedSceneIsEditor)
            {
                for (int i = 0; i < v.Parts.Count; i++)
                {
                    Part p = v.Parts[i];
                    if (p.dragModel == Part.DragModel.CUBE && !p.DragCubes.None)
                    {
                        DragCubeList cubes = p.DragCubes;
                        DragCubeList.CubeData p_drag_data = new DragCubeList.CubeData();

                        try
                        {
                            cubes.SetDragWeights();
                            cubes.SetPartOcclusion();
                            cubes.AddSurfaceDragDirection(-Vector3.forward, 0, ref p_drag_data);
                        }
                        catch (Exception)
                        {
                            cubes.SetDrag(Vector3.forward, 0);
                            cubes.ForceUpdate(true, true);
                            cubes.SetDragWeights();
                            cubes.SetPartOcclusion();
                            cubes.AddSurfaceDragDirection(-Vector3.forward, 0, ref p_drag_data);
                            //Debug.Log(String.Format("Trajectories: Caught NRE on Drag Initialization.  Should be fixed now.  {0}", e));
                        }
                    }
                }
            }

            simCurves = _simCurves;

            if (parts.Capacity < count)
                parts.Capacity = count;

            bool lgWarning = false;
            int stage = 0;
            for (int i = 0; i < count; i++)
            {
                if (!lgWarning)
                {
                    ModuleWheels.ModuleWheelDeployment gear = oParts[i].FindModuleImplementing<ModuleWheels.ModuleWheelDeployment>();
                    bool forcedRetract = !oParts[i].ShieldedFromAirstream && gear != null && gear.Position > 0;

                    if (forcedRetract)
                        lgWarning = true;
                }

                SimulatedPart simulatedPart = SimulatedPart.Borrow(oParts[i], this);
                parts.Add(simulatedPart);

                totalMass += simulatedPart.totalMass;
                dryMass += simulatedPart.dryMass;
                CoM += simulatedPart.totalMass * simulatedPart.CoM;
                CoM_dry += simulatedPart.dryMass * simulatedPart.CoM;
                
                ModuleLiftingSurface liftingSurface = oParts[i].FindModuleImplementing<ModuleLiftingSurface>();
                if (liftingSurface != null)
                {
                    parts[i].hasLiftModule = true;
                    if (liftingSurface is ModuleControlSurface ctrlSurface)
                    {
                        ctrls.Add(SimulatedControlSurface.Borrow(ctrlSurface, simulatedPart));
                        variableDragParts_ctrls.Add(simulatedPart);
                        if (ctrlSurface.ctrlSurfaceArea < 1)
                            surfaces.Add(SimulatedLiftingSurface.Borrow(ctrlSurface, simulatedPart));
                    }
                    else
                        surfaces.Add(SimulatedLiftingSurface.Borrow(liftingSurface, simulatedPart));
                }

                List<ITorqueProvider> torqueProviders = oParts[i].FindModulesImplementing<ITorqueProvider>();
                // TODO: Add them to a list.

                if(oParts[i].inverseStage > stage)
                {
                    SimulatedEngine.Release(engines);
                    engines.Clear();
                    stage = oParts[i].inverseStage;
                }
                if (oParts[i].inverseStage >= stage)
                {
                    MultiModeEngine multiMode = oParts[i].FindModuleImplementing<MultiModeEngine>();
                    if (multiMode != null)
                    {
                        engines.Add(SimulatedEngine.Borrow(oParts[i].FindModulesImplementing<ModuleEngines>().Find(engine => engine.engineID == multiMode.mode), simulatedPart));
                    }
                    else
                    {
                        ModuleEngines engine = oParts[i].FindModulesImplementing<ModuleEngines>().FirstOrDefault();
                        if (engine != null)
                            engines.Add(SimulatedEngine.Borrow(engine, simulatedPart));
                    }
                }
            }
            CoM /= totalMass;
            CoM_dry /= dryMass;

            if (lgWarning)
                ScreenMessages.PostScreenMessage("Landing gear deployed, results may not be accurate.", 5, ScreenMessageStyle.UPPER_CENTER);

            /*for (int i = 0; i < count; i++)
            {
                parts[i].CoM -= this.CoM;
                parts[i].CoL -= this.CoM;
                parts[i].CoP -= this.CoM;
            }*/

            parts.RemoveAll(part => variableDragParts_ctrls.Contains(part));
        }
Esempio n. 24
0
        //*******************************************************
        public static Vector3 SimAeroForce(Vessel _vessel, Vector3 v_wrld_vel, double altitude, double latitude = 0)
        {
            CelestialBody body     = _vessel.mainBody;
            double        pressure = body.GetPressure(altitude);
            // Lift and drag for force accumulation.
            Vector3d total_lift = Vector3d.zero;
            Vector3d total_drag = Vector3d.zero;

            // dynamic pressure for standard drag equation
            double rho          = GetDensity(altitude, body);
            double dyn_pressure = 0.0005 * rho * v_wrld_vel.sqrMagnitude;

            if (rho <= 0)
            {
                return(Vector3.zero);
            }

            double soundSpeed = body.GetSpeedOfSound(pressure, rho);
            double mach       = v_wrld_vel.magnitude / soundSpeed;

            if (mach > 25.0)
            {
                mach = 25.0;
            }

            // Loop through all parts, accumulating drag and lift.
            for (int i = 0; i < _vessel.Parts.Count; ++i)
            {
                // need checks on shielded components
                Part p = _vessel.Parts[i];
                if (p.ShieldedFromAirstream || p.Rigidbody == null)
                {
                    continue;
                }

                // Get Drag
                Vector3 sim_dragVectorDir      = v_wrld_vel.normalized;
                Vector3 sim_dragVectorDirLocal = -(p.transform.InverseTransformDirection(sim_dragVectorDir));

                Vector3  liftForce = new Vector3(0, 0, 0);
                Vector3d dragForce;

                switch (p.dragModel)
                {
                case Part.DragModel.DEFAULT:
                case Part.DragModel.CUBE:
                    DragCubeList cubes = p.DragCubes;

                    DragCubeList.CubeData p_drag_data = new DragCubeList.CubeData();

                    float drag;
                    if (cubes.None)     // since 1.0.5, some parts don't have drag cubes (for example fuel lines and struts)
                    {
                        drag = p.maximum_drag;
                    }
                    else
                    {
                        try
                        {
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                        }
                        catch (Exception)
                        {
                            cubes.SetDrag(sim_dragVectorDirLocal, (float)mach);
                            cubes.ForceUpdate(true, true);
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                            //Debug.Log(String.Format("Trajectories: Caught NRE on Drag Initialization.  Should be fixed now.  {0}", e));
                        }

                        float pseudoreynolds   = (float)(rho * Mathf.Abs(v_wrld_vel.magnitude));
                        float pseudoredragmult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(pseudoreynolds);
                        drag = p_drag_data.areaDrag * PhysicsGlobals.DragCubeMultiplier * pseudoredragmult;

                        liftForce = p_drag_data.liftForce;
                    }

                    double sim_dragScalar = dyn_pressure * (double)drag * PhysicsGlobals.DragMultiplier;
                    dragForce = -(Vector3d)sim_dragVectorDir * sim_dragScalar;

                    break;

                case Part.DragModel.SPHERICAL:
                    dragForce = -(Vector3d)sim_dragVectorDir * (double)p.maximum_drag;
                    break;

                case Part.DragModel.CYLINDRICAL:
                    dragForce = -(Vector3d)sim_dragVectorDir * (double)Mathf.Lerp(p.minimum_drag, p.maximum_drag, Mathf.Abs(Vector3.Dot(p.partTransform.TransformDirection(p.dragReferenceVector), sim_dragVectorDir)));
                    break;

                case Part.DragModel.CONIC:
                    dragForce = -(Vector3d)sim_dragVectorDir * (double)Mathf.Lerp(p.minimum_drag, p.maximum_drag, Vector3.Angle(p.partTransform.TransformDirection(p.dragReferenceVector), sim_dragVectorDir) / 180f);
                    break;

                default:
                    // no drag to apply
                    dragForce = new Vector3d();
                    break;
                }

                total_drag += dragForce;

                // If it isn't a wing or lifter, get body lift.
                if (!p.hasLiftModule)
                {
                    float simbodyLiftScalar = p.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier * (float)dyn_pressure;
                    simbodyLiftScalar *= PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Evaluate((float)mach);
                    Vector3 bodyLift = p.transform.rotation * (simbodyLiftScalar * liftForce);
                    bodyLift = Vector3.ProjectOnPlane(bodyLift, sim_dragVectorDir);
                    // Only accumulate forces for non-LiftModules
                    //Debug.Log("[Trajectories] bodyLift=" + bodyLift);
                    total_lift += bodyLift;
                }

                // Find ModuleLifingSurface for wings and liftforce.
                // Should catch control surface as it is a subclass
                for (int j = 0; j < p.Modules.Count; ++j)
                {
                    var   m = p.Modules[j];
                    float mcs_mod;
                    if (m is ModuleLiftingSurface)
                    {
                        mcs_mod = 1.0f;
                        double liftQ = dyn_pressure * 1000;
                        ModuleLiftingSurface wing = (ModuleLiftingSurface)m;
                        Vector3 nVel       = Vector3.zero;
                        Vector3 liftVector = Vector3.zero;
                        float   liftdot;
                        float   absdot;
                        wing.SetupCoefficients(v_wrld_vel, out nVel, out liftVector, out liftdot, out absdot);

                        double prevMach = p.machNumber;
                        p.machNumber = mach;
                        Vector3 local_lift = mcs_mod * wing.GetLiftVector(liftVector, liftdot, absdot, liftQ, (float)mach);
                        Vector3 local_drag = mcs_mod * wing.GetDragVector(nVel, absdot, liftQ);
                        p.machNumber = prevMach;

                        total_lift += local_lift;
                        total_drag += local_drag;
                    }
                }
            }
            // RETURN STUFF
            //Debug.Log("[Trajectories] total_lift" + total_lift + " total_drag=" + total_drag);
            Vector3 force = total_lift + total_drag;

            return(force);
        }
Esempio n. 25
0
        //*******************************************************
        public static Vector3 SimLiftForce(CelestialBody body, IShipconstruct vessel, Vector3 v_wrld_vel, double altitude, double latitude = 0.0)
        {
            //Profiler.Start("SimLiftForce");
            double pressure = body.GetPressure(altitude);
            // Lift and drag for force accumulation.
            Vector3d total_lift = Vector3d.zero;

            // dynamic pressure for standard drag equation
            double rho          = GetDensity(altitude, body);
            double dyn_pressure = 0.0005 * rho * v_wrld_vel.sqrMagnitude;

            if (rho <= 0)
            {
                return(Vector3.zero);
            }

            double soundSpeed = body.GetSpeedOfSound(pressure, rho);
            double mach       = v_wrld_vel.magnitude / soundSpeed;

            if (mach > 25.0)
            {
                mach = 25.0;
            }

            // Loop through all parts, accumulating drag and lift.
            for (int i = vessel.Parts.Count - 1; i >= 0; i--)
            {
                // need checks on shielded components
                Part part = vessel.Parts[i];

                if (part.ShieldedFromAirstream || part.Rigidbody == null)
                {
                    continue;
                }

                // Get Drag
                Vector3 sim_dragVectorDir      = v_wrld_vel.normalized;
                Vector3 sim_dragVectorDirLocal = -(part.transform.InverseTransformDirection(sim_dragVectorDir));

                Vector3 liftForce = new Vector3(0, 0, 0);

                //Profiler.Start("SimLiftForce#Body");
                switch (part.dragModel)
                {
                case Part.DragModel.DEFAULT:
                case Part.DragModel.CUBE:
                    DragCubeList cubes = part.DragCubes;

                    DragCubeList.CubeData p_drag_data = new DragCubeList.CubeData();

                    if (!cubes.None)     // since 1.0.5, some parts don't have drag cubes (for example fuel lines and struts)
                    {
                        try
                        {
                            cubes.SetDragWeights();
                            cubes.SetPartOcclusion();
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                        }
                        catch (Exception)
                        {
                            cubes.SetDrag(sim_dragVectorDirLocal, (float)mach);
                            cubes.ForceUpdate(true, true);
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                            //Debug.Log(String.Format("Trajectories: Caught NRE on Drag Initialization.  Should be fixed now.  {0}", e));
                        }

                        float pseudoreynolds   = (float)(rho * Mathf.Abs(v_wrld_vel.magnitude));
                        float pseudoredragmult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(pseudoreynolds);

                        liftForce = p_drag_data.liftForce;
                    }
                    break;
                }

                // If it isn't a wing or lifter, get body lift.
                if (!part.hasLiftModule)
                {
                    float simbodyLiftScalar = part.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier * (float)dyn_pressure;
                    simbodyLiftScalar *= PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Evaluate((float)mach);
                    Vector3 bodyLift = part.transform.rotation * (simbodyLiftScalar * liftForce);
                    bodyLift = Vector3.ProjectOnPlane(bodyLift, sim_dragVectorDir);
                    // Only accumulate forces for non-LiftModules
                    total_lift += bodyLift;
                }
                //Profiler.Stop("SimLiftForce#Body");

                // Find ModuleLifingSurface for wings and liftforce.
                // Should catch control surface as it is a subclass
                //Profiler.Start("SimLiftForce#LiftModule");
                for (int j = part.Modules.Count - 1; j >= 0; j--)
                {
                    if (part.Modules[j] is ModuleLiftingSurface)
                    {
                        float  mcs_mod            = 1.0f;
                        double liftQ              = dyn_pressure * 1000;
                        ModuleLiftingSurface wing = (ModuleLiftingSurface)part.Modules[j];
                        Vector3 nVel              = Vector3.zero;
                        Vector3 liftVector        = Vector3.zero;
                        float   liftdot;
                        float   absdot;
                        wing.SetupCoefficients(v_wrld_vel, out nVel, out liftVector, out liftdot, out absdot);

                        double prevMach = part.machNumber;
                        part.machNumber = mach;
                        Vector3 local_lift = mcs_mod * wing.GetLiftVector(liftVector, liftdot, absdot, liftQ, (float)mach);
                        part.machNumber = prevMach;

                        total_lift += local_lift;
                    }
                }
                //Profiler.Stop("SimLiftForce#LiftModule");
            }
            // RETURN STUFF
            //Profiler.Stop("SimLiftForce");
            return(total_lift);
        }
Esempio n. 26
0
        //*******************************************************
        public static Vector3d SimAeroForce(Vessel vessel, Vector3d v_wrld_vel, double altitude, double latitude = 0.0)
        {
            Profiler.Start("SimAeroForce");

            CelestialBody body     = vessel.mainBody;
            double        pressure = body.GetPressure(altitude);
            // Lift and drag for force accumulation.
            Vector3d total_lift = Vector3d.zero;
            Vector3d total_drag = Vector3d.zero;

            // dynamic pressure for standard drag equation
            double rho          = GetDensity(altitude, body);
            double dyn_pressure = 0.0005 * rho * v_wrld_vel.sqrMagnitude;

            if (rho <= 0)
            {
                return(Vector3.zero);
            }

            double soundSpeed = body.GetSpeedOfSound(pressure, rho);
            double mach       = v_wrld_vel.magnitude / soundSpeed;

            if (mach > 25.0)
            {
                mach = 25.0;
            }

            // Loop through all parts, accumulating drag and lift.
            for (int i = 0; i < vessel.Parts.Count; ++i)
            {
                // need checks on shielded components
                Part p = vessel.Parts[i];
#if DEBUG
                TrajectoriesDebug partDebug = VesselAerodynamicModel.DebugParts ? p.FindModuleImplementing <TrajectoriesDebug>() : null;
                if (partDebug != null)
                {
                    partDebug.Drag = 0;
                    partDebug.Lift = 0;
                }
#endif

                if (p.ShieldedFromAirstream || p.Rigidbody == null)
                {
                    continue;
                }

                // Get Drag
                Vector3d sim_dragVectorDir      = v_wrld_vel.normalized;
                Vector3d sim_dragVectorDirLocal = -(p.transform.InverseTransformDirection(sim_dragVectorDir));

                Vector3d liftForce = Vector3d.zero;
                Vector3d dragForce;


                Profiler.Start("SimAeroForce#drag");
                switch (p.dragModel)
                {
                case Part.DragModel.DEFAULT:
                case Part.DragModel.CUBE:
                    DragCubeList cubes = p.DragCubes;

                    DragCubeList.CubeData p_drag_data = new DragCubeList.CubeData();

                    double drag;
                    if (cubes.None)     // since 1.0.5, some parts don't have drag cubes (for example fuel lines and struts)
                    {
                        drag = p.maximum_drag;
                    }
                    else
                    {
                        try
                        {
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                        }
                        catch (Exception e)
                        {
                            cubes.SetDrag(sim_dragVectorDirLocal, (float)mach);
                            cubes.ForceUpdate(true, true);
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                            Util.DebugLogError("Exception {0} on drag initialization", e);
                        }

                        double pseudoreynolds   = rho * Math.Abs(v_wrld_vel.magnitude);
                        double pseudoredragmult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate((float)pseudoreynolds);
                        drag = p_drag_data.areaDrag * PhysicsGlobals.DragCubeMultiplier * pseudoredragmult;

                        liftForce = p_drag_data.liftForce;
                    }

                    double sim_dragScalar = dyn_pressure * drag * PhysicsGlobals.DragMultiplier;
                    dragForce = -sim_dragVectorDir * sim_dragScalar;

                    break;

                case Part.DragModel.SPHERICAL:
                    dragForce = -sim_dragVectorDir * p.maximum_drag;
                    break;

                case Part.DragModel.CYLINDRICAL:
                    dragForce = -sim_dragVectorDir *Mathf.Lerp(p.minimum_drag, p.maximum_drag, Mathf.Abs(Vector3.Dot(p.partTransform.TransformDirection(p.dragReferenceVector), sim_dragVectorDir)));

                    break;

                case Part.DragModel.CONIC:
                    dragForce = -sim_dragVectorDir *Mathf.Lerp(p.minimum_drag, p.maximum_drag, Vector3.Angle(p.partTransform.TransformDirection(p.dragReferenceVector), sim_dragVectorDir) / 180f);

                    break;

                default:
                    // no drag to apply
                    dragForce = Vector3d.zero;
                    break;
                }

                Profiler.Stop("SimAeroForce#drag");

#if DEBUG
                if (partDebug != null)
                {
                    partDebug.Drag += (float)dragForce.magnitude;
                }
#endif
                total_drag += dragForce;

                // If it isn't a wing or lifter, get body lift.
                if (!p.hasLiftModule)
                {
                    Profiler.Start("SimAeroForce#BodyLift");

                    float simbodyLiftScalar = p.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier * (float)dyn_pressure;
                    simbodyLiftScalar *= PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Evaluate((float)mach);
                    Vector3 bodyLift = p.transform.rotation * (simbodyLiftScalar * liftForce);
                    bodyLift = Vector3.ProjectOnPlane(bodyLift, sim_dragVectorDir);
                    // Only accumulate forces for non-LiftModules
                    total_lift += bodyLift;


                    Profiler.Stop("SimAeroForce#BodyLift");
                }


                Profiler.Start("SimAeroForce#LiftingSurface");

                // Find ModuleLifingSurface for wings and liftforce.
                // Should catch control surface as it is a subclass
                for (int j = 0; j < p.Modules.Count; ++j)
                {
                    var m = p.Modules[j];
                    if (m is ModuleLiftingSurface wing)
                    {
                        const float mcs_mod = 1.0f;
                        double      liftQ   = dyn_pressure * 1000;
                        wing.SetupCoefficients(v_wrld_vel, out var nVel, out var liftVector, out var liftdot, out var absdot);

                        double prevMach = p.machNumber;
                        p.machNumber = mach;
                        Vector3 local_lift = mcs_mod * wing.GetLiftVector(liftVector, liftdot, absdot, liftQ, (float)mach);
                        Vector3 local_drag = mcs_mod * wing.GetDragVector(nVel, absdot, liftQ);
                        p.machNumber = prevMach;

                        total_lift += local_lift;
                        total_drag += local_drag;

#if DEBUG
                        if (partDebug != null)
                        {
                            partDebug.Lift += local_lift.magnitude;
                            partDebug.Drag += local_drag.magnitude;
                        }
#endif
                    }
                }

                Profiler.Stop("SimAeroForce#LiftingSurface");
            }

            // RETURN STUFF
            Vector3 force = total_lift + total_drag;

            Profiler.Stop("SimAeroForce");
            return(force);
        }
Esempio n. 27
0
        //*******************************************************
        public static Vector3 SimDragForce(CelestialBody body, IShipconstruct vessel, Vector3 v_wrld_vel, double altitude, double latitude = 0.0)
        {
            double pressure = body.GetPressure(altitude);
            // Lift and drag for force accumulation.
            Vector3d total_drag = Vector3d.zero;

            // dynamic pressure for standard drag equation
            double rho          = GetDensity(altitude, body);
            double dyn_pressure = 0.0005 * rho * v_wrld_vel.sqrMagnitude;

            if (rho <= 0)
            {
                return(Vector3.zero);
            }

            double soundSpeed = body.GetSpeedOfSound(pressure, rho);
            double mach       = v_wrld_vel.magnitude / soundSpeed;

            if (mach > 25.0)
            {
                mach = 25.0;
            }

            // Loop through all parts, accumulating drag and lift.
            for (int i = vessel.Parts.Count - 1; i >= 0; i--)
            {
                // need checks on shielded components
                Part part = vessel.Parts[i];

                if (part.ShieldedFromAirstream || part.Rigidbody == null)
                {
                    continue;
                }

                // Get Drag
                Vector3 sim_dragVectorDir      = v_wrld_vel.normalized;
                Vector3 sim_dragVectorDirLocal = -(part.transform.InverseTransformDirection(sim_dragVectorDir));

                Vector3d dragForce;

                switch (part.dragModel)
                {
                case Part.DragModel.DEFAULT:
                case Part.DragModel.CUBE:
                    DragCubeList cubes = part.DragCubes;

                    DragCubeList.CubeData p_drag_data = new DragCubeList.CubeData();

                    float drag;
                    if (cubes.None)     // since 1.0.5, some parts don't have drag cubes (for example fuel lines and struts)
                    {
                        drag = part.maximum_drag;
                    }
                    else
                    {
                        try
                        {
                            cubes.SetDragWeights();
                            cubes.SetPartOcclusion();
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                        }
                        catch (Exception)
                        {
                            cubes.SetDrag(sim_dragVectorDirLocal, (float)mach);
                            cubes.ForceUpdate(true, true);
                            cubes.AddSurfaceDragDirection(-sim_dragVectorDirLocal, (float)mach, ref p_drag_data);
                            //Debug.Log(String.Format("Trajectories: Caught NRE on Drag Initialization.  Should be fixed now.  {0}", e));
                        }

                        float pseudoreynolds   = (float)(rho * Mathf.Abs(v_wrld_vel.magnitude));
                        float pseudoredragmult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate(pseudoreynolds);
                        drag = p_drag_data.areaDrag * PhysicsGlobals.DragCubeMultiplier * pseudoredragmult;
                    }

                    double sim_dragScalar = dyn_pressure * (double)drag * PhysicsGlobals.DragMultiplier;
                    dragForce = -(Vector3d)sim_dragVectorDir * sim_dragScalar;

                    break;

                case Part.DragModel.SPHERICAL:
                    dragForce = -(Vector3d)sim_dragVectorDir * (double)part.maximum_drag;
                    break;

                case Part.DragModel.CYLINDRICAL:
                    dragForce = -(Vector3d)sim_dragVectorDir * (double)Mathf.Lerp(part.minimum_drag, part.maximum_drag, Mathf.Abs(Vector3.Dot(part.partTransform.TransformDirection(part.dragReferenceVector), sim_dragVectorDir)));
                    break;

                case Part.DragModel.CONIC:
                    dragForce = -(Vector3d)sim_dragVectorDir * (double)Mathf.Lerp(part.minimum_drag, part.maximum_drag, Vector3.Angle(part.partTransform.TransformDirection(part.dragReferenceVector), sim_dragVectorDir) / 180f);
                    break;

                default:
                    // no drag to apply
                    dragForce = new Vector3d();
                    break;
                }

                total_drag += dragForce;


                // Find ModuleLifingSurface for wings and liftforce.
                // Should catch control surface as it is a subclass
                for (int j = part.Modules.Count - 1; j >= 0; j--)
                {
                    if (part.Modules[j] is ModuleLiftingSurface)
                    {
                        float  mcs_mod            = 1.0f;
                        double liftQ              = dyn_pressure * 1000;
                        ModuleLiftingSurface wing = (ModuleLiftingSurface)part.Modules[j];
                        Vector3 nVel              = Vector3.zero;
                        Vector3 liftVector        = Vector3.zero;
                        float   liftdot;
                        float   absdot;
                        wing.SetupCoefficients(v_wrld_vel, out nVel, out liftVector, out liftdot, out absdot);

                        double prevMach = part.machNumber;
                        part.machNumber = mach;
                        Vector3 local_drag = mcs_mod * wing.GetDragVector(nVel, absdot, liftQ);
                        part.machNumber = prevMach;

                        total_drag += local_drag;
                    }
                }
            }
            // RETURN STUFF
            return(total_drag);
        }