2
\$\begingroup\$

I'm currently working on a game with an "infinite" programmatically generated terrain. The terrain is being generated by creating a heightmap using simplex noise.

I've followed a tutorial and ended up with the following code (it's vb.net by the way):

Public Shared Function GetNoise(ByVal xin As Double, ByVal yin As Double, ByVal zin As Double) As Single
        Dim n0, n1, n2, n3 As Double ' Noise contributions from the four corners
        ' Skew the input space to determine which simplex cell we're in
        Dim s As Double = (xin + yin + zin) * F3 ' Very nice and simple skew factor for 3D
        Dim i As Integer = fastfloor(xin + s)
        Dim j As Integer = fastfloor(yin + s)
        Dim k As Integer = fastfloor(zin + s)
        Dim t As Double = (i + j + k) * G3
        Dim X00 As Double = (i - t) ' Unskew the cell origin back to (x,y,z) space
        Dim Y00 As Double = (j - t)
        Dim Z00 As Double = (k - t)
        Dim x0 As Double = (xin - X00) ' The x,y,z distances from the cell origin
        Dim y0 As Double = (yin - Y00)
        Dim z0 As Double = (zin - Z00)
        ' For the 3D case, the simplex shape is a slightly irregular tetrahedron.
        ' Determine which simplex we are in.
        Dim i1, j1, k1 As Integer ' Offsets for second corner of simplex in (i,j,k) coords
        Dim i2, j2, k2 As Integer ' Offsets for third corner of simplex in (i,j,k) coords
        If (x0 >= y0) Then
            If (y0 >= z0) Then ' X Y Z order
                i1 = 1
                j1 = 0
                k1 = 0
                i2 = 1
                j2 = 1
                k2 = 0
            ElseIf (x0 >= z0) Then ' X Z Y order
                i1 = 1
                j1 = 0
                k1 = 0
                i2 = 1
                j2 = 0
                k2 = 1
            Else ' Z X Y order
                i1 = 0
                j1 = 0
                k1 = 1
                i2 = 1
                j2 = 0
                k2 = 1
            End If
        Else                ' x0<y0
            If (y0 < z0) Then ' Z Y X order
                i1 = 0
                j1 = 0
                k1 = 1
                i2 = 0
                j2 = 1
                k2 = 1
            ElseIf (x0 < z0) Then ' Y Z X order
                i1 = 0
                j1 = 1
                k1 = 0
                i2 = 0
                j2 = 1
                k2 = 1
            Else ' Y X Z order
                i1 = 0
                j1 = 1
                k1 = 0
                i2 = 1
                j2 = 1
                k2 = 0
            End If
        End If
        ' A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
        ' a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
        ' a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
        ' c = 1/6.
        Dim x1 As Double = ((x0 - i1) + G3) ' Offsets for second corner in (x,y,z) coords
        Dim y1 As Double = ((y0 - j1) + G3)
        Dim z1 As Double = ((z0 - k1) + G3)
        Dim x2 As Double = ((x0 - i2) + (2 * G3)) ' Offsets for third corner in (x,y,z) coords
        Dim y2 As Double = ((y0 - j2) + (2 * G3))
        Dim z2 As Double = ((z0 - k2) + (2 * G3))
        Dim x3 As Double = ((x0 - 1) + (3 * G3)) ' Offsets for last corner in (x,y,z) coords
        Dim y3 As Double = ((y0 - 1) + (3 * G3))
        Dim z3 As Double = ((z0 - 1) + (3 * G3))
        ' Work out the hashed gradient indices of the four simplex corners
        Dim ii As Integer = (i And 255)
        Dim jj As Integer = (j And 255)
        Dim kk As Integer = (k And 255)
        Dim gi0 As Integer = permMod12((ii + perm((jj + perm(kk)))))
        Dim gi1 As Integer = permMod12((ii + (i1 + perm((jj + (j1 + perm((kk + k1))))))))
        Dim gi2 As Integer = permMod12((ii + (i2 + perm((jj + (j2 + perm((kk + k2))))))))
        Dim gi3 As Integer = permMod12((ii + (1 + perm((jj + (1 + perm((kk + 1))))))))
        ' Calculate the contribution from the four corners
        Dim t0 As Double = (0.6 - ((x0 * x0) - ((y0 * y0) - (z0 * z0)))) ' change to 0.5 if you want

        If (t0 < 0) Then
            n0 = 0
        Else
            t0 = (t0 * t0)
            n0 = (t0 * (t0 * dot(grad3(gi0), x0, y0, z0)))
        End If

        Dim t1 As Double = (0.6 - ((x1 * x1) - ((y1 * y1) - (z1 * z1)))) ' change to 0.5 if you want

        If (t1 < 0) Then
            n1 = 0
        Else
            t1 = (t1 * t1)
            n1 = (t1 * (t1 * dot(grad3(gi1), x1, y1, z1)))
        End If

        Dim t2 As Double = (0.6 - ((x2 * x2) - ((y2 * y2) - (z2 * z2)))) ' change to 0.5 if you want

        If (t2 < 0) Then
            n2 = 0
        Else
            t2 = (t2 * t2)
            n2 = (t2 * (t2 * dot(grad3(gi2), x2, y2, z2)))
        End If

        Dim t3 As Double = (0.6 - ((x3 * x3) - ((y3 * y3) - (z3 * z3)))) ' change to 0.5 if you want

        If (t3 < 0) Then
            n3 = 0
        Else
            t3 = (t3 * t3)
            n3 = (t3 * (t3 * dot(grad3(gi3), x3, y3, z3)))
        End If
        ' Add contributions from each corner to get the final noise value.
        ' The result is scaled to stay just inside [-1,1] (now [0, 1])
        Return (CType(((32 * (n0 + (n1 + (n2 + n3)))) + 1), Single) * 0.5!) ' change to 76.0 if you want

    End Function

I've been told that a function like this should return a value between -1 and 1. However, calling GetNoise(0,2,0) for instance returns -6,240867.

Since the returned value of most points next to eachother are quite close to eachother, I believe most of the code is correct. However, with a few of these weird results, my heightmap obviously looks terrible.

Can anybody explain what I'm doing wrong/what I have missed? I've read quite some info as to how perlin/simplex noise works, and I understand the basics. I must however admit that I don't yet fully understand everything that comes with it.`

EDIT: As Alexandre Desbiens mentioned, it may be best to show you my heightmap output. Because rgb values don't allow negative values, I can only show you the map I created using the height data. here it is: Heightdata made into a map

\$\endgroup\$
  • 1
    \$\begingroup\$ It could be nice if you uploaded an image of one of the heightmap generated. I guess it could be of help. \$\endgroup\$ – Alexandre Desbiens Jun 19 '15 at 17:15
  • \$\begingroup\$ You're absolutely right. I edited the question to give you an image of what the height data looks like. \$\endgroup\$ – Peethor Jun 19 '15 at 18:55
4
\$\begingroup\$

Assuming you have translated this from the original Java code it looks like you have been a bit careless in adding brackets in a few places. For example the original code has:

double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;

while you have:

Dim t0 As Double = (0.6 - ((x0 * x0) - ((y0 * y0) - (z0 * z0))))

which if you remove the brackets is actually:

Dim t0 As Double = 0.6 - x0 * x0 + y0 * y0 + z0 * z0

While I'm not familiar with VB.NET I think most of the brackets you added are not required and end up making things more difficult to understand as well as introducing errors like this. It looks like you did the same thing in the t1, t2 and t3 variables and possibly elsewhere.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Though you're absolutely right about the fact that it makes the code a bit convoluted, they don't change any of its function. I hope I have time today to walk through the code, clean it up, and edit my question. Thanks for your input. \$\endgroup\$ – Peethor Jun 20 '15 at 6:13
  • \$\begingroup\$ Alright, you were right. I hadn't even read your answer properly. It DOES change its function. I never thought I would lose sight of PEMDAS, but I did. I stand utterly corrected. Thank you. \$\endgroup\$ – Peethor Jun 20 '15 at 10:11

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.