├── README.md ├── osp-logo.svg └── docs └── Technical.md /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![OSP Logo](https://i.imgur.com/BeWsiYp.png) 3 | 4 | # OpenSpaceProgram 5 | 6 | ### A space game inspired by Kerbal Space Program 7 | 8 | For more information please refer to the Discord server or the website: https://www.openspaceprogram.org 9 | -------------------------------------------------------------------------------- /osp-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | O 23 | S 24 | P 25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/Technical.md: -------------------------------------------------------------------------------- 1 | 2 | ![OSP Logo](https://i.imgur.com/BeWsiYp.png) 3 | 4 | # OSP Technical Document 5 | 6 | 7 | Contributors to this document: @Capital-Asterisk 8 | 9 | TODO: need some diagrams, review, and a more writing 10 | 11 | # Table of Contents 12 | 13 | - [Introduction](#introduction) 14 | - [Overview](#overview) 15 | * [Possible Classes](#possible-classes) 16 | * [Universe](#universe) 17 | + [Coordinates](#coordinates) 18 | + [Active Physics Areas](#active-physics-areas) 19 | + [Trajectory](#trajectory) 20 | * [Crafts](#crafts) 21 | + [Machines](#machines) 22 | + [Wiring](#wiring) 23 | * [Units](#units) 24 | - [Resources and Configs](#resources-and-configs) 25 | * [glTF sturdy](#gltf-sturdy) 26 | * [Config Files](#config-files) 27 | - [Questions](#questions) 28 | - [Ideas](#ideas) 29 | 30 | 31 | # Introduction 32 | 33 | OpenSpaceProgram (OSP) is an open source initiative to make a spaceflight simulation game similar to KerbalSpaceProgram. 34 | 35 | 36 | ~~It's not rocket science, and a working prototype shouldn't take more than a year to complete.~~ 37 | 38 | 39 | Creating such a project isn't an easy task, and requires careful planning and teamwork. 40 | 41 | 42 | This document describes class names, data structures, algorithms, and considerations on how to make an implementation of OSP regardless of game engine. There will not be anything on gameplay or art direction. This document attempts to take in account all the ideas listed in previous OSP feature documents, discussions on the Discord channel, and tests from existing repositories. 43 | 44 | # Overview 45 | 46 | OSP is a simulation of a small universe the player can interact with it through spacecraft of their own design. OSP should be able to simulate orbital mechanics in an explorable solar systems, complete with a star, planets, moons, asteroids, and any astronomical body imaginable. The player will use a variety of parts and their knowledge of physics to build their craft for space missions and expand infastructure. 47 | 48 | 49 | **Solution** 50 | 51 | 52 | At it's core, OSP needs to simulate objects in space and their interactions with each other. Every object in space will be known as a `Satellite`, including all astronomical bodies, spacecraft, or even just virtual reference frames. The movement of Satellites are determined by their `Trajectory`. When a player controls a craft, the area around it has to be loaded into the game engine with physics enabled, handled by the `ActiveArea`. 53 | 54 | How the craft itself is represented depends on the game engine, but in general, is a collection of `Part`s. Functionality of these parts come from their `Machine` components. For example, adding a "rocket machine component" to a paperweight part makes it into a functioning rocket. There is also a wiring system that allows parts to control each other. 55 | 56 | 57 | **Other Implications** 58 | 59 | * OSP can also be used as a base for other space-related games. 60 | 61 | ## Possible Classes 62 | 63 | An OSP implementation should kind of be structured like this, not that it has to. 64 | 65 | ### Universe: 66 | 67 | * **Satellite** 68 | 69 | Base class for an object in the universe. Has properties such as position, mass, a `Trajectory`, a parent `Satellite`, and children `Satellite`s. 70 | 71 | Note: Maybe a good idea to not have parenting, and rely only on Trajectories. 72 | 73 | * **ActiveArea (Inherits / component of Satellite)** 74 | 75 | Contain the game scene with physics enabled, and loads/unloads `Satellite`s around it into their game engine representations. 76 | 77 | * **AstronomicalBody (Inherits / component of Satellite)** 78 | 79 | Describes a planet, moon, or star and has many tweakable properties 80 | 81 | * **Vehicle (Inherits / component of Satellite)** 82 | 83 | Wraps game engine objects into a `Satellite`, including the player's Craft and its arrangement of `Part`s. 84 | 85 | * **ReferenceFrame (Inherits / component of Satellite)** 86 | 87 | Virtual point in space used for barycenters, markers, and various other purposes. 88 | 89 | *List more ideas here* 90 | 91 | * **Trajectory** 92 | 93 | A strategy that describes how a `Satellite` moves through space as a function of time. Not associated with the game engine's physics. 94 | 95 | * **Landed (Inherits Trajectory)** 96 | 97 | Keeps a `Satellite` locked to its parent's surface. 98 | 99 | * **Kepler (Inherits Trajectory)** 100 | 101 | Makes a `Satellite` orbit its parent according to Kepler's laws. 102 | 103 | * **NBody (Inherits Trajectory)** 104 | 105 | Considers gravity from all physical `Satellite`s and moves accordingly. Not entirely sure how to do this efficiently. 106 | 107 | * **Ballistic (Inherits Trajectory)** 108 | 109 | A `Satellite` falling through an atmosphere but isn't loaded in the physics engine. 110 | 111 | *List more ideas here* 112 | 113 | ### Vehicles & Parts: 114 | 115 | * **PartPrototype** 116 | 117 | Unique data describing a Part: `Machine`s used, models, textures, transformations, etc... Direct result of loading a file. 118 | 119 | * **PartBlueprint** 120 | 121 | Disposable representation of a `PartPrototype`. Contains tweaked options and is arranged into `CraftBlueprint`s 122 | 123 | * **PartPhysical** 124 | 125 | A game engine object loaded in an `ActiveArea` with working `Machine`s and everything. 126 | 127 | * **VehicleBlueprint** 128 | 129 | An arrangement of `PartBlueprint`s and a list of structual connections between them. Usually created by the player. 130 | 131 | * **VehiclePhysical** 132 | 133 | A group of `PartPhysical`s 134 | 135 | * **Machine** 136 | 137 | Base class for a component of a Part and has `WireInput`s and `WireOutput`s 138 | 139 | * **Rocket (Inherits Machine)** 140 | 141 | Applies thrust and drains fuel 142 | 143 | * **Decoupler (Inherits Machine)** 144 | 145 | Detaches certain attachments when activated through a `WireInput`. 146 | 147 | * **Control (Inherits Machine)** 148 | 149 | Listens to player inputs and controls other to `WireOutput`s 150 | 151 | *List more ideas here* 152 | 153 | * **WireOutput** 154 | 155 | Used by a `Machine` to send data to another `Machine`. Stores a value of some datatype representing throttle percentage, attitude control, etc..., which is read by connected `WireInput`s. 156 | 157 | * **WireInput** 158 | 159 | Used by a `Machine` to read data from another `Machine` by connecting to one of its its `WireOutput`. 160 | 161 | *TODO: think about how to properly handle dynamic parts: fairings, hinges, extendable parts, etc... * 162 | 163 | *List more ideas here* 164 | 165 | 166 | ## Universe 167 | 168 | To represent a large universe, it makes sense to use an n-ary tree or hierarchy or Satellites. Satellites can be parented to other Satellites, and all coordinates are relative to their parent. There exists a root satellite at the center of the universe. 169 | 170 | 171 | Each Satellite also has a Trajectory class which describes how the object moves through space as a function of time, used to implement orbital mechanics. The system is open to different methods of calculating orbits, such as Patched Conics or n-Body. A wandering spacecraft that moves around has its Trajectory swapped out depending on its surroundings. "Landed on a surface" is also a Trajectory class. 172 | 173 | 174 | The player interacts with the universe through the Game Engine. This requires a special Satellite known as an `ActiveArea`. ActiveAreas contain the game scene with physics enabled, and loads/unloads Satellites around it into their game engine representations. 175 | 176 | 177 | The large universe consisting of Satellites is referred to as the "OSP universe" in this document. 178 | 179 | 180 | ### Coordinates 181 | 182 | In the real world, our solar system is 4.5 billion kilometers in radius, 183 | 184 | Using floating points, Precision will decrease as distance from the origin increases. At ±16,777,216 units, 32-bit floats will no longer be able to represent odd integers. Floats work best when they're close to zero, which is wasted as zero is the insides of a planet. 185 | 186 | TODO: Think about more stuff, maybe some octree or something n-body friendly. 187 | 188 | **Solution A** 189 | 190 | Note: this might be a bad idea 191 | 192 | Why not make a coordinate system that can scale down to the quantum level, but also be able to span lightyears? Well this is a working solution, I guess. 193 | 194 | Again, coordinates of a Satellite are relative to its parent. Coordinates are in signed 64 bit ints. How much units is equal to a meter, is defined by the parent Satellite's "precision" value, discussed later. Note that this is separate from the game physics and scene system, which likely uses floats. 195 | 196 | In general, 197 | 198 | * Universe is a tree of Satellites 199 | * Signed 64-bit ints used as XYZ coordinates 200 | * All coordinates are relative to parent 201 | * Coordinates can vary in precision 202 | 203 | Satellites control the precision of their children's coordinates, or how many 64-bit int increments is equal to a meter. The precision value is an exponent to 2. Increasing precision decreases maximum space around the Satellite, decreasing precision increases this maximum space. Precision of coordinates will always be a power of two, because that's what the robots like. Precision should be set to a high value for small planets with moons and landed crafts as children, and a low value for larger objects like stars with orbiting planets. The values are absolute and do not accumulate along ancestors. 204 | 205 | | precision | Meters per unit | 206 | |-------------|--------------------| 207 | | -3 | 8 | 208 | | -2 | 4 | 209 | | -1 | 2 | 210 | | 0 | 1 | 211 | | 1 | 1/2 | 212 | | 2 | 1/4 | 213 | | 3 | 1/8 | 214 | | 4 | 1/16 | 215 | | .. 10 | 1/1024 | 216 | 217 | * Relative coordinates between Satellites can be calculated through finding a common ancestor. 218 | * Satellites like the player's Vehicle, can change parents to nearby objects, switching to a different coordinate system, which works nicely for patched conics. 219 | 220 | Again, if you don't like this implementation then go to yell at @Capital-Asterisk. 221 | 222 | ### Active Physics Areas 223 | 224 | The `ActiveArea` is a special kind of Satellite which stores the physics-enabled game scene, projecting the OSP universe into a tiny space the game engine can handle. The player can interact with the game scene through controlling Vehicles, and changes will be made to the OSP universe accordingly. ActiveArea is positioned the same way as any other Satellite, but usually follows the player around. 225 | 226 | **Loading and Unloading Satellites** 227 | 228 | All Satellites have some "load radius" variable, describing a sphere around the satellite. When the sphere of a normal Satellite hits an ActiveArea's sphere, then the ActiveArea calls the Satellite's `load()` functions, requesting that it should load a representation of itself into the game scene. Whatever happens in `load()` is up to the Satellite's implementation. For example, a Planet should load terrain into the game scene when an ActiveArea calls its `load()`. 229 | 230 | Note: maybe make the sphere a cube instead 231 | 232 | **Loading Previews** 233 | 234 | The ActiveArea should also load previews of distant objects, such as rendering planets as normal spheres, and spacecraft as a bright light flare. 235 | 236 | **Floating Origin** 237 | 238 | The (0, 0, 0) position of the ActiveArea's internal game scene, corresponds to the center of the Satellite in the OSP universe. 239 | ActiveArea keeps units of its Scene in meters, regardless of any precision values. 240 | 241 | **Other Implications** 242 | 243 | * There can be multiple active areas, aside from supporting distant objects having active physics. It is essential for multiplayer servers, and would allow ideas like SpaceX-style landing boosters. 244 | 245 | ### Trajectory 246 | 247 | A Trajectory class describes the movement of Satellites when they're not loaded in an ActiveArea. Satellites should be able to follow many different kinds of paths in space. They can be can be orbiting, landed, falling through an atmosphere, etc... Hard-coding orbital mechanics into the Satellite just isn't right. Trajectories are interchangable strategies that make it easy to manage the state of a Satellite, as well as allow for different kinds of orbit solvers, such as N-body, to be implemented cleanly. 248 | 249 | **Some ideas for a Trajectory:** 250 | * Landed Trajectory: for Satellites landed on a surface 251 | * Kepler Orbit Trajectory: Used for Patched Conics 252 | * N-body Trajectory: RK4 intergrators or something 253 | 254 | 255 | **Some crazy ideas:** 256 | * In-Flight Autopilot Trajectory: Plane eats fuel while moving through the atmosphere at constant altitude 257 | * Parabolic Flat Earth Trajectory: because why not ¯\\_(ツ)_/¯ 258 | 259 | **Implications** 260 | 261 | * Some trajectories don't have to be updated every frame, and can just be functions of elapsed time or something. 262 | 263 | 264 | For an example of how this system might work, let's say a player is landed on the moon. The craft has active physics and is loaded, but is stationary and not moving. The player exits to the menu, causing the lander to get unloaded. The lander's Trajectory is then set to a LandedTrajectory, which only saves its spot on the surface. The player comes back to the lander after a few minutes, and the moon had rotated pretty far. For the game to know the lander's new position, it calls its Trajectory, which is set to a LandedTrajectory. LandedTrajectory calculates the craft new position based on it's stored relative position, and the current rotation of the planet. 265 | 266 | When the player takes off from the moon, the ActiveArea handles the physics up to orbit. The player exits to the menu again, unloading the craft. The craft is then automatically assigned a KeplerOrbitTrajectory set by configs. 267 | 268 | 269 | ### Machines 270 | 271 | TODO 272 | 273 | ### Wiring 274 | 275 | Parts have to respond to inputs. For example, rockets need a throttle and gimbal inputs. It may make sense to hard-code user input into the parts or craft directly, but that solution isn't future-proof, especially when considering addons. Inputs would quickly turn into a mess of if statements. How about parts that control other parts, such as an autopilot? What if the player wants to control the throttle of each rocket individually, or wants them to respond to different buttons? Or what if the player only wants to control a small portion of a craft instead of destroying the entire space station? There has to be a system that connects parts in an organized way. 276 | 277 | **Solution** 278 | 279 | A modular solution, is some sort of logic/wiring system, where a Part's Machines can be black boxes with inputs and output that can be dynamically connected to other Machines. 280 | 281 | ``` 282 | Familiar Examples (data types and Machines not discussed for simplicity): 283 | 284 | Rocket Engine: 285 | - Inputs: [Throttle] [Gimbal] [On/Off] [etc..] 286 | - Outputs: [Temperature] [Current Thrust] [etc..] 287 | 288 | Capsule: 289 | - Inputs: [Oxygen valve to kill crew] [I can't think of any] [etc...] 290 | - Outputs: [Throttle control] [Rotation control] [Stage] [Custom button] [# of crew] [etc...] 291 | 292 | Autopilot computer 293 | - Inputs: [On/Off] 294 | - Outputs: [Throttle control] [Rotation control] [Oxygen control] [etc...] 295 | ``` 296 | 297 | TODO: table for different kinds of supported datatypes 298 | 299 | **Typical use** 300 | 301 | A player can control parts that have a "Control Machine," such as a capsule, so that the player's input devices are interfaced on WireOutputs. These outputs can be connected to the throttle and gimbal WireInputs of the rockets. 302 | 303 | If the player wanted to connect a rocket to [custom button] instead, then the player can disconnect the throttle control of the rocket, and connect it to custom button instead. 304 | 305 | ``` 306 | Quadcoupler with differential thrust: 307 | The 4 rockets connected to this part will be automaticall wired to custom throttle controls, so that they respond to rotation controls. 308 | - Inputs: [Rotation control] 309 | - Outputs: [Throttle A] [Throttle B] [Throttle C] [Throttle D] 310 | 311 | ``` 312 | 313 | **Implications** 314 | 315 | 316 | 317 | ## Units 318 | 319 | Use SI units and meters, no argument here. 320 | 321 | TODO 322 | 323 | # Resources and Configs 324 | 325 | TODO 326 | 327 | ## glTF sturdy 328 | 329 | TODO 330 | 331 | ## Config Files 332 | 333 | TOML? 334 | 335 | TODO 336 | 337 | # Questions 338 | 339 | *How would X be handled?* 340 | 341 | TODO 342 | 343 | # Ideas 344 | 345 | TODO 346 | 347 | * Port Bulleted List Extender Continued 348 | --------------------------------------------------------------------------------