Created
June 5, 2016 07:35
-
-
Save dermotbalson/849d86ab727b58b39a8ec17ca6f1905c to your computer and use it in GitHub Desktop.
3D box
This file contains 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 | |
displayMode(FULLSCREEN) | |
function setup() | |
size,radius=200,10 | |
startPos=vec3(size/2,size/2,-size/2) --assumes centre of box is (0,0,0) | |
CreateScene(size,radius,startPos) | |
notStarted=true | |
end | |
function touched(t) | |
if t.state==ENDED then | |
local v=vec3(math.random()*6-3,math.random()*6-3,math.random()*6-3):normalize()*5 | |
PushBall(v) | |
notStarted=false | |
end | |
end | |
function CreateScene(size,radius,pos) --size is size of 3D box | |
--make two boxes end to end using 5 lines | |
boxSize=100 --size of virtual box | |
local s=boxSize | |
boxes={} | |
boxes[1]=physics.body(EDGE,vec2(-s,-s/2),vec2(s,-s/2)) | |
boxes[2]=physics.body(EDGE,vec2(-s,s/2),vec2(s,s/2)) | |
boxes[3]=physics.body(EDGE,vec2(-s,-s/2),vec2(-s,s/2)) | |
boxes[4]=physics.body(EDGE,vec2(0,-s/2),vec2(0,s/2)) | |
boxes[5]=physics.body(EDGE,vec2(s,-s/2),vec2(s,s/2)) | |
for _,b in pairs(boxes) do | |
b.restitution=1 | |
b.friction=0 | |
end | |
circles={} | |
for i=1,2 do | |
local p=physics.body(CIRCLE,10) | |
if i==1 then p.x,p.y=-s/2,0 else p.x,p.y=s/2,0 end | |
p.restitution=1 | |
p.bullet=true | |
circles[i]=p | |
end | |
physics.gravity(0,0) --turn off gravity | |
physics.continuous=true | |
scaling=boxSize/size | |
--create visible box | |
local img=readImage("SpaceCute:Background")--:copy(4,4,62,62) | |
box=CreateBlock(size,size,size,color(255),vec3(0,0,0),img) | |
ball=CreateSphere(radius,readImage("Cargo Bot:Starry Background"),color(255)) | |
end | |
function PushBall(v) | |
circles[1]:applyLinearImpulse(vec2(v.x,v.y)*scaling) | |
circles[2]:applyLinearImpulse(vec2(v.x,v.z)*scaling) | |
end | |
function GetPos() | |
return vec3(boxSize/2+circles[1].x,circles[1].y,circles[2].y)/scaling | |
end | |
function draw() | |
background(220) | |
perspective(90) | |
local p=GetPos() | |
camera(0,0,0,p.x,p.y,p.z) | |
box:draw() | |
pushMatrix() | |
translate(p:unpack()) | |
ball:draw() | |
popMatrix() | |
ortho() | |
viewMatrix(matrix()) | |
stroke(0) | |
strokeWidth(1) | |
local x,y=WIDTH-70,70 | |
local s=50 | |
local ss=s/scaling/size | |
line(x-s,y-s,x+s,y-s) | |
line(x-s,y+s,x+s,y+s) | |
line(x-s,y-s,x-s,y+s) | |
line(x+s,y-s,x+s,y+s) | |
fill(255,0,0,150) | |
ellipse(x+p.x*ss,y+p.y*ss,radius*2*ss) | |
text("XY",x-s+20,y+s-15) | |
y=180 | |
line(x-s,y-s,x+s,y-s) | |
line(x-s,y+s,x+s,y+s) | |
line(x-s,y-s,x-s,y+s) | |
line(x+s,y-s,x+s,y+s) | |
ellipse(x+p.x*ss,y+p.z*ss,radius*2*ss) | |
text("XZ",x-s+20,y+s-15) | |
if notStarted then | |
text( | |
[[You are at the centre of a box with a red ball. | |
You can't see anything because the ball is around you | |
Touch the screen to push the ball in a random direction | |
and the camera will follow its movement. | |
Touch the screen to push it again. | |
The two boxes below show the two physics planes used | |
to handle collisions with the sides of the box | |
]] | |
,WIDTH/2,HEIGHT/2) | |
end | |
end | |
--# Utility | |
function CreateBlock(w,h,d,col,pos,tex) --width,height,depth,colour,position,texture | |
local x,X,y,Y,z,Z=pos.x-w/2,pos.x+w/2,pos.y-h/2,pos.y+h/2,pos.z-d/2,pos.z+d/2 | |
local v={vec3(x,y,Z),vec3(X,y,Z),vec3(X,Y,Z),vec3(x,Y,Z),vec3(x,y,z),vec3(X,y,z),vec3(X,Y,z),vec3(x,Y,z)} | |
local vert={v[1],v[2],v[3],v[1],v[3],v[4],v[2],v[6],v[7],v[2],v[7],v[3],v[6],v[5],v[8],v[6],v[8],v[7], | |
v[5],v[1],v[4],v[5],v[4],v[8],v[4],v[3],v[7],v[4],v[7],v[8],v[5],v[6],v[2],v[5],v[2],v[1]} | |
local texCoords | |
if tex then | |
local t={vec2(0,0),vec2(1,0),vec2(0,1),vec2(1,1)} | |
texCoords={t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3], | |
t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3],t[1],t[2],t[4],t[1],t[4],t[3]} | |
end | |
local n={vec3(0,0,1),vec3(1,0,0),vec3(0,0,-1),vec3(-1,0,0),vec3(1,0,0),vec3(-1,0,0)} | |
local norm={} | |
for i=1,6 do for j=1,6 do norm[#norm+1]=n[i] end end | |
local ms = mesh() | |
ms.vertices = vert | |
ms.normals=norm | |
if tex then ms.texture,ms.texCoords = tex,texCoords end | |
ms:setColors(col or color(255)) | |
return ms | |
end | |
function CreateSphere(r,tex,col,nx,ny) | |
local vertices,tc = Sphere_OptimMesh(nx or 40,ny or 20) | |
vertices = Sphere_WarpVertices(vertices) | |
for i=1,#vertices do vertices[i]=vertices[i]*r end | |
local ms = mesh() | |
ms.vertices=vertices | |
if tex then ms.texture,ms.texCoords=tex,tc end | |
ms:setColors(col or color(255)) | |
return ms | |
end | |
function Sphere_OptimMesh(nx,ny) | |
local v,t={},{} | |
local k,s,x,y,x1,x2,i1,i2,sx,sy=0,1,0,0,{},{},0,0,nx/ny,1/ny | |
local c = vec3(1,0.5,0) | |
local m1,m2 | |
for y=0,ny-1 do | |
local nx1 = math.floor( nx * math.abs(math.cos(( y*sy-0.5)*2 * math.pi/2)) ) | |
if nx1<6 then nx1=6 end | |
local nx2 = math.floor( nx * math.abs(math.cos(((y+1)*sy-0.5)*2 * math.pi/2)) ) | |
if nx2<6 then nx2=6 end | |
x1,x2 = {},{} | |
for i1 = 1,nx1 do x1[i1] = (i1-1)/(nx1-1)*sx end x1[nx1+1] = x1[nx1] | |
for i2 = 1,nx2 do x2[i2] = (i2-1)/(nx2-1)*sx end x2[nx2+1] = x2[nx2] | |
local i1,i2,n,nMax,continue=1,1,0,0,true | |
nMax = nx*2+1 | |
while continue do | |
m1,m2=(x1[i1]+x1[i1+1])/2,(x2[i2]+x2[i2+1])/2 | |
if m1<=m2 then | |
v[k+1],v[k+2],v[k+3]=vec3(x1[i1],sy*y,1)-c,vec3(x1[i1+1],sy*y,1)-c,vec3(x2[i2],sy*(y+1),1)-c | |
t[k+1],t[k+2],t[k+3]=vec2(-x1[i1]/2,sy*y) ,vec2(-x1[i1+1]/2,sy*y),vec2(-x2[i2]/2,sy*(y+1)) | |
if i1<nx1 then i1 = i1 +1 end | |
else | |
v[k+1],v[k+2],v[k+3]=vec3(x1[i1],sy*y,1)-c,vec3(x2[i2],sy*(y+1),1)-c,vec3(x2[i2+1],sy*(y+1),1)-c | |
t[k+1],t[k+2],t[k+3]=vec2(-x1[i1]/2,sy*y),vec2(-x2[i2]/2,sy*(y+1)),vec2(-x2[i2+1]/2,sy*(y+1)) | |
if i2<nx2 then i2 = i2 +1 end | |
end | |
if i1==nx1 and i2==nx2 then continue=false end | |
k,n=k+3,n+1 | |
if n>nMax then continue=false end | |
end | |
end | |
return v,t | |
end | |
function Sphere_WarpVertices(verts) | |
local m = matrix(0,0,0,0, 0,0,0,0, 1,0,0,0, 0,0,0,0) | |
local vx,vy,vz,vm | |
for i,v in ipairs(verts) do | |
vx,vy = v[1], v[2] | |
vm = m:rotate(180*vy,1,0,0):rotate(180*vx,0,1,0) | |
vx,vy,vz = vm[1],vm[5],vm[9] | |
verts[i] = vec3(vx,vy,vz) | |
end | |
return verts | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment