Browse Source

- the balloon is now always an independent vessel (linked with a spring to the main vessel until detached)

- fixed balloon mesh and collider radius and scale
master
Youen Toupin 9 years ago
parent
commit
cbd8c4e811
  1. 62
      Plugin/ModuleBalloon.cs
  2. 53
      Plugin/ModuleBalloonCase.cs

62
Plugin/ModuleBalloon.cs

@ -53,17 +53,28 @@ namespace Aerostats
// replace mesh and collider by a sphere (hack until proper assets are created)
var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
gameObject.GetComponentInChildren<MeshFilter>().mesh = sphere.GetComponent<MeshFilter>().mesh;
Destroy(gameObject.collider);
var collider = gameObject.AddComponent<SphereCollider>();
collider.radius = 0.67f; // don't ask me, I don't know why
var meshFilter = gameObject.GetComponentInChildren<MeshFilter>();
meshFilter.mesh = sphere.GetComponent<MeshFilter>().mesh;
var t = meshFilter.transform;
while (t != transform)
{
t.localPosition = new Vector3(0, 0, 0);
t.localRotation = Quaternion.identity;
t.localScale = new Vector3(1, 1, 1);
t = t.parent;
}
var colliderObject = part.collider.gameObject;
Destroy(colliderObject.collider);
var collider = colliderObject.AddComponent<SphereCollider>();
collider.radius = 0.5f;
Destroy(sphere);
gameObject.AddComponent<Rigidbody>();
rigidbody.mass = EmptyMass * 0.001f;
rigidbody.velocity = initialVelocity; // start with the same velocity or everything explodes when deploying from a moving vessel
rigidbody.angularDrag = 10.0f;
part.mass = rigidbody.mass;
rigidbody.velocity = initialVelocity;
rigidbody.position = transform.position;
part.rb = rigidbody;
InjectGas(initialGasQuantity);
@ -108,7 +119,7 @@ namespace Aerostats
CelestialBody body = vessel.mainBody;
float externalTemperature = (float)FlightGlobals.getExternalTemperature(worldPos, body);
float balloonInternalTemperature = externalTemperature;
float balloonInternalTemperature = Mathf.Max(externalTemperature, 20.0f);
float externalPressure = Math.Max((float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f, 0.00001f);
float currentGasMoles = GasUtilities.StpVolumeToMoles * LiftingGasQuantity;
@ -124,9 +135,15 @@ namespace Aerostats
// V = 4/3*pi*r^3
Radius = Mathf.Pow(CurrentVolume * 0.75f / Mathf.PI, 0.333f);
float scale = Radius + 0.1f;
float scale = Mathf.Max(Radius * 2.0f, 0.1f);
if(AttachedCase != null)
{
float dist = Vector3.Distance(AttachedCase.transform.position, transform.position);
scale = Mathf.Min(Mathf.Max(dist, transform.localScale.x * 0.5f) - 0.005f, scale * 0.5f) * 2.0f; // to prevent physics explosion due to interpenetration of objects, don't scale the balloon more than the space available between the case and the balloon (this happens when expanding fast after deploy in vaccum for example)
}
transform.localScale = new Vector3(scale, scale, scale);
rigidbody.mass = (EmptyMass + balloonGasMass) * 0.001f;
part.mass = rigidbody.mass;
return LiftingGasQuantity;
}
@ -140,7 +157,7 @@ namespace Aerostats
CelestialBody body = vessel.mainBody;
float externalTemperature = (float)FlightGlobals.getExternalTemperature(worldPos, body);
float balloonInternalTemperature = externalTemperature;
float balloonInternalTemperature = Mathf.Max(externalTemperature, 20.0f);
float externalPressure = Math.Max((float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f, 0.00001f);
Util.PostDebugSingleScreenMessage("external atmo", "Temperature = " + externalTemperature + "K, Pressure=" + externalPressure + "Pa");
@ -158,23 +175,28 @@ namespace Aerostats
InjectGas(0); // update security valve venting
var gravityAccel = FlightGlobals.getGeeForceAtPosition(worldPos);
var gravityAccel = FlightGlobals.getGeeForceAtPosition(rigidbody.position);
//Util.PostSingleScreenMessage("gravity", "Gravity accel = (" + gravityAccel.x + ", " + gravityAccel.y + ", " + gravityAccel.z + ")");
float externalTemperature = (float)FlightGlobals.getExternalTemperature(worldPos, body);
float balloonInternalTemperature = externalTemperature;
float externalPressure = Math.Max((float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f, 0.00001f);
float externalPressure = (float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f;
float airDensity = (float)FlightGlobals.getAtmDensity(externalPressure / 1000.0f, externalTemperature, body);
rigidbody.AddForce(-gravityAccel * Lift / 1000.0f, ForceMode.Force);
rigidbody.angularDrag = Mathf.Max(0.5f, 10.0f * externalPressure / GasUtilities.StandardPressure);
// balloon drag
var airVelocity = rigidbody.velocity + Krakensbane.GetFrameVelocity() /*- vessel.mainBody.getRFrmVel(vessel.GetWorldPos3D())*/;
float sqVel = (float)airVelocity.magnitude;
sqVel *= sqVel;
float dragForce = 0.5f * airDensity * sqVel * DragCoeff * (Mathf.PI * Radius * Radius);
Util.PostDebugSingleScreenMessage("balloon drag", "Drag = " + dragForce + "N");
rigidbody.AddForce(-airVelocity.normalized * dragForce / 1000.0f, ForceMode.Force);
if (externalPressure > 0.00001f)
{
// lift
rigidbody.AddForce(-gravityAccel * Lift / 1000.0f, ForceMode.Force);
// balloon drag
var airVelocity = rigidbody.velocity + Krakensbane.GetFrameVelocity() /*- vessel.mainBody.getRFrmVel(vessel.GetWorldPos3D())*/;
float sqVel = (float)airVelocity.magnitude;
sqVel *= sqVel;
float dragForce = 0.5f * airDensity * sqVel * DragCoeff * (Mathf.PI * Radius * Radius);
Util.PostDebugSingleScreenMessage("balloon drag", "Drag = " + dragForce + "N");
rigidbody.AddForce(-airVelocity.normalized * dragForce / 1000.0f, ForceMode.Force);
}
}
}
}

53
Plugin/ModuleBalloonCase.cs

@ -61,8 +61,6 @@ namespace Aerostats
private bool Destroyed;
private Vector3 EstimatedNextFramePosition;
/// <summary>
/// Gas quantity currently inside the balloon
/// </summary>
@ -75,18 +73,6 @@ namespace Aerostats
private ModuleBalloon Balloon;
private LineRenderer Spring;
public static void RemoveAttachJointBetween(Part part1, Part part2)
{
if (part1.attachJoint && ((part1.attachJoint.Host == part1 && part1.attachJoint.Target == part2) || (part1.attachJoint.Host == part2 && part1.attachJoint.Target == part1)))
{
part1.attachJoint.DestroyJoint();
}
if (part2.attachJoint && ((part2.attachJoint.Host == part2 && part2.attachJoint.Target == part1) || (part2.attachJoint.Host == part1 && part2.attachJoint.Target == part2)))
{
part2.attachJoint.DestroyJoint();
}
}
[KSPEvent(guiActive = true, active = true, externalToEVAOnly = false, guiActiveUnfocused = true, guiName = "Deploy balloon", unfocusedRange = 5)]
public void Deploy()
{
@ -109,11 +95,14 @@ namespace Aerostats
Balloon = balloonObject.GetComponent<ModuleBalloon>();
Balloon.part = balloonPart;
float initialGasQuantity = Mathf.Min(0.1f, part.RequestResource("Helium", MinimumFillQuantity));
balloonObject.SetActive(true);
GameEvents.onVesselWasModified.Fire(vessel);
Balloon.part.decouple(); // after that, the balloon becomes an independent vessel
Balloon.part.vessel.vesselName = vessel.vesselName + " balloon";
float initialGasQuantity = Mathf.Min(0.1f, part.RequestResource("Helium", MinimumFillQuantity));
Balloon.Initialize(this, part.rigidbody.velocity, GasDensity, initialGasQuantity);
LiftingGasQuantity = Balloon.LiftingGasQuantity;
@ -126,8 +115,6 @@ namespace Aerostats
Spring.SetVertexCount(2);
part.OnJustAboutToBeDestroyed += OnPartDestroyed;
EstimatedNextFramePosition = part.Rigidbody.position;
}
[KSPEvent(guiActive = true, active = true, externalToEVAOnly = false, guiActiveUnfocused = true, guiName = "Cut rope", unfocusedRange = 5)]
@ -139,8 +126,6 @@ namespace Aerostats
if (Balloon != null)
{
Balloon.OnDetached();
Balloon.part.decouple(); // after that, the balloon becomes an independent vessel
Balloon.part.vessel.vesselName = vessel.vesselName + " balloon";
Balloon = null;
}
Destroy(Spring);
@ -162,19 +147,6 @@ namespace Aerostats
Cut();
}
private void CheckKrakensbane()
{
// detect Krakensbane teleportation, and fix up the balloon position (otherwise it results in instant ship disintegration due to extreme forces on the spring)
if ((part.Rigidbody.position - EstimatedNextFramePosition).magnitude > 1000.0f)
{
Util.PostDebugScreenMessage("Krakensbane teleportation detected! (dist=" + (part.Rigidbody.position - EstimatedNextFramePosition).magnitude + ")");
var offset = part.rigidbody.position - EstimatedNextFramePosition;
Balloon.rigidbody.position += offset;
Balloon.transform.position = Balloon.rigidbody.position;
}
EstimatedNextFramePosition = part.rigidbody.position + part.rigidbody.velocity * Time.fixedDeltaTime;
}
private void FixedUpdate()
{
if (Destroyed)
@ -191,11 +163,6 @@ namespace Aerostats
if (Deployed)
{
// makes sure the balloon can move freely relatively to the vessel (apparently, KSP creates a joint when attaching a part)
RemoveAttachJointBetween(Balloon.part, part);
CheckKrakensbane();
float currentMaxQuantity = Balloon.GetCurrentMaxQuantity();
LiftingGasTargetQuantity = Math.Max(MinimumFillQuantity, LiftingGasTargetQuantity);
@ -260,23 +227,11 @@ namespace Aerostats
if (Deployed)
{
CheckKrakensbane();
var balloonAttachPoint = Balloon.rigidbody.position - Balloon.transform.up.normalized * Balloon.Radius;
Spring.SetPosition(0, part.transform.position);
Spring.SetPosition(1, balloonAttachPoint);
}
}
private void Update()
{
if (Destroyed)
return;
if (Deployed)
{
CheckKrakensbane();
}
}
}
}

Loading…
Cancel
Save