1
\$\begingroup\$

I'm trying to write a Java class to generate Perlin Noise from a Cartesian coordinate. I'm trying to follow this tutorial but I am struggling to understand the theory.

Specifically, how do you divide coordinates into a unit square or unit cube?

My original though was to a find which was higher the X or Y, then divide one by the other, So either X = 1, y < 1, or Y = 1, X < 1. But doing this doesn't really make sense as the point would always lie on one of the cube/square vertices.

Can someone explain the math to me please.

\$\endgroup\$
1
\$\begingroup\$

First, we divide the x, y, and z coordinates into unit cubes. In other words, find [x,y,z] % 1.0 to find the coordinate's location within the cube.

What that means is you perform the value % 1.0 operation for each member of the [x,y,z] vector (the position):

[x', y', z'] = [x % 1.0, y % 1.0, z % 1.0]

x', y', and z' are the remainders of dividing each floating-point coordinate by 1.0.

In other words, they are the amount you "chop off" of each coordinate when you round towards zero.

[x', y', z'] represents the position inside a unit cube, from 0.0 to 1.0 on each axis.
But you can also imagine that unit cube is actually positioned in 3D space at the rounded (towards zero) coordinates of [(int)x, (int)y, (int)z].

Another way to visualize what [x', y', z'] means is to imagine a 1x1x1 grid superimposed over your game world. Each cell in the grid is a unit cube. If you have a point anywhere in that game world, it must be inside of of those cubes. [x', y', z'] is telling you where the point is inside that cube.

The original position can be recovered by adding the position of the unit cube and the position inside the unit cube:
[x, y, z] = [(int)x, (int)y, (int)z] + [x % 1.0, y % 1.0, z % 1.0]

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you so much for the detailed explanation. I understand what it means now. \$\endgroup\$ – joshua jackson Mar 5 at 7:48
0
\$\begingroup\$

Usually 3D Perlin noise would look a bit like this:

float PerlinNoise(Vector3 point) {

    Vector3Int root = new Vector3Int(
         FloorToInt(point.x),
         FloorToInt(point.y),
         FloorToInt(point.z));

    for(int i = 0; i < 8; i++) {
        Vector3Int corner = root + cornerOffset[i];
        Vector3 gradient = GetPerlinGradient(corner);
        contribution[i] = Vector3.Dot(gradient, point - corner);
     }

     Vector3 pointInCell = point - root;

     return Interpolate(
         Interpolate(
              Interpolate(
                   contribution[0],
                   contribution[1],
                   pointInCell.x
              ),
              Interpolate(
                   contribution[4],
                   contribution[5],
                   pointInCell.x
              ),
              pointInCell.y
         ),
         Interpolate(
              Interpolate(
                   contribution[3],
                   contribution[2],
                   pointInCell.x
              ),
              Interpolate(
                   contribution[7],
                   contribution[6],
                   pointInCell.x
              ),
              pointInCell.y
         ),
         pointInCell.z
     );
}

So dividing space into repeated cubes is just a matter of rounding/flooring the coordinate. The position within this cell is just the fraction left over.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ thanks for the code sample. I can use this later \$\endgroup\$ – joshua jackson Mar 5 at 7:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.