' Non-Convex 3D routine;
' ~~~~~~~~~~~~~~~~~~~~~~
'
' Unlike the convex 3D routines, the faces of the objects
' you create with this routine can overlap. The plus is
' that you can make very complex shapes, the minus is that
' the routine is a lot slower as it has to sort the faces.
'
' (C) Shockwave 2002.
' Use freely in your own programs but remember the credit
' if you use it!
'---------------------------------------------------------
debug=0

gosub initialise
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
repeat
    setdrawbuf dw
    dw=1-dw
    setdispbuf dw
setrgb 1,0,70,40
setrgb 2,100,0,60
setrgb 3,0,0,90
gtriangle 0,0 to 640,512 to 0,512
gtriangle 0,0 to 640,512 to 640,0

    gosub rotate
    gosub construct
if debug=1 then
y=50
 setrgb 1,200,200,200

 text 30,30,"DRAW  ORDER:"
for a=1 to visible
setrgb 1,0,0,0
 text 31,y+1,"FACE # "+str$(sort(a))
 setrgb 1,200,200,200
 text 30,y,"FACE # "+str$(sort(a))

 y=y+20
next a
for a=1 to points
 text tx(a),ty(a),str$(a),"cc"
next a
fi
setrgb 1,0,0,0
text 321,491,"NON CONVEX ROUTINE (C) SHOCKWAVE","cc"

setrgb 1,255,255,255
text 320,490,"NON CONVEX ROUTINE (C) SHOCKWAVE","cc"
until (and(peek("port1"),16384)<>0)

exit

'---------------------------------------------------------
'                     Draw The Object;
'---------------------------------------------------------
label construct
gosub draworder
for b=1 to visible
a=sort(b)
gosub draw
next b
return

'---------------------------------------------------------
'      Find Visible Faces, Sort them into order;
'---------------------------------------------------------

label draworder
visible=0
for a=1 to faces
  vx1= tx(f1(a))-tx(f2(a))
  vy1= ty(f1(a))-ty(f2(a))
  vx2= tx(f3(a))-tx(f2(a))
  vy2= ty(f3(a))-ty(f2(a))
  n(a)=  vx1*vy2-vx2*vy1
 if n(a)<0 then
 visible=visible+1
 sort(visible)=a
 n(a)=-(n(a)/150)
 fi
next a

for fk=1 to visible
for a=1 to visible-1
'get low z
 ref=sort(a)
 low=tz(f1(ref))
 if low>tz(f2(ref)) low=tz(f2(ref))
 if low>tz(f3(ref)) low=tz(f3(ref))
 if low>tz(f4(ref)) low=tz(f4(ref))
'get low z
 ref=sort(a+1)
 low2=tz(f1(ref))
 if low2>tz(f2(ref)) low2=tz(f2(ref))
 if low2>tz(f3(ref)) low2=tz(f3(ref))
 if low2>tz(f4(ref)) low2=tz(f4(ref))
 
if low2>low then
 temp=sort(a+1)
 sort(a+1)=sort(a)
 sort(a)=temp
fi

next a
next fk

return

'---------------------------------------------------------
'              Draw A Face Of The Object;
'---------------------------------------------------------

label draw
 setrgb 1,r(a)+n(a),g(a)+n(a),b(a)+n(a)
 fill triangle tx(f1(a)),ty(f1(a)) to tx(f2(a)),ty(f2(a)) to tx(f3(a)),ty(f3(a))
 fill triangle tx(f1(a)),ty(f1(a)) to tx(f4(a)),ty(f4(a)) to tx(f3(a)),ty(f3(a))
 if cls(a)=1 then
   setrgb 1,0,0,0
   line tx(f1(a)),ty(f1(a)) to tx(f2(a)),ty(f2(a))
   line tx(f2(a)),ty(f2(a)) to tx(f3(a)),ty(f3(a))
   line tx(f3(a)),ty(f3(a)) to tx(f4(a)),ty(f4(a))
   line tx(f4(a)),ty(f4(a)) to tx(f1(a)),ty(f1(a))
 fi
return

label rotate
'---------------------------------------------------------
'       Rotate And Scale Each Point! Store Result;
'---------------------------------------------------------
 for a=1 to points
  x1=x(a)
  y1=y(a)
  z1=z(a)
'---------------------------------------------------------
'                      X,Y,Z rotations;
'---------------------------------------------------------
  xx=x1
  yy=y1*cs(xr)+z1*sn(xr)
  zz=z1*cs(xr)-y1*sn(xr)
  y1=yy
  x1=xx*cs(yr)-zz*sn(yr)
  z1=xx*sn(yr)+zz*cs(yr)
  zz=z1
  xx=x1*cs(zr)-y1*sn(zr)
  yy=x1*sn(zr)+y1*cs(zr)
'---------------------------------------------------------
'                 Perspective Transformation;
'---------------------------------------------------------
  dv=(zz/40)+1
  xx=size*(xx/dv)+320
  yy=size*(yy/dv)+256
  tx(a)=xx
  ty(a)=yy
  tz(a)=zz
 next a
'---------------------------------------------------------
'                 Rotation adds and resets;
'---------------------------------------------------------
xr=xr+1
yr=yr+2
zr=zr+3
if xr>720 xr=xr-720
if yr>720 yr=yr-720
if zr>720 zr=zr-720
return

'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
' This Sub-Routine Initialises The Program.
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
label initialise
'---------------------------------------------------------
'                     Open Gfx Screen!
'---------------------------------------------------------

 open window 640,512

'---------------------------------------------------------
'            Define the necessary variables;
'---------------------------------------------------------
'       Change the three below to suit your object;
'_________________________________________________________
size=80: rem                       how big do you want it?
points=32: Rem          The amount of points in the object
faces=30 : Rem           The Amount of faces in the object
'_________________________________________________________
'                  Leave these all alone;
dw=1 : Rem                       Double buffering Variable
dim x(points): Rem            Original X co-ordinate store
dim y(points): Rem            Original Y co-ordinate store
dim z(points): Rem            Original Z co-ordinate store
dim tx(points): Rem       Transformed  X co-ordinate store
dim ty(points): Rem        Transformed Y co-ordinate store
dim tz(points): Rem        Transformed Z co-ordinate store
dim f1(faces):rem                   Connections definition
dim f2(faces):rem                   Connections definition
dim f3(faces):rem                   Connections definition
dim f4(faces):rem                   Connections definition
dim r(faces):rem                             Red Component
dim g(faces):rem                           Green Component
dim b(faces):rem                            Blue Component
dim cls(faces):rem                        Cell Shade Face?
dim sort(faces):rem                          Drawing order
dim n(faces):rem                           Surface normals
'---------------------------------------------------------
'   Define Sine Tables for faster matrix calculations;
'---------------------------------------------------------
 dim cs(720)
 dim sn(720)
 for ang=0 to 720
  cs(ang)=cos(ang*(pi/360))
  sn(ang)=sin(ang*(pi/360))
 next ang
'---------------------------------------------------------
'               Read in the object's points;
'---------------------------------------------------------
for a=1 to points
 read x(a),y(a),z(a)
next a
'---------------------------------------------------------
'         Read In Connections and face parameters;
'---------------------------------------------------------
for a=1 to faces
read f1(a)
read f2(a)
read f3(a)
read f4(a)
read r(a),g(a),b(a),cls(a)
next a
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'   The Object Description As Data!
'   The Data Below Describes A Cross thing. 
'   32 vertices, 30 faces.
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

'Points definition;
'~~~~~~~~~~~~~~~~~~
'Below are the points of the object defined as x,y,z;
'This object was created vith vector object editor v1.0
'by Shockwave. Object designed by Shockwave.

data 1,1,1,-1,1,1,-1,-1,1,1,-1,1
data 1,-1,3,1,1,3,-1,1,3,-1,-1,3
data -3,-1,1,-3,1,1,-1,3,1,1,3,1
data 3,1,1,3,-1,1,1,-3,1,-1,-3,1
data -1,-3,-1,1,-3,-1,3,-1,-1,3,1,-1
data 1,3,-1,-1,3,-1,-3,1,-1,-3,-1,-1
data -1,-1,-1,-1,1,-1,1,1,-1,1,-1,-1
data 1,-1,-3,1,1,-3,-1,1,-3,-1,-1,-3

'Connection definition;
'~~~~~~~~~~~~~~~~~~~~~~
'Below are the faces of the object defined as vertice
'numbers, specified in clockwise order. These are followed
'by r,g,b values for the face and finally cell shaded
'parameter (0)=off (1)=on.
'
'eg:
'join points 1 to 2 to 3 to 4 to 1
'golour 10red 20 blue 30 green cell shade on would be;
'
'data 1,2,3,4,10,20,30,1

data 5,8,7,6,10,20,10,1
data 1,2,11,12,10,10,30,1
data 10,9,24,23,30,10,10,1
data 17,16,15,18,30,10,30,1
data 20,19,14,13,10,20,10,1
data 12,11,22,21,10,50,10,1
data 29,30,31,32,40,10,10,1
data 24,25,26,23,10,20,10,1
data 26,25,32,31,0,0,10,1
data 26,31,30,27,30,10,50,1
data 24,9,3,25,10,20,10,1
data 9,10,2,3,10,30,70,1
data 7,8,3,2,70,10,10,1
data 17,25,3,16,80,30,10,1
data 11,2,26,22,10,40,60,1
data 10,23,26,2,60,60,60,1
data 22,26,27,21,10,80,10,1
data 3,8,5,4,10,10,90,1
data 3,4,15,16,100,10,10,1
data 32,25,28,29,10,20,10,1
data 19,20,27,28,10,10,40,1
data 28,18,15,4,10,50,10,1
data 19,28,4,14,60,10,10,1
data 28,25,17,18,10,70,10,1
data 30,29,28,27,10,10,80,1
data 1,6,7,2,10,80,80,1
data 5,6,1,4,90,90,10,1
data 14,4,1,13,90,90,10,1
data 12,21,27,1,10,10,10,1
data 20,13,1,27,10,40,10,1
return










