public static double TimeToDaylight(double lat, double lon, CelestialBody body) { CelestialBody sun = Planetarium.fetch.Sun; double rotPeriod, localTime; localTime = GetLocalTime(lon, body, sun); rotPeriod = body.rotationPeriod; var orbit = body.orbit; while (orbit?.referenceBody != sun) { orbit = orbit.referenceBody.orbit; } if (orbit != null) { //Convert the absolute rotation period into a day lenght rotPeriod = orbit.period * rotPeriod / (orbit.period - rotPeriod); } double dayLength = GetDayLengthPercentage(lat, body, sun); double timeOfDawn = 0.5 - dayLength / 2; double timeToDaylight = rotPeriod * UtilMath.WrapAround(timeOfDawn - localTime, 0, 1); return(timeToDaylight); }
public double GetTime(List <ProtoCrewMember> students) { double curTime = time; double level = ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex); curTime *= (1d - level * 0.5d); if (students == null || students.Count == 0 || !timeUseStupid) { return(curTime); } double averageStupid = 0d; int sC = students.Count; for (int i = sC; i-- > 0;) { averageStupid += students[i].stupidity; } averageStupid /= sC; return(curTime * UtilMath.Lerp(CrewHandler.Settings.trainingMissionStupidMin, CrewHandler.Settings.trainingMissionStupidMax, averageStupid)); }
protected void TransferResourceFromEVA(string resourceName) { double availableSpace = GetResourceAmount(resourceName, true) - GetResourceAmount(resourceName); double toAdd = 0d; for (int i = 0; i < FlightGlobals.ActiveVessel.evaController.ModuleInventoryPartReference.InventorySlots; i++) { if (availableSpace > 0d) { if (!FlightGlobals.ActiveVessel.evaController.ModuleInventoryPartReference.IsSlotEmpty(i)) { StoredPart sPart = FlightGlobals.ActiveVessel.evaController.ModuleInventoryPartReference.storedParts[i]; if (sPart.partName == RefuelCargoPartName) { ProtoPartResourceSnapshot res = sPart.snapshot.resources.Find(x => x.resourceName == resourceName); double availableResource = res.amount; double addable = UtilMath.Min(availableSpace, availableResource); toAdd += addable; Utils.Log($"Removed {addable} {resourceName} from {sPart.partName} ({availableResource} units in part, {availableSpace} space in target)"); availableSpace = UtilMath.Clamp(availableSpace - addable, 0, availableSpace); res.amount = UtilMath.Clamp(res.amount - addable, 0d, res.maxAmount); } } } } ScreenMessages.PostScreenMessage(new ScreenMessage(Localizer.Format("#LOC_SystemHeat_ModuleSystemHeatFissionFuelContainer_Message_Stored", toAdd.ToString("F2"), resourceName, part.partInfo.title ), 5.0f, ScreenMessageStyle.UPPER_CENTER));; Utils.Log($"Added {toAdd} {resourceName} to {part.partInfo.title}"); part.RequestResource(resourceName, -toAdd, ResourceFlowMode.NO_FLOW); }
/// <summary> /// /// </summary> /// <param name="altitude"></param> /// <returns></returns> double CalculateAltFactor(double altitude) { altitude -= BodyRadius; if (altitudeFalloff == FalloffType.Linear) { if (altitude > centerAltitude) { return(1d - UtilMath.Clamp((altitude - centerAltitude) / (maximumAltitude - centerAltitude), 0d, 1d)); } else { return(1d - UtilMath.Clamp((altitude - centerAltitude) / (minimumAltitude - centerAltitude), 0d, 1d)); } } else if (altitudeFalloff == FalloffType.None) { if (altitude >= minimumAltitude && altitude <= maximumAltitude) { return(1d); } else { return(0d); } } return(0d); }
public float GetTemperature(float altitude) { double temperature = 0; if (altitude >= body.atmosphereDepth) { return((float)this.SpaceTemperature); } if (!body.atmosphereUseTemperatureCurve) { temperature = body.atmosphereTemperatureSeaLevel - body.atmosphereTemperatureLapseRate * altitude; } else { lock (this.AtmosphereTemperatureCurve) temperature = !body.atmosphereTemperatureCurveIsNormalized ? this.AtmosphereTemperatureCurve.Evaluate((float)altitude) : UtilMath.Lerp(this.SpaceTemperature, body.atmosphereTemperatureSeaLevel, this.AtmosphereTemperatureCurve.Evaluate((float)(altitude / body.atmosphereDepth))); } lock (this.AtmosphereTemperatureSunMultCurve) temperature += this.AtmosphereTemperatureSunMultCurve.Evaluate(altitude) * (this.LatitudeTemperatureBiasCurve.Evaluate(0) + this.LatitudeTemperatureSunMultCurve.Evaluate(0) + this.AxialTemperatureSunMultCurve.Evaluate(0)); return((float)temperature); }
private void FixedUpdate() { float dt = ts.DeltaTime(); while (timerHesitate.TimeUp(dt)) { timerFinished = true; } if (timerFinished) { // Shrink the buffer. float stepSize = dt * shrinkSpeed; if (shrinkToLeft) { bufferUpper = UtilMath.Approach(bufferUpper, bufferLower, stepSize); } else { bufferLower = UtilMath.Approach(bufferLower, bufferUpper, stepSize); } UpdateBufferMeter(); if (bufferLower == bufferUpper) { timerFinished = false; } } }
public static double TimeToDaylight(double lat, double lon, CelestialBody body, double offset) { double rotPeriod, localTime; localTime = Sunrise.GetLocalTime(lon, body, instance.sun); rotPeriod = body.rotationPeriod; var orbit = body.orbit; while (orbit?.referenceBody != instance.sun) { orbit = orbit.referenceBody.orbit; } if (orbit != null) { double or = rotPeriod; rotPeriod = orbit.period * rotPeriod / (orbit.period - rotPeriod); Debug.Log($"[EarlyBird] rotation period: {or} reference period: {orbit.period} day length: {rotPeriod}"); } offset = (offset * 60) / rotPeriod; double dayLength = Sunrise.GetDayLength(lat, body, instance.sun); double timeOfDawn = 0.5 - dayLength / 2 + offset; double timeToDaylight = rotPeriod * UtilMath.WrapAround(timeOfDawn - localTime, 0, 1); Debug.Log($"[EarlyBird] WarpToMorning: daylight: {dayLength}({dayLength * rotPeriod}), dawn {timeOfDawn}, warpTime: {timeToDaylight}"); return(timeToDaylight); }
// 每一个状态对应一个特效,这个特效是循环特效,每一次战斗都要更新状态,双方的场牌,英雄卡、技能卡 override public void updateAttHurtStateEffect(FightItemBase item) { LinkEffect effect = null; if (item.bStateChange()) // 每一个状态对应一个特效,需要播放特效 { int idx = 0; TableStateItemBody stateTabelItem = null; for (idx = 1; idx < (int)StateID.CARD_STATE_MAX; ++idx) { if (UtilMath.checkState((StateID)idx, item.changedState)) // 如果这个状态改变 { if (UtilMath.checkState((StateID)idx, item.curState)) // 如果是增加状态 { stateTabelItem = Ctx.m_instance.m_tableSys.getItem(TableID.TABLE_STATE, (uint)idx).m_itemBody as TableStateItemBody; if (stateTabelItem.m_effectId > 0) { effect = m_card.effectControl.startStateEffect((StateID)idx, stateTabelItem.m_effectId); } } else // 删除状态,停止特效 { m_card.effectControl.stopStateEffect((StateID)idx); } } } } }
public static int GetBiomeIndex(CelestialBody body, double lat, double lon) { int currentBiomeIndex = -1; if (body.BiomeMap != null) { CBAttributeMapSO biomeMap = body.BiomeMap; // CBAttributeMapSO.GetAtt lon -= Math.PI / 2.0; lon = UtilMath.WrapAround(lon, 0.0, Math.PI * 2.0); double y = lat * (1.0 / Math.PI) + 0.5; double x = 1.0 - lon * 0.15915494309189535; Color pixelColor = biomeMap.GetPixelColor(x, y); currentBiomeIndex = 0; // this is mandatory because the first biome is a used as fallback in the stock code (!) float currentSqrMag = float.MaxValue; for (int i = 0; i < biomeMap.Attributes.Length; i++) { if (!biomeMap.Attributes[i].notNear) { float sqrMag = RGBColorSqrMag(pixelColor, biomeMap.Attributes[i].mapColor); if (sqrMag < currentSqrMag && (biomeMap.nonExactThreshold == -1f || sqrMag < biomeMap.nonExactThreshold)) { currentBiomeIndex = i; currentSqrMag = sqrMag; } } } } return(currentBiomeIndex); }
void loadDataFromTextFile(string file) { //open file string positionsAndMatrix = UtilMath.openFile(file); //@"C:\Users\maxc\Documents\OculusCave Design\ExpeGraphs\nodesMatrix0.txt"); string[] positionsAndMatrixSplit = positionsAndMatrix.Split('#'); List <Vector3> positionsGraph = convertPositions(positionsAndMatrixSplit[0]); int[,] adjencyMatrix = convertAdjencyMatrix(positionsAndMatrixSplit[1], positionsGraph.Count); if (interactiveEditing) { disconnectNodes(ref adjencyMatrix, 0, chainLength); disconnectNodes(ref adjencyMatrix, chainLength, 0); } //get the path if (positionsAndMatrixSplit[2].Length > 0) { path = convertPath(positionsAndMatrixSplit[2]); } //triangles //test length of the split file to see if there are triangles ... if (positionsAndMatrixSplit.Length > 3) { //read the triangles triangles = convertTriangleList(positionsAndMatrixSplit[3]); } createTubesFromDataUnityGeometry(scaleSphere, positionsGraph, adjencyMatrix, false); }
public void setDataDimension(float[] dat, VIEW_DIMENSION dimension) { float minValue = dat.Min(); float maxValue = dat.Max(); for (int i = 0; i < dat.Length; i++) { Vector3 p = positions[i]; switch (dimension) { case VIEW_DIMENSION.X: p.x = UtilMath.normaliseValue(dat[i], minValue, maxValue, -0.5f, 0.5f); break; case VIEW_DIMENSION.Y: p.y = UtilMath.normaliseValue(dat[i], minValue, maxValue, -0.5f, 0.5f); break; case VIEW_DIMENSION.Z: p.z = UtilMath.normaliseValue(dat[i], minValue, maxValue, -0.5f, 0.5f); break; } positions[i] = p; } }
public void SetMaxFilter(float val) { MaxFilter = Mathf.Clamp(val, -0.505f, 0.505f); OnFiltered.Invoke(MinFilter, MaxFilter); SetLocalYPosition(maxFilterObject.transform, UtilMath.normaliseValue(MaxFilter, -0.505f, 0.505f, -0.45f, 0.45f)); }
public static void WarpToMorning(double lat, double lon, CelestialBody body, double offset) { if (FlightDriver.Pause) { return; } if (instance.sun == null) { Debug.LogError("Cannot warp to next morning due to lack of sun"); return; } if (TimeWarp.fetch.CancelAutoWarp(0)) { return; } double rotPeriod, localTime; localTime = Sunrise.GetLocalTime(lon, body, instance.sun); rotPeriod = body.rotationPeriod; if (body.orbit != null) { rotPeriod = body.orbit.period * rotPeriod / (body.orbit.period - rotPeriod); } offset = (offset * 60) / rotPeriod; double dayLength = Sunrise.GetDayLength(lat, body, instance.sun); double timeOfDawn = 0.5 - dayLength / 2 + offset;; double timeToDaylight = rotPeriod * UtilMath.WrapAround(timeOfDawn - localTime, 0, 1); Debug.LogFormat("[EarlyBird] WarpToMorning: daylight: {0}({1}), dawn {2}, warpTime: {3}", dayLength, dayLength * rotPeriod, timeOfDawn, timeToDaylight); TimeWarp.fetch.WarpTo(Planetarium.GetUniversalTime() + timeToDaylight, 8, 1); }
public void SetState(double inputVal) { animState = (float)UtilMath.Clamp( (Math.Pow(inputVal * lerpInnerScalar, lerpPow) * lerpOuterScalar + lerpOffset) * lerpDivRecip, lerpMin, lerpMax); }
public double GetAutolandTargetVerticalSpeed(Vector3d vectorToWaypoint) { double timeToWaypoint = LateralDistance(vesselState.CoM, vectorToWaypoint) / vesselState.speedSurfaceHorizontal; double deltaAlt = GetAutolandTargetAltitude(vectorToWaypoint) - 10 - vesselState.altitudeASL; double vertSpeed = deltaAlt / timeToWaypoint; // If we are on final, we want to maintain glideslope as much as // possible so that we don't overshoot or undershoot the runway. if (approachState == AutolandApproachState.TOUCHDOWN || approachState == AutolandApproachState.FAP) { Debug.Assert(vertSpeed < 0); Vector3d vectorToCorrectPointOnGlideslope = runway.GetPointOnGlideslope(glideslope, LateralDistance(vesselState.CoM, runway.GetVectorToTouchdown())); double desiredAlt = GetAutolandTargetAltitude(vectorToCorrectPointOnGlideslope) - 10; double deltaToCorrectAlt = desiredAlt - vesselState.altitudeTrue; double expPerMeter = (Math.Log(maximumVerticalSpeedCorrection + 1) - Math.Log(1)) / desiredAlt; double adjustment = Math.Exp(expPerMeter * Math.Abs(deltaToCorrectAlt)) - 1; vertSpeed += deltaToCorrectAlt > 0 ? adjustment : -adjustment; } if (approachState == AutolandApproachState.FLARE) { vertSpeed = deltaAlt / 8 - 0.2f; vertSpeed = UtilMath.Clamp(vertSpeed, -2, 2); } return(vertSpeed); }
//Calculates the temperature of the chute and cuts it if needed private bool CalculateChuteTemp() { if (this.chuteTemperature < PhysicsGlobals.SpaceTemperature) { this.chuteTemperature = startTemp; } double flux = this.vessel.convectiveCoefficient * UtilMath.Lerp(1d, 1d + this.vessel.mach * this.vessel.mach * this.vessel.mach, (this.vessel.mach - PhysicsGlobals.FullToCrossSectionLerpStart) / (PhysicsGlobals.FullToCrossSectionLerpEnd)) * (this.vessel.externalTemperature - this.chuteTemperature); if (this.vessel.mach > PhysicsGlobals.MachConvectionStart) { double machLerp = (this.part.machNumber - PhysicsGlobals.MachConvectionStart) / (PhysicsGlobals.MachConvectionEnd - PhysicsGlobals.MachConvectionStart); machLerp = Math.Pow(machLerp, PhysicsGlobals.MachConvectionExponent); flux = UtilMath.Lerp(flux, this.vessel.convectiveMachFlux, machLerp); } this.chuteTemperature += 0.001 * this.invThermalMass * flux * this.convectionArea * TimeWarp.fixedDeltaTime; if (chuteTemperature > 0d) { this.chuteTemperature -= 0.001 * this.invThermalMass * PhysicsGlobals.StefanBoltzmanConstant * this.convectionArea * this.chuteEmissivity * PhysicsGlobals.RadiationFactor * TimeWarp.fixedDeltaTime * Math.Pow(this.chuteTemperature, PhysicsGlobals.PartEmissivityExponent); } this.chuteTemperature = Math.Max(PhysicsGlobals.SpaceTemperature, this.chuteTemperature); if (this.chuteTemperature > maxTemp) { ScreenMessages.PostScreenMessage("<color=orange>[RealChute]: " + this.part.partInfo.title + "'s parachute has been destroyed due to aero forces and heat.</color>", 6f, ScreenMessageStyle.UPPER_LEFT); Cut(); return(false); } this.currentTemp = (float)(this.chuteTemperature + absoluteZero); return(true); }
// Positions and resizes the camera so that a given edge of the camera matches // the line formed by the given vertices. Each vertex corresponds to one corner // of the camera. The vertices should be defined in a clockwise order. // If the given edge is diagonal, nothing happens. // (TODO: Perhaps diagonal edges should rotate the camera to match the edge?) public void AnchorClockwiseEdge(Vector3 vertexFirst, Vector3 vertexSecond) { float differenceX = vertexSecond.x - vertexFirst.x; float differenceY = vertexSecond.y - vertexFirst.y; int signX = UtilMath.SignWithZero(differenceX); int signY = UtilMath.SignWithZero(differenceY); if (signX == 0) { FitHeight(Mathf.Abs(differenceY)); position = new Vector3(vertexFirst.x + GetHalfWidth() * signY, vertexFirst.y + GetHalfHeight() * signY); } else if (signY == 0) { FitWidth(Mathf.Abs(differenceX)); position = new Vector3(vertexFirst.x + GetHalfWidth() * signX, vertexFirst.y - GetHalfHeight() * signX); } else { // The edge is diagonal. Debug.LogWarning("CameraDataOrtho2D: Attempted to anchor to diagonal edge."); } }
// Positions and resizes the camera so that the camera is placed between // two given points and has edges that contain those points. public void AnchorBetween(Vector3 first, Vector3 second) { position = Vector3.Lerp(first, second, 0.5f); float differenceX = second.x - first.x; float differenceY = second.y - first.y; int signX = UtilMath.SignWithZero(differenceX); int signY = UtilMath.SignWithZero(differenceY); float targetWidth = Mathf.Abs(differenceX); float targetHeight = Mathf.Abs(differenceY); if (signX == 0) { FitHeight(targetHeight); } else if (signY == 0) { FitWidth(targetWidth); } else { if (targetWidth / targetHeight < aspect) { FitHeight(targetHeight); } else { FitWidth(targetWidth); } } }
public double GetTemperature(Vector3d pos) { double altitude = pos.magnitude - bodyRadius; double temperature; if (altitude >= mainBody.atmosphereDepth) { return(PhysicsGlobals.SpaceTemperature); } if (!mainBody.atmosphereUseTemperatureCurve) { temperature = mainBody.atmosphereTemperatureSeaLevel - mainBody.atmosphereTemperatureLapseRate * altitude; } else { temperature = !mainBody.atmosphereTemperatureCurveIsNormalized ? simCurves.AtmosphereTemperatureCurve.Evaluate((float)altitude) : UtilMath.Lerp(PhysicsGlobals.SpaceTemperature, mainBody.atmosphereTemperatureSeaLevel, simCurves.AtmosphereTemperatureCurve.Evaluate((float)(altitude / mainBody.atmosphereDepth))); } double latitude = referenceFrame.Latitude(pos); temperature += simCurves.AtmosphereTemperatureSunMultCurve.Evaluate((float)altitude) * (simCurves.LatitudeTemperatureBiasCurve.Evaluate((float)latitude) + simCurves.LatitudeTemperatureSunMultCurve.Evaluate((float)latitude) + simCurves.AxialTemperatureSunMultCurve.Evaluate(0)); return(temperature); }
private void Rotate(float linearVelocity) { float angularVelocity = Angle.FromAngularVelocity(linearVelocity, radius) .GetDegrees() * UtilMath.Sign(inverted); mover.OffsetRotation(angularVelocity); }
private double GetServiceTime(ProtoCrewMember pcm) { return(86400d * 365d * (Settings.retireBaseYears + UtilMath.Lerp(Settings.retireCourageMin, Settings.retireCourageMax, pcm.courage) + UtilMath.Lerp(Settings.retireStupidMin, Settings.retireStupidMax, pcm.stupidity))); }
public static void UpdateThermodynamicsPre(ModularFI.ModularFlightIntegrator fi) { if (lastVessel != fi.Vessel || parts.Count != fi.partThermalDataList.Count) { parts.Clear(); lastVessel = fi.Vessel; for (int i = fi.partThermalDataList.Count; i-- > 0;) { var ptd = fi.partThermalDataList[i]; var part = ptd.part; if (part.GetComponent <ModuleNonReentryRated>()) { parts.Add(part); } } } for (int i = fi.partThermalDataList.Count; i-- > 0;) { PartThermalData ptd = fi.partThermalDataList[i]; var part = ptd.part; if (parts.Contains(part)) { ptd.convectionTempMultiplier = Math.Max(ptd.convectionTempMultiplier, 0.75d); ptd.convectionCoeffMultiplier = Math.Max(ptd.convectionCoeffMultiplier, 0.75d); ptd.convectionAreaMultiplier = Math.Max(ptd.convectionAreaMultiplier, 0.75d); ptd.postShockExtTemp = UtilMath.LerpUnclamped(part.vessel.atmosphericTemperature, part.vessel.externalTemperature, ptd.convectionTempMultiplier); ptd.finalCoeff = part.vessel.convectiveCoefficient * ptd.convectionArea * 0.001d * part.heatConvectiveConstant * ptd.convectionCoeffMultiplier; } } }
public static double CalculateBackgroundRadiationTemperature(double ambientTemp, double densityThermalLerp) { return(UtilMath.Lerp( ambientTemp, PhysicsGlobals.SpaceTemperature, densityThermalLerp)); }
private void Rotate(float linearVelocity) { float angularVelocity = UtilCircle.AngularVelocityDegrees(linearVelocity, radius) * UtilMath.Sign(inverted); mover.OffsetRotation(angularVelocity); }
/// <summary> /// Returns the mean anomaly of the orbit at the given time. /// </summary> /// /// <param name="orbit">The orbit whose anomaly is desired.</param> /// <param name="ut">The time at which to measure the mean anomaly.</param> /// <returns>The mean anomaly at the specified epoch.</returns> static double meanAnomalyAtUT(Orbit orbit, double ut) { double fracOrbit = (ut - orbit.epoch) / orbit.period; return(UtilMath.Clamp(orbit.meanAnomalyAtEpoch + 2.0 * Math.PI * fracOrbit, 0.0, 2.0 * Math.PI)); }
double getIntakeMultiplier() { if (this.part.ShieldedFromAirstream) { return(0.0f); } if (this.intakeTransform == null) { return(1.0f); } if (this.currentHarvestType == HarvestTypes.Planetary) { return(1.0f); } double density = this.part.vessel.atmDensity; if (currentHarvestType == HarvestTypes.Exospheric) { density = 1.0f; } double speed = this.part.vessel.srfSpeed + this.airSpeedStatic; double intakeAngle = UtilMath.Clamp01((double)Vector3.Dot((Vector3)this.vessel.srf_vel_direction, this.intakeTransform.forward)); return(density * speed * intakeAngle); }
public void FixedUpdate() { if (!HighLogic.LoadedSceneIsFlight) { return; } double skinTemp = part.skinTemperature; guiShieldTemp = skinTemp; guiShieldFlux = 0; guiShieldUse = 0; guiShieldEff = 0; part.skinInternalConductionMult = baseSkinIntMult; part.heatConductivity = baseCondMult; updateDebugGuiStatus(); if (part.atmDensity <= 0) { return; } if (part.temperature > part.skinTemperature) { return; } Vector3 localFlightDirection = -part.dragVectorDirLocal; float dot = Vector3.Dot(heatShieldVector, localFlightDirection); if (dot < heatShieldMinDot) { return; } //TODO check for occlusion float directionalEffectiveness = 0; if (dot > heatShieldMaxDot) { directionalEffectiveness = 1f; } else { float minMaxDelta = heatShieldMaxDot - heatShieldMinDot; float offset = dot - heatShieldMinDot; directionalEffectiveness = offset / minMaxDelta; } guiShieldEff = directionalEffectiveness; float mult = (1.0f - (0.8f * directionalEffectiveness)); part.skinInternalConductionMult = mult * baseSkinIntMult; part.heatConductivity = mult * baseCondMult; if (skinTemp > ablationStartTemp) { //convert input value to 0-1 domain double d = skinTemp - ablationStartTemp; d /= ablationEndTemp; d = UtilMath.Clamp(d, 0, 1); applyAblation(d, directionalEffectiveness); } }
public override void CalculatePerformance(double airRatio, double commandedThrottle, double flowMult, double ispMult) { // set base bits base.CalculatePerformance(airRatio, commandedThrottle, flowMult, ispMult); // Calculate Isp (before the shutdown check, so it displays even then) Isp = atmosphereCurve.Evaluate((float)(p0 * 0.001d * PhysicsGlobals.KpaToAtmospheres)) * ispMult; // if we're not combusting, don't combust and start cooling off bool shutdown = !running; statusString = "Nominal"; if (ffFraction <= 0d) { shutdown = true; statusString = "No propellants"; } if (shutdown || commandedThrottle <= 0d) { double declinePow = Math.Pow(tempDeclineRate, TimeWarp.fixedDeltaTime); chamberTemp = Math.Max(t0, chamberTemp * declinePow); return; } // get current flow, and thus thrust. double fuelFlowMult = FlowMult(); if (fuelFlowMult < 0.05d) { fuelFlow = 0d; } else { fuelFlow = flowMult * UtilMath.LerpUnclamped(minFlow, maxFlow, commandedThrottle) * fuelFlowMult; } double exhaustVelocity = Isp * 9.80665d; thrust = fuelFlow * exhaustVelocity; // Calculate chamber temperature as ratio double desiredTempRatio = Math.Max(tempMin, commandedThrottle); double machTemp = MachTemp() * 0.05d; desiredTempRatio = desiredTempRatio * (1d + machTemp) + machTemp; // set based on desired double desiredTemp = desiredTempRatio * chamberNominalTemp; if (Math.Abs(desiredTemp - chamberTemp) < 1d) { chamberTemp = desiredTemp; } else { double lerpVal = Math.Min(1d, tempLerpRate * TimeWarp.fixedDeltaTime); chamberTemp = UtilMath.LerpUnclamped(chamberTemp, desiredTemp, lerpVal); } }
/// <summary> /// Returns an angle from 0 to 360° between the two vectors, based on the up axis to tell left from right /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <param name="upAxis"></param> /// <returns></returns> public static float HeadingDegrees(Vector3 v1, Vector3 v2, Vector3 upAxis) { if (v1 == v2) { return(0f); } return(UtilMath.WrapAround(Mathf.Acos(Vector3.Dot(v1, v2)) * Mathf.Sign(Vector3.Dot(Vector3.Cross(v1, v2), upAxis)) * Mathf.Rad2Deg, 0f, 360f)); }
/// <summary> /// Returns an angle from 0 to 2PI between the two vectors, based on the up axis to tell left from right /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <param name="upAxis"></param> /// <returns></returns> public static float HeadingRadians(Vector3 v1, Vector3 v2, Vector3 upAxis) { if (v1 == v2) { return(0f); } return(UtilMath.WrapAround(Mathf.Acos(Vector3.Dot(v1, v2)) * Mathf.Sign(Vector3.Dot(Vector3.Cross(v1, v2), upAxis)), 0f, Mathf.PI * 2.0f)); }