Colours are now Vectors, added rainbow pigment.
[raymarcher.git] / Primitives.lua
1 -- Geometric primitives for raymarching
2 require "Vector"
3 local V = Vector
4
5 local function make_sphere(centre, radius, texture)
6    local norm = V.norm
7    return function(p)
8       return {dist = V.norm(p-centre) - radius,
9               texture = texture}
10    end
11 end
12
13 local function make_plane(centre, normal, texture)
14    return function(p)
15       return {dist = normal*(p-centre),
16               texture = texture}
17    end
18 end
19
20 local function make_pipe(centre, radius, axis, texture)
21    return function(p)
22       return {dist = V.norm(V.cross(p-centre, axis)) - radius,
23               texture = texture}
24    end
25 end
26
27 local function make_mandelbulb(centre, max_iter, power, texture)
28    return function(p)
29       local z = p - centre
30       local dr = 1.0
31       local r = 0.0
32
33       for i=1,max_iter do
34          r = V.norm(z)
35          if r>2.0 then
36             break
37          end
38          
39          -- convert to polar coordinates
40          theta = math.acos(z[3]/r)
41          phi = math.atan(z[2],z[1])
42          dr =  math.pow(r, power-1.0)*power*dr + 1.0
43          
44          -- scale and rotate the point
45          zr = math.pow(r, power)
46          theta = theta*power
47          phi = phi*power
48          
49          -- convert back to cartesian coordinates
50          z = V.new{math.sin(theta)*math.cos(phi),
51                    math.sin(phi)*math.sin(theta),
52                    math.cos(theta)} * zr
53          z = z + p
54       end
55    
56       return {dist = 0.5*math.log(r)*r/dr,
57               texture = texture}
58    end
59 end
60
61
62
63 Primitives = {
64    make_sphere = make_sphere,
65    make_plane = make_plane,
66    make_pipe = make_pipe,
67    make_mandelbulb = make_mandelbulb
68 }
69
70 return Primitives