Created
October 20, 2015 03:10
-
-
Save dermotbalson/56aef88dcca08f9d7445 to your computer and use it in GitHub Desktop.
Tank 4
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
--# Test | |
--[ | |
function setup() | |
img=readImage("Dropbox:3D-grass2x"):copy(0,50,25,50) | |
b1=CreateBlock(10,5,5,color(255,255,0),nil,img) | |
b2=CreateBlock(10,5,5,color(255),nil,img) --b2:setColors(color(100,0,0)) | |
b1.pos=vec3(0,0,100) b1.a=0 | |
b2.pos=vec3(0,0,0) b2.a=40 | |
s=vec3(10,5,5) | |
dp=1 | |
ap=0.25 | |
camPos,camLook=b1.pos,b2.pos | |
end | |
function draw() | |
background(102, 173, 202, 255) | |
perspective() | |
camera(camPos.x,camPos.y,camPos.z,camLook.x,camLook.y,camLook.z) | |
pushMatrix() | |
translate(b2.pos:unpack()) | |
rotate(b2.a,0,1,0) | |
b2:draw() | |
X,Y,w,h=GetScreenRect(b1,b2,s) | |
popMatrix() | |
b2.pos.z=b2.pos.z+dp if b2.pos.z<-300 or b2.pos.z>80 then dp=-dp end | |
b2.a=b2.a+ap | |
ortho() | |
viewMatrix(matrix()) | |
fill(255,255,0,50) | |
rect(X,Y,w,h) | |
end | |
function GetScreenRect(t1,t2,s) --t1 is camera, t2 is target, s is vec3 size of object | |
--assume target only rotates on y, take larger of x and z size to set rect size | |
local u=math.max(s.x,s.z) | |
--get direction and distance | |
local v=(t2.pos-t1.pos) | |
local d=v:len()-u/2 --position of t2 is assumed to be its centre, so adjust by 1\2 depth | |
v=v/d | |
--get drawing rectangle | |
local w = u*WIDTH*projectionMatrix()[1]/d/2 | |
local h = s.y*HEIGHT*projectionMatrix()[6]/d/2 | |
--draw our tank | |
local m = modelMatrix()*viewMatrix()*projectionMatrix() | |
--m = m:translate(0,0,-d) | |
local X,Y=(m[13]/m[16]+1)*WIDTH/2, (m[14]/m[16]+1)*HEIGHT/2 | |
return X-w/2,Y-h/2,w,h | |
end | |
--]] | |
--# Test3 | |
function setup() | |
img=readImage("Platformer Art:Block Brick") | |
b1=CreateBlock(10,5,5,color(255,255,0),nil,img) | |
b2=CreateBlock(10,5,5,color(255),nil,img) | |
b1.pos=vec3(0,0,100) b1.a=0 | |
b2.pos=vec3(0,0,0) b2.a=40 | |
s=vec3(10,5,5) | |
target=image(WIDTH,HEIGHT) | |
camPos,camLook=b1.pos,b2.pos | |
dp,ap=1,0.5 | |
parameter.number("FPS",1,60,60) | |
end | |
function draw() | |
FPS=FPS*0.9+0.1/DeltaTime | |
background(150) | |
perspective() | |
camera(camPos.x,camPos.y,camPos.z,camLook.x,camLook.y,camLook.z) | |
pushMatrix() | |
translate(b2.pos:unpack()) | |
rotate(b2.a,0,1,0) | |
b2:draw() | |
local X,Y,w,h=GetScreenRect(b1,b2,s) | |
local img=DrawTarget(X,Y,w,h,b2,b1.pos:dist(b2.pos)) | |
popMatrix() | |
b2.pos.z=b2.pos.z+dp if b2.pos.z<-300 or b2.pos.z>80 then dp=-dp end | |
b2.a=b2.a+ap | |
--ortho() | |
--viewMatrix(matrix()) | |
--sprite(img,w/2,h/2) | |
end | |
function GetScreenRect(t1,t2,s) --t1 is camera, t2 is target, s is vec3 size of object | |
--assume target only rotates on y, take larger of x and z size to set rect size | |
local u=math.max(s.x,s.z) | |
--get direction and distance | |
local v=(t2.pos-t1.pos) | |
local d=v:len()-u/2 --position of t2 is assumed to be its centre, so adjust by 1\2 depth | |
v=v/d | |
--get drawing rectangle | |
local w = u*WIDTH*projectionMatrix()[1]/d/2 | |
local h = s.y*HEIGHT*projectionMatrix()[6]/d/2 | |
--draw our tank | |
local m = modelMatrix()*viewMatrix()*projectionMatrix() | |
--m = m:translate(0,0,-d) | |
local X,Y=(m[13]/m[16]+1)*WIDTH/2, (m[14]/m[16]+1)*HEIGHT/2 | |
return X-w/2,Y-h/2,w,h | |
end | |
function DrawTarget(X,Y,w,h,t,d) | |
setContext(target) | |
background(50) | |
perspective(45,WIDTH/HEIGHT,0.1,d) | |
clip(X,Y,w,h) | |
t:draw() | |
clip() | |
setContext() | |
local XX,YY,ww,hh=math.floor(X),math.floor(Y),math.ceil(w),math.ceil(h) | |
return target:copy(XX,YY,ww,hh) | |
end | |
--# Test5 | |
function setup() | |
targetColor=color(255,0,0) --target colour | |
--draw a target image with a red square in the middle on a green background | |
--we want to count the red pixels | |
img=image(200,200) | |
noSmooth() | |
setContext(img) | |
background(0,255,0) | |
fill(targetColor) | |
rect(50,50,50,50) | |
setContext() | |
smooth() | |
--count yellow pixels ------------------ | |
--create the smallest mesh possible, seems to be a triangle with 2x2 pixels | |
mm=mesh() | |
mm.vertices={vec2(1,1),vec2(2,1),vec2(1,2)} | |
mm.shader=shader(pixelCountShader.vertexShader,pixelCountShader.fragmentShader) | |
mm.shader.c=targetColor --target colour | |
mm.shader.w=200 --width of texture | |
mm.shader.h=200 --height of texture | |
mm.shader.threshold=3000 --number of pixels required to pass threshold | |
img2=image(2,2) | |
mm.texture=img --pass through test image | |
mm:draw() | |
----------------------------------- | |
r,g,b=img2:get(2,2) --this seems to be the best pixel to get | |
setContext() | |
print("time=",os.time()-t) | |
print("Result=",r/255,2500/mm.shader.threshold) | |
end | |
function draw() | |
background(200) | |
sprite(img,WIDTH/2,HEIGHT/2,300) --draw test image | |
end | |
pixelCountShader = { | |
vertexShader=[[ | |
uniform mat4 modelViewProjection; | |
attribute vec4 position; | |
varying lowp vec4 vPosition; | |
void main() | |
{ | |
gl_Position = modelViewProjection * position; | |
vPosition=position; | |
} | |
]], | |
fragmentShader = [[ | |
precision highp float; | |
uniform lowp sampler2D texture; | |
uniform vec4 c; | |
uniform float w; | |
uniform float h; | |
uniform float threshold; | |
varying highp vec4 vPosition; | |
void main() | |
{ | |
gl_FragColor=vec4(1.0,1.0,1.0,1.0); | |
if (vPosition.x>1.0 && vPosition.y>1.0) { | |
float t=0.0; | |
for (float x=0.0; x<w; x++) | |
for (float y=0.0; y<h; y++) { | |
vec4 p=texture2D(texture,vec2(x/w,y/h)); | |
if (p.r==c.r) t+=1.0; | |
} | |
gl_FragColor.a = t/threshold; | |
} | |
} | |
]]} | |
--# Test6 | |
function setup() | |
targetColor=color(0,0,255) --target colour | |
--draw a target image with a red square in the middle on a green background | |
--we want to count the red pixels | |
img=image(200,200) | |
--noSmooth() | |
setContext(img) | |
background(0,255,0) | |
fill(targetColor) | |
s=200/3 | |
rect(50-s/2,50-s/2,s,s) | |
setContext() | |
img2=image(4,4) | |
setContext(img2) | |
sprite(img,2,2,4) | |
setContext() | |
t=0 | |
for i=1,img2.width do | |
for j=1,img2.height do | |
r,g,b=img2:get(i,j) | |
print(r,g,b) | |
t=t+b | |
end | |
end | |
print("Result=",t/255/img2.width/img2.height) | |
end | |
function draw() | |
background(200) | |
sprite(img,WIDTH/2,HEIGHT/2,300) --draw test image | |
sprite(img2,WIDTH/2,HEIGHT/2,50) | |
end | |
--# Test7 | |
function setup() | |
tank=BuildTank(color(150, 189, 128, 255)) | |
camPos=vec3(0,0,50) | |
ax,ay=0,0 | |
backgroundColor=color(220) | |
end | |
function draw() | |
background(backgroundColor) | |
perspective() | |
camera(camPos.x,camPos.y,camPos.z,0,0,0) | |
rotate(ay,0,1,0) rotate(ax,1,0,0) | |
for _,m in pairs(tank) do | |
m.shader.mModel=modelMatrix() | |
m.shader.camPos=camPos | |
m:draw() | |
end | |
end | |
function touched(t) | |
if t.state~=ENDED then | |
ay,ax=ay+t.deltaX,ax+t.deltaY | |
end | |
end | |
function BuildTank(col) | |
local x1,x2,y1,y2,y3,z1,z2 | |
--body of tank | |
local body=mesh() | |
local v,t,c={},{},{} | |
x1,x2,y,z1,z2=-8.25,8.25,6.5,4.5,-4.5 --deck | |
v[#v+1]=vec3(x1,y,z1) v[#v+1]=vec3(x2,y,z1) v[#v+1]=vec3(x2,y,z2) | |
v[#v+1]=vec3(x2,y,z2) v[#v+1]=vec3(x1,y,z2) v[#v+1]=vec3(x1,y,z1) | |
x,y1,y2,z1,z2=8.25,2,6.5,4.5,-4.5 --back | |
v[#v+1]=vec3(x,y1,z1) v[#v+1]=vec3(x,y1,z2) v[#v+1]=vec3(x,y2,z2) | |
v[#v+1]=vec3(x,y2,z2) v[#v+1]=vec3(x,y2,z1) v[#v+1]=vec3(x,y1,z1) | |
x,y1,y2,z1,z2=-8.25,4.5,6.5,4.5,-4.5 --front | |
v[#v+1]=vec3(x,y1,z1) v[#v+1]=vec3(x,y1,z2) v[#v+1]=vec3(x,y2,z2) | |
v[#v+1]=vec3(x,y2,z2) v[#v+1]=vec3(x,y2,z1) v[#v+1]=vec3(x,y1,z1) | |
x1,x2,y1,y2,z1,z2=-11,-8.25,3,4.5,4.5,-4.5 --front #2 angle | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
x1,x2,y1,y2,y3,z1,z2=-8.25,8.25,2,2,6.5,4.5,-4.5 --sides | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x2,y3,z1) | |
v[#v+1]=vec3(x2,y3,z1) v[#v+1]=vec3(x1,y3,z1) v[#v+1]=vec3(x1,y1,z1) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x1,y3,z2) | |
v[#v+1]=vec3(x1,y3,z2) v[#v+1]=vec3(x2,y3,z2) v[#v+1]=vec3(x2,y2,z2) | |
x1,x2,y1,z1,z2=-11,8.25,2,-2.5,2.5 --underneath | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y1,z2) | |
v[#v+1]=vec3(x2,y1,z2) v[#v+1]=vec3(x2,y1,z1) v[#v+1]=vec3(x1,y1,z1) | |
x,y1,y2,z1,z2=-11,2,3,-2.5,2.5 --front bottom | |
v[#v+1]=vec3(x,y1,z1) v[#v+1]=vec3(x,y1,z2) v[#v+1]=vec3(x,y2,z2) | |
v[#v+1]=vec3(x,y2,z2) v[#v+1]=vec3(x,y2,z1) v[#v+1]=vec3(x,y1,z1) | |
body.vertices=v | |
body:setColors(color(90)) | |
body.texture=MakeBodyTexture() | |
--tracks | |
local track,v=mesh(),{} | |
x1,x2,y1,y2,z1,z2=8.25,8.25,1,2,4.5,2.5 --back right vert | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
z1,z2=-2.5,-4.5 --back left vert | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
x1,x2,y1,y2,z1,z2=7.25,8.25,0,1,4.5,2.5 --back right slant | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
z1,z2=-2.5,-4.5 --back left slant | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
x1,x2,y1,y2,z1,z2=-11,-11,2,3,2.5,4.5 --front right vert | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
z1,z2=-4.5,-2.5 --front left vert | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
x1,x2,y1,y2,z1,z2=-9,-11,0,2,2.5,4.5 --front right slant | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
z1,z2=-4.5,-2.5 --front left slant | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
x1,x2,y1,y2,z1,z2=-9,7.25,0,0,2.5,4.5 --bottom right track | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y1,z2) | |
v[#v+1]=vec3(x2,y1,z2) v[#v+1]=vec3(x2,y1,z1) v[#v+1]=vec3(x1,y1,z1) | |
z1,z2=-2.5,-4.5 --bottom left track | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y1,z2) | |
v[#v+1]=vec3(x2,y1,z2) v[#v+1]=vec3(x2,y1,z1) v[#v+1]=vec3(x1,y1,z1) | |
track.vertices=v | |
track:setColors(color(40)) | |
track.texture=MakeTrackTexture() | |
local a={body=body,track=track} | |
for _,m in pairs(a) do | |
local norm={} | |
local v=m:buffer("position") | |
for i=1,m.size,3 do | |
local v1,v2=v[i]-v[i+2],v[i+1]-v[i+2] | |
local n=(v1:cross(v2)):normalize() | |
norm[i],norm[i+1],norm[i+2]=n,n,n | |
end | |
m.normals=norm | |
m=SetLighting(m) | |
end | |
print("vertices=",body.size+track.size) | |
return a | |
end | |
function SetLighting(m) | |
m.shader=shader(TankShader.v,TankShader.f) | |
m.shader.directDirection=vec4(-1,1,1,0):normalize() | |
m.shader.ambientColor=color(255)*0.3 | |
m.shader.directColor=color(255)*0.7 | |
m.shader.fog=1000 | |
m.shader.mistColor=backgroundColor | |
return m | |
end | |
function MakeBodyTexture() | |
local img=image(50,50) | |
setContext(img) | |
background(122, 184, 121, 255) | |
setContext() | |
return img | |
end | |
function MakeTrackTexture() | |
local img=image(50,50) | |
setContext(img) | |
background(110, 104, 102, 255) | |
setContext() | |
return img | |
end | |
--# TerrainShader | |
--Terrain plus shader | |
local atan,rand,min,max=math.atan,math.random,math.min,math.max | |
local rad=math.pi/180 | |
local Terrain={} | |
function MakeTerrain() | |
local w,d,pic,f=1000,1000,"Dropbox:3D-grass2x",.02 | |
LoadImages() | |
local floor=mesh() | |
local img=readImage(pic) | |
floor.texture=img | |
local wn,dn=w/img.width/f,d/img.height/f | |
floor.vertices={vec3(0,0,0),vec3(w,0,0),vec3(w,0,-d),vec3(w,0,-d),vec3(0,0,-d),vec3(0,0,0)} | |
floor.texCoords={vec2(0,0),vec2(wn,0),vec2(wn,dn),vec2(wn,dn),vec2(0,dn),vec2(0,0)} | |
floor.shader=shader(TileShader.v,TileShader.f) | |
floor.shader.fog=5000 | |
floor.shader.mistColor=backgroundColor | |
floor.shader.mModel=modelMatrix() | |
local trees,treePos=mesh(),{} | |
for i=1,400 do | |
local a=1 --rand(1,#treeImages) | |
local s=0.15*(0.5+rand()) | |
local ww,hh=treeImages[a].width*s,treeImages[a].height*s | |
local pos=vec3(rand(1,w),hh/2,rand(-d,-1)) | |
local n=trees.size | |
trees:addRect(0,0,ww,hh) | |
local v=trees:buffer("position") | |
if i==1 then for i=1,6 do print(v[i]) end end | |
for i=n+1,n+6 do v[i]=v[i]+pos end | |
treePos[i]=pos | |
end | |
trees.texture=treeImages[1] | |
trees=SetLighting(trees,TreeShader) | |
trees.shader.mModel=modelMatrix() | |
Terrain={floor=floor,trees=trees} | |
end | |
function LoadImages() | |
treeImages={readImage("Dropbox:3D-tree"),readImage("Dropbox:3D-tree3"),readImage("Dropbox:3D-tree7"), | |
readImage("Dropbox:3D-tree8")} | |
end | |
function DrawTerrain() | |
Terrain.floor.shader.camPos=camPos | |
Terrain.floor:draw() | |
noSmooth() | |
Terrain.trees:draw() | |
smooth() | |
end | |
TreeShader={ | |
v=[[ | |
uniform mat4 modelViewProjection; | |
uniform mat4 mModel; | |
uniform vec4 directColor; | |
uniform vec4 directDirection; | |
uniform vec4 ambientColor; | |
uniform float fog; | |
uniform vec4 mistColor; | |
uniform vec3 camPos; | |
attribute vec4 position; | |
attribute vec3 normal; | |
attribute vec2 texCoord; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
gl_Position = modelViewProjection * position; | |
vTexCoord = texCoord; | |
vec4 norm = normalize(mModel * vec4( normal, 0.0 )); | |
float diffuse = max( 0.0, dot( norm, directDirection )); | |
vec4 p=mModel*position; | |
float f = clamp(distance(p.xyz,camPos)/fog,0.0,1.0); | |
vColor = mix(( diffuse * directColor + ambientColor ),mistColor,f); | |
vColor.a=1.0; | |
} | |
]], | |
f=[[ | |
precision highp float; | |
uniform lowp sampler2D texture; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
vec4 col=texture2D(texture,vTexCoord); | |
if (col.a<.01) discard; | |
else gl_FragColor=col*vColor; | |
} | |
]]} | |
--# Terrain | |
--Terrain | |
function MakeTerrain(pos,width,depth,height,cellSize,smoothness) | |
local ws,ds=width/cellSize,depth/cellSize | |
local grid0={} | |
local rw,rd=math.random(),math.random() | |
for w=0,ws do | |
grid0[w]={} | |
for d=0,ds do | |
local h=height/2*(1+noise(rw+w*smoothness,rd+d*smoothness))-1 | |
grid0[w][d]=vec3(w*cellSize,h,-d*cellSize)+pos | |
end | |
end | |
local grid={} | |
for w=0,ws do | |
grid[w]={} | |
for d=0,ds do | |
grid[w][d]=grid0[w][d] | |
end | |
end | |
for w=1,ws-1 do | |
for d=1,ds-1 do | |
grid[w][d]=(grid0[w][d-1]+grid0[w-1][d]+grid0[w][d+1]+grid0[w+1][d])/8+grid0[w][d]/2 | |
end | |
end | |
--normals are averaged | |
gn={} | |
for w=0,ws do | |
gn[w]={} | |
for d=0,ds do | |
if w==0 or w==ws or d==0 or d==ds then gn[w][d]=vec3(0,1,0) | |
else | |
gn[w][d]=(GetNormal(grid[w][d],grid[w-1][d],grid[w][d-1])+ | |
GetNormal(grid[w][d],grid[w+1][d],grid[w][d-1])+ | |
GetNormal(grid[w][d],grid[w+1][d],grid[w][d+1])+ | |
GetNormal(grid[w][d],grid[w-1][d],grid[w][d+1]))/4 | |
end | |
end | |
end | |
local v,c,n={},{},{} | |
col=color(62, 208, 72, 255) | |
for w=1,ws do | |
for d=1,ds do | |
local v1,v2,v3,v4=grid[w-1][d-1],grid[w][d-1],grid[w][d],grid[w-1][d] | |
local n1,n2,n3,n4=gn[w-1][d-1],gn[w][d-1],gn[w][d],gn[w-1][d] | |
local c1,c2,c3,c4=col,col,col,col | |
v[#v+1]=v1 n[#n+1]=n1 c[#c+1]=c1 | |
v[#v+1]=v2 n[#n+1]=n2 c[#c+1]=c2 | |
v[#v+1]=v3 n[#n+1]=n3 c[#c+1]=c3 | |
v[#v+1]=v3 n[#n+1]=n3 c[#c+1]=c3 | |
v[#v+1]=v4 n[#n+1]=n4 c[#c+1]=c4 | |
v[#v+1]=v1 n[#n+1]=n1 c[#c+1]=c1 | |
end | |
end | |
local m=mesh() | |
m.vertices=v | |
m.normals=n | |
m.colors=c | |
m.shader=shader(LightingShader.v,LightingShader.f) | |
m.shader.directDirection=vec4(0,3,0,0):normalize() | |
m.shader.ambientColor=color(255)*0.3 | |
m.shader.directColor=color(255)*0.7 | |
m.shader.fog=500000 | |
m.shader.mistColor=backgroundColor | |
return m | |
end | |
function GetNormal(v1,v2,v3) | |
local a,b=v1-v3,v2-v3 | |
return (a:cross(b)):normalize() | |
end | |
displayMode(NORMAL) | |
function setup() | |
backgroundColor=color(154, 197, 208, 255) | |
camPos=vec3(0,100,50) | |
camLook=vec3(500,50,-500) | |
camDist,camAngle,deltaAngle=100,0,0.01 | |
terrain=MakeTerrain(vec3(0,0,0),1000,1000,100,10,0.06) | |
ax,ay=0,0 | |
tank=BuildTank(color(150, 189, 128, 255)) | |
end | |
function draw() | |
background(backgroundColor) | |
perspective() | |
camAngle=camAngle+deltaAngle | |
camPos.x,camPos.z=camLook.x+camDist*math.cos(camAngle),camLook.z-camDist*math.sin(camAngle) | |
camera(camPos.x,camPos.y,camPos.z,camLook.x,camLook.y,camLook.z) | |
terrain.shader.mModel=modelMatrix() | |
terrain.shader.camPos=camPos | |
terrain:draw() | |
translate(500,50,-500) | |
for _,t in pairs(tank) do | |
t.shader.mModel=modelMatrix() | |
t.shader.camPos=camPos | |
t:draw() | |
end | |
end | |
--# Utility | |
--Utility | |
function CreateBlock(w,h,d,col,pos,tex,ms) --width,height,depth,colour,position,texture | |
pos=pos or vec3(0,0,0) | |
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(0,1,0),vec3(0,-1,0)} | |
local norm={} | |
for i=1,6 do for j=1,6 do norm[#norm+1]=n[i] end end | |
if not ms then ms=mesh() end | |
if ms.size==0 then | |
ms.vertices=vert | |
ms.normals=norm | |
if tex then ms.texture,ms.texCoords=tex,texCoords end | |
else | |
for i=1,#vert do | |
table.insert(ms.vertices,vert[i]) | |
table.insert(ms.normals,norm[i]) | |
if tex then table.insert(ms.texCoords,texCoords[i]) end | |
end | |
end | |
ms:setColors(col or color(255)) | |
return ms | |
end | |
function AddBlock(w,h,d,col,pos,rot,texture,vertices,texCoords,normals,colors) --width,height,depth,colour,position,texture | |
local x,X,y,Y,z,Z=-w/2,w/2,-h/2,h/2,-d/2,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]} | |
if rot then | |
m=modelMatrix() | |
m=m:translate(pos:unpack()) | |
m=m:rotate(rot.x,1,0,0) m=m:rotate(r.y,0,1,0) m=m:rotate(r.z,0,0,1) | |
for i=1,#vert do vertices[#vertices+1]=m*vert[i] end | |
else | |
for i=1,#vert do vertices[#vertices+1]=pos+vert[i] end | |
end | |
local tex | |
if texture then | |
local t={vec2(0,0),vec2(1,0),vec2(0,1),vec2(1,1)} | |
tex={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]} | |
for i=1,#tex do texCoords[#texCoords+1]=tex[i] end | |
end | |
local n={vec3(0,0,1),vec3(1,0,0),vec3(0,0,-1),vec3(-1,0,0),vec3(0,1,0),vec3(0,-1,0)} | |
for i=1,6 do | |
for j=1,6 do | |
normals[#normals+1]=n[i] | |
colors[#colors+1]=col | |
end | |
end | |
return vertices,texCoords,normals,colors | |
end | |
--# Shaders | |
--Shaders | |
TankShader={ | |
v=[[ | |
uniform mat4 modelViewProjection; | |
uniform mat4 mModel; | |
uniform vec4 directColor; | |
uniform vec4 directDirection; | |
uniform vec4 ambientColor; | |
uniform float offset; | |
attribute vec4 position; | |
attribute vec3 normal; | |
attribute vec2 texCoord; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying highp vec4 vPosition; | |
void main() | |
{ | |
gl_Position = modelViewProjection * position; | |
vTexCoord = vec2(texCoord.x+offset,texCoord.y); | |
vec4 norm = normalize(mModel * vec4( normal, 0.0 )); | |
float diffuse = max( 0.0, dot( norm, directDirection )); | |
vPosition = mModel*position; | |
vColor = diffuse * directColor + ambientColor; | |
} | |
]], | |
f=[[ | |
precision highp float; | |
uniform lowp sampler2D texture; | |
uniform float offset2; | |
uniform vec4 mistColor; | |
uniform float fog; | |
uniform vec3 camPos; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying highp vec4 vPosition; | |
void main() | |
{ | |
vec4 col = texture2D(texture, vec2(mod(vTexCoord.x+offset2,1.0),mod(vTexCoord.y,1.0)))*vColor; | |
float f = clamp(distance(vPosition.xyz,camPos)/fog,0.0,1.0); | |
col = mix( col, mistColor, f); | |
col.a=1.0; | |
gl_FragColor=col; | |
} | |
]]} | |
TreeShader={ | |
v=[[ | |
uniform mat4 modelViewProjection; | |
attribute vec4 position; | |
attribute vec2 texCoord; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
gl_Position = modelViewProjection * position; | |
vTexCoord = texCoord; | |
} | |
]], | |
f=[[ | |
precision highp float; | |
uniform lowp sampler2D texture; | |
uniform vec4 mistColor; | |
uniform float visibility; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
vec4 col = texture2D(texture,vTexCoord); | |
if (col.a<0.05) discard; | |
else { | |
col=mix(mistColor,col,visibility); | |
gl_FragColor=col; | |
} | |
} | |
]]} | |
LightingShader={ | |
v=[[ | |
uniform mat4 modelViewProjection; | |
uniform mat4 mModel; | |
uniform vec4 directColor; | |
uniform vec4 directDirection; | |
uniform vec4 ambientColor; | |
uniform float fog; | |
uniform vec4 mistColor; | |
uniform vec3 camPos; | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec3 normal; | |
varying lowp vec4 vColor; | |
void main() | |
{ | |
gl_Position = modelViewProjection * position; | |
vec4 norm = normalize(mModel * vec4( normal, 0.0 )); | |
float diffuse = max( 0.0, dot( norm, directDirection )); | |
vec4 p=mModel*position; | |
float f = clamp(distance(p.xyz,camPos)/fog,0.0,1.0); | |
vColor = mix(color * ( diffuse * directColor + ambientColor ),mistColor,f); | |
vColor.a=1.0; | |
} | |
]], | |
f=[[ | |
precision highp float; | |
varying lowp vec4 vColor; | |
void main() | |
{ | |
gl_FragColor=vColor; | |
} | |
]]} | |
--Tile | |
TileShader = { | |
v = [[ | |
uniform mat4 modelViewProjection; | |
uniform mat4 mModel; | |
attribute vec4 position; | |
attribute vec2 texCoord; | |
varying highp vec2 vTexCoord; | |
varying highp vec4 vPosition; | |
void main() | |
{ | |
vTexCoord = texCoord; | |
vPosition=mModel*position; | |
gl_Position = modelViewProjection * position; | |
} | |
]], | |
f = [[ | |
precision highp float; | |
uniform lowp sampler2D texture; | |
uniform float fog; | |
uniform vec4 mistColor; | |
uniform vec3 camPos; | |
varying highp vec2 vTexCoord; | |
varying highp vec4 vPosition; | |
void main() | |
{ | |
lowp vec4 col = texture2D(texture, vec2(mod(vTexCoord.x,1.0),mod(vTexCoord.y,1.0))); | |
float f = clamp(distance(vPosition.xyz,camPos)/fog,0.0,1.0); | |
gl_FragColor = mix(col,mistColor,f); | |
} | |
]]} | |
--# Terrain2 | |
--Terrain2 | |
local atan,rand,min,max,cos=math.atan,math.random,math.min,math.max,math.cos | |
local rad=math.pi/180 | |
local Terrain={} | |
function MakeTerrain() | |
local w,d,pic,f=1000,1000,"Dropbox:3D-grass2x",.02 | |
LoadImages() | |
local floor=mesh() | |
local img=readImage(pic) | |
floor.texture=img | |
local wn,dn=w/img.width/f,d/img.height/f | |
floor.vertices={vec3(0,0,0),vec3(w,0,0),vec3(w,0,-d),vec3(w,0,-d),vec3(0,0,-d),vec3(0,0,0)} | |
floor.texCoords={vec2(0,0),vec2(wn,0),vec2(wn,dn),vec2(wn,dn),vec2(0,dn),vec2(0,0)} | |
floor=SetLighting(floor,TileShader) | |
local trees={} | |
for i=1,400 do | |
table.insert(trees,AddBillboard(0,0,w,-d,treeImages,0.15)) | |
end | |
Terrain={floor=floor,trees=trees} | |
end | |
function LoadImages() | |
treeImages={readImage("Dropbox:3D-tree"),readImage("Dropbox:3D-tree3"),readImage("Dropbox:3D-tree7"), | |
readImage("Dropbox:3D-tree8")} | |
end | |
function AddBillboard(x1,z1,x2,z2,imgList,f) | |
local i=rand(1,#imgList) | |
local h=0.5+rand() | |
local w=imgList[i].width*h*f --width | |
local pos=vec3(rand(x1,x2),imgList[i].height*f/4*h,rand(min(z1,z2),max(z1,z2))) | |
local m=mesh() | |
m:addRect(0,0,w,imgList[i].height*h*f) | |
m.texture=imgList[i] | |
m.shader=shader(TreeShader.v,TreeShader.f) | |
m.shader.mistColor=backgroundColor | |
return {m=m,pos=pos,r=w/2} | |
end | |
--[[ | |
function DrawBillboards(billboards) | |
local PM1=projectionMatrix()[1] | |
local lookPos=camPos+(camLook-camPos):normalize()*5000 | |
for _,b in pairs(billboards) do | |
if lineDistB(b.pos,camPos,lookPos)-b.r>camPos:dist(b.pos)/PM1 then b.pov=0 else b.pov=1 end | |
b.visibility=max(0,1-b.pos:dist(camPos)/fogRange) | |
end | |
--calc distance to camera and sort from furthest to nearest, every two seconds | |
if ElapsedTime>(lastSort or -9) +2 then | |
--for _,b in pairs(billboards) do b.visibility=max(0,1-b.pos:dist(camPos)/fogRange) end | |
table.sort(billboards,function(a,b) return a.visibility<b.visibility end) | |
lastSort=ElapsedTime | |
end | |
for i=1,#billboards do | |
local b=billboards[i] | |
if b.visibility*b.pov>0 then | |
pushMatrix() | |
--move to the centre of our image | |
local p=b.pos | |
translate(p:unpack()) | |
--calculate difference in x and z | |
local dx,dz=p.x-camPos.x,-p.z+camPos.z | |
--calculate angle we need to turn | |
local ang=atan(dx/-dz)/rad | |
--turn and draw | |
rotate(ang,0,1,0) --print(i,-ang) | |
b.m.shader.visibility=b.visibility | |
b.m:draw() | |
popMatrix() | |
end | |
end | |
end | |
--]] | |
function DrawTerrain() | |
Terrain.floor.shader.camPos=camPos | |
Terrain.floor:draw() | |
DrawBillboards(Terrain.trees,camPos) | |
end | |
function LookAt(source,target) | |
local z=(source-target):normalize() | |
local x=(vec3(0,1,0):cross(z)):normalize() | |
local y=(z:cross(x)):normalize() | |
return matrix(x.x,x.y,x.z,0, y.x,y.y,y.z,0, z.x,z.y,z.z,0, source.x,source.y,source.z,1) | |
end | |
function GetScreenRect(t1,t2,s) --t1 is camera, t2 is target, s is vec3 size of object | |
--get direction and distance | |
local v=(t2.pos-t1.pos) | |
local d=v:len()-u/2 --position of t2 is assumed to be its centre, so adjust by 1\2 depth | |
v=v/d | |
--get drawing rectangle | |
local w = u*WIDTH*projectionMatrix()[1]/d/2 | |
local h = s.y*HEIGHT*projectionMatrix()[6]/d/2 | |
--draw our tank | |
local m = modelMatrix()*viewMatrix()*projectionMatrix() | |
--m = m:translate(0,0,-d) | |
local X,Y=(m[13]/m[16]+1)*WIDTH/2, (m[14]/m[16]+1)*HEIGHT/2 | |
return X-w/2,Y-h/2,w,h | |
end | |
function DrawBillboards(billboards) | |
local PM1=projectionMatrix()[1] | |
--local lookPos=camPos+(camLook-camPos):normalize()*5000 | |
for _,b in pairs(billboards) do | |
b.pov=IsVisible(b.pos,camPos,camLook,b.r) | |
b.visibility=max(0,1-b.pos:dist(camPos)/fogRange) | |
end | |
--calc distance to camera and sort from furthest to nearest, every two seconds | |
if ElapsedTime>(lastSort or -9) +2 then | |
--for _,b in pairs(billboards) do b.visibility=max(0,1-b.pos:dist(camPos)/fogRange) end | |
table.sort(billboards,function(a,b) return a.visibility<b.visibility end) | |
lastSort=ElapsedTime | |
end | |
for i=1,#billboards do | |
local b=billboards[i] | |
if b.pov and b.visibility>0 then | |
pushMatrix() | |
--move to the centre of our image | |
local p=b.pos | |
translate(p:unpack()) | |
--calculate difference in x and z | |
local dx,dz=p.x-camPos.x,-p.z+camPos.z | |
--calculate angle we need to turn | |
local ang=atan(dx/-dz)/rad | |
--turn and draw | |
rotate(ang,0,1,0) --print(i,-ang) | |
b.m.shader.visibility=b.visibility | |
b.m:draw() | |
popMatrix() | |
end | |
end | |
end | |
function IsVisible(pos,camPos,camLook,radius) | |
local xDist=(pos-camPos):dist(math.max(math.min((pos-camPos):dot(camLook-camPos)/ | |
(camLook-camPos):lenSqr(),1),0)*(camLook-camPos)) | |
return xDist-radius<camPos:dist(pos)/projectionMatrix()[1] | |
end | |
--# Model2 | |
--Model2 | |
Tank=class() | |
Tank.turretMaxAngle=40 | |
Tank.barrelMaxAngles=vec2(-3,20) | |
Tank.width=19 | |
Tank.colors={color(158, 171, 48, 255),color(74, 81, 45, 255)} | |
function Tank:init() | |
if not Tank.model then | |
Tank.LoadTextures() | |
Tank.CreateModel() | |
end | |
self.trackOffset=0 | |
self.turretAngle=0 | |
self.gunAngle=0 | |
self.health=100 | |
self.speed=0.25 | |
self.angle=-90 | |
self.rad=math.rad(self.angle) | |
self.pos=vec3(0,0,0) | |
self.offset2=math.random() | |
end | |
function Tank:draw(camPos,camLook) | |
self.trackOffset=self.trackOffset-self.speed/200 | |
self.pos=self.pos+vec3(math.cos(self.rad),0,math.sin(self.rad))*self.speed | |
if not IsVisible(self.pos,camPos,camLook,Tank.width/2) then return end | |
local m=Tank.model | |
m.track.shader.offset=self.trackOffset | |
pushMatrix() | |
translate(self.pos:unpack()) | |
rotate(self.angle,0,1,0) | |
Tank.Wobble() | |
m.wheels.shader.mModel=modelMatrix() | |
m.wheels.shader.camPos=camPos | |
m.wheels:draw() | |
m.track.shader.mModel=modelMatrix() | |
m.track.shader.camPos=camPos | |
m.track:draw() | |
m.body.shader.mModel=modelMatrix() | |
m.body.shader.camPos=camPos | |
m.body.shader.offset2=self.offset2 | |
m.body:draw() | |
rotate(self.turretAngle,0,1,0) | |
m.turret.shader.mModel=modelMatrix() | |
m.turret.shader.camPos=camPos | |
m.turret.shader.offset2=self.offset2 | |
m.turret:draw() | |
translate(-3.8,5.75,0) | |
rotate(self.gunAngle,0,0,1) | |
m.barrel.shader.mModel=modelMatrix() | |
m.barrel.shader.camPos=camPos | |
m.barrel.shader.offset2=self.offset2 | |
m.barrel:draw() | |
popMatrix() | |
end | |
function Tank:rotate(a) | |
self.angle=self.angle+a | |
self.rad=math.rad(self.angle) | |
end | |
function Tank.Wobble() | |
local f=.1 | |
local a,b=ElapsedTime*f,ElapsedTime*math.pi*f | |
rotate(10*noise(a,b),1,0,0) | |
rotate(3*noise(b,a),0,0,1) | |
end | |
function Tank.LoadTextures() | |
Tank.texBody=readImage("Dropbox:Tank_Body") | |
if not Tank.texBody then | |
local w,h,f=400,400,5 | |
local img1=image(w,h) | |
for i=1,w do | |
for j=1,h do | |
local m=(noise(i/w*f,j/h*f)+1)/2 | |
img1:set(i,j,Tank.colors[1]:mix(Tank.colors[2],m)) | |
end | |
end | |
saveImage("Dropbox:Tank_Body",img1) | |
Tank.texBody=img1 | |
end | |
--Track------- | |
Tank.texTrack=readImage("Dropbox:Tank_Track") | |
if not Tank.texTrack then | |
local img=image(50,5) | |
setContext(img) | |
pushStyle() | |
noSmooth() | |
background(123, 122, 122, 255) | |
stroke(25) | |
strokeWidth(0.5) | |
for i=1,img.width do | |
line(i,0,i,5) | |
end | |
popStyle() | |
setContext() | |
saveImage("Dropbox:Tank_Track",img) | |
Tank.texTrack=img | |
end | |
--Wheel------- | |
Tank.texWheel=readImage("Dropbox:Tank_Wheel") | |
if not Tank.texWheel then | |
img=image(100,10) | |
local col=Tank.colors[1]*2/3+Tank.colors[2]/3 col.a=255 | |
print(col) | |
setContext(img) | |
background(0) | |
pushStyle() | |
noSmooth() | |
fill(col) | |
stroke(Tank.colors[2]) | |
strokeWidth(2) | |
for i=1,4 do | |
ellipse(i*26-11,10,20) | |
end | |
fill(Tank.colors[2]) | |
for i=1,4 do | |
ellipse(i*26-11,10,4) | |
end | |
fill(col) | |
for i=1,3 do | |
ellipse(2+i*26,9,20) | |
end | |
fill(Tank.colors[2]) | |
for i=1,4 do | |
ellipse(2+i*26,9,4) | |
end | |
popStyle() | |
setContext() | |
saveImage("Dropbox:Tank_Wheel",img) | |
Tank.texWheel=img | |
end | |
end | |
function Tank.CreateModel() | |
local x1,x2,x3,y1,y2,y3,z1,z2,z3,z4,f1,f2 | |
--body of tank | |
local body=mesh() | |
local v,t,c={},{},{} | |
x1,x2,y,z1,z2=-8.25,8.25,4.5,3.5,-3.5 --deck | |
v[#v+1]=vec3(x1,y,z1) v[#v+1]=vec3(x2,y,z1) v[#v+1]=vec3(x2,y,z2) | |
v[#v+1]=vec3(x2,y,z2) v[#v+1]=vec3(x1,y,z2) v[#v+1]=vec3(x1,y,z1) | |
x,y1,y2,z1,z2=8.25,2,4.5,3.5,-3.5 --back | |
v[#v+1]=vec3(x,y1,z1) v[#v+1]=vec3(x,y1,z2) v[#v+1]=vec3(x,y2,z2) | |
v[#v+1]=vec3(x,y2,z2) v[#v+1]=vec3(x,y2,z1) v[#v+1]=vec3(x,y1,z1) | |
x1,x2,y1,y2,z1,z2,z3,z4=-11,-8.25,3,4.5,-4.5,4.5,-3.5,3.5 --front #2 angle | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z4) | |
v[#v+1]=vec3(x2,y2,z4) v[#v+1]=vec3(x2,y2,z3) v[#v+1]=vec3(x1,y1,z1) | |
x1,x2,y1,y2,y3,z1,z2=-8.25,8.25,2,2,3.5,4.5,-4.5 --sides | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x2,y3,z1) | |
v[#v+1]=vec3(x2,y3,z1) v[#v+1]=vec3(x1,y3,z1) v[#v+1]=vec3(x1,y1,z1) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x1,y3,z2) | |
v[#v+1]=vec3(x1,y3,z2) v[#v+1]=vec3(x2,y3,z2) v[#v+1]=vec3(x2,y2,z2) | |
x1,x2,y1,y2,z1,z2=-8.25,8.25,3.5,4.5,4.5,3.5 | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x2,y1,z1) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x1,y2,z2) v[#v+1]=vec3(x1,y1,z1) | |
x1,x2,y1,y2,z1,z2=8.25,-8.25,3.5,4.5,-4.5,-3.5 | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x2,y1,z1) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x1,y2,z2) v[#v+1]=vec3(x1,y1,z1) | |
x1,x2,y1,z1,z2=-10,7.25,1,-2.5,2.5 --underneath | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x2,y1,z1) v[#v+1]=vec3(x2,y1,z2) | |
v[#v+1]=vec3(x2,y1,z2) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x1,y1,z1) | |
x,y1,y2,z1,z2=-11,2,3,-4.5,4.5 --front bottom | |
v[#v+1]=vec3(x,y1,z1) v[#v+1]=vec3(x,y1,z2) v[#v+1]=vec3(x,y2,z2) | |
v[#v+1]=vec3(x,y2,z2) v[#v+1]=vec3(x,y2,z1) v[#v+1]=vec3(x,y1,z1) | |
x1,x2,y1,y2,z1,z2=-10,-11,1,2,-2.5,2.5 --front under slant | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
x1,x2,y1,y2,z1,z2=7.25,8.25,1,2,2.5,-2.5 --back under slant | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
x1,x2,x3,y1,y2,y3,z1,z2=-11,-8.25,-8.25,3,2,3.5,4.5,3.5 --fill the cracks | |
v[#v+1]=vec3(x,y1,z1) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x3,y3,z1) | |
z1=-4.5 | |
v[#v+1]=vec3(x,y1,z1) v[#v+1]=vec3(x3,y3,z1) v[#v+1]=vec3(x2,y2,z1) | |
x1,x2,x3,y1,y2,y3,z1=-11,-11,-8.25,3,2,2,4.5 | |
v[#v+1]=vec3(x,y1,z1) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x3,y3,z1) | |
z1=-4.5 | |
v[#v+1]=vec3(x,y1,z1) v[#v+1]=vec3(x3,y3,z1) v[#v+1]=vec3(x2,y2,z1) | |
x1,x2,y1,y2,y3,z1,z2=-11,-8.25,3,3.5,4.5,4.5,3.5 | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x2,y3,z2) | |
v[#v+1]=vec3(x1,y1,-z1) v[#v+1]=vec3(x2,y3,-z2) v[#v+1]=vec3(x2,y2,-z1) | |
x1,y1,y2,z1,z2=8.25,5.5,6.5,3.5,-3.5 | |
x1,y1,y2,z1,z2=8.25,2,3.5,4.5,3.5 | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x1,y2,z2) | |
v[#v+1]=vec3(x1,y2,z2) v[#v+1]=vec3(x1,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
v[#v+1]=vec3(x1,y1,-z1) v[#v+1]=vec3(x1,y2,-z2) v[#v+1]=vec3(x1,y1,-z2) | |
v[#v+1]=vec3(x1,y2,-z2) v[#v+1]=vec3(x1,y1,-z1) v[#v+1]=vec3(x1,y2,-z1) | |
x1,y1,y2,z1,z2=8.25,3.5,4.5,4.5,3.5 | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x1,y2,z2) | |
z1,z2=-3.5,-4.5 | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x1,y2,z1) | |
body.vertices=v | |
body:setColors(color(90)) | |
body.texture=Tank.texBody | |
body.name="body" | |
--tracks | |
local track,v,t=mesh(),{},{} | |
local f=.05 | |
x1,x2,y1,y2,z1,z2,f1,f2=8.25,8.25,1,2,4.5,2.5,0,f*2 --back right vert | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
t[#t+1]=vec2(f1,0) t[#t+1]=vec2(f1,1) t[#t+1]=vec2(f2,1) | |
t[#t+1]=vec2(f2,1) t[#t+1]=vec2(f2,0) t[#t+1]=vec2(f1,0) | |
z1,z2=-2.5,-4.5 --back left vert | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
t[#t+1]=vec2(f1,0) t[#t+1]=vec2(f1,1) t[#t+1]=vec2(f2,1) | |
t[#t+1]=vec2(f2,1) t[#t+1]=vec2(f2,0) t[#t+1]=vec2(f1,0) | |
x1,x2,y1,y2,z1,z2,f1,f2=7.25,8.25,0,1,4.5,2.5,f*2,f*4 --back right slant | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
t[#t+1]=vec2(f1,0) t[#t+1]=vec2(f1,1) t[#t+1]=vec2(f2,1) | |
t[#t+1]=vec2(f2,1) t[#t+1]=vec2(f2,0) t[#t+1]=vec2(f1,0) | |
z1,z2=-2.5,-4.5 --back left slant | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
t[#t+1]=vec2(f1,0) t[#t+1]=vec2(f1,1) t[#t+1]=vec2(f2,1) | |
t[#t+1]=vec2(f2,1) t[#t+1]=vec2(f2,0) t[#t+1]=vec2(f1,0) | |
x1,x2,y1,y2,z1,z2,f1,f2=-9,-11,0,2,2.5,4.5,0,f*2 --front right slant | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
t[#t+1]=vec2(f2,0) t[#t+1]=vec2(f2,1) t[#t+1]=vec2(f1,1) | |
t[#t+1]=vec2(f1,1) t[#t+1]=vec2(f1,0) t[#t+1]=vec2(f2,0) | |
z1,z2=-4.5,-2.5 --front left slant | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y2,z2) | |
v[#v+1]=vec3(x2,y2,z2) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
t[#t+1]=vec2(f2,0) t[#t+1]=vec2(f2,1) t[#t+1]=vec2(f1,1) | |
t[#t+1]=vec2(f1,1) t[#t+1]=vec2(f1,0) t[#t+1]=vec2(f2,0) | |
x1,x2,y1,y2,z1,z2,f1,f2=-9,7.25,0,0,4.5,2.5,4*f,20.25*f --bottom right track | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y1,z2) | |
v[#v+1]=vec3(x2,y1,z2) v[#v+1]=vec3(x2,y1,z1) v[#v+1]=vec3(x1,y1,z1) | |
t[#t+1]=vec2(f1,0) t[#t+1]=vec2(f1,1) t[#t+1]=vec2(f2,1) | |
t[#t+1]=vec2(f2,1) t[#t+1]=vec2(f2,0) t[#t+1]=vec2(f1,0) | |
z1,z2=-2.5,-4.5 --bottom left track | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y1,z2) v[#v+1]=vec3(x2,y1,z2) | |
v[#v+1]=vec3(x2,y1,z2) v[#v+1]=vec3(x2,y1,z1) v[#v+1]=vec3(x1,y1,z1) | |
t[#t+1]=vec2(f1,0) t[#t+1]=vec2(f1,1) t[#t+1]=vec2(f2,1) | |
t[#t+1]=vec2(f2,1) t[#t+1]=vec2(f2,0) t[#t+1]=vec2(f1,0) | |
track.vertices=v | |
track.texCoords=t | |
track:setColors(color(40)) | |
track.texture=Tank.texTrack | |
track.name="track" | |
wheels,v,t=mesh(),{},{} | |
x1,x2,y1,y2,z1=-11,-9,2,0,4 | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x2,y1,z1) | |
x1,x2,y1,y2,z1=-9,7.25,2,0,4 | |
v[#v+1]=vec3(x1,y2,z1) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x2,y1,z1) | |
v[#v+1]=vec3(x2,y1,z1) v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y2,z1) | |
x1,x2,y1,y2,y3,z1=7.25,8.25,0,1,2,4 | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y3,z1) | |
v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x2,y3,z1) v[#v+1]=vec3(x1,y3,z1) | |
x1,x2,y1,y2,z1=-11,-9,2,0,-4 | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x2,y1,z1) v[#v+1]=vec3(x2,y2,z1) | |
x1,x2,y1,y2,z1=-9,7.25,2,0,-4 | |
v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y2,z1) v[#v+1]=vec3(x1,y1,z1) | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x2,y1,z1) v[#v+1]=vec3(x2,y2,z1) | |
x1,x2,y1,y2,y3,z1=7.25,8.25,0,1,2,-4 | |
v[#v+1]=vec3(x1,y1,z1) v[#v+1]=vec3(x1,y3,z1) v[#v+1]=vec3(x2,y2,z1) | |
v[#v+1]=vec3(x2,y2,z1) v[#v+1]=vec3(x1,y3,z1) v[#v+1]=vec3(x2,y3,z1) | |
for i=1,#v/2 do t[#t+1]=vec2((v[i].x+11)/19,v[i].y/2) end | |
for i=#v/2+1,#v do t[#t+1]=vec2(-(8.25-v[i].x)/19,v[i].y/2) end | |
wheels.vertices=v | |
wheels.texCoords=t | |
wheels:setColors(color(255,0,0)) | |
wheels.texture=Tank.texWheel | |
wheels.name="wheels" | |
local turret,v=mesh(),{} | |
local h,y,slope=2.5,4.5,0.5 | |
local p={vec3(-4,0,1.5),vec3(0,0,3.5),vec3(2,0,3),vec3(4,0,1),vec3(4,0,-1), | |
vec3(2,0,-3),vec3(0,0,-3.5),vec3(-4,0,-1.5)} | |
for i=1,#p do p[i].y=y+(p[i].x/8+0.5)*slope end | |
for i=1,#p do | |
local a,b=p[i],p[i+1] or p[1] | |
v[#v+1]=vec3(a.x,y,a.z) | |
v[#v+1]=vec3(b.x,y,b.z) | |
v[#v+1]=vec3(b.x,b.y+h,b.z) | |
v[#v+1]=vec3(b.x,b.y+h,b.z) | |
v[#v+1]=vec3(a.x,a.y+h,a.z) | |
v[#v+1]=vec3(a.x,y,a.z) | |
end | |
local norm={} | |
for i=1,#v do norm[i]=v[i]:normalize() end | |
--roof | |
for i=1,#p do | |
local a,b=p[i],p[i+1] or p[1] | |
v[#v+1]=vec3(a.x,a.y+h,a.z) | |
v[#v+1]=vec3(b.x,b.y+h,b.z) | |
v[#v+1]=vec3(0,y+h+slope/2,0) | |
for j=1,3 do norm[#norm+1]=vec3(0,1,0) end | |
end | |
turret.vertices=v | |
turret.normals=norm | |
turret:setColors(color(90)) | |
turret.texture=Tank.texBody | |
turret.name="turret" | |
barrel,p,v,norm=mesh(),{},{},{} | |
local x1,x2,r1,r2,y=-4,-7,0.75,0.4,7.75 | |
for i=1,8 do p[i]=vec3(0,math.cos(i*math.pi/4),math.sin(i*math.pi/4)) end | |
for i=1,8 do | |
local p1,p2=p[i],p[i+1] or p[1] | |
v[#v+1]=vec3(x1,y+p1.y*r1,p1.z*r1) | |
v[#v+1]=vec3(x2,y+p1.y*r2,p1.z*r2) | |
v[#v+1]=vec3(x2,y+p2.y*r2,p2.z*r2) | |
v[#v+1]=vec3(x2,y+p2.y*r2,p2.z*r2) | |
v[#v+1]=vec3(x1,y+p2.y*r1,p2.z*r1) | |
v[#v+1]=vec3(x1,y+p1.y*r1,p1.z*r1) | |
end | |
local x1,x2,r1,r2,y=-7,-17,0.4,0.3,7.75 | |
for i=1,8 do p[i]=vec3(0,math.cos(i*math.pi/4),math.sin(i*math.pi/4)) end | |
for i=1,8 do | |
local p1,p2=p[i],p[i+1] or p[1] | |
v[#v+1]=vec3(x1,y+p1.y*r1,p1.z*r1) | |
v[#v+1]=vec3(x2,y+p1.y*r2,p1.z*r2) | |
v[#v+1]=vec3(x2,y+p2.y*r2,p2.z*r2) | |
v[#v+1]=vec3(x2,y+p2.y*r2,p2.z*r2) | |
v[#v+1]=vec3(x1,y+p2.y*r1,p2.z*r1) | |
v[#v+1]=vec3(x1,y+p1.y*r1,p1.z*r1) | |
end | |
for i=1,#v do norm[i]=(v[i]-vec3(v[i].x,y,0)):normalize() end | |
for i=1,#v do v[i].x,v[i].y=v[i].x+4,v[i].y-7.75 end | |
barrel.vertices=v | |
barrel.normals=norm | |
barrel:setColors(color(90)) | |
barrel.texture=Tank.texBody | |
barrel.name="barrel" | |
print("vertices=",body.size+track.size+turret.size+barrel.size+wheels.size) | |
local tank={body=body,track=track,turret=turret,barrel=barrel,wheels=wheels} | |
for _,m in pairs(tank) do | |
local norm={} | |
local nn=m:buffer("normal") | |
if nn[1]==nil then | |
local v=m:buffer("position") | |
for i=1,m.size,3 do | |
local v1,v2=v[i]-v[i+2],v[i+1]-v[i+2] | |
local n=(v1:cross(v2)):normalize() | |
norm[i],norm[i+1],norm[i+2]=n,n,n | |
end | |
m.normals=norm | |
end | |
if m.texture==Tank.texBody then | |
local t={} | |
local v=m:buffer("position") | |
for i=1,m.size do | |
t[i]=vec2(v[i].x/8+v[i].y/5,v[i].z/6+v[i].y/9)/2 | |
end | |
m.texCoords=t | |
end | |
m=SetLighting(m) | |
m.shader.offset2=0 | |
end | |
Tank.model=tank | |
end | |
--# Main | |
-- Tiger | |
displayMode(FULLSCREEN) | |
function setup() | |
backgroundColor=color(129, 162, 201, 255) | |
T=Tank() | |
T.speed=0 | |
camPos=vec3(0,10,30) | |
ax,ay=0,0 | |
da=0.1 | |
end | |
function draw() | |
background(backgroundColor) | |
perspective() | |
camera(camPos.x,camPos.y,camPos.z,0,0,0) | |
rotate(ay,0,1,0) rotate(ax,1,0,0) | |
--T.turretAngle=T.turretAngle+0.5 | |
--T.gunAngle=T.gunAngle-da | |
--if -T.gunAngle<T.turretMaxAngles[1] or -T.gunAngle>T.turretMaxAngles[2] then da=-da end | |
T:draw(camPos) | |
end | |
function touched(t) | |
if t.state~=ENDED then | |
ay,ax=ay+t.deltaX,ax+t.deltaY | |
end | |
end | |
function SetLighting(m,s) | |
local s=s or TankShader | |
m.shader=shader(s.v,s.f) | |
m.shader.directDirection=vec4(-1,1,1,0):normalize() | |
m.shader.ambientColor=color(255)*0.3 | |
m.shader.directColor=color(255)*0.7 | |
m.shader.fog=5000 | |
m.shader.mistColor=backgroundColor | |
m.shader.offset=0 | |
return m | |
end | |
--# Main2 | |
-- Tiger2 | |
displayMode(FULLSCREEN) | |
function setup() | |
backgroundColor=color(255) | |
fogRange=5000 | |
FOV=45 | |
-- angleFOV=math.cos(math.rad(FOV/2*WIDTH/HEIGHT)) | |
T={} | |
for j=1,20 do | |
T[j]=Tank() | |
T[j].pos=vec3(500+math.random(-40,40),0.5,-900+j*40) | |
T[j].turretAngle=0 | |
T[j]:rotate(180) | |
T[j].turretAngle=math.random(-35,35) | |
T[j].gunAngle=math.random(0,5) | |
T[j].turretAngleChange=0.25 | |
T[j].gunAngleChange=0.1 | |
end | |
camPos=vec3(500,10,-200) | |
camLook=vec3(0,0,0) | |
camAngle=math.pi/2 | |
speed=0 | |
maxSpeed=1 | |
FPS=60 | |
MakeTerrain() | |
joy=JoyStick({damp=nil}) | |
end | |
function draw() | |
background(backgroundColor) | |
FPS=FPS*0.9+0.1/DeltaTime | |
perspective(FOV) | |
local d=joy:update() | |
camAngle=camAngle-d.x/60 | |
speed=d.y/2 | |
local v=vec3(math.cos(camAngle),0,-math.sin(camAngle)) | |
camPos=camPos+v*speed | |
camLook=camPos+v*5000 | |
camera(camPos.x,camPos.y,camPos.z,camLook.x,camLook.y,camLook.z) | |
for _,t in pairs(T) do | |
a=t.turretAngle+t.turretAngleChange | |
if math.abs(a)>Tank.turretMaxAngle then t.turretAngleChange=-t.turretAngleChange end | |
t.turretAngle=t.turretAngle+t.turretAngleChange | |
local a=t.gunAngle+t.gunAngleChange | |
if -a<Tank.barrelMaxAngles[1] or -a>Tank.barrelMaxAngles[2] then | |
t.gunAngleChange=-t.gunAngleChange | |
end | |
t.gunAngle=t.gunAngle+t.gunAngleChange | |
t:draw(camPos,camLook) | |
end | |
DrawTerrain(camPos) | |
joy:draw() | |
ortho() | |
viewMatrix(matrix()) | |
fill(0) | |
fontSize(18) | |
text("FPS: "..math.floor(FPS),50,50) | |
end | |
function SetLighting(m,s) | |
s=s or TankShader | |
m.shader=shader(s.v,s.f) | |
m.shader.directDirection=vec4(-2,2,1,0):normalize() | |
m.shader.ambientColor=color(255)*0.5 | |
m.shader.directColor=color(255)*0.5 | |
m.shader.fog=fogRange | |
m.shader.mistColor=backgroundColor | |
m.shader.offset=0 | |
m.shader.mModel=modelMatrix() | |
return m | |
end | |
function touched(t) | |
--if t.state~=ENDED then | |
-- camAngle=camAngle+t.deltaX/300 | |
--end | |
joyTouched=joy:touched(t) | |
end | |
--# Controls | |
--joystick | |
JoyStick = class() | |
local tick=1/60 | |
--Note all the options you can set below. Pass them through in a named table | |
function JoyStick:init(t) | |
t = t or {} | |
self.radius = t.radius or 100 --size of joystick on screen | |
self.stick = t.stick or 30 --size of inner circle | |
self.centre = t.centre or self.radius * vec2(1,1) + vec2(5,5) | |
self.damp=nil | |
self.position = vec2(0,0) --initial position of inner circle | |
self.target = vec2(0,0) --current position of inner circle (used when we interpolate movement) | |
self.value = vec2(0,0) | |
self.delta = vec2(0,0) | |
self.mspeed = 30 | |
self.moving = 0 | |
end | |
function JoyStick:draw() | |
ortho() | |
viewMatrix(matrix()) | |
pushStyle() | |
fill(160, 182, 191, 1) | |
stroke(118, 154, 195, 100) stroke(0,0,0,25) | |
strokeWidth(3) | |
ellipse(self.centre.x,self.centre.y,2*self.radius) | |
fill(78, 131, 153, 1) | |
ellipse(self.centre.x+self.position.x, self.centre.y+self.position.y, self.stick*2) | |
popStyle() | |
end | |
function JoyStick:touched(t) | |
if t.state == BEGAN then | |
local v = vec2(t.x,t.y) | |
if v:dist(self.centre)<self.radius-self.stick then | |
self.touch = t.id | |
--else return false | |
end | |
end | |
if t.id == self.touch then | |
if t.state~=ENDED then | |
local v = vec2(t.x,t.y) | |
if v:dist(self.centre)>self.radius-self.stick then | |
v = (v - self.centre):normalize()*(self.radius - self.stick) + self.centre | |
end --set x,y values for joy based on touch | |
self.target=v - self.centre | |
else --reset joystick to centre when touch ends | |
self.target=vec2(0,0) | |
self.touch = false | |
end | |
else return false | |
end | |
return true | |
end | |
function JoyStick:update() | |
local p = self.target - self.position | |
if p:len() < tick * self.mspeed then | |
self.position = self.target | |
if not self.touch then | |
if self.moving ~= 0 then | |
self.moving = self.moving - 1 | |
end | |
else | |
self.moving = 2 | |
end | |
else | |
self.position = self.position + p:normalize() * tick * self.mspeed | |
self.moving = 2 | |
end | |
local v=self.position/(self.radius - self.stick) | |
return self:Dampen(v) | |
end | |
function JoyStick:Dampen(v) | |
if not self.damp then return v end | |
if v.x>0 then v.x=math.max(0,(v.x-self.damp.x)/(1-self.damp.x)) | |
else v.x=math.min(0,(v.x+self.damp.x)/(1-self.damp.x)) end | |
if v.y>0 then v.y=math.max(0,(v.y-self.damp.y)/(1-self.damp.y)) | |
else v.y=math.min(0,(v.y+self.damp.y)/(1-self.damp.y)) end | |
return v | |
end | |
function JoyStick:isMoving() | |
return self.moving | |
end | |
function JoyStick:isTouched() | |
return self.touch | |
end | |
--# Test8 | |
--[[ | |
function setup() | |
perspective() | |
camPos=vec3(100,0,-50) print("camPos",camPos) | |
look=vec3(0,0,-1) print("look",look) | |
pos=vec3(-200,0,-1000) print("pos",pos) | |
r=25 print("r",r) | |
d=camPos:dist(pos) print("d",d) | |
local lookX=camPos.x+look.x*d print("lookX",lookX) | |
local limit=d/2/projectionMatrix()[1] print("PM1",projectionMatrix()[1]) print("limit",limit) | |
local treeDir=(pos-camPos):normalize() print("treeDir",treeDir) | |
local treeWidth=treeDir.z*r print("treeWidth",treeWidth) | |
local x0=pos.x print("x0",x0) | |
local x1,x2=x0-treeWidth,x0+treeWidth print("x1",x1) print("x2",x2) | |
print("<x0",math.abs(lookX-x0)) | |
print("<x1",math.abs(lookX-x1)) | |
print("<x2",math.abs(lookX-x2)) | |
end | |
function draw() | |
background(0) | |
--sprite(img1,300,300) | |
end | |
--]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment