Here’s a quick profiler comparing different ways of drawing meshes. Similar tests have been done before of course, so I think it’s quite well known how much faster the setRect
method is than repeated calls to translate
. Unfortunately, method 2 here, moving a single mesh around, is only slightly faster than the slowest method, method 3, having an individual mesh for each object.
Although this is for 2D, I’m interested in the implications for 3D. I think that for an acceptable voxel system, you’d need to write an addCube, setCube function. Or if anyone can make method 2 run faster…
--# Main
-- 2D Mesh Profiling
function setup()
methods = {Box, Box2, Box3}
parameter.integer("number",200,5000,500)
parameter.integer("method", 1,3,1)
parameter.action("INITIALISE", initialise)
profiler.init()
for i=1,#methods do
print("Method "..i..": "..methods[i].doc)
end
initialise()
end
function draw()
background(40, 40, 50)
for i=1, #object do
object[i]:draw()
end
if method==1 then Box.mesh:draw() end --just one draw operation with rectangle method
profiler.draw()
end
function initialise()
object={}
Box.mesh:clear()
collectgarbage()
for i=1,number do
object[i]=methods[method]()
end
end
profiler={}
function profiler.init()
profiler.del=0
profiler.c=0
profiler.fps=0
profiler.mem=0
parameter.watch("profiler.fps")
parameter.watch("profiler.mem")
end
function profiler.draw()
profiler.del = profiler.del + DeltaTime
profiler.c = profiler.c + 1
if profiler.c==10 then
profiler.fps=profiler.c/profiler.del
profiler.del=0
profiler.c=0
profiler.mem=collectgarbage("count", 2)
end
end
--# Box
Box = class()
Box.doc = "The objects are drawn as rectangles on a single mesh using setRect. No translation used"
local size=20
Box.mesh=mesh()
Box.mesh.texture=readImage("Platformer Art:Block Brick")
function Box:init()
self.pos = vec2(math.random(WIDTH),math.random(HEIGHT))
self.angle = math.random(2*math.pi)
self.vel = vec2(math.random(11)-6,math.random(11)-6)
self.angleVel=(math.random()-0.5)*.02
self.col=color(math.random(255), math.random(255), math.random(255))
self:add(self.pos, self.angle)
end
function Box:draw() --nb no need for translate or rotate
self:move()
self.mesh:setRect(self.rect, self.pos.x, self.pos.y, size, size, self.angle)
end
function Box:move()
self.pos = self.pos + self.vel
if self.pos.x > WIDTH + size then self.pos.x = - size
elseif self.pos.x < - size then self.pos.x = WIDTH + size
end
if self.pos.y > HEIGHT + size then self.pos.y = - size
elseif self.pos.y < - size then self.pos.y = HEIGHT + size
end
self.angle = self.angle + self.angleVel
end
function Box:add(pos,ang)
self.rect=self.mesh:addRect(pos.x,pos.y,size,size,ang)
self.mesh:setRectTex(self.rect,0,0,1,1)
self.mesh:setRectColor(self.rect, self.col)
end
--# Box2
Box2 = class(Box) --a subclass, just changes add and draw
Box2.doc = "A single mesh with a single rectangle is drawn repeatedly over the screen using translate/ rotate/ setColors to set positions/ angle/ colour"
local size = 20
Box2.mesh=mesh()
Box2.mesh.texture=readImage("Platformer Art:Block Brick")
Box2.mesh:addRect(0,0,size,size) --a single rectangle this time
function Box2:draw()
self:move()
pushMatrix()
translate(self.pos.x,self.pos.y)
rotate(math.deg(self.angle))
self.mesh:setColors(self.col) --self.mesh here is actually Box2.mesh. Weird, huh?
self.mesh:draw()
popMatrix()
end
function Box2:add()
-- empty function so that we don't inherit the add function from Box
end
--# Box3
Box3 = class(Box)
Box3.doc = "Each object has its own mesh, drawn using translate/ rotate to set positions/ angle."
function Box3:draw() --just one line different (no need to set colour) compared to Box2
self:move()
pushMatrix()
translate(self.pos.x,self.pos.y)
rotate(math.deg(self.angle))
self.mesh:draw()
popMatrix()
end
function Box3:add()
self.mesh=mesh() --a separate mesh for each instance
self.mesh.texture=readImage("Platformer Art:Block Brick")
Box.add(self,vec2(0,0),0)
end