vengi
vengi copied to clipboard
VOXELGENERATOR: convert the tree generators into lua code
- [x] Create bindings for
ShapeGenerator.h
functions - [ ] Convert the code in
TreeGenerator.h
into lua code
local module = {}
-- Define the Spiral class in Lua
local Spiral = {}
Spiral.__index = Spiral
-- Constructor for Spiral
function Spiral.new()
local self = setmetatable({}, Spiral)
self._layer = 1
self._leg = 0
self._x = 0
self._z = 0
return self
end
-- Move to the next position in the spiral
function Spiral:next(amount)
amount = amount or 1
for i = 1, amount do
if self._leg == 0 then
self._x = self._x + 1
if self._x == self._layer then
self._leg = 1
end
elseif self._leg == 1 then
self._z = self._z + 1
if self._z == self._layer then
self._leg = 2
end
elseif self._leg == 2 then
self._x = self._x - 1
if -self._x == self._layer then
self._leg = 3
end
elseif self._leg == 3 then
self._z = self._z - 1
if -self._z == self._layer then
self._leg = 0
self._layer = self._layer + 1
end
end
end
end
-- Get the current x-coordinate
function Spiral:x()
return self._x
end
-- Get the current z-coordinate
function Spiral:z()
return self._z
end
function module.createTrunk(volume, ctx, voxel)
local endPos = g_ivec3.new(
ctx.pos.x,
ctx.pos.y + ctx.trunkHeight,
ctx.pos.z
)
g_shape.line(volume, ctx.pos, endPos, voxel, ctx.trunkStrength)
end
function module.createBezierTrunk(volume, ctx, voxel)
local trunkTop = g_ivec3.new(ctx.pos.x, ctx.pos.y + ctx.trunkHeight, ctx.pos.z)
local shiftX = ctx.trunkWidth
local shiftZ = ctx.trunkDepth
local endPos = g_ivec3.new(trunkTop.x + shiftX, trunkTop.y, trunkTop.z + shiftZ)
local trunkSize = ctx.trunkStrength
local control = g_ivec3.new(ctx.pos.x, ctx.pos.y + ctx.trunkControlOffset, ctx.pos.z)
g_shape.bezier(volume, ctx.pos, endPos, control, voxel,
function(vol, last, pos, voxel)
-- TODO: this should be some kind of polygon - not a line - we want a flat trunk
g_shape.line(vol, pos, last, voxel, math.max(1, math.ceil(trunkSize)))
trunkSize = trunkSize * ctx.trunkFactor
end,
ctx.trunkHeight
)
endPos.y = endPos.y - 1
return endPos
end
function module.createTreePalm(volume, ctx, trunkVoxel, leavesVoxel)
local start = module.createBezierTrunk(volume, ctx, trunkVoxel)
local stepWidth = math.rad(360.0 / ctx.branches)
local w = ctx.leavesWidth
local angle = math.random(0.0, 2.0 * math.pi)
for b = 1, ctx.branches do
local branchSize = ctx.branchSize
local x = math.cos(angle)
local z = math.sin(angle)
local randomLength = math.random(ctx.leavesHeight, ctx.leavesHeight + ctx.randomLeavesHeightOffset)
local control = g_ivec3.new(
start.x - x * (w / 2.0),
start.y + ctx.branchControlOffset,
start.z - z * (w / 2.0)
)
local endPos = g_ivec3.new(
start.x - x * w,
start.y - randomLength,
start.z - z * w
)
g_shape.BezierFunc(volume, start, endPos, control, leavesVoxel,
function(vol, last, pos, voxel)
-- TODO: this should be some kind of polygon - not a line - we want a flat leaf
g_shape.line(vol, pos, last, voxel, math.max(1, math.ceil(branchSize)))
branchSize = branchSize * ctx.branchFactor
end,
ctx.leavesHeight / 4
)
angle = angle + stepWidth
end
end
-- Create a tree with ellipsis-shaped leaves
function module.createTreeEllipsis(volume, ctx, trunkVoxel, leavesVoxel)
module.createTrunk(volume, ctx, trunkVoxel)
local leavesCenter = g_ivec3.new(
ctx.pos.x,
ctx.pos.y + ctx.trunkHeight + ctx.leavesHeight / 2,
ctx.pos.zg_ivec
)
g_shape.ellipse(volume, leavesCenter, "y", ctx.leavesWidth, ctx.leavesHeight, ctx.leavesDepth,
leavesVoxel)
end
-- Create a tree with cone-shaped leaves
function module.createTreeCone(volume, ctx, trunkVoxel, leavesVoxel)
module.createTrunk(volume, ctx, trunkVoxel)
local leavesCenter = g_ivec3.new(
ctx.pos.x,
ctx.pos.y + ctx.trunkHeight + ctx.leavesHeight / 2,
ctx.pos.z
)
g_shape.cone(volume, leavesCenter, "y", false, ctx.leavesHeight, ctx.leavesWidth, ctx.leavesDepth,
leavesVoxel)
end
-- Create a tree with fir-like leaves
function module.createTreeFir(volume, ctx, trunkVoxel, leavesVoxel)
module.createTrunk(volume, ctx, trunkVoxel)
local stepWidth = math.rad(360.0 / ctx.branches)
local angle = math.random(0.0, 2.0 * math.pi)
local leafesPos = g_ivec3.new(ctx.pos.x, ctx.pos.y + ctx.trunkHeight, ctx.pos.z)
local halfHeight = ((ctx.amount - 1) * ctx.stepHeight) / 2
local center = g_ivec3.new(ctx.pos.x, ctx.pos.y + ctx.trunkHeight - halfHeight, ctx.pos.z)
g_shape.cube(volume, center, ctx.trunkStrength, halfHeight * 2, ctx.trunkStrength, leavesVoxel)
local w = ctx.w
for n = 1, ctx.amount do
for b = 1, ctx.branches do
local start = leafesPos
local endPos = start
local x = math.cos(angle)
local z = math.sin(angle)
local randomZ = math.random(4, 8)
endPos.y = endPos.y - randomZ
endPos.x = endPos.x - x * w
endPos.z = endPos.z - z * w
g_shape.line(volume, start, endPos, leavesVoxel, ctx.branchStrength)
local end2 = endPos
end2.y = end2.y - ctx.branchDownwardOffset
end2.x = end2.x - x * w * ctx.branchPositionFactor
end2.z = end2.z - z * w * ctx.branchPositionFactor
g_shape.line(volume, endPos, end2, leavesVoxel, ctx.branchStrength)
angle = angle + stepWidth
w = w + 1.0 / b
end
leafesPos.y = leafesPos.y - ctx.stepHeight
end
end
-- Create a tree with a dome of leaves
function module.createTreeDome(volume, ctx, trunkVoxel, leavesVoxel)
module.createTrunk(volume, ctx, trunkVoxel)
local leavesCenter = g_ivec3.new(
ctx.pos.x,
ctx.pos.y + ctx.trunkHeight + ctx.leavesHeight / 2,
ctx.pos.z
)
g_shape.dome(volume, leavesCenter, "y", false, ctx.leavesWidth, ctx.leavesHeight, ctx.leavesDepth,
leavesVoxel)
end
-- Create a tree with a dome of leaves and hanging branches
function module.createTreeDomeHangingLeaves(volume, ctx, trunkVoxel, leavesVoxel)
module.createTrunk(volume, ctx, trunkVoxel)
local leavesCenter = g_ivec3.new(
ctx.pos.x,
ctx.pos.y + ctx.trunkHeight + ctx.leavesHeight / 2,
ctx.pos.z
)
g_shape.dome(volume, leavesCenter, "y", false, ctx.leavesWidth, ctx.leavesHeight, ctx.leavesDepth,
leavesVoxel)
local stepWidth = math.rad(360.0 / ctx.branches)
local angle = math.randomf(0.0, 2 * math.pi)
local y = ctx.pos.y + ctx.trunkHeight + 1
for b = 1, ctx.branches do
local x = math.cos(angle)
local z = math.sin(angle)
local randomLength = math.random(ctx.hangingLeavesLengthMin, ctx.hangingLeavesLengthMax)
local start = g_ivec3.new(
math.round(ctx.pos.x - x * (ctx.leavesWidth - 1.0) / 2.0),
y,
math.round(ctx.pos.z - z * (ctx.leavesDepth - 1.0) / 2.0)
)
local endPos = { x = start.x, y = start.y - randomLength, z = start.z }
g_shape.line(volume, start, endPos, leavesVoxel, ctx.hangingLeavesThickness)
angle = angle + stepWidth
end
end
-- Create a tree with cube-shaped leaves
function module.createTreeCube(volume, ctx, trunkVoxel, leavesVoxel)
module.createTrunk(volume, ctx, trunkVoxel)
local leavesCenter = g_ivec3.new(
ctx.pos.x,
ctx.pos.y + ctx.trunkHeight + ctx.leavesHeight / 2,
ctx.pos.z
)
g_shape.cube(volume, leavesCenter, ctx.leavesWidth, ctx.leavesHeight, ctx.leavesDepth, leavesVoxel)
g_shape.cube(volume, leavesCenter, ctx.leavesWidth + 2, ctx.leavesHeight - 2, ctx.leavesDepth - 2, leavesVoxel)
g_shape.cube(volume, leavesCenter, ctx.leavesWidth - 2, ctx.leavesHeight + 2, ctx.leavesDepth - 2, leavesVoxel)
g_shape.cube(volume, leavesCenter, ctx.leavesWidth - 2, ctx.leavesHeight - 2, ctx.leavesDepth + 2, leavesVoxel)
end
-- Create a tree with cube-shaped leaves and side ellipsis-shaped leaves
function module.createTreeCubeSideCubes(volume, ctx, trunkVoxel, leavesVoxel)
module.createTrunk(volume, ctx, trunkVoxel)
local leafesPos = g_ivec3.new(ctx.pos.x, ctx.pos.y + ctx.trunkHeight + ctx.leavesHeight / 2, ctx.pos.z)
g_shape.cube(volume, leafesPos, ctx.leavesWidth, ctx.leavesHeight, ctx.leavesDepth, leavesVoxel)
g_shape.cube(volume, leafesPos, ctx.leavesWidth + 2, ctx.leavesHeight - 2, ctx.leavesDepth - 2, leavesVoxel)
g_shape.cube(volume, leafesPos, ctx.leavesWidth - 2, ctx.leavesHeight + 2, ctx.leavesDepth - 2, leavesVoxel)
g_shape.cube(volume, leafesPos, ctx.leavesWidth - 2, ctx.leavesHeight - 2, ctx.leavesDepth + 2, leavesVoxel)
local o = Spiral.new()
o:next(1)
local halfWidth = ctx.leavesWidth / 2
local halfHeight = ctx.leavesHeight / 2
local halfDepth = ctx.leavesDepth / 2
for i = 1, 4 do
local leafesPos2 = leafesPos
leafesPos2.x = leafesPos2.x + o:x() * halfWidth
leafesPos2.z = leafesPos2.z + o:z() * halfDepth
g_shape.ellipse(volume, leafesPos2, "y", halfWidth, halfHeight, halfDepth, leavesVoxel)
o:next(2)
end
end
return module