Skip to content

Instantly share code, notes, and snippets.

@JDPKSP
Last active December 23, 2015 05:49
Show Gist options
  • Save JDPKSP/6589153 to your computer and use it in GitHub Desktop.
Save JDPKSP/6589153 to your computer and use it in GitHub Desktop.
using System;
using UnityEngine;
class ModuleSolarSail : ModuleAnimateGeneric {
[KSPField]
public string ForceTransformName = "ForceTransform";
[KSPField]
public float MaxForce = 0f;
private Transform ForceTransform;
//returns the direction of the green axis of the ForceTransform.
private Vector3 ForceDir {
get {
return ForceTransform.up;
}
}
bool lineOfSight(Vector3 Origin, Vector3 Target, Vector3 sunDir) {
//check for all CelesTialBodies except the sun and return false if the body obstructs the sun.
foreach (CelestialBody referenceBody in FlightGlobals.Bodies)
if (referenceBody != Planetarium.fetch.Sun) {
Vector3d bodyFromOrigin = referenceBody.position - Origin;
Vector3d OriginFromTarget = Target - Origin;
if (Vector3d.Dot(bodyFromOrigin, OriginFromTarget) > 0) {
Vector3d bFromAnorm = OriginFromTarget.normalized;
if (Vector3d.Dot(bodyFromOrigin, bFromAnorm) < OriginFromTarget.magnitude) { // check lateral offset from line between b and a
Vector3d lateralOffset = bodyFromOrigin - Vector3d.Dot(bodyFromOrigin, bFromAnorm) * bFromAnorm;
if (lateralOffset.magnitude < (referenceBody.Radius - 5)) {
return false;
}
}
}
}
//check if any colliders within the 2 km loading range obstructs the sun.
if (Physics.Raycast(Origin, sunDir, 2000)) return false;
return true;
}
//returns a rough area representation of the angle; going from 0, if right angle (90 degrees) to 1 if 0 degrees.
private float ForceModifier {
get {
Vector3 Origin = ForceTransform.position;
Vector3 Sun = Planetarium.fetch.Sun.position;
Vector3 SunDir = (Sun - Origin).normalized;
//return 0 if sun is obstructed.
if (!lineOfSight(Origin, Sun, SunDir)) return 0;
float angle = Mathf.Deg2Rad * Vector3.Angle(SunDir, ForceDir);
//returns negative if the sun is behind the sail (angle above 90 degrees), resulting in a negative force being applied, accelerating in the correct direction (away from the sun).
//if this behaviour is not wanted, just return 1f - (float)Math.Cos(angle)
if (angle > Math.PI / 2)
return -(1f - (float)Math.Cos(angle));
else
return 1f - (float)Math.Cos(angle);
}
}
public override void OnStart(PartModule.StartState state) {
base.OnStart(state);
//find the ForceTransform;
this.ForceTransform = part.FindModelTransform(ForceTransformName);
}
public override void OnUpdate() {
base.OnUpdate();
float forcemodifier = ForceModifier;
//do nothing if the sail is folded or no force should be applied.
if (!base.animSwitch || forcemodifier == 0) return;
//Change orbit velocity if physics is not active, apply force if physics is active
if (vessel.HoldPhysics) {
float acceleration = (MaxForce * forcemodifier) / vessel.GetTotalMass();
vessel.orbit.vel += ForceDir * acceleration * TimeWarp.deltaTime;
} else
part.rigidbody.AddForce(ForceDir * MaxForce * forcemodifier * TimeWarp.deltaTime);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment