# A WebGL 3D Solar System!

This week we looked at WebGL and how it can be used in Javascript to easily create 3D animations and games.  After looking at different shapes for a while, someone suggested building a solar system so that’s what we did!  This project just did the first sample planet.

The code is up on github as usual!

## What is WebGL?

WebGL is a javascript API that allows your programs to use the graphic cards on your computer.  Graphics cards are built for really fast graphics and have specially encoded hardware to quickly do the calculations needed for common graphics.  With 2D, you can often get away without graphics cards, but they really make things a lot faster in 3D!

There are several javascript libraries that let you use webGL – the most famous and probably the best of them is one called three.js, which lets you do really advanced 3d – however our trusty p5.js also has a pretty decent set of functions and for us is much easier to use.

## Initializing the p5 canvas for 3D

The great thing we found about p5.js 3d is that is is REALLY similar to the 2D shape functions, so much so that we all intuitively were able to get going with little need to look at documentation.

Sadly, it’s not easy to mix 2D and 3D code in P5 as the “canvas” is created differently.

To get it started, we had to add one word to the createCanvas function call – “WEBGL” – so to create a canvas we use the function:

```
setup() {

createCanvas(800, 600, WEBGL);

}

```

## P5 3D primitives

There are many better reference guides online so I won’t go int great detail here but the main built-in shapes that you can use to create things with are:

• Box for all manners of cuboids
• Plane for a flat plane (a “rect” also works actually!)
• Sphere for a (duh!) sphere
• Ellipsoid for a rugby ball shaped thing
• Cone for a cone-shape
• Torus for a donut shape
• Cylinder for a cylinder

Using these basic building blocks, it’s possible to create all manner of shapes.

There is also a “loadModel” function that allows you to read in a model from a 3D package like “Blender”.  These can be models of spaceships, bad-guys, houses, ponies, whatever you like!  Maybe at some stage in the future we’ll try to learn a bit about blender.  One of the ninjas already had played with blended and managed to load in a model of a meteorite he’d been working on!

## Positioning shapes

The models and shapes don’t have any coordinates on them – it’s all stuff like size and grid size.

Our first program involved creating a box and moving it around.

To position the shapes you use the “translate” function, just like you can in 2d. With this we moved the shape around

```
function draw(){
background(50);

push();
translate(0, 0, 0);
box(100, 100, 100);
pop();

// increase X - move right
push();
translate(200, 0, 0);
box(100, 100, 100);
pop();

// increase Y - move down
push();
translate(0, 200, 0);
box(100, 100, 100);
pop();

// upper left and closer to viewer
push();
translate(-200, -200, 200);
box(100, 100, 100);
pop();
}

```

We quickly noticed that the axis are slightly different:

1. The box appeared in the center of the screen – i.e. 0,0 is the middle of the screen (like scratch) rather than the top left. (Box 1 below)
2. Making X bigger moved it to the right (Box 2)
3. That making Y bigger still moved it “down” unlike scratch! (Box 3)
4. That making Z bigger moved it towards the viewer (Box 4)
5. That there is perspective automatically built in

To Rotate shapes, there are three functions that are handy: rotateX, rotateY, rotateZ – these can rotate around the axes.  Just like in 2D the ddefault unit is radians so you need to set angleMode(DEGREES) if you want degrees.  For example – rotating the box by 45 degrees is per below:

```angleMode(DEGREES);
rotateX(45);
box(50, 50, 50);
```

Push() and pop() can be used to stack the transformations on top of each other – just like in the 2d sketches!

## Lights!

We learnt that there are three types of light:

1. AmbientLight is light which comes from everywhere – it casts no shadow.  We just give it a color ambientLight(255) is a white ambient light for example
2. pointLight is a light which is centered on a point.  It just has a color and a position – e.g. pointLight(r, g, b, x, y, z).  Pointlights are pretty dim, but you can stack lots of them on the same location to make them brighter – this is what we did for our sun!
3. directionalLight is a light which has a color and a direction – this is very similar to the pointLight except that the light just shines in one direction and can be used for e.g. spotlights.

## Material!

Depending on the material, the light reflects different ways – the main material types we tried were:

• ambientMaterial: This is normal “Matte” material
• specularMaterial: this is reflective material – it shines back like glass or water
• normalMaterial: This is the default material type – this is kind of weird looking to me and I’d usually use ambient…

For each of these types, you simply set the material before drawing the shape – kind of like the fill function.

## Explaining the Solar System Code

Our “Solar System” code was very basic – what we have here was one planet orbiting around a Sun in a spherical orbit, with a moon orbiting around that planet.  We didn’t have any physics in there – just spheres orbiting each other.

We did the following:

1. set nostroke
2. started a rotation around the Y axis
3. created a bunch of lights at the center where the sun is
4. drew a big yellow sphere for the sun
5. translate 300 pixels out to draw a blue sphere
6. set it’s rotation to 12 times faster than the “earths”
7. moved 50 pixels out.
8. drew another small white sphere

This sounds like a lot but the code is really simple and can be seen here.

## Challenge!!

We did one planet and moon in the class because a lot of the time was spent playing with our own projects.  How about you take our solar system and change it so that all the planets have accurate relative rotation speeds?  i.e.

Mercury: 87.97 days (0.2 years)
Venus : 224.70 days (0.6 years)
Earth: 365.26 days(1 year)
Mars: 686.98 days(1.9 years)
Jupiter: 4,332.82 days (11.9 years)
Saturn: 10,755.70 days (29.5 years)
Uranus: 30,687.15 days (84 years)
Neptune: 60,190.03 days (164.8 years)

Try putting a ring (torus?) around Saturn!

The distance from the sun could also be put in, but it might be a bit weird looking – in fact you wouldn’t even see most of the planets as they get pretty spaced out as you move out!