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 8 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) // replace mesh and collider by a sphere (hack until proper assets are created)
var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
gameObject.GetComponentInChildren<MeshFilter>().mesh = sphere.GetComponent<MeshFilter>().mesh; var meshFilter = gameObject.GetComponentInChildren<MeshFilter>();
Destroy(gameObject.collider); meshFilter.mesh = sphere.GetComponent<MeshFilter>().mesh;
var collider = gameObject.AddComponent<SphereCollider>(); var t = meshFilter.transform;
collider.radius = 0.67f; // don't ask me, I don't know why 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); Destroy(sphere);
gameObject.AddComponent<Rigidbody>(); gameObject.AddComponent<Rigidbody>();
rigidbody.mass = EmptyMass * 0.001f; rigidbody.mass = EmptyMass * 0.001f;
rigidbody.velocity = initialVelocity; // start with the same velocity or everything explodes when deploying from a moving vessel part.mass = rigidbody.mass;
rigidbody.angularDrag = 10.0f; rigidbody.velocity = initialVelocity;
rigidbody.position = transform.position; rigidbody.position = transform.position;
part.rb = rigidbody;
InjectGas(initialGasQuantity); InjectGas(initialGasQuantity);
@ -108,7 +119,7 @@ namespace Aerostats
CelestialBody body = vessel.mainBody; CelestialBody body = vessel.mainBody;
float externalTemperature = (float)FlightGlobals.getExternalTemperature(worldPos, body); 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 externalPressure = Math.Max((float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f, 0.00001f);
float currentGasMoles = GasUtilities.StpVolumeToMoles * LiftingGasQuantity; float currentGasMoles = GasUtilities.StpVolumeToMoles * LiftingGasQuantity;
@ -124,9 +135,15 @@ namespace Aerostats
// V = 4/3*pi*r^3 // V = 4/3*pi*r^3
Radius = Mathf.Pow(CurrentVolume * 0.75f / Mathf.PI, 0.333f); 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); transform.localScale = new Vector3(scale, scale, scale);
rigidbody.mass = (EmptyMass + balloonGasMass) * 0.001f; rigidbody.mass = (EmptyMass + balloonGasMass) * 0.001f;
part.mass = rigidbody.mass;
return LiftingGasQuantity; return LiftingGasQuantity;
} }
@ -140,7 +157,7 @@ namespace Aerostats
CelestialBody body = vessel.mainBody; CelestialBody body = vessel.mainBody;
float externalTemperature = (float)FlightGlobals.getExternalTemperature(worldPos, body); 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 externalPressure = Math.Max((float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f, 0.00001f);
Util.PostDebugSingleScreenMessage("external atmo", "Temperature = " + externalTemperature + "K, Pressure=" + externalPressure + "Pa"); Util.PostDebugSingleScreenMessage("external atmo", "Temperature = " + externalTemperature + "K, Pressure=" + externalPressure + "Pa");
@ -158,23 +175,28 @@ namespace Aerostats
InjectGas(0); // update security valve venting 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 + ")"); //Util.PostSingleScreenMessage("gravity", "Gravity accel = (" + gravityAccel.x + ", " + gravityAccel.y + ", " + gravityAccel.z + ")");
float externalTemperature = (float)FlightGlobals.getExternalTemperature(worldPos, body); float externalTemperature = (float)FlightGlobals.getExternalTemperature(worldPos, body);
float balloonInternalTemperature = externalTemperature; float externalPressure = (float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f;
float externalPressure = Math.Max((float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f, 0.00001f);
float airDensity = (float)FlightGlobals.getAtmDensity(externalPressure / 1000.0f, externalTemperature, body); 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 if (externalPressure > 0.00001f)
var airVelocity = rigidbody.velocity + Krakensbane.GetFrameVelocity() /*- vessel.mainBody.getRFrmVel(vessel.GetWorldPos3D())*/; {
float sqVel = (float)airVelocity.magnitude; // lift
sqVel *= sqVel; rigidbody.AddForce(-gravityAccel * Lift / 1000.0f, ForceMode.Force);
float dragForce = 0.5f * airDensity * sqVel * DragCoeff * (Mathf.PI * Radius * Radius);
Util.PostDebugSingleScreenMessage("balloon drag", "Drag = " + dragForce + "N"); // balloon drag
rigidbody.AddForce(-airVelocity.normalized * dragForce / 1000.0f, ForceMode.Force); 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 bool Destroyed;
private Vector3 EstimatedNextFramePosition;
/// <summary> /// <summary>
/// Gas quantity currently inside the balloon /// Gas quantity currently inside the balloon
/// </summary> /// </summary>
@ -75,18 +73,6 @@ namespace Aerostats
private ModuleBalloon Balloon; private ModuleBalloon Balloon;
private LineRenderer Spring; 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)] [KSPEvent(guiActive = true, active = true, externalToEVAOnly = false, guiActiveUnfocused = true, guiName = "Deploy balloon", unfocusedRange = 5)]
public void Deploy() public void Deploy()
{ {
@ -109,11 +95,14 @@ namespace Aerostats
Balloon = balloonObject.GetComponent<ModuleBalloon>(); Balloon = balloonObject.GetComponent<ModuleBalloon>();
Balloon.part = balloonPart; Balloon.part = balloonPart;
float initialGasQuantity = Mathf.Min(0.1f, part.RequestResource("Helium", MinimumFillQuantity));
balloonObject.SetActive(true); balloonObject.SetActive(true);
GameEvents.onVesselWasModified.Fire(vessel); 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); Balloon.Initialize(this, part.rigidbody.velocity, GasDensity, initialGasQuantity);
LiftingGasQuantity = Balloon.LiftingGasQuantity; LiftingGasQuantity = Balloon.LiftingGasQuantity;
@ -126,8 +115,6 @@ namespace Aerostats
Spring.SetVertexCount(2); Spring.SetVertexCount(2);
part.OnJustAboutToBeDestroyed += OnPartDestroyed; part.OnJustAboutToBeDestroyed += OnPartDestroyed;
EstimatedNextFramePosition = part.Rigidbody.position;
} }
[KSPEvent(guiActive = true, active = true, externalToEVAOnly = false, guiActiveUnfocused = true, guiName = "Cut rope", unfocusedRange = 5)] [KSPEvent(guiActive = true, active = true, externalToEVAOnly = false, guiActiveUnfocused = true, guiName = "Cut rope", unfocusedRange = 5)]
@ -139,8 +126,6 @@ namespace Aerostats
if (Balloon != null) if (Balloon != null)
{ {
Balloon.OnDetached(); Balloon.OnDetached();
Balloon.part.decouple(); // after that, the balloon becomes an independent vessel
Balloon.part.vessel.vesselName = vessel.vesselName + " balloon";
Balloon = null; Balloon = null;
} }
Destroy(Spring); Destroy(Spring);
@ -162,19 +147,6 @@ namespace Aerostats
Cut(); 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() private void FixedUpdate()
{ {
if (Destroyed) if (Destroyed)
@ -191,11 +163,6 @@ namespace Aerostats
if (Deployed) 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(); float currentMaxQuantity = Balloon.GetCurrentMaxQuantity();
LiftingGasTargetQuantity = Math.Max(MinimumFillQuantity, LiftingGasTargetQuantity); LiftingGasTargetQuantity = Math.Max(MinimumFillQuantity, LiftingGasTargetQuantity);
@ -260,23 +227,11 @@ namespace Aerostats
if (Deployed) if (Deployed)
{ {
CheckKrakensbane();
var balloonAttachPoint = Balloon.rigidbody.position - Balloon.transform.up.normalized * Balloon.Radius; var balloonAttachPoint = Balloon.rigidbody.position - Balloon.transform.up.normalized * Balloon.Radius;
Spring.SetPosition(0, part.transform.position); Spring.SetPosition(0, part.transform.position);
Spring.SetPosition(1, balloonAttachPoint); Spring.SetPosition(1, balloonAttachPoint);
} }
} }
private void Update()
{
if (Destroyed)
return;
if (Deployed)
{
CheckKrakensbane();
}
}
} }
} }

Loading…
Cancel
Save