Colours are now Vectors, added rainbow pigment.
[raymarcher.git] / Primitives.lua
index 88a3849..1648392 100644 (file)
@@ -3,14 +3,68 @@ require "Vector"
 local V = Vector
 
 local function make_sphere(centre, radius, texture)
-      return function(p)
-         return {dist = V.norm(p-centre) - radius,
-                 texture = texture}
+   local norm = V.norm
+   return function(p)
+      return {dist = V.norm(p-centre) - radius,
+              texture = texture}
+   end
+end
+
+local function make_plane(centre, normal, texture)
+   return function(p)
+      return {dist = normal*(p-centre),
+              texture = texture}
+   end
+end
+
+local function make_pipe(centre, radius, axis, texture)
+   return function(p)
+      return {dist = V.norm(V.cross(p-centre, axis)) - radius,
+              texture = texture}
+   end
+end
+
+local function make_mandelbulb(centre, max_iter, power, texture)
+   return function(p)
+      local z = p - centre
+      local dr = 1.0
+      local r = 0.0
+
+      for i=1,max_iter do
+         r = V.norm(z)
+         if r>2.0 then
+            break
+         end
+         
+         -- convert to polar coordinates
+         theta = math.acos(z[3]/r)
+         phi = math.atan(z[2],z[1])
+         dr =  math.pow(r, power-1.0)*power*dr + 1.0
+         
+         -- scale and rotate the point
+         zr = math.pow(r, power)
+         theta = theta*power
+         phi = phi*power
+         
+         -- convert back to cartesian coordinates
+         z = V.new{math.sin(theta)*math.cos(phi),
+                   math.sin(phi)*math.sin(theta),
+                   math.cos(theta)} * zr
+         z = z + p
       end
+   
+      return {dist = 0.5*math.log(r)*r/dr,
+              texture = texture}
+   end
 end
 
+
+
 Primitives = {
-   make_sphere = make_sphere
+   make_sphere = make_sphere,
+   make_plane = make_plane,
+   make_pipe = make_pipe,
+   make_mandelbulb = make_mandelbulb
 }
 
 return Primitives