Skip to content

Instantly share code, notes, and snippets.

@sp4cemonkey
Created April 27, 2015 18:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sp4cemonkey/ac2a490f0124de77c008 to your computer and use it in GitHub Desktop.
Save sp4cemonkey/ac2a490f0124de77c008 to your computer and use it in GitHub Desktop.
Cube World Performance Comparison
--# 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