tralala
September 21, 2011, 3:30pm
1
Hello,
I tried to create a minecraft like world by using the perlin noise.
Result : fail, it only creates a 2d heightmap.

Basically the problem is that perlin noise returns only 1 value.

So i dont know how to map it to the x, y, z variables to make a random 3d map.

I tried this :

[java]

for (int i = 0; i < points; i++)

{

float xNoise = perlin.noise(seed

i, 0f, 0f);
float yNoise = perlin.noise(0f, seed i, 0f);

float zNoise = perlin.noise(0f, 0f, seed*i);

tile.move(xNoise * size, yNoise * size, zNoise * size);

…

}

[/java]

However the point distribution is biased and they tend to gather towards the center.

http://i.imgur.com/tUgmD.png

sbook
September 21, 2011, 4:23pm
2
I want to see more done around that second image! That’s a really neat looking system that got created!

tralala
September 21, 2011, 4:47pm
3
for each box i did :
mat.setColor(“Color”, ColorHSL.hueToColor( map[x][y][z], 1f, 0.55f ));
To explain it better i only change the “hue”, and because the perlin map returns a value at [0,1] it automatically generates the correct colors.
map[x][y][z] is the returned value of the perlin map.
[java]
package max.util.riven;
import com.jme3.math.ColorRGBA;
/** Riven : Riven :: code </> brain :: dump: Color :: HSL <> RGB
*/
public class ColorHSL
{
public static final void rgb2hsl(int[] rgb, float[] hsl)
{
float R = rgb[0] / 255.0f;
float G = rgb[1] / 255.0f;
float B = rgb[2] / 255.0f;
float MAX = Math.max(R, Math.max(G, B));
float MIN = Math.min(R, Math.min(G, B));
float H, L, S;
if (MIN == MAX)
H = 0.0f;
else if (R == MAX)
H = 0.16666666f * ((G - B) / (MAX - MIN)) + 0.00000000f;
else if (G == MAX)
H = 0.16666666f * ((B - R) / (MAX - MIN)) + 0.33333333f;
else
H = 0.16666666f * ((R - G) / (MAX - MIN)) + 0.66666666f;
L = 0.5f * (MIN + MAX);
if (L == 0.0f || (MIN == MAX))
S = 0.0f;
else if (L <= 0.5f)
S = (MAX - MIN) / (2 * L);
else
S = (MAX - MIN) / (2 - 2 * L);
hsl[0] = absMod(H, 1.0f);
hsl[1] = S;
hsl[2] = L;
}
/**

@param hue : value between 0 - 1. Use hue/360f if hue is specified in degrees.
/
public static ColorRGBA hueToColor(float hue, float saturation, float light)
{
float[] hsl = new float[3];
hsl[0] = hue ;
hsl[1] = saturation;
hsl[2] = light ;
int[] rgb = new int[3];
hsl2rgb(hsl,rgb);
return new ColorRGBA(rgb[0]/255f,rgb[1]/255f,rgb[2]/255f,1f);
}
/ * @return hsl[0] : hue (value between 0 - 1). Use hsl[0]*360 to convert to degrees. */
public static float[] colorToHue(ColorRGBA color)
{
int[] rgb = new int[3];
rgb[0] = (int)(color.getRed() * 255);
rgb[1] = (int)(color.getGreen() * 255);
rgb[2] = (int)(color.getBlue() * 255) ;
float[] hsl = new float[3];
rgb2hsl(rgb,hsl);
hsl[0] = hsl[0];
return hsl;
}
public static final int[] hsl2rgb(float[] hsl, int[] rgb)
{
float H = hsl[0];
float S = hsl[1];
float L = hsl[2];
float R, G, B;
if (S == 0.0f)
{
R = G = B = L;
}
else
{
float Q = (L < 0.5f) ? (L * (1.0f + S)) : ((L + S) - (L * S));
float P = 2.0f * L - Q;
float Hk = absMod(H, 1.0f);
R = convert(Q, P, Hk + 0.33333333333f);
G = convert(Q, P, Hk + 0.00000000000f);
B = convert(Q, P, Hk - 0.33333333333f);
}
rgb[0] = (int) (clamp(R, 0.0f, 1.0f) * 255.0f);
rgb[1] = (int) (clamp(G, 0.0f, 1.0f) * 255.0f);
rgb[2] = (int) (clamp(B, 0.0f, 1.0f) * 255.0f);
return rgb;
}
private static final float convert(float Q, float P, float Tx)
{
Tx = absMod(Tx, 1.0f);
if (Tx < 1.0f / 6.0f)
return P + ((Q - P) * 6.0f * Tx);
if (Tx < 3.0f / 6.0f)
return Q;
if (Tx < 4.0f / 6.0f)
return P + ((Q - P) * 6.0f * (4.0f / 6.0f - Tx));
return P;
}
public static final float absMod(float val, float max)
{
return ((val % max) + max) % max;
}
public static final float clamp(float cur, float min, float max)
{
return (cur < min ? min : (cur > max ? max : cur));
}
}
[/java]

sbook
September 21, 2011, 4:51pm
4
My bad, I meant the last image… but either way they’re all cool
p.s: I love the title “Canvas torture methods”

anthyon
September 21, 2011, 5:40pm
5
hi,
the main problem is that you seem to misunderstand what perlin noise - or noise in general - is powerful in: you are using 3D noise function but only in 1D for all 3 dimensions you get. The function itself will create one value, it’s true but it’s up to you, how you interpret it, as it does not have any predefined meaning.
Maybe you can try using it in one of the following two ways:
1.
[java]
float height = perlin.noise(x * someScaleX, z * someScaleZ, fineTune);
[/java]
this will give you a height value in every (x,z) coords (y is up ). someScale is used to transform the coords into a scaled coordinate system, as perlin noise gives you 0 values in every integer points, and fineTune can be used for anything: find a constant that gives you a nice terrain, or you can change it frame by frame using it as a time value, and create some nice animation.
2.
[java]
float density = perlin.noise(x * someScaleX, y * someScaleY, z * someScaleZ);
[/java]
calculate a density value in every point in space, and interpret it as needed. Eg. positives values mean solid material, while negative and zero values mean air.
I don’t know if I was clear enough.

tralala
September 21, 2011, 9:13pm
6
yes, you were clear, now i need to implement it.
I also found blockmania , an open source java minecraft project which i may use if i cant implement it.

Not sure if its still time for you to take a look at it, but I based my Voxel code on this project: http://code.google.com/p/jme3-voxel/
It was created by another member from community and is a really good start to understand all the Voxel details and have it working inside jMonkey itself.
Hope it helps.