proceduralism

sphRand and even random distributions on a sphere

While taking an excellent math course over at fxPhd someone asked about the math behind Maya’s sphRand command, and it kicked off a back and forth exploration into the difficulties behind getting an even distribution of random points on a sphere. This is useful for any number of applications where random vectors are needed.

[Note: This topic has been covered (better) elsewhere on the web, but I thought it was interesting enough to preserve for myself on this blog. -am]

So how do you generate a random vector in 3D space? The natural inclination is to generate each point based on a simple random azimuth and elevation. But because the circumference of latitudes decreases from the equator towards the poles, the result is an uneven distribution. Generate a few vectors and things will seem fine. But if you generate a large set of thousands of points, you get this:

But we need an even distribution. How about this: generate random values between -1 and 1 for each X, Y and Z. Then normalize those vectors, and again you have a collection of random points on a sphere. But the distribution still isn’t even… you are basically projecting the points of a cubic volume onto the sphere surface:

 

 

You can solve this problem by culling points outside the radius of the sphere (magnitude >1) as they are being generated, and the result is an even distribution on a sphere. This is known as the rejection method, and it works, but it’s inefficient. You are computing a lot of rejected points. Additionally, as a practical matter “N iterations” yields some number less than “N” vectors, making it difficult to specify the total number of vectors to be created by such a function.

 

Enter the trigonometric method (something of a misnomer seeing as how the method involves the integral of the surface of revolution.)

θ = υ(-1,1)

And Φ = υ(0,2π)

Where υ(a,b) is equal to a uniform random scalar.

So, go from Polar to Cartesian coordinates, and you get:

x = cos(θ) cos(Φ)

y = sin(Φ)

z = cos(θ) sin(Φ)

 

And it works.

 

Digression: if you want to get down to the heart of things, getting a random scalar value, or more specifically a repeatable pseudo-random value based on a specified seed, is it’s own challenge. Here’s a snippet of GLSL code, a function written by Stephen Gustavson which generates a “random” scalar value from a scalar seed input… (cos and mod should be familiar…the “fract” function returns the fractional (decimal) portion of it’s input.)

float randomizer(const float x) { float z = mod(x, 5612.0); z = mod(z, 3.1415927 * 2.0); return(fract(cos(z) * 56812.5453)); }

Terrain Generation Basis Functions

Having established a good start on hydraulic erosion, I moved to another area necessary for any good terrain toolkit – establishing a set of basis functions, from which you can achieve a the natural complexity needed by mixing various basis functions based on criteria such as latitude, slope, height, other fractals etc. Each basis function has it’s own character and “look” so to get a good heterogeneous result it’s valuable to be able to draw from a number of different functions. For example, here is a set of simple spheres deformed by a compound in which I use ICE’s excellent worley noise as a basis, which is then iterated through over a user-defined number of octaves, some of which are further modulated by a simplex fractal. You can see the character of the worley noise clearly, but where the simplex modulation comes into play you get a much more interesting result:

 

 

Less “terrain-like” is this output from a reticulation compound, which uses as it’s basis the “computational” noise described by Stephen Gustafson et al:

 

Interestingly, I approached this project having not read Ken Musgrave’s various writing on the subject of terrain generation outside of white papers. Once I did, I found that much of what I have discovered anecdotally he thought through in detail long ago. This is awesome, because it shows that my thinking has validity (after all, there are few who have spent more time and energy on the subject than he) and also because it gives me more threads to pull. I now have a series of compounds at my disposal that do various “terrain stuff,” now I can take a step back and decide how to assemble those experimental compounds into a more user-friendly and extensible set of ICE building blocks…

Terrain Generation via ICE

In between other projects I’ve slowly been building a number of softimage ICE compounds which deal with aspects of terrain generation. Here’s a result of two of them: a ridged perlin fractal and an iterative slope-based errosion. Only the basics are in place as of now – for instance I need to change the compounds to optionally deform along the original surface normal as opposed to just a y-up implementation (so you can generate planet surfaces etc) and create a set of nodes that let you blen various types of generation schemes (to get, say, a mix of ridged multifractal and fault-fracture methods.) Other items on my “to-do” list include:

Texture masks based on height, curvature and slope

River generation (I have one approach but it leaves a lot to be desired)

Additional fractal deforms (worley and other cell based schemes, “hill”, variants on multifractals)

Crater formation, ecosystem maps, more refined erosion, and mountain/valley range formation

So, there’s a lot to do. But one step at a time.

Leadership

Disney Animation is promoting the use of Partio, an open source particle library for use across various toolsets. You can find out more here.

That “metaball” look (has got to go)

In a recent discussion online another artist complained that metaballs have a distinctive look and that that look is never seen in nature. I get what they’re saying, “blobbies” are kind of like lensflares in that they are useful and necessary but can easily be overdone and distracting. But I would also point out that they don’t have to look “blobby.” Below are a couple of images created easily and in just a few minutes using ICE and emPolygonizer2 (and photoshop for the one, because I just had to fiddle around…)

I am a metaball mesh, yessir.

Ice – stretchy strands

Doing some stuff with strands. This is pretty primitive still, have to get dynamics working with strands which are constrained on either end, and come up with a scheme for breaking strands, tweak texture approach etc.

Diffusion limited aggregation redux

Over time people have been asking me to share the DLA compound I wrote waaay back. So here it is.

The compound can be found in the downloads section.

Diffusion limited aggregation is a natural phenomena in which particles in solution build up over time – as particles are deposited they limit the locations where subsequent particles can be deposited, resulting in a pseudo-random growth of deposits with characteristic nodules and ‘fjords’. You can see examples of DLA systems in nature all over, from veins of copper to urban growth patterns. In this simple ICE implementation particles are emitted from geometry and then pulled towards a “seed” point, namely the point cloud the compound is applied to. If there are no existing points in the cloud the first will be deposited at the origin. This causes DLA structures to build towards the provided surface and then to spread across it or inside it’s volume. The compound has a turbulence node which adds a random tropisim as well as a vector input for user-directed tropisims. Please be aware this was never intended as more than an experiment: it works fine but is a pretty simple implementation.

To use: apply the compound to a point cloud (typically with a single point) in a simulated ice tree… …