Skip to content

Instantly share code, notes, and snippets.

@dermotbalson
Created November 17, 2015 04:52
Show Gist options
  • Save dermotbalson/1376155bfae6d18666e3 to your computer and use it in GitHub Desktop.
Save dermotbalson/1376155bfae6d18666e3 to your computer and use it in GitHub Desktop.
Frustum test 3
--Circles2
local dx,dy,f1x,f1y,f2x,f2y,invPM1,cosFOV,cosFOV2
local sqrt=math.sqrt
function setup()
pos=vec2(100,100) --circle position
camPos=vec2(WIDTH/2,HEIGHT/2) --fixed camera
far=700
print("Fructum is in blue, pointing up")
print("True tangent is in pink")
print("Fake tangent is in green")
print("Use your finger to drag the circle around")
print("The circle goes bright yellow when it enters the frustum")
FOV=45
parameter.integer("radius",10,100,50)
--parameter.number("PM1",1,12,2.6)
parameter.integer("angle",0,360,0,SetAngle)
parameter.integer("FOV",10,120,45,SetAngle)
end
function SetAngle()
perspective(FOV)
camposX,camposY=camPos.x,camPos.y
tangentAdjust=1/math.sin(math.rad(FOV/2))
PM1=projectionMatrix()[1]
ortho()
camDir=vec2(math.cos(math.rad(angle)),math.sin(math.rad(angle)))
camdirX,camdirY=camDir.x,camDir.y
fructum=mesh()
local w=far/PM1*vec2(-camDir.y,camDir.x)
fructum.vertices={camPos,camPos+far*camDir-w,camPos+far*camDir+w}
fructum:setColors(color(136, 168, 199, 255))
end
function draw()
background(150)
fructum:draw()
pushStyle()
stroke(99, 124, 183, 255)
strokeWidth(2)
line(camPos.x,camPos.y,camPos.x+far*camDir.x,camPos.y+far*camDir.y)
popStyle()
DrawCircle()
end
function DrawCircle()
--calculate fake tangent
local fake=pos+camDir*radius*tangentAdjust
pushStyle()
cosFOV=math.cos(math.rad(FOV/2))
cosFOV2=cosFOV*cosFOV
if IsVisible3(pos,camPos,camDir,radius,far) then fill(255,255,0) else fill(255,255,0,100) end
ellipse(pos.x,pos.y,radius*2)
stroke(195, 72, 169, 255) strokeWidth(2)
stroke(52, 162, 48, 255)
line(camPos.x,camPos.y,fake.x,fake.y)
--ellipse(tangent.x,tangent.y,10)
popStyle()
end
function touched(t)
pos=vec2(t.x,t.y)
end
--[
function setup()
FOV=45
tangentAdjust=1/math.sin(math.rad(FOV/2))
pos=vec2(100,100) --circle position
camPos=vec2(WIDTH/2,0) --fixed camera
camposX,camposY=camPos.x,camPos.y
camDir=vec2(0,1)
camdirX,camdirY=camDir.x,camDir.y
radius=50
n=20000000
PM1=2.5
cosFOV=math.cos(math.rad(FOV/2))
cosFOV2=cosFOV*cosFOV
t=os.time()
for i=1,n do
a=IsVisible4(pos,radius)
end
print("1=",os.time()-t)
print(n/60/(os.time()-t))
t=os.time()
for i=1,n do
a=IsVisible5(pos,radius)
end
print("2=",os.time()-t)
print(n/60/(os.time()-t))
end
function draw()
end
--]]
function IsVisible(pos,camPos,camDir,radius)
local px,py,pcx,pcy,pdx,pdy=pos.x,pos.y,camPos.x,camPos.y,camDir.x,camDir.y
--local dx,dy=px-pcx,py-pcy
--if dx*pdx+dy*pdy<0 then return end
local u=radius*tangentAdjust
local ptx,pty=px+pdx*u-pcx,py+pdy*u-pcy
local sq=ptx*ptx+pty*pty
local a=ptx*pdx+pty*pdy
return a*a>cosFOV2*sq
end
function IsVisible2(pos,camPos,camDir,radius)
local v=(pos+camDir*(radius*PM1)-camPos):normalize()
return v:dot(camDir)>cosFOV
end
function IsVisible3(pos,camPos,camDir,radius)
local px,py,pcx,pcy,pdx,pdy=pos.x,pos.y,camPos.x,camPos.y,camDir.x,camDir.y
local dx,dy=px-pcx,py-pcy
if dx*pdx+dy*pdy<0 then return end
local u=radius*tangentAdjust
local ptx,pty=px+pdx*u-pcx,py+pdy*u-pcy
local sq=ptx*ptx+pty*pty
local a=ptx*pdx+pty*pdy
return a*a>cosFOV2*sq
end
function IsVisible4(pos,radius) --fastest
local px,py=pos.x,pos.y
local dx,dy=px-camposX,py-camposY
if dx*camdirX+dy*camdirY<0 then return end
local u=radius*tangentAdjust
local ptx,pty=px+camdirX*u-camposX,py+camdirY*u-camposY
local sq=ptx*ptx+pty*pty
local a=ptx*camdirX+pty*camdirY
return a*a>cosFOV2*sq
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment