I’ve been always fascinated by 3D and 3D presentation on the web space, well, since the tragic VRML(http://en.wikipedia.org/wiki/VRML). During the time in the university, I poked around Direct3D and OpenGL a little bit and after then anything with 3D on its name attracted my attention but haven’t achieved anything serious thanks to my laziness.
And one day, there came a chance that I needed to do some, admittedly nothing fancy like what you can see on http://www.chromeexperiments.com/, 3D action in an actual project.
During the search, I came across Sprite3D.js (https://github.com/boblemarin/Sprite3D.js/tree/v2) that gave me an idea to use CSS3 3D transform instead of canvas or WebGL.
Surprisingly, I struggled to find any articles explaining how to draw a simple 3D object with code from scratch (that I could just copy and paste easily...), such as a closed cylinder for my coin in this case.
So I planned to use a shallow box as a base of the coin, texture the top and bottom face with the coin’s face and tail, and then place a reasonably smoothly segmented cylinder between the top and the bottom face to make the coin.
What is underneath…
The image below shows the basic of how CSS3 3D space looks like.
If the centre of your screen is the origin of the 3D space, it’s positive x toward your right, positive y toward up, and positive z toward you. The camera’s position is represented by perspective.
Lower perspective usually produces dramatically exaggerated distance look so called perspective distortion like using wide angle lens, and higher perspective vice versa.
It can be quite fiddly job to find the right perspective to work on different situations but normally between 700px and 1000px is acceptable. Sprite3D.js uses 800px as default.
A Box that is...
After the stage is set, I made a box to use it as the base of the coin.
Lots of triangles...
The next is to make a cylinder and this gets a bit trickier.
Let’s start with 8-facet cylinder so it’s easier to illustrate.
[gist id="4943805" file="draw-8-facet-cylinder-part.js"]
In short, to draw a polygon like above, we need “w” that is the width of each facets, angle “d” of the first facet to be used to find "p(x, y)", and then duplicate the facet and rotate angle “d” until fill the full circle.
First, we need “d” that is the angle of the facet and convert it to radian to be used with Math.sin() and Math.cos().
And get “w”, width of the facet
And get the distance between “o” and “p” to get the position of the first facet
And then rotate it for each facets
With 80-facet cylinder it looks a lot smoother.
And now texture the cylinder and make it a bit thinner so it looks more like a coin.
Now it’s the time to toss it and add a shadow layer for the finishing touch..
With a bit of randomness with Math.random() and an easing function, it’s possible to create a convincing animation without physics engine.