Toggle menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Transform System Guide

From Kerbal Space Program 2 Modding Wiki
Revision as of 07:46, 3 January 2025 by Foonix (talk | contribs) (write some stuff about physics space)

Guide to the KSP 2 Transform system

KSP 2 uses a 64-bt double-precision system for tracking object position and movement. This guide attempts to explain how it works and how to use it.

The system is used to keep track of all objects in game, is used for game save state, and dealing with position between objects very long distances away. It works in tandem with Unity's 32-bit space, but provides better accuracy when dealing with astronomical distances or sizes.

This guide will assume some knowledge of how Unity transforms works, and 3d programming concepts such as points, vectors, quaternions, etc.

Major classes / structs

TransformFrame

TransformFrame represents a reference frame (Cartesian coordinate system) that can contain points or other spatial objects. They can be nested, that is, a frame can be "inside" of another frame.

Moving points and vectors from one transform frame to another is similar to using Unity's Transform matricies to move between objects spaces. However, there is no "global" space frame. Kerbol can be treated as a root level frame that all bodies move inside of (its position is (0,0,0), but most calculations will try to find the closest common parent .For example, if the player is on the Mun, but the game needs to draw an icon for a vessel on Minmus, the calculation will go through Kerbin's reference frame.

TransformModel

TransformModel represents a particular object inside of a reference frame. It is similar to Unity's Transform class.

TransformModel has a 1:1 relationship with the simulation SimulationObjectModel.

A model can have other models as children, or directly "float" in the reference frame.

Primitive types

There are double-precision types comparable to common Unit types, but using double or other underlying storage. These are straight forward replacements for various unity single-precision types. They are castable too and from the corresponding Unity types.

All of these primitive types are value types (struct).

Primitive types
KSP2 primative Unity Analog Underlying storage
Matrix4x4D Matrix4x4 Unity.Mathematics.double4x4
Vector3d Vector3 double (3x)
Vector4d Vector4 double (4x)
QuaternionD Quaternion double (4x)

Frame tracked types

There are certain types that are similar to primitive types, but include a reference to the coordinate system that they are created with respect to.

The transform system provides helpers to get relative position and rotations between points that are not in the same reference frame without having to explicitly pass around which frame they came from.

Frame tracked types
KSP2 class Underlying storage Unity Analog Usage notes
TransformFrame Vector3d/QuaternionD/Matrix4x4D (Unity coordinate system)
TransformModel Vector3d/QuaternionD Transform
Position Vector3d Vector3 A vector representing a position
Rotation QuaternionD Quaternion
Vector Vector3d - A vector representing a direction
Velocity Vector - Physics velocity vector
AngularVelocity Vector -

Interfaces

A number of interfaces denote which methods should be used on a given type.

The "Internal" interfaces are generally meant to be methods that a given type uses when calling between objects of its own type.

The "Driver" interfaces provide notification callbacks for specific value changes.

Name Implemented by Use
ITransformFrameInternal TransformFrame Calls between different kinds of TransformFrame subclasses
ITransformFrame TransformFrame Consumers of TransformFrame
ITransformModelInternal TransformModel Calls between different TransformModel objectss
ITransformModel TransformModel Consumers of TransformModel
ICoordinateSystem TransformFrame,

TransformModel

Translate a position, rotation, vector, or transform matrix that exists in some other ICoordinateSystem into the implementing coordinate system.
IPositionDriver (various) Change or listen for changes to an object's position.
IRotationDriver (various) Change or listen for changes to an object's rotation.
ILinearMotionDriver Change or listen for changes to an object's velocity.
IAngularMotionDriver Change or listen for changes to an object's angular velocity.
IMotionFrame Translate a velocity or angular velocity between moving reference frames.
IMotion The velocity and angular velocity between two objects (or reference frames).
IMotionRelative
IPhysicsSpaceProvider PhysicsSpaceProvider Translate between simulation space and Unity object space

The relationship between the game simulation and PhysX simulation

Normally, simulation object positions are determined entirely by the game's internal simulation engine. That is, `SimulationObjectModel` (the main object for simulation objects) are moved around by classes that live on the object like `OrbiterComponent`. This allows the game to track and move objects that don't exist in the Unity engine.

In that mode, most entities are essentially abstract. For example, the position of a part on a vessel can be calculated relative to the vessel, and in turn relative the the body it is orbiting. However, the part is not individually simulated (except for components that might do background calculations.). The part's position is just implied based on its relative position to the vessel.

When a vessel gets close enough to the player to be visible in game, the relationship between the parts and the vessel changes.The parts are individually loaded into Unity, the simulation positions are copied to unity GameObjects, and then PhysX eventually becomes the "source of truth" as to where exactly the part is. The vessel position is then calculated as an average of the of all of the part positions.

The coordinate system in Unity is referred to as "physics space" by the simulation code. Physics space is a moving reference frame used for showing sim objects to the player, and leveraging PhysX for physics simulation. Typically, physics space follows a vessel's orbit around (or location on) a planet. This means that although a vessel/part may be moving very fast and traveling long distances in sim terms, it may be moving very slowly and traveling short distances in PhysX terms.

The game will periodically "reset" physics space according to what the vessel does; It will move and change velocity of the physics space frame, and subtract that movement/position change to keep them from moving too far away from the origin or too high a speed. This is how the "floating origin" concept often mentioned in KSP context is actually implemented.

While a sim object is in physics space, the code will hold one of two states:

  • The game simulation position drives the unity position. That is, the unity position is set kinematically by the simulation layer based in the the physics space frame. PhysX is not allowed to move the objects.
  • The unity position drives the game sim position. PhysX (or possibly future network sync code) does whatever it wants to set the position in Unity space, and then the resulting unity space position is used to set the simulation position.

When a vessel is being loaded into physics space, it starts out in the first state. It will stay in that state for some number of frames until all of the parts are loaded, unpacked, and initialized in Unity. Then it will switch over to the second state.

When a vessel is unloaded from physics space, it will save the last known sim positions and destroy all of the associated Unity GameObjects. The simulation objects' positions return to being controlled by the simulation engine.