Skip to content

Instantly share code, notes, and snippets.

@dermotbalson
Created November 16, 2015 15:21
Show Gist options
  • Save dermotbalson/2f3e191d4c67a8557a67 to your computer and use it in GitHub Desktop.
Save dermotbalson/2f3e191d4c67a8557a67 to your computer and use it in GitHub Desktop.
Frustum test2
function setup()
FOV=45
perspective(FOV)
PM1=1/projectionMatrix()[1]
ortho()
pos=vec2(100,100) --circle position
camPos=vec2(WIDTH/2,HEIGHT/2) --fixed camera
--camDir=vec2(0.25,1):normalize() --camera direction
far=700
--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))
--radius=50 --collision circle radius
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")
parameter.integer("radius",10,100,50)
parameter.integer("angle",0,360,0,SetAngle)
end
function SetAngle()
camDir=vec2(math.cos(math.rad(angle)),math.sin(math.rad(angle)))
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
local dx,dy,f1x,f1y,f2x,f2y,PM1,cosFOV
local sqrt=math.sqrt
function DrawCircle()
--local tangent=GetTangent(pos,radius,camPos,camDir)
--calculate fake tangent
local fake=pos+camDir*radius*2.6
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)
--line(camPos.x,camPos.y,tangent.x,tangent.y)
stroke(52, 162, 48, 255)
line(camPos.x,camPos.y,fake.x,fake.y)
--ellipse(tangent.x,tangent.y,10)
popStyle()
end
function GetTangent(centre,radius,camPos,camDir)
--calculate offset from centre
local s=(centre.x-camPos.x)/(-centre.y+camPos.y)
local a=(radius/math.sqrt(1+s*s))*vec2(1,s)
--now figure out which side of the circle is closest to the camera direction
--this formula tells which side of a line, a point is on
local d=camPos+camDir*1000
local e=(centre.x-camPos.x)*(d.y-camPos.y)-(centre.y-camPos.y)*(d.x-camPos.x)
if e>0 then return centre-a else return centre+a end --adjust the centre by the offset
end
function touched(t)
pos=vec2(t.x,t.y)
end
--[[
function setup()
FOV=45
pos=vec2(100,100) --circle position
camPos=vec2(WIDTH/2,0) --fixed camera
camDir=vec2(0,1)
radius=50
n=20000000
cosFOV=math.cos(math.rad(FOV/2))
cosFOV2=cosFOV*cosFOV
t=os.time()
for i=1,n do
a=IsVisible(pos,camPos,camDir,radius)
end
print("Non vector",os.time()-t)
print(n/60/(os.time()-t))
t=os.time()
for i=1,n do
a=IsVisible3(pos,camPos,camDir,radius)
end
print("Vector",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 u=radius*2.6
local ptx,pty=px+pdx*u-pcx,py+pdy*u-pcy
local sq=sqrt(ptx*ptx+pty*pty)
return (ptx*pdx+pty*pdy)>cosFOV*sq
end
function IsVisible2(pos,camPos,camDir,radius)
local v=(pos+camDir*(radius*2.6)-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 u=radius*2.6
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment