Skip to content

Instantly share code, notes, and snippets.

@Powersaurus
Created June 11, 2021 14:44
Show Gist options
  • Save Powersaurus/e8c2e07b0e9c5f3c0863a38c6f87db55 to your computer and use it in GitHub Desktop.
Save Powersaurus/e8c2e07b0e9c5f3c0863a38c6f87db55 to your computer and use it in GitHub Desktop.
Slowly working my way towards perspective correct 3D dots - references https://lodev.org/cgtutor/raycasting3.html
function init_palette()
--pal()
pal(2,141,1)
pal(7,135,1)
pal(8,137,1)
pal(10,140,1)
pal(11,138,1)
pal(12,134,1)
pal(14,131,1)
pal(15,133,1)
poke(0x5f2e,1)
end
function _init()
init_palette()
a=0.25
pt={}
-- starting dir
-- -1 0 1
-- -1 * o * g
-- 0 /\
-- 1 * r * b
-- add(pt,point(-1,0,1,8))--red
-- add(pt,point(1,0,-1,3))--green
-- add(pt,point(1,0,1,10))--blue
add(pt,point(-1,0,-1,9))--orange
--[[for x=-1,1,1/3 do
for y=-1,1,1/3 do
for z=-1,1,1/3 do
add(pt,point(x,y,z))
end
end
end--]]
cam={}
cam.x,cam.z,
cam.drx,cam.drz,
cam.cx,cam.cz=
0,0,
0,-1,
0,1
mode=0
end
function point(x,y,z,c)
local p={}
p.x,p.y,p.z=x,y,z
p.col=c or 8+(x*3+y*2)%8
return p
end
function _update()
local da=0
if(btn(0))da+=0.009
if(btn(1))da-=0.009
a+=da
local old_camcx,old_plane_x=
0,cam.cx
cam.drx,cam.drz=
cos(a),sin(a)
cam.cx,cam.cz=
old_plane_x*cos(da)
+cam.cz*sin(da),
old_plane_x*sin(da)
+cam.cz*cos(da)
printh(cam.drx..","..cam.drz.." "..cam.cx..","..cam.cz)
if btn(2) then
cam.z+=cam.drz/8
cam.x+=cam.drx/8
end
if btn(3) then
cam.z-=cam.drz/8
cam.x-=cam.drx/8
end
if btnp(4) then
mode=(mode+1)%4
end
if(a>1)a-=1
if(a<0)a+=1
end
modes={
[0]="2d, no rotation",
"2d with rotation",
"3d projected",
"perspective correct"
}
function _draw()
cls(0)
--a=0.3622
if mode==0 then
draw_2d_no_rot()
elseif mode==1 then
draw_2d()
else
draw_3d()
end
print("x= cos("..a..
")="..cos(a),0,0,7)
print("y= sin("..a..")="..-sin(a),0,6,7)
print("mode: "..modes[mode],0,122)
end
function draw_2d_no_rot()
local lxe,lye=
64+cos(a)*8,
64+sin(a)*8
line(64,64,lxe,lye,13)
local nxe,nye=
64-sin(a)*8,
64+cos(a)*8
line(64,64,nxe,nye,9)
pset(64,64,7)
for p in all(pt) do
pset(
64+(p.x+cam.x)*8,
64+(p.z+cam.z)*8,p.col)
end
end
function draw_2d()
line(64,64,64,56,13)
line(64,64,72,64,9)
pset(64,64,7)
local yaw=a
for p in all(pt) do
local wx=(p.x-cam.x)*8
local wz=(p.z-cam.z)*8
local tr_x,tr_z=
rot(wx,wz,a)
pset(64-tr_x,64-tr_z,p.col)
end
end
function draw_3d()
project(pt)
end
function rot(x,y,a)
local xd=x
x=sin(a)*xd-cos(a)*y
y=cos(a)*xd+sin(a)*y
return x,y
end
function project(pt)
-->cam space
for p in all(pt) do
p.cx,p.cz=rot(
p.x-cam.x,
p.z-cam.z,a)
-- p.cy,p.cz=rot(p.y,p.cz,t()/7)
p.cy=p.y
-- p.cz+=2 +cos(t()/6)
end
-- sort
for pass=1,3 do
for i=1,#pt-1 do
if pt[i].cz<pt[i+1].cz then
pt[i],pt[i+1]=
pt[i+1],pt[i]
end
end
for i=#pt-1,1,-1 do
if pt[i].cz<pt[i+1].cz then
pt[i],pt[i+1]=
pt[i+1],pt[i]
end
end
end
--]]
-->screen space
for p in all(pt) do
-- screen coordinates
-- derived only from
-- the cam coordinates
-- cz means "further
-- from the camera"
-- goes 3d -> 2d
if mode==2 then
sx=64-p.cx*64/p.cz
sy=64+p.cy*64/p.cz
rad=8/p.cz
else
local invdet=1/
(cam.cx*cam.drz-
cam.drx*cam.cz)
local trx=invdet*(
cam.drz*p.x-cam.drx*p.y
)
local try=invdet*(
-cam.cz*p.x+cam.cx*p.y
)
sx=64*(1+trx/try)
-- local sx_pcnt=
-- (sx-64)/128
rad=abs(8/try)
--rad=6
local s_height=abs(128/try)
sy=-s_height/2+64
printh(try)
end
if p.cz>0.1 then
circfill(sx,sy,rad,p.col)
circfill(sx+rad/3,sy-rad/3,
rad/3,7)
end
end
print(stat(1))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment