Procedural sphere generation (cube to sphere) - few math questions

Hello guys.
As I’m not much of a mathematician, I have a few questions about the following lines of code from YouTube for which I’d be very grateful if someone could help me.

Question 1:
On the video: [Unity] Procedural Planets (E01 the sphere) - YouTube

Video name: [Unity] Procedural Planets (E01 the sphere)

Timestamp: 15:49 (where TerrainFace.cs could could be seen)

Lines 19 and 20 (TerrainFace.cs):
Why is he mixing the values for newly created Vector3?
Newly created Vector3.x = localUp.y , y = z and z = x?


What’s the purpose of this?
Could it be any other way?

Also, on line 20, what’s the purpose of vector cross product?
Could someone explain it to me in detail (if possible graphically?)

Question 2:
Same video, same timestamp, line 36.

Vector3 pointOnUnitSphere = pointOnUnitCube.normalized

I know what normalized means (values from -1 to 1 if I’m not mistaken) but how the cube face “knows” that only egdes must be bent (and not e.g. upper center on the line)?

At a glance, it looks like their “axisA” and “axisB” variables are being used in a less-than-foolproof attempt to produce a non-parallel vector pair to act as a Tangent and Bitangent, versus the Normal of the given “terrain face” (“localUp”, in this case). If all three axes were the same for any reason, the vector would be parallel and a viable cross product wouldn’t be possible, resulting in a zero-vector.


For reference, a normalized vector has a length of 1, regardless of the direction that vector faces. The basic formula, in terms of spatial coordinates, would look something like:

x2 + y2 + z2 = 1

The simplest example(s) of this would be a vector facing straight along any axis, such as (1, 0, 0) or (0, -1, 0). A 45° angle along a pair of axes might be roughly (0.707, 0, -0.707) (sqrt(2) = ~1.414, then divide that by 2)


As a point of reference, many shapes can be "spherized" by normalizing the positions of their vertices. A tessellated cube is a common example of this, since the resulting distribution of vertices will generally be consistent and symmetrical along all three (local) axes.

So, if I understood this correctly, that means if for example:

AxisA = {1,0,0}

localUp = {0,1,0} in the terms of “real UP”

than the AxisB (cross-product of localUp and AxisB) will be {0,0,-1}?

X = red ;
Y = blue ;
Z = green

I still don’t get it, what excatly is the purpose of AxisB vector (which is a cross-product).
It only has Z component that equals to -1.

Does it “describe” how much indentation will cube face have or what exactly?

Can you explain in layman’s terms (remember, im not a mathemathician) please?

I know what normalized means (values from -1 to 1 if I’m not mistaken) but how the cube face “knows” that only egdes must be bent (and not e.g. upper center on the line)?

I think your main problem is here. Normalized does not mean values from -1 to 1. A normalized vector has a fix length of 1. It’s true that the individual components are in the range -1 to 1 after normalization, but the important part is the total length of 1. What actually happens is that the initial cube already covers the whole surface area. All you do is take each vertex of the cube relative to the center point and normalize this vector. So the point on the cube gets projected onto the unit sphere. After that you can multiply by your desired radius.

In addition you could apply a hight map displacement which you simply add to the radius when you multiply the unit vector. I’ve made an example long time ago (around 2012) where I even created a Unity WebPlayer build that demonstrated this. However the WebPlayer plugin is no longer supported. I just searched through my local files and found my ancient project. The migration didn’t went that well since it was a really old project. Though I fixed all issues and created a WebGL build of my old example. You can find it here.

Note that there are 3 sliders. The first one is actually a lerp between the initial cube and “spherified” cube. So you can gradually see the change as you move the slider from left(cube) to right(sphere)
The second slider is the target sphere radius. So changing this slider changes the size of the resulting sphere.
The third slider is a multiplication factor for the height map. So if you drag it all the way to the left, no heightmap would be added and you get a perfect sphere.

At the bottom right there’s a “Tex” button that lets you cycle through 4 materials. The first one is just plain white, the second one is the heightmap texture applied as albedo, so it would match the hills and valleys of the heightmap. The other 2 are just debug textures.

You can use the right mouse button to orbit the camera and use the mouse wheel to move the camera closer / further away… The JoinEdges button / toggle lets you disable the simple edge joining code. Because I apply the exact same heightmap to all 6 sides, we get the same displacement on each face. However the edges of two adjacent sides usually do not match, so as a result you would get gaps between the two sides. JoinEdges just makes sure the corresponding vertices along the edge of two faces have the same height. It simply calculates the average of the two. This is by no means a great solution. You usually need to apply a better gradient to slowly merge the two edges. Of course corners get even more trickier since you have 3 edges meeting. JoinEdges at least makes sure the mesh is closed.

The 6 sides are actually seperate meshes and seperate mesh renderers. All 6 gameobjects are located at the center of the sphere / cube and the vertices of each plane are simply offset. The plane mesh is generated procedurally.