REM Welcome to 3dStudio!
REM Developed by Mikael Lagre (c) 2001

open window 640,512

alp = 30
bet = 30
gam = 30
scale_f=1.0
viewz=200
drawtype=1
debug = 0
object = 1

label start
if (object = 1) restore objCube
if (object = 2) restore objX


read nrVertex
read nrPolys
dim cosD(360), sinD(360)
dim px(nrVertex),py(nrVertex),pz(nrVertex)
dim screenX(nrVertex), screenY(nrVertex)
dim poly(nrPolys,4)
dim polyRed(nrPolys), polyGreen(nrPolys), polyBlue(nrPolys)

dim vertexZ(nrVertex)
dim visible(nrPolys)
dim sortz(nrPolys)
dim renderOrder(nrPolys)


for i=0 to 360
  cosD(i)=cos(i*pi/180)
  sinD(i)=sin(i*pi/180)
next i

for i=1 to nrVertex
  read px(i),py(i),pz(i)
next i

for i=1 to nrPolys
 for v=1 to 4
  read poly(i,v)
 next v
 read polyRed(i),polyGreen(i),polyBlue(i)
 visible(i)=0
next i

curbuffer = 0
setdispbuf curbuffer
curbuffer = 1 - curbuffer
setdrawbuf curbuffer
clear window

setrgb 1,255,255,255






if (debug = 2) then
 oldtime = val(mid$(time$,7,2))
 fps = 0
endif

'Start the Loop
label loop


setdispbuf curbuffer
curbuffer = 1 - curbuffer
setdrawbuf curbuffer
clear window


'$$$$$$$$$$$$$$$$$$$$$$$$$$$$
'Controller
REM "Up-Rotate Up"
if (and(peek("port1"),16) > 0) then 
 bet = bet - 3
 if bet < 0 bet=360-abs(bet)
endif

REM "Down-Rotate Down"
if (and(peek("port1"),64) > 0) then 
 bet = bet + 3
 if bet > 360 bet=bet-360
endif

REM "Right-Rotate Right"
if (and(peek("port1"),32) > 0) then 
 gam = gam + 3
 if gam > 360 gam=gam-360
endif

REM "Left-Rotate Left"
if (and(peek("port1"),128) > 0) then 
 gam = gam - 3
 if gam < 0 gam=360-abs(gam)
endif

REM "L1-Roll Left"
if (and(peek("port1"),1024) > 0) then 
 alp = alp + 3
 if alp > 360 alp=alp-360
endif

REM "R1-Roll right"
if (and(peek("port1"),2048) > 0) then 
 alp = alp - 3
 if alp < 0 alp=360-abs(alp)
endif

REM "R2-Zoom in"
if (and(peek("port1"),512) > 0) then 
 viewz = viewz - 3
 if viewz < 150 viewz = 150
endif

REM "L2-Zoom out"
if (and(peek("port1"),256) > 0) then 
 viewz = viewz + 3
 if viewz > 500 viewz = 500
endif

REM "Triangle - drawtype 1"
if (and(peek("port1"),4096) > 0) then 
 drawtype=1
endif

REM "Circle - drawtype 2"
if (and(peek("port1"),8192) > 0) then 
 drawtype=2
endif

REM "X - drawtype 3"
if (and(peek("port1"),16384) > 0) then 
 drawtype=3
endif

REM "Square - drawtype 4"
if (and(peek("port1"),32768) > 0) then 
 drawtype=4
endif

REM "Select - change Object"
if (and(peek("port1"),1) > 0) then 
 object = object+1
 if object > 2 object=1
 goto start
endif






'$$$$$$$$$$$$$$$$$$$$$$$$$$$$




'rotate alp,bet,gam
mx1 = sinD(gam)*sinD(bet)*sinD(alp)+cosD(gam)*cosD(alp)
my1 = cosD(bet)*sinD(alp)
mz1 = sinD(gam)*cosD(alp)-cosD(gam)*sinD(bet)*sinD(alp)

mx2 = sinD(gam)*sinD(bet)*cosD(alp)-cosD(gam)*sinD(alp)
my2 = cosD(bet)*cosD(alp)
mz2 = -cosD(gam)*sinD(bet)*cosD(alp)-sinD(gam)*sinD(alp)

mx3 = -sinD(gam)*cosD(bet)
my3 = sinD(bet)
mz3 = cosD(gam)*cosD(bet)



'Calculate 2d
for i=1 to nrVertex
 newx = px(i)*mx1 + py(i)*my1 + pz(i)*mz1
 newy = px(i)*mx2 + py(i)*my2 + pz(i)*mz2
 newz = px(i)*mx3 + py(i)*my3 + pz(i)*mz3

 newz = newz + viewz
 vertexZ(i)=newz
 screenX(i) = scale_f*(320*newx/(newz-50))/(16/9)+320
 screenY(i) = scale_f*(256*newy/(newz-50))+256
next i



'Backface Culling and CalcZ
nrVisible=0
for i=1 to nrPolys
 x1 = screenX(poly(i,1))
 y1 = screenY(poly(i,1))
 x2 = screenX(poly(i,2))
 y2 = screenY(poly(i,2))
 x3 = screenX(poly(i,3))
 y3 = screenY(poly(i,3))
 x4 = screenX(poly(i,4))
 y4 = screenY(poly(i,4))
 if (((x2-x1)*(y3-y1)-(y2-y1)*(x3-x1)) <= 0) then
  z1 = vertexZ(poly(i,1))
  z2 = vertexZ(poly(i,2))
  z3 = vertexZ(poly(i,3))
  z4 = vertexZ(poly(i,4))
  nrVisible=nrVisible+1
  REM Find Lowest z on polygon
  if (z1 <= z2 and z1 <= z3 and z1<=z4) zmin = z1
  if (z2 <= z1 and z2 <= z3 and z2<=z4) zmin = z2
  if (z3 <= z1 and z3 <= z2 and z3<=z4) zmin = z3
  if (z4 <= z1 and z4 <= z2 and z4<=z3) zmin = z4
  sortz(nrVisible) = zmin
  renderOrder(nrVisible)=i
 endif
next i

if (debug = 1) then
 text 10,10, "Before sort"
 for i = 1 to nrVisible
  text 10,20+(i*20), str$(i) + ": " + str$(renderOrder(i)) + "  " + str$(sortz(i))
 next i
endif


'Bubble sort to determine RenderOrder for polygons
done = 0
while (done=0)
 done=1    REM Will turn to 0 if swapped Z
 for p=1 to nrVisible-1
  if (sortz(p) < sortz(p+1)) then
   temp = sortz(p)
   sortz(p) = sortz(p+1)
   sortz(p+1) = temp
   REM Changing RenderOrder also
   tempr = renderOrder(p)
   renderOrder(p) = renderOrder(p+1)
   renderOrder(p+1) = tempr
   done = 0
  endif
 next p
wend

if (debug = 1) then
 printy = 20+(nrVisible*20)
 text 10,50+printy, "After sort"
 for i = 1 to nrVisible
  text 10,50+printy+(i*20), str$(i) + ": " + str$(renderOrder(i)) + "  " + str$(sortz(i))
 next i
endif


'Draw

if (drawtype = 1) then
 for y=1 to nrVisible
  i=renderOrder(y)
  x1 = screenX(poly(i,1))
  y1 = screenY(poly(i,1))
  x2 = screenX(poly(i,2))
  y2 = screenY(poly(i,2))
  x3 = screenX(poly(i,3))
  y3 = screenY(poly(i,3))
  x4 = screenX(poly(i,4))
  y4 = screenY(poly(i,4))  
  setrgb 1,polyRed(i),polyGreen(i),polyBlue(i)
  setrgb 2,polyRed(i),polyGreen(i),polyBlue(i)
  setrgb 3,polyRed(i),polyGreen(i),polyBlue(i)
  gtriangle x1,y1 to x2,y2 to x3,y3
  gtriangle x1,y1 to x4,y4 to x3,y3
 next y
elsif (drawtype=2) then
 for i = 1 to nrPolys
  x1 = screenX(poly(i,1))
  y1 = screenY(poly(i,1)) 
  x2 = screenX(poly(i,2))
  y2 = screenY(poly(i,2))
  x3 = screenX(poly(i,3))
  y3 = screenY(poly(i,3))
  x4 = screenX(poly(i,4))
  y4 = screenY(poly(i,4)) 
  setrgb 1,0,255,0
  line x1,y1 to x2,y2
  line to x3,y3
  line to x4,y4
  line to x1,y1
 next i

elsif (drawtype=3) then
 for y = 1 to nrVisible
  i = renderOrder(y)
  x1 = screenX(poly(i,1))
  y1 = screenY(poly(i,1)) 
  x2 = screenX(poly(i,2))
  y2 = screenY(poly(i,2))
  x3 = screenX(poly(i,3))
  y3 = screenY(poly(i,3))
  x4 = screenX(poly(i,4))
  y4 = screenY(poly(i,4)) 
  setrgb 1,0,0,0
  setrgb 2,0,0,0
  setrgb 3,0,0,0
  gtriangle x1,y1 to x2,y2 to x3,y3
  gtriangle x1,y1 to x4,y4 to x3,y3 
  setrgb 1,0,255,0
  line x1,y1 to x2,y2
  line to x3,y3
  line to x4,y4
  line to x1,y1
 next y

elseif (drawtype = 4) then
 setrgb 1,255,255,255
 for i = 1 to nrVertex
  dot screenX(i), screenY(i)
 next i
endif

if (debug = 1) then
for i = 1 to nrVertex
 x1 = screenX(i)
 y1 = screenY(i)
 setrgb 1,255,255,255
 text x1,y1, str$(int(vertexZ(i)))
next i
endif



REM So we can count Frames per Second
if (debug = 2) then
 fps = fps+1
 setrgb 1,255,255,255
 text 10,20, "Fps: " + str$(lastfps)
 newtime = val(mid$(time$,7,2))
 if (newtime-oldtime >= 1) then
  lastfps = fps
  oldtime = val(mid$(time$,7,2))
  fps = 0
 endif
endif


goto loop     REM And....Let's do it all again..shall we!



'########################
label objCube
'Vertex and polygons
data 8,6

'Vertex Data
data -50, 50, 50
data  50, 50, 50
data  50,-50, 50
data -50,-50, 50
data -50, 50,-50
data  50, 50,-50
data  50,-50,-50
data -50,-50,-50

'Polygon connector data and color in r,g,b values
data  2, 1, 4, 3,     0,255,  0
data  5, 6, 7, 8,   255,  0,  0
data  1, 5, 8, 4,     0,  0,255
data  6, 2, 3, 7,   255,255,  0
data  5, 1, 2, 6,     0,255,255
data  8, 7, 3, 4,   255,  0,255


'########################
label objX

data 24,18
data  20, 40,-20
data  60, 40,-20
data -20,-40,-20
data -60,-40,-20
data   0,-20,-20
data  20,  0,-20
data  60,-40,-20
data  20,-40,-20
data -60, 40,-20
data -20, 40,-20
data   0, 20,-20
data -20,  0,-20
data  20, 40, 20
data  60, 40, 20
data -20,-40, 20
data -60,-40, 20
data   0,-20, 20
data  20,  0, 20
data  60,-40, 20
data  20,-40, 20
data -60, 40, 20
data -20, 40, 20
data   0, 20, 20
data -20,  0, 20

'Connector
data  1, 2, 3, 4,   255,  0,  0
data  5, 6, 7, 8,   255,  0,  0
data  9,10,11,12,   255,  0,  0
data 16,15,14,13,   255,  0,  0
data 20,19,18,17,   255,  0,  0
data 24,23,22,21,   255,  0,  0
data  4, 3,15,16,     0,100,255
data  3, 5,17,15,     0,100,255
data  5, 8,20,17,     0,100,255
data  8, 7,19,20,     0,100,255
data  6,18,19, 7,     0, 55,  0
data  2,14,18, 6,     0, 55,  0
data  1,13,14, 2,     0,100,255
data 11,23,13, 1,     0,100,255
data 10,22,23,11,     0,100,255
data  9,21,22,10,     0,100,255
data  9,12,24,21,     0, 55,  0
data  24,12,4,16,     0, 55,  0

