Formation of the Solar System

This is our chance to throw some real science into our project. The following table shows the actual distance, size, rotation, and orbit values for each of the planets. (Most of this data came from http://www.enchantedlearning.com/subjects/astronomy/planets/.)

Planet

Distance from Sun (millions km)

Radius size (km)

Day length (Earth hours)

Year length (Earth years)

Mercury

57.9

2440

1408.8

0.24

Venus

108.2

6052

5832

0.615

Earth

147.1

6371

24

1.0

Earth's Moon

0.363 (from Earth)

1737

0

 

Mars

227.9

3390

24.6

2.379

Jupiter

778.3

69911

9.84

11.862

Saturn

1427.0

58232

10.2

29.456

Uranus

2871.0

25362

17.9

84.07

Neptune

4497

24622

19.1

164.81

Pluto (still counts)

5913

1186

6.39

247.7

We also have texture images for each of the planets. These files are included with the downloads for this book. They should be added to the res/drawable folder, named mercury_tex.png, venus_tex.png, and so on. The following table identifies the sources we have used and where you can find them as well:

Setting up planets in MainActivity

We're going to set up all the planets in MainActivity using a setupPlanets method that will be called from setup. Let's go for it.

At the top of the class, declare a planets array:

    Planet[] planets;

Then, we declare a number of constants which we'll explain in a moment:

    // tighten up the distances (millions km)
    float DISTANCE_FACTOR = 0.5f; // this is 100x relative to interplanetary distances
    float SCALE_FACTOR = 0.0001f; // animation rate for one earth rotation (seconds per rotation)
    float EDAY_RATE = 10f; // rotation scale factor e.g. to animate earth: dt * 24 * // DEG_PER_EHOUR
    float DEG_PER_EHOUR = (360f / 24f / EDAY_RATE); // animation rate for one earth rotation (seconds per orbit)//  (real is EDAY_RATE * 365.26)
    float EYEAR_RATE = 1500f; // orbit scale factorfloat DEG_PER_EYEAR = (360f / EYEAR_RATE); 

The setupPlanets method uses our celestial data and builds new planets accordingly. First, let's define the physical data, as follows:

    public void setupPlanets(Transform origin) {

        float[] distances = new float[] { 57.9f, 108.2f, 149.6f, 227.9f, 778.3f, 1427f, 2871f, 4497f, 5913f };
        float[] fudged_distances = new float[] { 57.9f, 108.2f, 149.6f, 227.9f, 400f, 500f, 600f, 700f, 800f };

        float[] radii = new float[] { 2440f, 6052f, 6371f, 3390f, 69911f, 58232f, 25362f, 24622f, 1186f };

        float[] rotations = new float[] { 1408.8f * 0.05f, 5832f * 0.01f, 24f, 24.6f, 9.84f, 10.2f, 17.9f, 19.1f, 6.39f };

        float[] orbits = new float[] { 0.24f, 0.615f, 1.0f, 2.379f, 11.862f, 29.456f, 84.07f, 164.81f, 247.7f };

The distances array has the distance of each planet from the Sun in millions of km. This is really huge, especially for the outer planets that are really far away and are not very visible relative to other planets. To make things more interesting, we'll fudge the distance of those planets (Jupiter through Pluto), so the values that we'll use are in the fudged_distances array.

The radii array has the actual size of each planet in kms.

The rotations array has the day length, in Earth hours. Since Mercury and Venus spin really fast compared to the Earth, we'll artificially slow them down by arbitrary scale factors.

The orbits array has the length of each planet's year in Earth years and the time it takes for one complete rotation around the Sun.

Now, let's set up the texture IDs for each planet's materials:

        int[] texIds = new int[]{
                R.drawable.mercury_tex,
                R.drawable.venus_tex,
                R.drawable.earth_tex,
                R.drawable.mars_tex,
                R.drawable.jupiter_tex,
                R.drawable.saturn_tex,
                R.drawable.uranus_tex,
                R.drawable.neptune_tex,
                R.drawable.pluto_tex
        };

Now initialize the planets array, creating a new Planet object for each:

        planets = new Planet[distances.length + 1];
        for(int i = 0; i < distances.length; i++){
            planets[i] = new Planet(
                    fudged_distances[i] * DISTANCE_FACTOR,
                    radii[i] * SCALE_FACTOR,
                    rotations[i] * DEG_PER_EHOUR,
                    orbits[i] * DEG_PER_EYEAR * fudged_distances[i]/distances[i],
                    texIds[i],
                    origin);
        }

While we fudged some of the planets' actual distances so that they'd be closer to the inner Solar System, we also multiply all the distances by a DISTANCE_FACTOR scalar, mostly to not blow up our float precision calculations. We scale all the planet sizes by a different SCALE_FACTOR variable to make them relatively larger than life (a factor of 0.0001 is actually a factor of 100 because radii are calculated in km while the distance is calculated in millions of km).

The rotation animation rate is the actual length of the day of the planet scaled by how fast we want to animate a day in VR. We default to 10 seconds per Earth day.

Lastly, the planetary orbit animation has its own scale factor. We've sped it up about 2 X. You can also adjust the orbit rate of the distance fudge factors (for example, Pluto orbits the Sun once every 247 Earth years, but we've moved it a lot closer so it needs to slow down).

Then, we add the Earth's moon. We've used some artistic license here as well, adjusting the distance and radius and speeding up its orbit rate to make it compelling to watch in VR:

        // Create the moon
        planets[distances.length] = new Planet(7.5f, 0.5f, 0, - 0.516f, R.drawable.moon_tex, planets[2].getTransform());}

Let's take a look at one more method: goToPlanet. It'll be convenient to position the Camera near a specific planet. Since the planets are located at data-driven positions and will be moving in orbit, it's best to make the camera a child of the planet's transform. This is one of the reasons why we separated out the orbiting transform from the planet's transform. We don't want the camera to spin around with the planet—you might get sick! Here's the implementation:

    void goToPlanet(int index){
        RenderBox.mainCamera.getTransform().setParent( planets[index].getOrbitransform(), false);
        RenderBox.mainCamera.getTransform().setLocalPosition( planets[index].distance, planets[index].radius * 1.5f, planets[index].radius * 2f);
    }

Note

Note that the scale and distance values we finally use in the code are derived from but not the actual celestial measurements. For a lovely VR experience of the Solar System with real educational value, check out Titans of Space (http://www.titansofspacevr.com/).

Camera's planet view

The gotoPlanet function is called with a planet index (for example, Earth is 2), so we can position the camera near the specified planet. The Camera component gets parented to the planet's orbitTransform variable as a way to obtain the planet's current orbit rotation. Then, it's positioned as the planet's distance from the Sun, and then offset a bit, relative to the planet's size.

In MainActivity class's setup method, we have already set up the Sun and the Earth. We'll replace the Earth sphere with a call to a setupPlanets helper method:

    public void setup() { 
        //Sun ...

        // Planets
        setupPlanets(origin);

        // Start looking at Earth   
        goToPlanet(2);
    }

If you build and run the project now, you will see the Earth, the Sun, and maybe some of the planets. But not until they're moving in their orbits will they come to life.

Animating the heavenly bodies

Now that we have all the planets instantiated, we can animate their orbit and axis rotations. All it takes is updating their transforms in the MainAcitvity class's preDraw method:

    @Override
    public void preDraw() {
        float dt = Time.getDeltaTime();
        for(int i = 0; i < planets.length; i++){
            planets[i].preDraw(dt);
        }
    }

Run! Oh, wow! I feel like a god. Well, not exactly, because it's dark outside. We need stars!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset