turtle = {} local matrix = {} local x = { x=1, y=0, z=0 } local y = { x=0, y=1, z=0 } local z = { x=0, y=0, z=1 } local is_num = function(c) return type(tonumber(c))=="number" or c=="-" and true or false end local round = function(n) return math.floor(n+0.5) end turtle.spawn = function (pos, def) local min = { x = pos.x, y = pos.y, z = pos.z } local max = { x = pos.x, y = pos.y, z = pos.z } local nodes = {} local materials = {} print("huh: "..dump(def)) for _, mat in pairs(def.materials) do table.insert( materials, minetest.get_content_id(mat) ) end local tmp = matrix.new() local rot = matrix.orient(tmp, math.pi/2, z ) local pos = vector.new(pos) local stk = {} local axis = y local angle = 0 local pen_down = true local mat = 1 local arg = "" for c in def.prog:gmatch"." do if is_num(c) then arg = arg..c elseif c == "G" then if pen_down then if pos.x < min.x then min.x = pos.x end if pos.y < min.y then min.y = pos.y end if pos.z < min.z then min.z = pos.z end if pos.x > max.x then max.x = pos.x end if pos.y > max.y then max.y = pos.y end if pos.z > max.z then max.z = pos.z end local rpos = { x=round(pos.x), y=round(pos.y), z=round(pos.z)} table.insert(nodes, { pos=rpos, mat=materials[mat] } ) end pos = pos + matrix.transpose(rot, x) elseif c == "U" then pen_down = false elseif c == "D" then pen_down = true elseif c == "T" then pen_down = not pen_down elseif c == "[" then table.insert(stk, { rot=rot, pos=pos } ) elseif c == "]" then local s = table.remove(stk) rot = s.rot pos = s.pos elseif c == "X" then axis = x elseif c == "Y" then axis = y elseif c == "Z" then axis = z elseif c == "A" then angle = tonumber(arg) or 0 arg = "" elseif c == "M" then mat = tonumber(arg) or 1 arg = "" elseif c == "R" then tmp = matrix.id() tmp = matrix.orient(tmp, angle*math.pi/180, axis) rot = matrix.mul(tmp, rot) elseif c == "I" then tmp = matrix.id() tmp = matrix.orient(tmp, math.pi/2, axis) rot = tmp end end local vm = VoxelManip() min, max = vm:read_from_map(min, max) local area = VoxelArea:new{ MinEdge = min, MaxEdge = max } local data = vm:get_data() for _, node in pairs(nodes) do local index = area:indexp(node.pos) data[index] = node.mat end vm:set_data(data) vm:write_to_map() vm:update_map() end matrix.new = function() local m = {} for i = 1,4 do m[i] = {} for j = 1,4 do m[i][j] = 0 end end return m end matrix.id = function() local m = {} for i = 1, 4 do m[i] = {} for j = 1, 4 do if i == j then m[i][j] = 1 else m[i][j] = 0 end end end return m end matrix.mul = function(m1, m2) local m = {} for i = 1, 4 do m[i] = {} for j = 1, 4 do local num = 0 for n = 1, 4 do num = num + m1[i][n] * m2[n][j] end m[i][j] = num end end return m end matrix.orient = function(m, angle, axis) local c = math.cos(angle) local s = math.sin(angle) local t = 1.0 - c local tx = t * axis.x local ty = t * axis.y local tz = t * axis.z local sx = s * axis.x local sy = s * axis.y local sz = s * axis.z m[1][1] = tx * axis.x + c m[1][2] = tx * axis.y + sz m[1][3] = tx * axis.z - sy m[2][1] = ty * axis.x - sz m[2][2] = ty * axis.y + c m[2][3] = ty * axis.z + sx m[3][1] = tz * axis.x + sy m[3][2] = tz * axis.y - sx m[3][3] = tz * axis.z + c return m end matrix.transpose = function (m, v) local x = m[1][1] * v.x + m[2][1] * v.y + m[3][1] * v.z + m[4][1] local y = m[1][2] * v.x + m[2][2] * v.y + m[3][2] * v.z + m[4][2] local z = m[1][3] * v.x + m[2][3] * v.y + m[3][3] * v.z + m[4][3] return vector.new(x,y,z) end