You can support the development on the Github Sponsors page.


Tools > AXES - 3D LUA LIBRARY


3d lua library
made by @j1m4k1
uploaded by jimaki
added:
download cartridge
- CLICK TO PLAY -

12


AXES - 3D Lua Library
AXES is an easily portable 3D Lua library made specifically but not implicitly for fantasy consoles such as TIC-80.
Created by @J1M4K1 (github.com/jimaki/AXES)
Buy the normal (not minified) source code for 4.99$ on Gumroad here: gum.co/AXESengine

Comments


SgtGigz

stupid you think you can charge for this...not what Tic-80 stands for...

kahdeg

axes=
{
_calculate_radius=function(l,m)
local n=l._objects[m]
local o={}
for q=1,#n.shape do c=n.shape[q]for r=1,#c do d=c[r]for s=1,3 do o[#o+1]=d[s]-n.position[s]end end end o=l:_quicksort(o,'des')
local p=o[1]+0.5 return p end,create_object=function(l,m,n,o,p,q,r,s,t,u)
local v=l:_deepcopy(n)
local w,x,y,z,A,B,C=o or{0,0,0},p or false,q or false,r or 4,s or 1,t or{0,0,0},u or false local D={shape=v,position={0,0,0},wireframe=x,fill=y,color=z,scale=1,rotation={0,0,0},solid=C}
l._objects[m]=D l:set_scale(m,A)
l:set_rotation(m,B)
l:set_position(m,w)
local E=l:_calculate_radius(m)
l._objects[m].radius=E end,_debug_mode=function(l)
print('FPS:'..l:_get_fps(),1,1,4)
end,_deepcopy=function(l,m)
local n={}
if type(m)=='table'
then for o,p in next,m,nil do n[l:_deepcopy(o)]=l:_deepcopy(p)
end setmetatable(n,l:_deepcopy(getmetatable(m)))
else n=m end return n end,delete_object=function(l,m)
l._objects[m]=nil end,draw_line=function(l,m,n,o)
local p=o or 4 local q=l:_shift(m)
local r=l:_shift(n)
if(not q[4])
and(not r[4])
then return end if(not q[4])
or(not r[4])
then if not q[4]then local y,z,A,B A=0.01 B=(A-r[3])/(q[3]-r[3])
y=r[1]+(q[1]-r[1])*B z=r[2]+(q[2]-r[2])*B q={y,z,A}
end if not r[4]then local y,z,A,B A=0.01 B=(A-q[3])/(r[3]-q[3])
y=q[1]+(r[1]-q[1])*B z=q[2]+(r[2]-q[2])*B r={y,z,A}
end end q[4]=true r[4]=true local s,t,u=l:_project(q)
local v,w,x=l:_project(r)
line(s,t,v,w,p)
end,_draw_object=function(l,m,n,o,p,q,r,s)
e={}
for t=1,#m do local u=m[t]local v={}
for w=1,#u do d=u[w]local x,y,z=d[1]-l._cam.x,d[2]-l._cam.y,d[3]-l._cam.z local A=(-l._cam.cos_x*l._cam.sin_y*l._cam.cos_z+l._cam.sin_x*l._cam.sin_z)*x+(l._cam.cos_x*l._cam.sin_y*l._cam.sin_z+l._cam.sin_x*l._cam.cos_z)*y+l._cam.cos_x*l._cam.cos_y*z v[#v+1]=A end v=l:_quicksort(v,'des')
u.dz=(v[1]+v[#v])/2 e[#e+1]=u.dz end e=l:_quicksort(e,'des')
for t=1,#e do for u=1,#m do local v=m[u]if v.dz==e[t]then if type(q)=='table'
then q=q[u]end if p then l:_fill_polygon(v,q)
if q==0 then f=3 end if q==1 then f=6 end if q==2 then f=8 end if q==3 then f=10 end if q==4 then f=9 end if q==5 then f=11 end if q==6 then f=1 end if q==7 then f=3 end if q==8 then f=2 end if q==9 then f=4 end if q==10 then f=3 end if q==11 then f=5 end if q==12 then f=4 end if q==13 then f=8 end if q==14 then f=9 end if q==15 then f=10 end else f=q end if o then for w=1,#v do if w==#v then l:draw_line(v[#v],v[1],f)
else l:draw_line(v[w],v[w+1],f)
end end end end end end end,draw_point=function(l,m,n)
local o=n or 4 local p,q,r=l:_project(l:_shift(m))
if r then point(p,q,o)
end end,_fill_polygon=function(l,m,n)
local o={}
for p=1,#m do local q,r,s=l:_project(l:_shift(m[p]))
if not s then return end table.insert(o,{q,r})
end for p=1,#o-2 do local q,r,s=o[1],o[p+1],o[p+2]tri(q[1],q[2],r[1],r[2],s[1],s[2],n)
end end,_get_fps=function(l)
if time()-l._fps.last_time<=1000 then l._fps.frames=l._fps.frames+1 else l._fps.value=l._fps.frames l._fps.frames=0 l._fps.last_time=time()
end return l._fps.value end,init=function(l)
local m,n,o,p=1/(2*math.sqrt(2))*2,1/(2*((1+math.sqrt(5))/2))*2,2-((1+math.sqrt(5))/2),1/((1+math.sqrt(5))/2)
local q=l or{}
local r={_cam={x=q._cam_x or 0,y=q._cam_y or 2,z=q._cam_z or-10,theta_x=math.rad(q._cam_theta_x or 0),theta_y=math.rad(q._cam_theta_y or 0),theta_z=math.rad(q._cam_theta_z or 0),fov=q._cam_fov or math.pi,sin_x=0,sin_y=0,sin_z=0,cos_x=0,cos_y=0,cos_z=0},create_object=axes.create_object,debug=false,delete_object=axes.delete_object,draw_line=axes.draw_line,draw_point=axes.draw_point,get_cam=axes.set_cam,get_color=axes.get_color,get_fill=axes.get_fill,get_position=axes.get_position,get_rotation=axes.get_rotation,get_scale=axes.get_scale,get_solid=axes.get_solid,get_wireframe=axes.get_wireframe,move_cam=axes.move_cam,set_cam=axes.set_cam,set_color=axes.set_color,set_fill=axes.set_fill,set_position=axes.set_position,set_rotation=axes.set_rotation,set_scale=axes.set_scale,set_solid=axes.set_solid,set_wireframe=axes.set_wireframe,update=axes.update,_calculate_radius=axes._calculate_radius,_debug_mode=axes._debug_mode,_deepcopy=axes._deepcopy,_draw_object=axes._draw_object,_fill_polygon=axes._fill_polygon,_fps={value=0,frames=0,last_time=-1000},_get_fps=axes._get_fps,_polyfill=axes._polyfill,_project=axes._project,_quicksort=axes._quicksort,_round=axes._round,_screen_height=q.screen_height or 128,_screen_width=q.screen_width or 128,_shift=axes._shift,_objects={},shapes={tetrahedron={{{1,1,1},{-1,1,-1},{1,-1,-1}},{{-1,1,-1},{-1,-1,1},{1,-1,-1}},{{1,1,1},{1,-1,-1},{-1,-1,1}},{{1,1,1},{-1,-1,1},{-1,1,-1}}},octahedron={{{-m,0,m},{-m,0,-m},{0,1,0}},{{-m,0,-m},{m,0,-m},{0,1,0}},{{m,0,-m},{m,0,m},{0,1,0}},{{m,0,m},{-m,0,m},{0,1,0}},{{m,0,-m},{-m,0,-m},{0,-1,0}},{{-m,0,-m},{-m,0,m},{0,-1,0}},{{m,0,m},{m,0,-m},{0,-1,0}},{{-m,0,m},{m,0,m},{0,-1,0}}},cube={{{-1,-1,-1},{1,-1,-1},{1,-1,1},{-1,-1,1}},{{-1,-1,-1},{-1,-1,1},{-1,1,1},{-1,1,-1}},{{-1,-1,1},{1,-1,1},{1,1,1},{-1,1,1}},{{-1,1,-1},{-1,1,1},{1,1,1},{1,1,-1}},{{1,-1,-1},{1,1,-1},{1,1,1},{1,-1,1}},{{-1,-1,-1},{-1,1,-1},{1,1,-1},{1,-1,-1}}},icosahedron={{{0,n,-1},{n,1,0},{-n,1,0}},{{0,n,1},{-n,1,0},{n,1,0}},{{0,n,1},{0,-n,1},{-1,0,n}},{{0,n,1},{1,0,n},{0,-n,1}},{{0,n,-1},{0,-n,-1},{1,0,-n}},{{0,n,-1},{-1,0,-n},{0,-n,-1}},{{0,-n,1},{n,-1,0},{-n,-1,0}},{{0,-n,-1},{-n,-1,0},{n,-1,0}},{{-n,1,0},{-1,0,n},{-1,0,-n}},{{-n,-1,0},{-1,0,-n},{-1,0,n}},{{n,1,0},{1,0,-n},{1,0,n}},{{n,-1,0},{1,0,n},{1,0,-n}},{{0,n,1},{-1,0,n},{-n,1,0}},{{0,n,1},{n,1,0},{1,0,n}},{{0,n,-1},{-n,1,0},{-1,0,-n}},{{0,n,-1},{1,0,-n},{n,1,0}},{{0,-n,-1},{-1,0,-n},{-n,-1,0}},{{0,-n,-1},{n,-1,0},{1,0,-n}},{{0,-n,1},{-n,-1,0},{-1,0,n}},{{0,-n,1},{1,0,n},{n,-1,0}}},dodecahedron={{{o,0,1},{-o,0,1},{-p,p,p},{0,1,o},{p,p,p}},{{-o,0,1},{o,0,1},{p,-p,p},{0,-1,o},{-p,-p,p}},{{o,0,-1},{-o,0,-1},{-p,-p,-p},{0,-1,-o},{p,-p,-p}},{{-o,0,-1},{o,0,-1},{p,p,-p},{0,1,-o},{-p,p,-p}},{{0,1,-o},{0,1,o},{p,p,p},{1,o,0},{p,p,-p}},{{0,1,o},{0,1,-o},{-p,p,-p},{-1,o,0},{-p,p,p}},{{0,-1,-o},{0,-1,o},{-p,-p,p},{-1,-o,0},{-p,-p,-p}},{{0,-1,o},{0,-1,-o},{p,-p,-p},{1,-o,0},{p,-p,p}},{{1,o,0},{1,-o,0},{p,-p,p},{o,0,1},{p,p,p}},{{1,-o,0},{1,o,0},{p,p,-p},{o,0,-1},{p,-p,-p}},{{-1,o,0},{-1,-o,0},{-p,-p,-p},{-o,0,-1},{-p,p,-p}},{{-1,-o,0},{-1,o,0},{-p,p,p},{-o,0,1},{-p,-p,p}}},pyramid={{{1,-1,1},{1,-1,-1},{-1,-1,-1},{-1,-1,1}},{{1,-1,-1},{1,-1,1},{0,1,0}},{{1,-1,1},{-1,-1,1},{0,1,0}},{{-1,-1,1},{-1,-1,-1},{0,1,0}},{{1,-1,-1},{-1,-1,-1},{0,1,0}}}}}
return r end,get_cam=function(l)
return{l._cam.x,l._cam.y,l._cam.z,l._cam.theta_x,l._cam.theta_y,l._cam.theta_z}
end,get_color=function(l,m)
return l._objects[m].color end,get_fill=function(l,m)
return l._objects[m].fill end,get_position=function(l,m)
return l._objects[m].position end,get_rotation=function(l,m)
return l._objects[m].rotation end,get_scale=function(l,m)
return l._objects[m].scale end,get_solid=function(l,m)
return l._objects[m].solid end,get_wireframe=function(l,m)
return l._objects[m].wireframe end,move_cam=function(l,m,n,o,p,q,r)
local s,t,u,v,w,x=m or 0,n or 0,o or 0,p or 0,q or 0,r or 0 l._cam.theta_x=l._cam.theta_x+v l._cam.theta_y=l._cam.theta_y+w l._cam.theta_z=l._cam.theta_z+x for y,z in pairs(l._objects)
do if z.solid then local A,B,C=math.abs(z.position[1]-l._cam.x-s),math.abs(z.position[2]-l._cam.y-t),math.abs(z.position[3]-l._cam.z-u)
local D=math.sqrt(math.pow(A,2)+math.pow(B,2)+math.pow(C,2))-z.radius if D<0 then return end end end l._cam.x=l._cam.x+s l._cam.y=l._cam.y+t l._cam.z=l._cam.z+u end,_polyfill=function(l,m,n)
local o,p,q,r,s,t local u={}
local v,w=l._screen_height,0 for x=1,#m do o=m[x]if o[2]<v then v=o[2]end if o[2]>w then w=o[2]end end for x=v,w do p=#m q=0 for y=1,#m do o=m[y]r=m[p]if o[2]<x and r[2]>=x or r[2]<x and o[2]>=x then q=q+1 u[q]=l:_round((o[1]+(x-o[2])/(r[2]-o[2])*(r[1]-o[1])))
end p=y end s=1 while s<q do if u[s]>u[s+1]then t=u[s]u[s]=u[s+1]u[s+1]=t if s>1 then s=s-1 end else s=s+1 end end for y=1,q-1,2 do if u[y]>=l._screen_width then break end if u[y+1]>0 then if u[y]<0 then u[y]=-1 end if u[y+1]>l._screen_width then u[y+1]=l._screen_width end line(u[y],x,u[y]+u[y+1]-u[y],x,n)
end end end end,_shift=function(l,m)

local n,o,p=m[1],m[2],m[3]local q,r,s=n-l._cam.x,o-l._cam.y,p-l._cam.z local t,u,v=l._cam.sin_x,l._cam.sin_y,l._cam.sin_z local w,x,y=l._cam.cos_x,l._cam.cos_y,l._cam.cos_z local z,A,B z=x*y*q-x*v*r+u*s A=(t*u*y+w*v)*q+(-t*u*v+w*y)*r-t*x*s B=(-w*u*y+t*v)*q+(w*u*v+t*y)*r+w*x*s if B>0 then g=true else g=false end return{z,A,B,g}
end,_project=function(l,m)

local n,o,p,q=m[1],m[2],m[3],m[4]if not q then return 0,0,false end if l._screen_width>l._screen_height then h=l._screen_width/4 else h=l._screen_height/4 end local r,s,t=2,1.25,l._cam.fov i=l:_round(((t/p)*n+r)*h)
j=l:_round((-(t/p)*o+s)*h)
return i,j,true end,_quicksort=function(l,m,n,o,p)
o=o or 1 p=p or#m if o<p then local q=m local r,s=q[p],o-1 for u=o,p-1 do if n=='asc'
then if q[u]<=r then s=s+1 local v=q[s]q[s]=q[u]q[u]=v end elseif n=='des'
then if q[u]>=r then s=s+1 local v=q[s]q[s]=q[u]q[u]=v end end end local t=q[s+1]q[s+1]=q[p]q[p]=t k=s+1 l:_quicksort(m,n,o,k-1)
l:_quicksort(m,n,k+1,p)
end return m end,_round=function(l,m)
return math.floor(m+0.5)
end,set_cam=function(l,m,n,o,p,q,r)

local s,t,u,v,w,x=m or l._cam.x,n or l._cam.y,o or l._cam.z,p or l._cam.theta_x,q or l._cam.theta_y,r or l._cam.theta_z l._cam.x=s l._cam.y=t l._cam.z=u l._cam.theta_x=v l._cam.theta_y=w l._cam.theta_z=x end,set_color=function(l,m,n)
local o=l._objects[m]local p=n or o.color o.color=p end,set_fill=function(l,m,n)
local o=l._objects[m]local p=n or o.fill o.fill=p end,set_position=function(l,m,n)
local o=l._objects[m]local p=n or o.position if p==o.position then return end local q={}
for r=1,3 do q[r]=p[r]-o.position[r]end o.position=p for r=1,#o.shape do local s=o.shape[r]for t=1,#s do d=s[t]for u=1,3 do d[u]=d[u]+q[u]end end end end,set_rotation=function(l,m,n)
local o=l._objects[m]local p=n or o.rotation if p==o.rotation then return end local q={}
for r=1,3 do q[r]=p[r]-o.rotation[r]end o.rotation=p for r=1,#o.shape do local s=o.shape[r]for t=1,#s do local u=s[t]local v=o.position local w,x,y=u[1],u[2],u[3]local z,A,B=w-v[1],x-v[2],y-v[3]local C,D,E=math.sin(math.rad(q[1])),math.sin(math.rad(q[2])),math.sin(math.rad(q[3]))
local F,G,H=math.cos(math.rad(q[1])),math.cos(math.rad(q[2])),math.cos(math.rad(q[3]))
local I,J,K I=G*H*z-G*E*A+D*B J=(C*D*H+F*E)*z+(-C*D*E+F*H)*A-C*G*B K=(-F*D*H+C*E)*z+(F*D*E+C*H)*A+F*G*B o.shape[r][t]={I+v[1],J+v[2],K+v[3]}
end end end,set_scale=function(l,m,n)
local o=l._objects[m]local p=n or o.scale if p==o.scale then return end local q=p/o.scale o.scale=p for r=1,#o.shape do c=o.shape[r]for s=1,#c do d=c[s]for t=1,3 do d[t]=(d[t]-o.position[t])*q+o.position[t]end end end end,set_solid=function(l,m,n)
local o=l._objects[m]local p=n or o.solid o.solid=p end,set_wireframe=function(l,m,n)
local o=l._objects[m]local p=n or o.wireframe o.wireframe=p end,update=function(l,m)
local n,o,p,q,r,s=0.125,0.125,0.125,0.02,0.02,0.02 if m=='plane'
then if btn(2)
then a:move_cam(-n*math.cos(l._cam.theta_y),0,-p*math.sin(l._cam.theta_y),0,0,0)
end if btn(3)
then a:move_cam(n*math.cos(l._cam.theta_y),0,p*math.sin(l._cam.theta_y),0,0,0)
end if btn(0)
then a:move_cam(-n*math.sin(l._cam.theta_y),0,p*math.cos(l._cam.theta_y),0,0,0)
end if btn(1)
then a:move_cam(n*math.sin(l._cam.theta_y),0,-p*math.cos(l._cam.theta_y),0,0,0)
end if btn(4)
then a:move_cam(0,0,0,0,r,0)
end if btn(5)
then a:move_cam(0,0,0,0,-r,0)
end elseif m=='free'
then if btn(2)
then a:move_cam(0,0,0,0,r,0)
end if btn(3)
then a:move_cam(0,0,0,0,-r,0)
end if btn(0)
then a:move_cam(0,0,0,q,0,0)
end if btn(1)
then a:move_cam(0,0,0,-q,0,0)
end if btn(4)
then a:move_cam(n*math.sin(l._cam.theta_y),-o*math.sin(l._cam.theta_x),-p*math.cos(l._cam.theta_y),0,0,0)
end if btn(5)
then a:move_cam(-n*math.sin(l._cam.theta_y),o*math.sin(l._cam.theta_x),p*math.cos(l._cam.theta_y),0,0,0)
end elseif m=='centered'
then if btn(2)
then a:move_cam(0,0,0,0,0,0)
end if btn(3)
then a:move_cam(0,0,0,0,0,0)
end if btn(0)
then a:move_cam(0,0,0,0,0,0)
end if btn(1)
then a:move_cam(0,0,0,0,0,0)
end if btn(4)
then a:move_cam(0,0,0,0,0,0)
end if btn(5)
then a:move_cam(0,0,0,0,0,0)
end end l._cam.sin_x,l._cam.sin_y,l._cam.sin_z=math.sin(l._cam.theta_x),math.sin(l._cam.theta_y),math.sin(l._cam.theta_z)
l._cam.cos_x,l._cam.cos_y,l._cam.cos_z=math.cos(l._cam.theta_x),math.cos(l._cam.theta_y),math.cos(l._cam.theta_z)

local t={}
for u,v in pairs(l._objects)
do local w,x,y=v.position[1]-l._cam.x,v.position[2]-l._cam.y,v.position[3]-l._cam.z local z,A,B=l._cam.sin_x,l._cam.sin_y,l._cam.sin_z local C,D,E=l._cam.cos_x,l._cam.cos_y,l._cam.cos_z v.dz=(-C*A*E+z*B)*w+(C*A*B+z*E)*x+C*D*y table.insert(t,v.dz)
end t=l:_quicksort(t,'des')
for u=1,#t do for v,w in pairs(l._objects)
do
if w.dz==t[u]then l:_draw_object(w.shape,w.position,w.wireframe,w.fill,w.color,w.scale,w.rotation)
end end end if l.debug then l:_debug_mode()
end end
}



Clikpb

@SgtGigz This isn't just a TIC80 project, the thing you have to pay for is the source code, NOT the program.

atesin

i am sure there are better lua/tic80 3d libs, AND FOSS

vurpo

FOSS is not against paying for software


Post comment