noise experiments

Experimenting with terrain generation..
noise tower
simplex noise (for those unfamiliar: it’s sort of newer perlin noise algorithm but not so popular) borrowed from
http://codeflow.org/entries/2010/dec/09/minecraft-like-rendering-experiments-in-opengl-4/#volume-data
translated to pascal in case someone needs it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//http://codeflow.org/entries/2010/dec/09/minecraft-like-rendering-experiments-in-opengl-4/#volume-data
unit core_simplex_noise;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, math;
 
  function simplex_noise(octaves:integer;x,y,z:single):single;
  function noise3d(xin,yin,zin:single):single;
 
implementation
 
const
  grad:array[0..11,0..2] of single = (
      (1.0,1.0,0.0),(-1.0,1.0,0.0),(1.0,-1.0,0.0),(-1.0,-1.0,0.0),
      (1.0,0.0,1.0),(-1.0,0.0,1.0),(1.0,0.0,-1.0),(-1.0,0.0,-1.0),
      (0.0,1.0,1.0),(0.0,-1.0,1.0),(0.0,1.0,-1.0),(0.0,-1.0,-1.0)
  );
 
  perm:array [0..511] of integer = (151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180, 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180);
 
function dot(x,y,z:single; g:psingle):single;
begin
    result:= x*g[0] + y*g[1] + z*g[2];
end;
 
function noise3d(xin,yin,zin:single):single;
var
    F3, G3, t, X0, Y0, Z0, xx0, yy0, zz0, s, x1, y1, z1, x2, y2, z2, x3, y3, z3, t0, t1, t2, t3, n0, n1, n2, n3:single;
    i, j, k, ii, jj, kk, i1, j1, k1, i2, j2, k2, gi0, gi1, gi2, gi3:integer;
begin
    F3 := 1.0 / 3.0;
    s := (xin+yin+zin)*F3;
    i := round(xin+s);
    j := round(yin+s);
    k := round(zin+s);
    G3 := 1.0/6.0;
    t := (i+j+k)*G3;
    X0 := i-t;
    Y0 := j-t;
    Z0 := k-t;
    xx0 := xin-X0;
    yy0 := yin-Y0;
    zz0 := zin-Z0;
 
    if(xx0 >= yy0) then begin
        if(yy0 >= zz0) then begin
            i1:=1; j1:=0; k1:=0; i2:=1; j2:=1; k2:=0;
        end
        else if(xx0 >= zz0) then begin
             i1:=1; j1:=0; k1:=0; i2:=1; j2:=0; k2:=1;
        end
        else begin
            i1:=0; j1:=0; k1:=1; i2:=1; j2:=0; k2:=1;
        end
    end
    else begin
        if(yy0 < zz0) then begin
            i1:=0; j1:=0; k1:=1; i2:=0; j2:=1; k2:=1;
        end
        else if(xx0 < zz0) then begin
            i1:=0; j1:=1; k1:=0; i2:=0; j2:=1; k2:=1;
        end
        else begin
            i1:=0; j1:=1; k1:=0; i2:=1; j2:=1; k2:=0;
        end
    end;
 
    x1 := xx0 - i1 + G3;
//    end;
    y1 := yy0 - j1 + G3;
    z1 := zz0 - k1 + G3;
    x2 := xx0 - i2 + 2.0*G3;
    y2 := yy0 - j2 + 2.0*G3;
    z2 := zz0 - k2 + 2.0*G3;
    x3 := xx0 - 1.0 + 3.0*G3;
    y3 := yy0 - 1.0 + 3.0*G3;
    z3 := zz0 - 1.0 + 3.0*G3;
 
    ii := i and 255;
    jj := j and 255;
    kk := k and 255;
 
    gi0 := perm[ii+perm[jj+perm[kk]]] mod 12;
    gi1 := perm[ii+i1+perm[jj+j1+perm[kk+k1]]] mod 12;
    gi2 := perm[ii+i2+perm[jj+j2+perm[kk+k2]]] mod 12;
    gi3 := perm[ii+1+perm[jj+1+perm[kk+1]]] mod 12;
 
    t0 := 0.6 - xx0*xx0 - yy0*yy0 - zz0*zz0;
    if(t0<0) then begin
         n0 := 0.0;
    end
    else begin
        t0 := t0*t0;
        n0 := t0 * t0 * dot(xx0, yy0, zz0, grad[gi0]);
    end;
 
    t1 := 0.6 - x1*x1 - y1*y1 - z1*z1;
    if(t1<0) then begin
         n1 := 0.0;
    end
    else begin
        t1 := t1*t1;
        n1 := t1 * t1 * dot(x1, y1, z1, grad[gi1]);
    end;
    t2 := 0.6 - x2*x2 - y2*y2 - z2*z2;
    if(t2<0) then begin
         n2 := 0.0;
    end
    else begin
        t2 := t2*t2;
        n2 := t2 * t2 * dot(x2, y2, z2, grad[gi2]);
    end;
    t3 := 0.6 - x3*x3 - y3*y3 - z3*z3;
    if(t3<0) then begin
         n3 := 0.0;
    end
    else begin
        t3 := t3*t3;
        n3 := t3 * t3 * dot(x3, y3, z3, grad[gi3]);
    end ;
    result:= 16.0*(n0 + n1 + n2 + n3)+1.0;
end;
 
function simplex_noise(octaves:integer;x,y,z:single):single;
var
    value:single = 0.0;
    i:integer;
begin
    for i:=0 to octaves-1 do begin
        value := value + noise3d(
        x*power(2, i),
        y*power(2, i),
         z*power(2, i)
        );
    end;
    result:= value;
end;
 
end.

3d voxel picking with Bresenham’s line algorithm

After some research on 3d picking it came to me that most obvious solution for non-octree ‘voxel’ world would be plotting a 3d line through the chunks grid, checking for collision with blocks along the line. And that is where Bresenham’s line algorithm is really usefull. Took me a while to find 3d adopted pascal version so I’m repostiong it here for anyone to use :P. For my project I modified it to go certain amount of steps before failing if no collision is found.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
procedure SwapAB(var a,b :integer);
var
    c   :integer;
begin
    c := a;
    a := b;
    b := c;
end;
 
procedure line3D(x0,y0,z0,x1,y1,z1:integer);
var
    x, delta_x, step_x  :integer;
    y, delta_y, step_y  :integer;
    z, delta_z, step_z  :integer;
    swap_xy, swap_xz            :boolean;
    drift_xy, drift_xz          :integer;
    cx, cy, cz,stepCount        :integer;
begin
    //start and end points (change these values)
    //x0 := 0     x1 := -2
    //y0 := 0     y1 := 5
    //z0 := 0     z1 := -10
 
    //'steep' xy Line, make longest delta x plane
    swap_xy := Abs(y1 - y0) > Abs(x1 - x0);
    if swap_xy then begin
        SwapAB(x0, y0);
        SwapAB(x1, y1);
    end;
 
    //do same for xz
    swap_xz := Abs(z1 - z0) > Abs(x1 - x0);
    if swap_xz then begin
        SwapAB(x0, z0);
        SwapAB(x1, z1);
    end;
 
    //delta is Length in each plane
    delta_x := Abs(x1 - x0);
    delta_y := Abs(y1 - y0);
    delta_z := Abs(z1 - z0);
 
    //drift controls when to step in 'shallow' planes
    //starting value keeps Line centred
    drift_xy  := delta_x div 2;
    drift_xz  := (delta_x div 2);
 
    //direction of line
    step_x := 1;  if (x0 > x1) then  step_x := -1;
    step_y := 1;  if (y0 > y1) then  step_y := -1;
    step_z := 1;  if (z0 > z1) then  step_z := -1;
 
    //starting point
    y := y0;
    z := z0;
 
    //step through longest delta (which we have swapped to x)
    x:= x0;
    stepCount:=0;
    while (stepCount<256) do begin
        inc(stepCount);
        //copy position
        cx := x;    cy := y;    cz := z;
 
        //unswap (in reverse)
        if swap_xz then SwapAB(cx, cz);
        if swap_xy then SwapAB(cx, cy);
 
        //spit results
        log(': ' + inttostr(cx) + ', ' + inttostr(cy) + ', ' + inttostr(cz));
 
        //update progress in other planes
        drift_xy := drift_xy - delta_y;
        drift_xz := drift_xz - delta_z;
 
        //step in y plane
        if drift_xy < 0 then begin
            y := y + step_y;
            drift_xy := drift_xy + delta_x;
        end;
        //same in z
        if drift_xz < 0 then begin
            z := z + step_z;
            drift_xz := drift_xz + delta_x;
        end;
        x:=x+step_x;
    end;
end;

picking and culling