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(); }
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; }
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)); }