1

I'm working on a simulation of the Saturn system that will allow the user to, for example, increase the mass of its largest Moon Titan to that of Earth and see how the other moons and rings get perturbed as a result. My representation of the rings is a crude particle system where each particle starts out with a set of x, y, z position and velocity vectors. If I set the z position and velocity vectors to 0, I get a fairly nice looking ring that rotates around Saturn, but the problem is that Saturn has an axial tilt (the inclination of its axis of rotation to its orbital plane) of 27 degrees, so you have to take the z position and velocity vectors into account for the simulation to be at least somewhat realistic, but after lots of moaning and groaning, I haven't been able to get the inclination of the rings right.

This is the method that creates the initial conditions for the particles that make up the ring:

init() {

  for (let i = 0; i < this.numberOfParticles; i++) {

    const rad = Math.PI * 2 * Math.random();
    const dist = (25 + 20 * Math.random()) / 32000;

    this.particles.push({
      x: Math.cos(rad) * dist,
      y: Math.sin(rad) * dist,
      z: 0,
      vx: (Math.cos(rad + Math.PI / 2 + (Math.PI / 180 * 6 - Math.PI / 180 * 12) * 0) * Math.sqrt(500 / dist)) / 120,
      vy: (Math.sin(rad + Math.PI / 2 + (Math.PI / 180 * 6 - Math.PI / 180 * 12) * 0) * Math.sqrt(500 / dist)) / 120,
      vz: 0
    });

  }

}

Is there anybody out there that could help me figure out how to get the z position and velocity vectors right given the code above? As mentioned above, the axial tilt should be 27 degrees.

Happy Koala
  • 239
  • 1
  • 3
  • 10
  • Have you tried treating the particles as if they only exist in a standard axis-aligned plane, and then rotating the entire `Points` object to achieve the desired axial tilt? – TheJim01 Jun 05 '18 at 17:17
  • I have, and it looks alright, but as it's a gravity simulation, the distances and alas the perturbations won't come out right, which is why I really want to get the z vectors right. – Happy Koala Jun 05 '18 at 17:22
  • 1
    You can get the world positions of each point by extracting the a particle's position, and then using `particleRings.localToWorld(particlePosition);`. Note that this is destructive, so only use it on a temporary `Vector3` representing the point. Once you've done your calculations, you can convert back to local space using `worldToLocal`. – TheJim01 Jun 05 '18 at 17:26
  • That's something to work with, but that will only give me the position and not velocity vectors, no? – Happy Koala Jun 05 '18 at 17:28
  • You should be able to apply the same transformation on the velocity vector as you did to the particle. Try this: `velocityVector.applyQuaternion(particleRings.quaternion);`. That should apply the tilt to the velocity. – TheJim01 Jun 05 '18 at 17:37
  • I'm not that familliar with quaternions, but I know they are used for representing rotations, which leads me to think it's a potential solution, so would it be possible for you to take my code, make the modifications you suggested and create an answer? – Happy Koala Jun 05 '18 at 17:41
  • 1
    If you can create a [`Minimal, Complete, and Verifiable example`](https://stackoverflow.com/help/mcve) using [snippets](https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/), I'll copy it and give it a try. – TheJim01 Jun 05 '18 at 17:50

1 Answers1

3

Just a concept of how you can do it:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 10, 20);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setClearColor(0x101010);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var sun = new THREE.Mesh(new THREE.SphereGeometry(2, 16, 8), new THREE.MeshBasicMaterial({
  color: "orange"
}));
scene.add(sun);

var orbitGeom = new THREE.CircleGeometry(10, 32);
orbitGeom.rotateX(-Math.PI * 0.5);
orbitGeom.vertices.shift();
var orbit = new THREE.LineLoop(orbitGeom, new THREE.LineBasicMaterial({
  color: "yellow"
}));
scene.add(orbit);

var saturnSys = new THREE.Group();
var saturnSysAxis = new THREE.Vector3(0, 1, 0);
saturnSys.rotation.z = THREE.Math.degToRad(27);
saturnSys.add(new THREE.AxesHelper(5));
var saturnPlanet = new THREE.Mesh(new THREE.SphereGeometry(1, 8, 6), new THREE.MeshBasicMaterial({
  color: 0xFACE8D,
  wireframe: true
}));
saturnSys.add(saturnPlanet);

var saturnRingGeom = new THREE.Geometry();
var vertices = [];
for (let i = 0; i < 2000; i++) {
  let r = THREE.Math.randFloat(1.5, 4);
  let angle = THREE.Math.randFloat(0, Math.PI * 2);
  let v = new THREE.Vector3(
    Math.cos(angle) * r,
    0,
    Math.sin(angle) * r
  );
  v.angularVelocity = THREE.Math.randFloat(0.1, Math.PI);
  vertices.push(v);
}

saturnRingGeom.vertices = vertices;

var saturnRing = new THREE.Points(saturnRingGeom, new THREE.PointsMaterial({
  size: 0.1,
  color: "red"
}));
saturnSys.add(saturnRing);

scene.add(saturnSys);

var clock = new THREE.Clock();
var time = 0;
var delta = 0;

render();

function render() {
  requestAnimationFrame(render);
  delta = clock.getDelta();
  time += delta * 0.1;
  saturnSys.position.set(
    Math.cos(time) * 10,
    0,
    Math.sin(time) * 10
  );
  saturnPlanet.rotation.y = time * 3;
  saturnRing.geometry.vertices.forEach(v => {
    v.applyAxisAngle(saturnSysAxis, v.angularVelocity * delta);
  });
  saturnRing.geometry.verticesNeedUpdate = true;
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/93/three.min.js"></script>
prisoner849
  • 16,894
  • 4
  • 34
  • 68
  • Thank you and my apologies for the late reply! I have one question, though: how could I convert the angular velocity into state vectors, i.e velocity X, velocity Y and velocity Z? – Happy Koala Jun 09 '18 at 20:20
  • @HappyKoala You're welcome :) To be honest, I didn't get why you want to use a vector instead of an angle. Is there a working example, using vectors? You can put this question on the [forum](https://discourse.threejs.org/). – prisoner849 Jun 09 '18 at 20:28
  • I just posted a question over there with some code and a link to the git repository where you can find all of the code for this project. Fingers crossed :D. Link to the question: https://discourse.threejs.org/t/getting-initial-conditions-for-the-rings-of-saturn/3082 – Happy Koala Jun 09 '18 at 20:58