<!DOCTYPE html>
<html>
<head>
<title>1: Solar Systems</title>
<link rel="stylesheet" href="/style.css"/>
<link rel="stylesheet" href="/prism/prism.css"/>
<script src="/prism/prism.js"></script>
</head>
<body>
<div class="window">
<div class="window-title"><h2 style="padding: 0px; margin: 0px;">Learning Rust : Solar Systems</h2></div>
<i>How do I store non-owning references to collection members?</i>
<div class="window-content">
<a class="link-button" href="/projects/learning-rust"><</a>
<p>I want to make a data-driven viewer for the solar system, as part of a game inspired by <a href="https://www.aurora2.pentarch.org/">Aurora 4x</a> but Rust is an entirely different beast from C.</p>
<p>I have prior experience writing systems like this, so I figured it would be as easy as:</p>
<pre><code class="language-rust">
pub struct Orbital {
//Some optional non-owning reference to the parent orbital
mass : f64,
semi_major_axis : f64,
eccentricity : f64,
inclination : f64,
long_asc_node : f64,
argument_periapsis : f64,
mean_anomaly_epoch : f64
}
</code></pre>
<p>The question then is: How do we store the reference to the parent orbital?</p>
<p>note: by parent orbital, I mean the orbital body that the given orbital body orbits.</p>
<p>In C, we would just store a pointer into the data of the owning container (i.e. a dynamic array).</p>
<p>I understand that the method above could cause problems with object lifetimes and dead references, but in this case we are assuming a static lifetime with a fixed-width container.</p>
<p>So my first instinct is to look in the Rust docs for a non-owning reference type.</p>
<p>I wasted about a day researching Rc's and RefCell's when I had a revelation; what I wanted was over-engineered. Instead of storing a reference to the parent orbital, I could just store an index into the system's orbital container. All I need to do to make this work is pass a borrowed ref to the system object to the orbital's update function.</p>
<p>But not every part of the update function needs the parent orbital's position, so I can split the update into two parts:</p>
<p>1: Update the orbital elements relative to the parent object</p>
<p>2: Use the parent orbital's position to transform the relative coordinates into absolute coordinates</p>
<p>So here's what I came up with.</p>
<pre><code class="language-rust">
pub struct Orbital {
parent_index : usize,
//Temporary state variables for later update.
rel_pos : (f64, f64, f64)
//Orbital parameters
mass : f64,
semi_major_axis : f64,
eccentricity : f64,
inclination : f64,
long_asc_node : f64,
argument_periapsis : f64,
mean_anomaly_epoch : f64
}
//...
impl Orbital {
//...
pub fn update_rel(&mut self) -> Orbital {
//...
}
pub fn update(&self, &system : System) -> (f64, f64, f64) {
//...
}
}
</code></pre>
</div>
</div>
</body>
</html>