Hey all. I got asked to write up a little about how I pulled of a fairly convincing spinning discoball in AltspaceVR. The SDK doesnt really support dynamic lighting, or reflections, so we have to approach this as a bit of a visual trick.
When you look at a disco ball, all you are seeing is a normal chrome ball, but the faceted reflections means each face of the ball is reflecting just a fraction of the area it would be on a smooth surface. However overall the reflection is still spherical, just with a lot of gaps between the reflected areas.
So I thought, we can do this with some UV jiggerypokery!
So First, Here’s what we’ll be making:
The most important part of this is prepping your sphere. A simple hard faced sphere wont work because we need the faces’ UVs to be very separated and isolated, but still in the right places relative to the other faces.
So here’s what I did:
Then I mapped my skybox image onto it. This could also be a proper reflection sphere image for the location you plan to place the ball. Here’s the image I used (made from Altspace’s own skybox):
OK, so that’s a nice ball. Now we need to Separate the faces in the UVs so we get that faceted look. I also hardened the normals on the mesh at this point.
But we need to split the faces so they are no longer connected, and then shrink them into themselves. After separating the edges I used a Maya MEL script I found here to shrink each UV “Shell” down towards its own center. Resulting in this:
Here’s how things are looking in our 3D view:
Now the trick here is that in Altspace we’ll use code to offset the image across these UVs horizontally. The separation will make them seem to flash and sparkle.
The relevant code in Altspace, after loading the object is:
discoballMat = discoball.children.material;
discoballMat.map.wrapT = THREE.RepeatWrapping;
discoballMat.map.wrapS = THREE.RepeatWrapping;
This puts the current material to a variable. and then sets the map of that material to repeat the texture in all directions. So that once we start animating it to the side there’s another of the same image to go into.
The relevant part in the animation loop is this:
discoball.rotation.y += 0.01;
discoballMat.map.offset.x = (THREE.Math.radToDeg(discoball.rotation.y)/360);
And with that, you should have this!