-
-
Save rolantin/3108faf415bdde91075248bdda93d223 to your computer and use it in GitHub Desktop.
Cube World Performance Comparison
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# Main | |
-- Cube World | |
-- Use this function to perform your initial setup | |
function setup() | |
print(math.floor(3/4)) | |
--print(3\4) | |
--mode = QuadViewCulling() | |
--mode = OneMeshCulled() | |
mode = OneMesh() | |
--mode = OneCube() | |
mode:buildWorld() | |
camAngle = vec2(3,0) | |
camLookAt=vec3(5.5,1.0,5.5) | |
frame = 0 | |
print(collectgarbage("count") / 1024) | |
end | |
-- This function gets called once every frame | |
function draw() | |
frame=frame+1 | |
if frame == 100 then | |
p4c = Profiler4Codea(mode) | |
p4c:start() | |
end | |
if frame == 1100 then | |
local out = p4c:stop() | |
print(out) | |
end | |
camAngle = camAngle:rotate(math.rad(1.5)) | |
--print(camAngle) | |
-- This sets a dark background color | |
background(40, 40, 50) | |
camera(camLookAt.x + camAngle.x,camLookAt.y+0.5,camLookAt.z + camAngle.y, camLookAt.x, camLookAt.y, camLookAt.z) | |
--perspective(45,WIDTH/HEIGHT,.1,15) | |
perspective() | |
mode:drawWorld() | |
end | |
--# CubeBuilder | |
--Returns a set of vertices for a cube 1x1x1 centered on x,y | |
function Cube(x,y,z,m, top, bottom, left, right, front, back) | |
top = top or 1 | |
bottom = bottom or 1 | |
left = left or 1 | |
right = right or 1 | |
front = front or 1 | |
back = back or 1 | |
local vertices = { | |
vec3(-0.5+x, -0.5+y, 0.5+z), -- Left bottom front | |
vec3( 0.5+x, -0.5+y, 0.5+z), -- Right bottom front | |
vec3( 0.5+x, 0.5+y, 0.5+z), -- Right top front | |
vec3(-0.5+x, 0.5+y, 0.5+z), -- Left top front | |
vec3(-0.5+x, -0.5+y, -0.5+z), -- Left bottom back | |
vec3( 0.5+x, -0.5+y, -0.5+z), -- Right bottom back | |
vec3( 0.5+x, 0.5+y, -0.5+z), -- Right top back | |
vec3(-0.5+x, 0.5+y, -0.5+z), -- Left top back | |
} | |
-- now construct a cube out of the vertices above | |
curVerts = m.size | |
m:resize(curVerts+(top+bottom+left+right+front+back)*6) | |
if (front == 1) then | |
m:vertex(curVerts+1, vertices[1]) | |
m:vertex(curVerts+2, vertices[2]) | |
m:vertex(curVerts+3, vertices[3]) | |
m:vertex(curVerts+4, vertices[1]) | |
m:vertex(curVerts+5, vertices[3]) | |
m:vertex(curVerts+6, vertices[4]) | |
TextureVerts(m,curVerts) | |
curVerts = curVerts + 6 | |
end | |
if (right == 1) then | |
m:vertex(curVerts+1, vertices[2]) | |
m:vertex(curVerts+2, vertices[6]) | |
m:vertex(curVerts+3, vertices[7]) | |
m:vertex(curVerts+4, vertices[2]) | |
m:vertex(curVerts+5, vertices[7]) | |
m:vertex(curVerts+6, vertices[3]) | |
TextureVerts(m,curVerts) | |
curVerts = curVerts + 6 | |
end | |
if (back == 1) then | |
m:vertex(curVerts+1, vertices[6]) | |
m:vertex(curVerts+2, vertices[5]) | |
m:vertex(curVerts+3, vertices[8]) | |
m:vertex(curVerts+4, vertices[6]) | |
m:vertex(curVerts+5, vertices[8]) | |
m:vertex(curVerts+6, vertices[7]) | |
TextureVerts(m,curVerts) | |
curVerts = curVerts + 6 | |
end | |
if (left == 1) then | |
m:vertex(curVerts+1, vertices[5]) | |
m:vertex(curVerts+2, vertices[1]) | |
m:vertex(curVerts+3, vertices[4]) | |
m:vertex(curVerts+4, vertices[5]) | |
m:vertex(curVerts+5, vertices[4]) | |
m:vertex(curVerts+6, vertices[8]) | |
TextureVerts(m,curVerts) | |
curVerts = curVerts + 6 | |
end | |
if (top == 1) then | |
m:vertex(curVerts+1, vertices[4]) | |
m:vertex(curVerts+2, vertices[3]) | |
m:vertex(curVerts+3, vertices[7]) | |
m:vertex(curVerts+4, vertices[4]) | |
m:vertex(curVerts+5, vertices[7]) | |
m:vertex(curVerts+6, vertices[8]) | |
TextureVerts(m,curVerts) | |
curVerts = curVerts + 6 | |
end | |
if (bottom == 1) then | |
m:vertex(curVerts+1, vertices[5]) | |
m:vertex(curVerts+2, vertices[6]) | |
m:vertex(curVerts+3, vertices[2]) | |
m:vertex(curVerts+4, vertices[5]) | |
m:vertex(curVerts+5, vertices[2]) | |
m:vertex(curVerts+6, vertices[1]) | |
TextureVerts(m,curVerts) | |
curVerts = curVerts + 6 | |
end | |
end | |
function TextureVerts(m,curVerts) | |
m:texCoord(curVerts+1, vec2(0,0)) | |
m:texCoord(curVerts+2, vec2(1,0)) | |
m:texCoord(curVerts+3, vec2(1,1)) | |
m:texCoord(curVerts+4, vec2(0,0)) | |
m:texCoord(curVerts+5, vec2(1,0)) | |
m:texCoord(curVerts+6, vec2(1,1)) | |
end | |
--# Map | |
map = { | |
{ | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbb bbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbb bbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbb bbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbb bbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" | |
}, | |
{ | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
" ", | |
" ", | |
" ", | |
" bb ", | |
" bb ", | |
" bb ", | |
" bb ", | |
" bb ", | |
" bb ", | |
" bb ", | |
" bb ", | |
"bbbb bbbbbbbbbbbbbbbbbbbbbbbb", | |
"b b", | |
"b b", | |
"b b", | |
"b b", | |
"b b", | |
"b b", | |
"bbbbbbbb bbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbb bbbbbbbbbbbbbbbbbbbb", | |
" ", | |
" ", | |
" ", | |
" bb ", | |
" bb ", | |
" bb ", | |
" bb ", | |
" bb ", | |
" bb ", | |
" bb ", | |
" bb ", | |
"bbbb bbbbbbbbbbbbbbbbbbbbbbbb", | |
"b b", | |
"b b", | |
"b b", | |
"b b", | |
"b b", | |
"b b", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" | |
}, | |
{ | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
" ", | |
" ", | |
" ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
" ", | |
" ", | |
" ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
" bbbbbbbbbbbbbbbbbbbb ", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", | |
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" | |
} | |
} | |
--# OneCube | |
--this is a single cube then dynamically placed for each block | |
OneCube = class() | |
function OneCube:buildWorld() | |
cubeMesh = mesh() | |
Cube(0.5,0.5,0.5,cubeMesh) | |
blocks = {} | |
level=0 | |
for k,v in ipairs(map) do | |
row=0 | |
for l,w in ipairs(v) do | |
for col=1,#w do | |
local c = w:sub(col,col) | |
if c == "b" then | |
table.insert(blocks, vec3(row,level,col)) | |
end | |
end | |
row=row+1 | |
end | |
level=level+1 | |
end | |
cubeMesh:setColors(color(255,255,255)) | |
cubeMesh.texture = readImage("Cargo Bot:Crate Yellow 2") | |
end | |
function OneCube:drawWorld() | |
for k,v in pairs(blocks) do | |
translate(v.x,v.y,v.z) | |
cubeMesh:draw() | |
resetMatrix() | |
end | |
end | |
--# OneMesh | |
--this is a single mesh built for the whole world map | |
OneMesh = class() | |
function OneMesh:buildWorld() | |
worldMesh = mesh() | |
level=0 | |
for k,v in ipairs(map) do | |
row=0 | |
for l,w in ipairs(v) do | |
for col=1,#w do | |
local c = w:sub(col,col) | |
if c == "b" then | |
Cube(row + 0.5, level + 0.5, col-0.5, worldMesh) | |
end | |
end | |
row=row+1 | |
end | |
level=level+1 | |
end | |
worldMesh:setColors(color(255,255,255)) | |
worldMesh.texture = readImage("Cargo Bot:Crate Yellow 2") | |
end | |
function OneMesh:drawWorld() | |
worldMesh:draw() | |
end | |
--# OneMeshCulled | |
--this is a single mesh built for the whole world map, culling faces that are internal to the structure | |
OneMeshCulled = class() | |
function OneMeshCulled:buildWorld() | |
worldMesh = mesh() | |
level=0 | |
for k,v in ipairs(map) do | |
row=0 | |
for l,w in ipairs(v) do | |
for col=1,#w do | |
local c = w:sub(col,col) | |
local top = 1 | |
local bottom = 1 | |
local left = 1 | |
local right = 1 | |
local front = 1 | |
local back = 1 | |
if c == "b" then | |
-- top, bottom, left, right, front, back | |
if map[level] ~= nil and map[level][row+1]:sub(col,col) == "b" then | |
bottom = 0 | |
end | |
if map[level+2] ~= nil and map[level+2][row+1]:sub(col,col) == "b" then | |
top = 0 | |
end | |
if map[level+1][row] ~=nil and map[level+1][row]:sub(col,col) == "b" then | |
left = 0 | |
end | |
if map[level+1][row+2] ~= nil and map[level+1][row+2]:sub(col,col) == "b" then | |
right = 0 | |
end | |
if col-1 > 0 and w:sub(col-1,col-1) == "b" then | |
back = 0 | |
end | |
if col+1 < w:len() and w:sub(col+1, col+1) == "b" then | |
front = 0 | |
end | |
Cube(row + 0.5, level + 0.5, col-0.5, worldMesh, top, bottom,left,right,front,back) | |
end | |
end | |
row=row+1 | |
end | |
level=level+1 | |
end | |
worldMesh:setColors(color(255,255,255)) | |
worldMesh.texture = readImage("Cargo Bot:Crate Yellow 2") | |
end | |
function OneMeshCulled:drawWorld() | |
worldMesh:draw() | |
end | |
--# Profiler | |
Profiler4Codea = class() | |
Profiler4Codea.TimesInvoked = "timesInvoked" | |
Profiler4Codea.TotalTime = "totalTime" | |
Profiler4Codea.AvgTime = "avgTime" | |
Profiler4Codea.Descending = "descending" | |
Profiler4Codea.Ascending = "ascending" | |
function Profiler4Codea:init(obj) | |
self.obj = obj | |
if(type(obj) ~= "table") then | |
error("Profiler4Codea:init: obj must be table or class: "..tostring(self.obj)) | |
end | |
local metaTable = getmetatable(self.obj) | |
if(metaTable) then | |
self.obj = metaTable | |
end | |
self.metaData = {} | |
end | |
function Profiler4Codea:start() | |
self.clockTime = os.clock() | |
for name, member in pairs(self.obj) do | |
local mType = type(member) | |
if(mType == "function") then | |
if(not self.metaData[name]) then | |
self.metaData[name] = { | |
totalTime = 0, | |
timesInvoked = 0, | |
func = name | |
} | |
end | |
self.metaData[name].origFunction = member | |
self.obj[name] = function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) | |
local elapsedTime = os.clock() | |
local r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 = | |
self.metaData[name].origFunction(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) | |
self.metaData[name].totalTime = self.metaData[name].totalTime + | |
(os.clock() - elapsedTime) | |
self.metaData[name].timesInvoked = self.metaData[name].timesInvoked + 1 | |
return r1, r2, r3, r4, r5, r6, r7, r8, r9, r10 | |
end | |
elseif(mType == "table") then | |
-- Could recurse here for nested/inner-classed objects | |
end | |
end | |
end | |
function Profiler4Codea:stop() | |
-- Restore function pointers | |
for name, meta in pairs(self.metaData) do | |
self.obj[name] = meta.origFunction | |
end | |
return self:report() | |
end | |
function Profiler4Codea:report(sortKey, ascDesc) | |
sortKey = sortKey or Profiler4Codea.TimesInvoked | |
ascDesc = ascDesc or Profiler4Codea.Descending | |
local data = {} | |
for name, meta in pairs(self.metaData) do | |
-- Calculate average time so we can sort by if required | |
if(meta.timesInvoked > 0) then | |
meta.avgTime = meta.totalTime/meta.timesInvoked | |
else | |
meta.avgTime = 0 | |
end | |
table.insert(data, meta) | |
end | |
if(ascDesc == Profiler4Codea.Descending) then | |
table.sort(data, function(a,b) return b[sortKey] < a[sortKey] end) | |
elseif(ascDesc == Profiler4Codea.Ascending) then | |
table.sort(data, function(a,b) return a[sortKey] < b[sortKey] end) | |
else | |
error("Unknown sort key") | |
end | |
local sb = {} | |
table.insert(sb, "Profiler4Codea: Sample time: ") | |
table.insert(sb, os.clock() - self.clockTime) | |
table.insert(sb, "\r\n") | |
table.insert(sb, "Sort key: ") | |
table.insert(sb, sortKey) | |
table.insert(sb, "\r\n") | |
table.insert(sb, "Asc/Desc: ") | |
table.insert(sb, ascDesc) | |
table.insert(sb, "\r\n") | |
for k, meta in ipairs(data) do | |
if(meta.timesInvoked > 0) then | |
table.insert(sb, " function:") | |
table.insert(sb, meta.func) | |
table.insert(sb, "\r\n") | |
table.insert(sb, " totalTime: ") | |
table.insert(sb, tostring(meta.totalTime)) | |
table.insert(sb, "\r\n") | |
table.insert(sb, " timesInvoked: ") | |
table.insert(sb, tostring(meta.timesInvoked)) | |
table.insert(sb, "\r\n") | |
table.insert(sb, " avgTime: ") | |
table.insert(sb, string.format("%.6f", meta.avgTime)) | |
table.insert(sb, "\r\n") | |
end | |
end | |
return table.concat(sb) | |
end | |
--# QuadViewCulling | |
--this is a single mesh built for the whole world map, culling faces that are internal to the structure | |
QuadViewCulling = class() | |
function QuadViewCulling:buildWorld() | |
--build the bottom level quads | |
quads = {} | |
quadSize = 2 | |
level=0 | |
height = #map/2 | |
radius = math.sqrt(quadSize*quadSize*2+height*height) | |
print(radius) | |
for k,v in ipairs(map) do | |
row=0 | |
for l,w in ipairs(v) do | |
for col=1,#w do | |
q = nil | |
for k,v in pairs(quads) do | |
if v.mid.x -quadSize <= row and v.mid.x+quadSize-1 >= row and v.mid.z -quadSize+1 <= col and v.mid.z+quadSize >=col then | |
q = v | |
end | |
--if something to identify if it's my quad, otherwise add one I guess... | |
end | |
if q == nil then | |
q = { m = mesh(), mid = vec3(math.floor(row/(quadSize*2))*quadSize*2+quadSize,height,math.floor((col-1)/(quadSize*2))*quadSize*2+quadSize), radius=radius } | |
table.insert(quads, q) | |
end | |
local c = w:sub(col,col) | |
local top = 1 | |
local bottom = 1 | |
local left = 1 | |
local right = 1 | |
local front = 1 | |
local back = 1 | |
if c == "b" then | |
-- top, bottom, left, right, front, back | |
if map[level] ~= nil and map[level][row+1]:sub(col,col) == "b" then | |
bottom = 0 | |
end | |
if map[level+2] ~= nil and map[level+2][row+1]:sub(col,col) == "b" then | |
top = 0 | |
end | |
if map[level+1][row] ~=nil and map[level+1][row]:sub(col,col) == "b" then | |
left = 0 | |
end | |
if map[level+1][row+2] ~= nil and map[level+1][row+2]:sub(col,col) == "b" then | |
right = 0 | |
end | |
if col-1 > 0 and w:sub(col-1,col-1) == "b" then | |
back = 0 | |
end | |
if col+1 < w:len() and w:sub(col+1, col+1) == "b" then | |
front = 0 | |
end | |
Cube(row + 0.5, level + 0.5, col-0.5, q.m, top, bottom,left,right,front,back) | |
end | |
end | |
row=row+1 | |
end | |
level=level+1 | |
end | |
for k,v in pairs(quads) do | |
v.m:setColors(color(255,255,255)) | |
v.m.texture = readImage("Cargo Bot:Crate Yellow 2") | |
end | |
--build the quadtree | |
while #quads > 1 do | |
quads = self:buildTree(quadSize, quads) | |
quadSize = quadSize * 2 | |
end | |
worldQuad = quads[1] | |
end | |
function QuadViewCulling:buildTree(qSize, qS) | |
newLayer = {} | |
row = 1 | |
col = 1 | |
hasRow = 1 | |
hasCol = 1 | |
while hasRow == 1 do | |
hasRow = 0 | |
while hasCol == 1 do | |
hasCol = 0 | |
newQuad = {mid = vec3(row*qSize*2,height,col*qSize*2), radius = math.sqrt(quadSize*quadSize*8+height*height), subQuads = {}} | |
for k,v in pairs(qS) do | |
if v.mid.x == qSize * 2 * row - qSize then | |
if v.mid.z == qSize*2*col - qSize then | |
table.insert(newQuad.subQuads, v) | |
hasCol = 1 | |
hasRow = 1 | |
end | |
if v.mid.z == qSize*2*col + qSize then | |
table.insert(newQuad.subQuads, v) | |
end | |
end | |
if v.mid.x == qSize * 2 * row + qSize then | |
if v.mid.z == qSize*2*col - qSize then | |
table.insert(newQuad.subQuads, v) | |
end | |
if v.mid.z == qSize*2*col + qSize then | |
table.insert(newQuad.subQuads, v) | |
end | |
end | |
end | |
col = col + 2 | |
if hasCol == 1 then | |
table.insert(newLayer, newQuad) | |
end | |
end | |
row = row + 2 | |
col = 1 | |
hasCol = 1 | |
end | |
return newLayer | |
end | |
function QuadViewCulling:drawWorld() | |
setupFrustum() | |
self:evaluateQuads(worldQuad.subQuads) | |
end | |
function QuadViewCulling:evaluateQuads(quads) | |
for k,v in pairs(quads) do | |
if isSphereInFrustum(v.mid, v.radius) then | |
if v.subQuads == nil then | |
v.m:draw() | |
else | |
self:evaluateQuads(v.subQuads) | |
end | |
end | |
end | |
end | |
--this creates a set of variables representing the planes surrounding the frustum | |
--it bases it off the modelViewProjection matrix, and the rest of it I found on the web | |
function setupFrustum() | |
clip = modelMatrix() * viewMatrix() * projectionMatrix() | |
frustum = {} | |
--/* Extract the numbers for the RIGHT plane */ | |
frustum[0] = {} | |
frustum[0][0] = clip[ 4] - clip[ 1] | |
frustum[0][1] = clip[ 8] - clip[ 5] | |
frustum[0][2] = clip[12] - clip[ 9] | |
frustum[0][3] = clip[16] - clip[13] | |
--/* Normalize the result */ | |
t = math.sqrt( frustum[0][0] * frustum[0][0] + frustum[0][1] * frustum[0][1] + frustum[0][2] * frustum[0][2] ) | |
frustum[0][0] = frustum[0][0] / t | |
frustum[0][1] = frustum[0][1] / t | |
frustum[0][2] = frustum[0][2] / t | |
frustum[0][3] = frustum[0][3] / t | |
--/* Extract the numbers for the LEFT plane */ | |
frustum[1] = {} | |
frustum[1][0] = clip[ 4] + clip[ 1] | |
frustum[1][1] = clip[ 8] + clip[ 5] | |
frustum[1][2] = clip[12] + clip[ 9] | |
frustum[1][3] = clip[16] + clip[13] | |
--/* Normalize the result */ | |
t = math.sqrt( frustum[1][0] * frustum[1][0] + frustum[1][1] * frustum[1][1] + frustum[1][2] * frustum[1][2] ) | |
frustum[1][0] = frustum[1][0] / t | |
frustum[1][1] = frustum[1][1] / t | |
frustum[1][2] = frustum[1][2] / t | |
frustum[1][3] = frustum[1][3] / t | |
--/* Extract the BOTTOM plane */ | |
frustum[2] = {} | |
frustum[2][0] = clip[ 4] + clip[ 2]; | |
frustum[2][1] = clip[ 8] + clip[ 6]; | |
frustum[2][2] = clip[12] + clip[ 10]; | |
frustum[2][3] = clip[16] + clip[14]; | |
--/* Normalize the result */ | |
t = math.sqrt( frustum[2][0] * frustum[2][0] + frustum[2][1] * frustum[2][1] + frustum[2][2] * frustum[2][2] ) | |
frustum[2][0] = frustum[2][0] / t | |
frustum[2][1] = frustum[2][1] / t | |
frustum[2][2] = frustum[2][2] / t | |
frustum[2][3] = frustum[2][3] / t | |
--/* Extract the TOP plane */ | |
frustum[3] = {} | |
frustum[3][0] = clip[ 4] - clip[ 2]; | |
frustum[3][1] = clip[ 8] - clip[ 6]; | |
frustum[3][2] = clip[12] - clip[ 10]; | |
frustum[3][3] = clip[16] - clip[14]; | |
--/* Normalize the result */ | |
t = math.sqrt( frustum[3][0] * frustum[3][0] + frustum[3][1] * frustum[3][1] + frustum[3][2] * frustum[3][2] ) | |
frustum[3][0] = frustum[3][0] / t | |
frustum[3][1] = frustum[3][1] / t | |
frustum[3][2] = frustum[3][2] / t | |
frustum[3][3] = frustum[3][3] / t | |
--/* Extract the FAR plane */ | |
frustum[4] = {} | |
frustum[4][0] = clip[ 4] - clip[ 3]; | |
frustum[4][1] = clip[ 8] - clip[ 7]; | |
frustum[4][2] = clip[12] - clip[11]; | |
frustum[4][3] = clip[16] - clip[15]; | |
--/* Normalize the result */ | |
t = math.sqrt( frustum[4][0] * frustum[4][0] + frustum[4][1] * frustum[4][1] + frustum[4][2] * frustum[4][2] ) | |
frustum[4][0] = frustum[4][0] / t | |
frustum[4][1] = frustum[4][1] / t | |
frustum[4][2] = frustum[4][2] / t | |
frustum[4][3] = frustum[4][3] / t | |
--/* Extract the NEAR plane */ | |
frustum[5] = {} | |
frustum[5][0] = clip[ 4] + clip[ 3]; | |
frustum[5][1] = clip[ 8] + clip[ 7]; | |
frustum[5][2] = clip[12] + clip[11]; | |
frustum[5][3] = clip[16] + clip[15]; | |
--/* Normalize the result */ | |
t = math.sqrt( frustum[5][0] * frustum[5][0] + frustum[5][1] * frustum[5][1] + frustum[5][2] * frustum[5][2] ) | |
frustum[5][0] = frustum[5][0] / t | |
frustum[5][1] = frustum[5][1] / t | |
frustum[5][2] = frustum[5][2] / t | |
frustum[5][3] = frustum[5][3] / t | |
end | |
--this function checks whether a sphere at loc with a radius falls even partially in the view frustum | |
function isSphereInFrustum(loc, radius) | |
for p = 0,5 do | |
if ( frustum[p][0] * loc.x + frustum[p][1] * loc.y + frustum[p][2] * loc.z + frustum[p][3] <= -radius ) then | |
return false | |
end | |
end | |
return true | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment