Spark – Our Solar System Explorer
This is my first blog post as I am the newest team member in Emit Knowledge. My first project at Emit Knowledge is called Spark. It’s an interactive web application generally for learning interesting facts about the planets in our solar system. In my opinion, and I’m sure that everyone will agree with me, nobody wants to look at tables including facts or some numbers, for example: the mass of Jupiter is 1.89813 × 1027 kilograms. The main point is to give this facts some fancy look.
That’s why we decided to use this facts and make something that has better graphic approach and you can interact with it. For this project we needed a technology that’s going to be cross-platform, and not dependent on browser’s plugins. As you can assume we decided to use WebGL.
As I said before, the application is going to be an interactive Solar System, so I needed textures about all the planets in the solar system. After a little research, I found a Three.js extension threex.planets.js. This extension contains functions already implementing the planet’s texture, rings (if there are any) as well as textures for the rings.
3D ViewThis is how the 3D View looks like on the finished application:
Now let’s go step by step, starting from WebGL renderer, main camera and scene initialization.
Scene and camera:
As you can see, at the end of the camera initialization, we add the camera to the scene. Actually the scene contains all the elements that we need or we want to see (as 3D Objects or Meshes). For every view I added a camera (for focus view other camera as well as for 2D view). This way it is more flexible.
Next thing are the lights. In three.js there are 7 main types of lights. In Spark, we are using 2 of them: Directional and Ambient Light.
In order for the render to start rendering the scene with its lights and objects, we need a render function that we’ll call it in the animation function.
After all this we create an array in which we push functions that need to be performed in the render, or some stuff that need to be performed all the time when the application is running and we add that function in the animate function.
Now let’s talk about the creating of the planets and their rotation around the sun and around their own axis. For this example we’ll take one planet, the Earth. I have a function CreatePlanet that takes the following arguments: the planet’s container (containers are 3D objects that contain all of the planet’s elements), their Mesh (as provided by Threex.planets.js), their size according to the size of the Earth, and their starting coordinates.
Next we use this function to create the Earth.
In three.js the rotations are actually changing the object’s position while rendering.
Firstly let’s see about the Earth’s rotation around its own axis. In the render array we push the following line, where delta is a constant.
About the planets rotation around the sun, I had a little bit of mathematic problem. I couldn’t find how to circular rotate the planet around a point in space (in this case, the sun). After doing a little research about trigonometry I found that in order to rotate an object in circular motion, one of the coordinates should be a cosine of a number, and the other should be a sine of a number. In order to have the right speed, compared to the earth (because if we put the real planet’s speed, it’ll be too slow). So we make a variable earthSpeed = 0.0001. After this we make a variable for the angle, ex. e_angle = time * earthSpeed. (If this was about Uranus the formula would be: u_angle = time * earthSpeed * 0.228).
Enough talking, this is what I was talking about:
We have two almost identical events, one for the 3D view, the other one for the 2D view. The philosophy in the both of the events is the same. We create a Raycaster, which produces rays from the camera to the place where the mouse pointer points at. Of course, this happens when the mouse is clicked. If the ray intersects an object, it returns a value greater than null. That’s how we check if a object (actually a planet mesh) has been clicked. And if the returned value is different from null, than we focus on a planet.
After importing OrbitControls.js plugin for moving around 3D environment for three.js we implement by making a control for the camera. In fact you are moving the camera.
We have a function named createPath which has a radius parameter which is different for every planet.
In this view we use the second camera, which is positioned only on the Y axis, so we can have a view from the top.
Lines and Text
For the lines we use a LineBasicMaterial for the material and Geometry for the geometry. In the geometry we push three Vector3 as vertices. Actually this three vectors are the coordinates of the points that are connected with the line. So, we have a function like this:
After that we simply put the coordinates in these functions and we get the lines. Here are the createLine functions for the Sun, Mercury, Venus and the Earth:
About the text we are using a MeshPhongMaterial where the map parameter is the link to the picture (actually the text is a png image) and a Mesh with PlaneGeometry (we need a Mesh, so it will be clickable). Here is how looks the function that puts the text for the Earth:
Generally it has been an interesting project and I enjoyed working on it. I learned a lot of things and got stuck on problems few times, but at the end it all went well. The final product is available on spark.emitknowledge.com. Feel free to give any suggestions in making Spark better.