home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fujiology Archive
/
fujiology_archive_v1_0.iso
/
!FALCON
/
LINEOUT
/
OUT.ZIP
/
SOURCE.ZIP
/
KALEIDO.SO
< prev
next >
Wrap
Text File
|
2004-01-15
|
47KB
|
2,287 lines
; 3d kaleidoscope involving spacecut alike stuff.
;
; The idea for the effect is as follows:
;
; 1) decode u-fly object to clipper format
; 2) clip the object, keeping track of new and old vertices
; 3) encode the clipped object to u-fly again
; 4) mirror the object using the ref-data you have efficiently
; 5) u-fly engine madness
;
; Might seem a bit dodgy, but actually it's better than doing the clipping
; with references. You see, vertices come and go with every plane-clip.
; To avoid major redundancy you would have needed very nasty routs to purge
; obsolete vertices!!
;
; TODO:
; 1) bug fucking: wrong normal intersection, (backface fuck)
; what is this hellcrap? tried to fix it for ages, but i'm losing my mind
; here. maybe it's just a thing inherent to integer precision, i don't know.
; 2) make opt version run on std falcon.
;******* OBJECT TABLE ********
IFND DEMO_SYSTEM
testmode: = 0
move.l #Kaleido.table,fxAdr
INCLUDE TESTER.S
TEXT
INCLUDE SFLY_DSP.S
TEXT
INCLUDE OBJECT3D.I
TEXT
ENDC
;******* OBJECT EQUATES ********
Kaleido.BLOCKCLEARING: = 0 ; 'fast' clearing..
Kaleido.NORMAL_CORRECTION: = 0
; Total amount of vertices + normals is 16 times this amount, so keep low!
Kaleido.MAX_VERTICES: = 64
Kaleido.MAX_CVERTICES: = 256
******** Matrix
RSRESET
matrixXX: RS.W 1
matrixXY: RS.W 1
matrixXZ: RS.W 1
matrixYX: RS.W 1
matrixYY: RS.W 1
matrixYZ: RS.W 1
matrixZX: RS.W 1
matrixZY: RS.W 1
matrixZZ: RS.W 1
matrixTX: RS.L 1
matrixTY: RS.L 1
matrixTZ: RS.L 1
matrixSize: RS.B 0
Kaleido.table:
DC.L Kaleido.mainLoop
DC.L Kaleido.init
DC.L Kaleido.initRT
DC.L Kaleido.deinitRT
DC.L Kaleido.switchRot
DC.L 0
;******* RESOLUTION SETTING ROUTINE ********
Kaleido.initRT:
move.l #rts,vbl_gfx
bsr.l HumanFly.init
lea Viewport.settingsTable,a0
move.w #320,Viewport.XSCREEN(a0)
move.w #200,Viewport.YSCREEN(a0)
move.w #0,Viewport.XSTART(a0)
move.w #0,Viewport.YSTART(a0)
move.w #320,Viewport.XEND(a0)
move.w #200,Viewport.YEND(a0)
move.w #160,Viewport.XCENTER(a0)
move.w #100,Viewport.YCENTER(a0)
move.w #256+32,Viewport.ASPECT(a0)
move.w #$100,Viewport.FOCAL(a0)
bsr.l Viewport.update
lea Kaleido.textureTable,a0
bsr.l Polygon.init
bsr.l ObjectRegistry.clear
; lea Kaleido.object,a0
; move.l #Object3d.spikeyEnd-Object3d.spikey,d0
; bsr ObjectRegistry.set
move.w monitormode,d0
cmpi.w #vga60,d0
beq.s .vga60
cmpi.w #vga100,d0
beq.s .vga100
cmpi.w #rgb50,d0
beq.s .rgb50
; Unknown monitormode..
.end: rts
.vga60: move.l #vga60_16bit_320_200,resRout
rts
.vga100:move.l #vga100_16bit_320_200,resRout
rts
.rgb50: move.l #rgb50_16bit_320_200,resRout
rts
;******* INIT SUBROUTINE ********
; OUTPUT:
; d0.l: =0 all clear, <0 error
Kaleido.init:
lea sine_tbl,a1
bsr.l Matrix.init
lea Object3d.spikey,a1
move.l #Object3d.spikeyEnd-Object3d.spikey,d0
lea Kaleido.spikey,a0
bsr.l Object3d.copy
lea Kaleido.spikey,a0
move.w #0,d0
move.w #8,d1
move.w #$200/5,d2
bsr.l Object3d.scale
lea Kaleido.spikey,a0
move.w #8,d0
move.w #6,d1
move.w #$0080,d2
bsr.l Object3d.scale
lea Kaleido.spikey,a1
move.l #Object3d.spikeyEnd-Object3d.spikey,d0
lea Kaleido.object,a0
bsr.l Object3d.copy
.success:
moveq #0,d0
rts
.error: moveq #-1,d0
rts
Kaleido.deinitRT:
rts
;******* SCREENINIT SUBROUTINE ********
Kaleido.initScreen:
movea.l scr,a0
bsr.l CLEAR_320200TSCR
rts
;******* MAINLOOP SUBROUTINE ********
Kaleido.mainLoop:
move.w $0468.w,.old468
move.l frmcnt,d0
sub.l lastframecount,d0
cmpi.l #3,d0
bhs.s .end_screeninit
bsr Kaleido.initScreen
.end_screeninit:
bsr Kaleido.getRotPos
; bsr getTime
move.w d0,d1
move.w d0,d2
mulu.w #11,d0
lsr.l #2,d0
mulu.w #3,d1
mulu.w #7,d2
lsr.l d1
lsr.l d2
bsr.l Kaleido.generateMatrix
bsr Kaleido.getRotPos
move.w d0,d1
bsr getTime
move.w d0,d2
move.w d1,d0
mulu.w #5,d1
lsr.l #3,d1
mulu.w #3,d2
lsr.l #2,d2
subi.w #sintbllen/4,d0
subi.w #sintbllen/4,d1
subi.w #sintbllen/4,d2
Do_SinModulo d0
Do_SinModulo d1
Do_SinModulo d2
lea sine_tbl,a1
Get_Sin a1,d0,d0
Get_Sin a1,d1,d1
Get_Sin a1,d2,d2
addi.w #$8000,d0
addi.w #$8000,d1
addi.w #$8000,d2
lsr.w #6,d0
lsr.w #6,d1
lsr.w #6,d2
bsr.l Kaleido.translate
lea Kaleido.object,a0
lea Kaleido.spikey,a2
bsr.l Kaleido.transform
lea Kaleido.clippedObject,a0
lea Kaleido.object,a1
bsr.l Kaleido.testClip
; d0.l=size, a0: obj
; bsr.l Kaleido.paintClippedObjectOpt
bsr.l Kaleido.paintClippedObject
lea scr,a0
move.l (a0)+,d0
move.l (a0)+,d1
move.l (a0),-4(a0)
move.l d0,(a0)
move.l d1,-8(a0)
movea.l resRout,a0
suba.l a1,a1
movea.l d0,a2
bsr.l Screen.requestUpdate
clr.l resRout
move.w .old468(pc),d0
.wait: cmp.w $0468.w,d0
beq.s .wait
rts
.old468:DC.W 0
;******* OBJECT SUBROUTINES ********
Kaleido.switchRot:
bsr Kaleido.getRotPos
move.l d0,Kaleido.oldRotPos
bsr getTime
move.l d0,Kaleido.rotSwitchTime
neg.w Kaleido.rotDir
not.l Kaleido.bgColor
rts
Kaleido.getRotPos:
bsr getTime
sub.l Kaleido.rotSwitchTime,d0 ; t-T (T<=t)
muls.w Kaleido.rotDir,d0 ; d(t-T)
add.l Kaleido.oldRotPos,d0 ; OP+d(t-T)
rts
Kaleido.bgColor:
DS.L 1
Kaleido.rotSwitchTime:
DS.L 1
Kaleido.oldRotPos:
DS.L 1
Kaleido.rotDir:
DC.W +1
* Seems to work ok, since there has been some patching on the overflow
* errors (caused by combination of finite accuracy and use of maximum range)
* INPUT: d0.w: X rotation (a)
* d1.w: Y rotation (b)
* d2.w: Z rotation (c)
Kaleido.generateMatrix:
lea Kaleido.matrix,a0
* 1> rotate 3 axis.
Do_SinModulo d0
Do_SinModulo d1
Do_SinModulo d2
movea.w d0,a3
movea.w d1,a4
movea.w d2,a5
lea sine_tbl,a2
* X := + x*cos(b)*cos(c)
* - y*cos(b)*sin(c)
* + z*sin(b)
Get_SinCos a2,d1,d3,d4
Get_SinCos a2,d2,d5,d6
muls.w d4,d6 * / cos(b)*sin(c)
add.l d6,d6 * |
; bvc.s .skipxd6
; subq.l #1,d6
;.skipxd6:
swap d6 * \
muls.w d4,d5 * / -cos(b)*sin(c)
add.l d5,d5 * |
; bvc.s .skipxd5
; subq.l #1,d5
;.skipxd5:
swap d5 * |
neg.w d5 * \
move.w d6,(a0)+
move.w d5,(a0)+
move.w d3,(a0)+
* Y := + x*(sin(a)*sin(b)*cos(c)+cos(a)*sin(c))
* + y*(cos(a)*cos(c)-sin(a)*sin(b)*sin(c))
* - z*sin(a)*cos(b)
Get_SinCos a2,a3,d0,d1
Get_Sin a2,a4,d2
Get_SinCos a2,a5,d4,d5
muls.w d0,d2
add.l d2,d2
; bvc.s .skipyd2
; subq.l #1,d2
;.skipyd2:
swap d2
muls.w d2,d5
add.l d5,d5
; bvc.s .skipyd5
; subq.l #1,d5
;.skipyd5:
swap d5
muls.w d1,d4
add.l d4,d4
; bvc.s .skipyd4
; subq.l #1,d4
;.skipyd4:
swap d4
add.w d4,d5
bvc.s .skipyvd5
addq.w #1,d5
neg.w d5
.skipyvd5:
move.w d5,d3
;Get_SinCos a2,a3,d0,d1
Get_Sin a2,a4,d2
Get_SinCos a2,a5,d4,d5
muls.w d1,d5
add.l d5,d5
; bvc.s .skipy2d5
; subq.l #1,d5
;.skipy2d5:
swap d5
muls.w d0,d2
add.l d2,d2
; bvc.s .skipy2d2
; subq.l #1,d2
;.skipy2d2:
swap d2
muls.w d2,d4
add.l d4,d4
swap d4
sub.w d4,d5
bvc.s .skipyv2d5
addq.w #1,d5
neg.w d5
.skipyv2d5:
Get_Cos a2,a4,d4
muls.w d0,d4
add.l d4,d4
; bvc.s .skipy2d4
; subq.l #1,d4
;.skipy2d4:
swap d4
neg.w d4
move.w d3,(a0)+
move.w d5,(a0)+
move.w d4,(a0)+
* Z := + x*(sin(a)*sin(c)-cos(a)*sin(b)*cos(c))
* + y*(cos(a)*sin(b)*sin(c)+sin(a)*cos(c))
* + z*cos(a)*cos(b)
Get_SinCos a2,a3,d0,d1
Get_Sin a2,a4,d2
Get_SinCos a2,a5,d4,d5
muls.w d0,d4
add.l d4,d4
; bvc.s .skipzd4
; subq.l #1,d4
;.skipzd4:
swap d4
muls.w d1,d2
add.l d2,d2
; bvc.s .skipzd2
; subq.l #1,d2
;.skipzd2:
swap d2
muls.w d2,d5
add.l d5,d5
swap d5
sub.w d5,d4
bvc.s .skipzvd4
addq.w #1,d4
neg.w d4
.skipzvd4:
move.w d4,d3
;Get_SinCos a2,a3,d0,d1
Get_Sin a2,a4,d2
Get_SinCos a2,a5,d4,d5
muls.w d1,d2
add.l d2,d2
; bvc.s .skipz2d2
; subq.l #1,d2
;.skipz2d2:
swap d2
muls.w d2,d4
add.l d4,d4
swap d4
muls.w d0,d5
add.l d5,d5
; bvc.s .skipzd5
; subq.l #1,d5
;.skipzd5:
swap d5
add.w d4,d5
bvc.s .skipzvd5
addq.w #1,d5
neg.w d5
.skipzvd5:
Get_Cos a2,a4,d4
muls.w d1,d4
add.l d4,d4
; bvc.s .skipz2d4
; subq.l #1,d4
;.skipz2d4:
swap d4
move.w d3,(a0)+
move.w d5,(a0)+
move.w d4,(a0)+
* Translation vector := (0,0,0)
moveq #0,d0
move.l d0,(a0)+
move.l d0,(a0)+
move.l d0,(a0)+
rts
* Translate the object's translation vector.
* INPUT: d0.w: X translation
* d1.w: Y translation
* d2.w: Z translation
Kaleido.translate:
lea Kaleido.matrix,a0
add.w d0,matrixTX(a0)
add.w d1,matrixTY(a0)
add.w d2,matrixTZ(a0)
rts
* Transform vertices.
* INPUT: a0: destination obj
* a2: source obj
Kaleido.transform:
lea Kaleido.matrix,a1
lea Matrix.TX(a1),a3
move.w (a2)+,d7 * total amount of vertices
move.w (a2)+,a6 * amount of normal vectors
movem.w d7/a6,(a0)
sub.w a6,d7 * amount of vertices
* Transform vertices...
.transform_vertices:
subq.w #1,d7
movea.l d7,a5
movea.l a0,a4
addq #4,a0
move.w a6,-(sp)
movem.l (a3),d6/a3/a6
.vertexloop:
movem.w (a2)+,d0-d2
* X
move.w d0,d3
move.w d1,d4
move.w d2,d5
muls.w (a1)+,d3
muls.w (a1)+,d4
muls.w (a1)+,d5
add.l d3,d5
add.l d4,d5
add.l d5,d5
add.l d6,d5 * Translate coordinate.
swap d5
move.w d5,(a0)+ * Store coordinate.
* Y
move.w d0,d3
move.w d1,d4
move.w d2,d5
muls.w (a1)+,d3
muls.w (a1)+,d4
muls.w (a1)+,d5
add.l d3,d5
add.l d4,d5
add.l d5,d5
add.l a3,d5 * Translate coordinate.
swap d5
move.w d5,(a0)+ * Store coordinate.
* Z
move.w d0,d3
move.w d1,d4
move.w d2,d5
muls.w (a1)+,d3
muls.w (a1)+,d4
muls.w (a1)+,d5
add.l d3,d5
add.l d4,d5
add.l d5,d5
add.l a6,d5 * Translate coordinate.
swap d5
move.w d5,(a0)+ * Store coordinate.
lea -3*6(a1),a1
dbf d7,.vertexloop
movea.w (sp)+,a6
.end_transform:
* Transform normal vectors...
.transform_normals:
move.w a6,d7
subq.w #1,d7
bmi.s .end_transformnormals
.normalloop:
movem.w (a2)+,d0-d2
moveq #3-1,d6
.normalcolumnloop:
move.w d0,d3
move.w d1,d4
move.w d2,d5
muls.w (a1)+,d3
muls.w (a1)+,d4
muls.w (a1)+,d5
add.l d3,d5
add.l d4,d5
add.l d5,d5
swap d5
move.w d5,(a0)+ * Store coordinate.
dbra d6,.normalcolumnloop
lea -3*6(a1),a1
dbf d7,.normalloop
.end_transformnormals:
rts
; Decodes a u-fly envmapped object to a format suitable to the clipper.
; INPUT:
; a0: dst buffer (clipper format: head, polylist)
; a1: src u-fly2 object
; a4: reftable
; PRE:
; Object must be totally envmapped.
Kaleido.decodeEnvObject:
move.w (a1)+,d0 ; d0.w=v+n
move.w d0,d2 ; d2.w=v+n
move.w (a1)+,d1 ; d1.w=n, a1: vertextable
sub.w d1,d2 ; d2.w=v
mulu.w #Vertex.SIZE,d0 ; d1.l=offset to 2dlist
lea (a1,d0.l),a2 ; a2: 2d vertex table
move.w (a2)+,d0 ; d0.w=#2d vertices
mulu.w #Vertex2d.SIZE,d0 ; d0.l=offset to polylist
add.l d0,a2 ; a2: polytable
move.w (a2)+,d7 ; d7.w=#polys
move.w d7,(a0)+ ; Store #polys.
subq.w #1,d7
.poly_loop:
move.w (a2)+,d0 ; d0.w=polyheader
andi.w #Primitive.TYPEMASK,d0
moveq #Primitive.TYPESHIFT,d1
lsr.w d1,d0
move.w d0,d6 ; d6.w=#vertices-1
addq.w #1,d0
lea (a2,d0.w*2),a3 ; a3: shadetable
move.w d0,(a0)+ ; Store #vertices.
.decode_vertex_loop:
move.w (a2)+,d2 ; d2.w=vertexref
move.w d2,(a4)+ ; Store ref.
mulu.w #Vertex.SIZE,d2
move.l (a1,d2.l),(a0)+ ; Store x,y.
move.w 4(a1,d2.l),(a0)+ ; Store z.
move.w (a3)+,d2 ; d3.w=normalref
mulu.w #Vertex.SIZE,d2
move.l (a1,d2.l),(a0)+ ; Store n.x, n.y.
move.w 4(a1,d2.l),(a0)+ ; Store n.z.
dbf d6,.decode_vertex_loop
movea.l a3,a2 ; a2: next poly
dbf d7,.poly_loop
rts
; Encodes a clipper object to a u-fly (envmapped) object.
; Does this the efficient way, be removing unused old vertices and normals.
; INPUT:
; a0: dest buffer (u-fly2 object)
; a1: clipped object (head, polylist)
; a2: ref table
; a3: src u-fly object
; PRE:
; Source object must be totally envmapped (6 coords per vertex).
Kaleido.encodeEnvObjectEff:
move.w (a3),d0
sub.w 2(a3),d0
move.w d0,.srcvertices
addq #4,a3 ; Skip src header
; Pass 1 - Count and store used old vertices in src object.
; 1a: Clear all marks.
lea Kaleido.markTable,a5 ; a5: marked refs table
moveq #Kaleido.MAX_VERTICES/4-1,d7
clr.l d0
.clearloop:
move.l d0,(a5)+
dbf d7,.clearloop
; 1b: Mark it up..
lea Kaleido.markTable,a5 ; a5: marked refs table
movea.l a1,a6 ; a6: src object
movea.l a2,a4 ; a4: reftable
move.w (a1)+,d7 ; d7.w=#polys
move.w d7,.polys
subq.w #1,d7
moveq #1,d0
.poly_loop0:
move.w (a1)+,d5 ; d5.w=#vertices
subq.w #1,d5
.poly0_v_loop:
move.w (a2)+,d1 ; d1.w=ref
bmi.s .next
move.b d0,(a5,d1.w) ; Mark reference.
.next: adda.w #12,a1
dbf d5,.poly0_v_loop
dbf d7,.poly_loop0
move.w d6,(a0) ; Store #old vertices.
move.w d6,.vertices ; Store #old vertices.
move.l a0,-(sp)
; 1c: Sum up marktable, to get the relocation table..
lea Kaleido.markTable,a5 ; a5: marked refs table
lea Kaleido.relocTable,a2 ; a2: relocation table
move.w #Kaleido.MAX_VERTICES-2,d7
; move.w .srcvertices(pc),d7
; subq.w #2,d7
moveq #-1,d0
.sum_loop:
add.b (a5)+,d0
move.b d0,(a2)+
dbf d7,.sum_loop
ext.w d0
addq.w #1,d0
move.w d0,.vertices ; Store #old vertices.
move.w d0,(a0)
; 1d: Relocate old marked vertices to dst.
lea Kaleido.relocTable,a5 ; a5: relocation table
movea.l a6,a1 ; a1: polylist
movea.l a4,a2 ; a2: reftable
move.w (a1)+,d7 ; d7.w=#polys
subq.w #1,d7
addq #4,a0 ; Skip dst header
.poly_loop1d:
move.w (a1)+,d5 ; d5.w=#vertices
subq.w #1,d5
.poly1d_v_loop:
move.w (a2)+,d1 ; d1.w=ref
bmi.s .next1d
clr.w d0
move.b (a5,d1.w),d0 ; d0.w=npos
mulu.w #Vertex.SIZE,d1 ; d1.l=src poly offset
mulu.w #Vertex.SIZE,d0 ; d0.l=dst poly offset
move.l (a3,d1.l),(a0,d0.l)
move.w 4(a3,d1.l),4(a0,d0.l)
.next1d:adda.w #12,a1 ; a1: next vertex
dbf d5,.poly1d_v_loop
dbf d7,.poly_loop1d
movea.l (sp),a0 ; a0: dst
movea.l a0,a5
move.w .vertices(pc),d0
mulu.w #Vertex.SIZE,d0
lea 4(a0,d0.l),a0 ; a0: room for new vertices
movea.l a6,a1
movea.l a4,a2
; Pass 2 - Get new vertices in table.
move.w (a1)+,d7 ; d7.w=#polys
subq.w #1,d7
clr.w d6
.poly_loop1:
move.w (a1)+,d5 ; d5.w=#vertices
subq.w #1,d5
.poly1_v_loop:
move.w (a2)+,d1 ; d1.w=ref
bmi.s .new_ref1
adda.w #12,a1
bra.s .end_handle_ref1
.new_ref1:
addq.w #1,d6 ; Increase #new vertices.
; Store vertex.
move.l (a1)+,(a0)+
move.w (a1)+,(a0)+
addq #6,a1 ; Skip normal.
.end_handle_ref1:
dbf d5,.poly1_v_loop
dbf d7,.poly_loop1
add.w d6,(a5)
movea.l a6,a1
movea.l a4,a2
; a0: end of vertextable in dst obj
; Pass 3 - Store used old normals.
; Adjust refs!
move.w .srcvertices(pc),d2 ; d2.w=total #vertices
lea Kaleido.relocTable,a5 ; a5: relocation table
movea.l a6,a1 ; a1: polylist
movea.l a4,a2 ; a2: reftable
move.w (a1)+,d7 ; d7.w=#polys
subq.w #1,d7
.poly_loop3:
move.w (a1)+,d5 ; d5.w=#vertices
subq.w #1,d5
.poly3_v_loop:
move.w (a2),d1 ; d1.w=ref
bmi.s .next3
clr.w d0
move.b (a5,d1.w),d0 ; d0.w=npos
move.w d0,(a2)
add.w d2,d1
mulu.w #Vertex.SIZE,d1 ; d1.l=src poly offset
mulu.w #Vertex.SIZE,d0 ; d0.l=dst poly offset
move.l (a3,d1.l),(a0,d0.l)
move.w 4(a3,d1.l),4(a0,d0.l)
.next3: adda.w #12,a1 ; a1: next vertex
addq #2,a2 ; a2: next ref
dbf d5,.poly3_v_loop
dbf d7,.poly_loop3
move.w .vertices(pc),d0
mulu.w #Vertex.SIZE,d0
adda.l d0,a0
; a0: current end of normaltable in dst obj
; Pass 4 - Get new normals in table.
movea.l a6,a1
movea.l a4,a2
move.w (a1)+,d7 ; d7.w=#polys
move.w d7,d0
subq.w #1,d7
.poly_loop2:
move.w (a1)+,d5 ; d5.w=#vertices
subq.w #1,d5
.poly2_v_loop:
move.w (a2)+,d1 ; d1.w=ref
bmi.s .new_ref2
adda.w #12,a1
bra.s .end_handle_ref2
.new_ref2:
addq #6,a1 ; Skip vertex.
; Store normal.
move.l (a1)+,(a0)+
move.w (a1)+,(a0)+
.end_handle_ref2:
dbf d5,.poly2_v_loop
dbf d7,.poly_loop2
clr.w (a0)+ ; Store #2dvertices.
; Pass 5 - Store all polys.
movea.l a6,a1
movea.l a4,a2
movea.l (sp)+,a5 ; a5: dst
move.w (a5),d2 ; d5.w=total #vertices
move.w .vertices(pc),d6
move.w (a1)+,d7
move.w d7,(a0)+ ; Store #polys.
subq.w #1,d7
.store_poly_loop:
move.w (a1)+,d5 ; d5.w=#vertices
move.w d5,d4
move.w d5,d0
mulu.w #3*2*2,d0
adda.l d0,a1 ; Proceed to next src poly.
subq.w #1,d5
move.w d5,d0
moveq #Primitive.TYPESHIFT,d1
lsl.w d1,d0
ori.w #Polygon.ENVMAPPED,d0
move.w d0,(a0)+ ; Store polyheader.
lea (a0,d4.w*2),a3 ; a3: shadetable.
.poly5_v_loop:
move.w (a2)+,d1 ; d1.w=ref
bmi.s .new_ref5
move.w d1,(a0)+ ; Store vertexref.
move.w d1,d0
add.w d2,d0
move.w d0,(a3)+ ; Store normalref.
bra.s .end_handle_ref5
.new_ref5:
move.w d6,(a0)+ ; Store vertexref.
move.w d6,d0
add.w d2,d0
move.w d0,(a3)+ ; Store normalref.
addq.w #1,d6 ; Increase #new vertices.
.end_handle_ref5:
dbf d5,.poly5_v_loop
movea.l a3,a0 ; Proceed to next poly.
dbf d7,.store_poly_loop
; Adjust dst v,n counts..
move.w (a5),d0
move.w d0,2(a5)
add.w d0,d0
move.w d0,(a5)
move.l a0,d0
sub.l a5,d0 ; d0.l=dst objectsize
rts
.srcvertices:
DC.W 0
.vertices:
DC.W 0 ; #old vertices
.normals:
DC.W 0
.polys: DC.W 0
; Clips a polygon against XY, YZ, XZ planes. Vertices in (+,+,+) octant
; are seen as 'in', rest is 'out'.
; INPUT:
; d1.w= vertexwidth (words per vertex)
; a0: polygon (#v, x1, y1, z1, u1, v1, ... , x2, y2, z2, u2, v2, ....)
; a3: src reftable
; a4: dst reftable (with enough mem free!)
; OUTPUT:
; d0.w= cullstatus (0=culled, 1=visible)
; a0: clipped polygon (only if visible)
; a3: next src reftable
; a4: next dst reftable
; PRE:
; Must be a polygon (3 points minimum!), coord range [0..2047]
Kaleido.clipRefPoly:
movea.l a0,a6 ; a6:src poly
move.w (a0)+,d0
move.w d0,.srcvertices
move.w d1,.width
; First, we check which sides of the poly are clipped.
subq.w #1,d0
subq.w #3,d1
add.w d1,d1
moveq #$FFFFFFFF,d3 ; d3.w=andflags
clr.w d4 ; d4.w=orflags
.test_clip_loop:
clr.w d2 ; flags=0 (current point)
tst.w (a0)+ ; Test x.
bpl.s .x_okay
ori.w #%001,d2 ; X clipped.
.x_okay:tst.w (a0)+ ; Test y.
bpl.s .y_okay
ori.w #%010,d2 ; Y clipped.
.y_okay:tst.w (a0)+ ; Test z.
bpl.s .z_okay
ori.w #%100,d2 ; Z clipped.
.z_okay:and.w d2,d3 ; Update andflags.
or.w d2,d4 ; Update orflags.
adda.w d1,a0 ; next vertex
dbf d0,.test_clip_loop
tst.w d3
beq.s .test_if_in
; Clipped off totally.
.out: move.w .srcvertices(pc),d0
add.w d0,d0
add.w d0,a3 ; Proceed to next reftable.
clr.w d0 ; Indicate 'culled'.
rts
.test_if_in:
tst.w d4 ; No clipflags? Then don't clip at all!
bne.s .in
move.w .srcvertices(pc),d0
subq.w #1,d0
.copy_s2dref_loop:
move.w (a3)+,(a4)+
dbf d0,.copy_s2dref_loop
movea.l a6,a0
moveq #1,d0 ; Indicate 'in'.
rts
.in: move.w d4,.clipflags
; Scale coords up 4 bits.
; Assume we have all coords 0..2047 here, because lower 4 bits are used for
; extra precision.
movea.l a6,a0
lea Kaleido.polyTable,a1
movea.l a1,a5 ; a5: src poly
move.w (a0)+,d0
move.w d0,(a1)+
mulu.w .width(pc),d0
subq.w #1,d0
.scale_up_loop:
move.w (a0)+,d1
lsl.w #4,d1
move.w d1,(a1)+
dbf d0,.scale_up_loop
; scale up wrapped stuff!
lea 2(a5),a0
move.w .width(pc),d0
subq.w #1,d0
.scale_up_loop_w:
move.w (a0)+,(a1)+
dbf d0,.scale_up_loop_w
; Backup src reftable to ref dst and reserve some extra mem for clippoints.
; i.e. make double buffers.
move.l a4,-(sp) ; Backup dst reftable.
move.l a4,.refsrc
move.w .srcvertices(pc),d0
move.w d0,d7
subq.w #1,d7
move.w (a3),d1
.copy_ref_loop:
move.w (a3)+,(a4)+
dbf d7,.copy_ref_loop
move.w d1,(a4)+ ; wrap crap
lea (a4,d0.w*2),a4 ; Keep a good margin for extra clippoints!
move.l a4,.refdst
move.l a3,-(sp) ; Backup src reftable.
; Process each planeclip.
lea Kaleido.polyTable2,a1
movea.l a5,a0 ; a0=a5=src poly
movea.l a1,a6 ; a6=a1=dst poly
btst #0,.clipflags+1(pc)
beq.s .no_clip_x
bsr.l .clip
tst.w (a0)
beq .culled
.no_clip_x:
btst #1,.clipflags+1(pc)
beq.s .no_clip_y
bsr.s .clip_y
tst.w (a0)
beq .culled
.no_clip_y:
btst #2,.clipflags+1(pc)
beq.s .no_clip_z
bsr.s .clip_z
tst.w (a0)
beq .culled
.no_clip_z:
; Store all references to final dst reftable.
movea.l (sp)+,a3 ; a3: next src reftable
movea.l (sp)+,a4 ; a4: current dst reftable
movea.l .refsrc(pc),a1
move.w (a0),d7 ; d7.w=#vertices of clipped poly
subq.w #1,d7
.store_ref_loop:
move.w (a1)+,(a4)+
dbf d7,.store_ref_loop
movea.l .refsrc(pc),a1
move.w (a1)+,(a4) ; wrap crap
; Scale coords down again..
move.w (a0)+,d0 ; d0.w=#vertices of clipped poly
addq.w #1,d0 ; extra point for wrap
mulu.w .width(pc),d0
subq.w #1,d0
movea.l a5,a0 ; a0: clipped poly
addq #2,a5 ; Skip header.
.scale_down_loop:
move.w (a5),d1
asr.w #4,d1
bcc.s .rounded
addq.w #1,d1
.rounded:
move.w d1,(a5)+
dbf d0,.scale_down_loop
; Clipping done!
.end: moveq #1,d0
rts
.culled:
; Set back to previous ref tables.
movea.l (sp)+,a3 ; a3: next src reftable
movea.l (sp)+,a4 ; a4: current dst reftable
clr.w d0 ; Indicate 'culled'.
rts
.clip_y:
; Swap y with x. The edge clipper works with x coords..
movea.l a0,a2
move.w .width(pc),d5
move.w (a2)+,d6
.swap_yx_loop:
move.l (a2),d0
swap d0
move.l d0,(a2)
lea (a2,d5.w*2),a2
dbf d6,.swap_yx_loop
bsr.s .clip
; Swap x and y again..
movea.l a0,a2
move.w .width(pc),d5
move.w (a2)+,d6
.swap_xy_loop:
move.l (a2),d0
swap d0
move.l d0,(a2)
lea (a2,d5.w*2),a2
dbf d6,.swap_xy_loop
rts
.clip_z:
; Swap z with x. The edge clipper works with x coords..
movea.l a0,a2
move.w .width(pc),d5
move.w (a2)+,d6
.swap_zx_loop:
move.w (a2),d0
move.w 4(a2),(a2)
move.w d0,4(a2)
lea (a2,d5.w*2),a2
dbf d6,.swap_zx_loop
bsr.s .clip
; Swap z and x again..
movea.l a0,a2
move.w .width(pc),d5
move.w (a2)+,d6
.swap_xz_loop:
move.w (a2),d0
move.w 4(a2),(a2)
move.w d0,4(a2)
lea (a2,d5.w*2),a2
dbf d6,.swap_xz_loop
rts
; Clips one corner.
; INPUT:
; a0: src poly
; a1: dst poly
; a5: src poly
; a6: dst poly
; OUTPUT:
; a0: dst poly
; a1: scr poly
; a5: dst poly
; a6: src poly
.clip: movea.l .refsrc(pc),a3
movea.l .refdst(pc),a4
clr.l d6
move.w .width(pc),d6
move.w d6,d5
subq.w #1,d5
add.l d6,d6
; Clip all edges.
move.w (a0)+,d7 ; d7.w=#src vertices
subq.w #1,d7
clr.w .vertices ; #output vertices
addq #2,a1 ; Skip dst header.
.corner_loop:
bsr.s .clip_edge
dbf d7,.corner_loop
move.w .vertices(pc),(a6) ; Store #dst vertices.
; wrap-crap
lea 2(a6),a2
move.w .width(pc),d7
subq.w #1,d7
.width_loop:
move.w (a2)+,(a1)+
dbf d7,.width_loop
movea.l .refdst(pc),a2
move.w (a2),(a4) ; ref wrapcrap
; Swap src and dst polytables, reftables.
exg a5,a6
movea.l a5,a0
movea.l a6,a1
move.l .refsrc(pc),d0
move.l .refdst(pc),.refsrc
move.l d0,.refdst
rts
; Clips against YZ plane.
; INPUT:
; d5.w=vertexwidth-1
; d6.l=offset to next vertex
; a0: src poly
; a1: dst poly
.clip_edge:
tst.w (a0)
bmi.s .check_2nd_out
tst.w (a0,d6.l)
bpl.s .inside
; The source edge goes from inside to outside.
; Write the clipped point.
.inout: move.w #-1,(a4)+ ; Store new ref.
addq #2,a3 ; Proceed to next src ref.
move.w (a0,d6.l),d2 ; d2.w=xend
move.w (a0)+,d0 ; d0.w=xstart
ext.l d0
sub.w d0,d2 ; d2.w=xend-xstart(=dx)
ext.l d2
neg.l d0
clr.w (a1)+ ; Store clipped x(=0).
move.w d5,d4
subq.w #1,d4
.inout_loop:
move.w (a0,d6.l),d3 ; d3.w=yend
move.w (a0)+,d1 ; d1.w=ystart
bsr.s .intersect
move.w d3,(a1)+ ; Store clipped coord.
dbf d4,.inout_loop
addq.w #1,.vertices ; #output vertices +1.
rts
.check_2nd_out:
tst.w (a0,d6.l)
bpl.s .outin
; Source edge is outside. Don't write it out.
.outside:
addq #2,a3 ; Proceed to next ref.
adda.l d6,a0 ; Proceed to next vertex.
rts
; The source edge goes from outside to inside.
; Write the clipped point and the inside point as well.
.outin: move.w #-1,(a4)+ ; Store new ref.
addq #2,a3 ; Proceed to next src ref.
move.w (a0,d6.l),d2 ; d2.w=xend
move.w (a0)+,d0 ; d0.w=xstart
ext.l d0
sub.w d0,d2 ; d2.w=xend-xstart(=dx)
neg.w d2
ext.l d2
clr.w (a1)+ ; Store clipped x(=0).
move.w d5,d4
subq.w #1,d4
.outin_loop:
move.w (a0,d6.l),d3 ; d3.w=yend
move.w (a0)+,d1 ; d1.w=ystart
bsr.s .intersect
move.w d3,(a1)+ ; Store clipped coord.
dbf d4,.outin_loop
suba.l d6,a0 ; Back to 1st vertex in edge.
subq #2,a3 ; Back 1 ref.
addq.w #1,.vertices ; #output vertices +1.
; Write inside point (2nd point in edge!).
.inside:addq #2,a3
move.w (a3),(a4)+ ; Store old ref.
adda.l d6,a0 ; Proceed to next point.
movea.l a0,a2
move.w d5,d4
.copy_loop:
move.w (a2)+,(a1)+
dbf d4,.copy_loop
addq.w #1,.vertices ; #output vertices +1.
rts
; Generic intersection routine. The start x coord is 'in', the end is 'out'.
; yi = ystart + xstart*(dy/dx)
; INPUT:
; d0.w= xstart
; d1.w= ystart
; d2.l= xend - xstart (=dx)
; d3.w= yend
; OUTPUT:
; d3.w=yi
.intersect:
sub.w d1,d3 ; d3.w=dy
swap d3
clr.w d3
divs.l d2,d3 ; d3.l=(dy<<16)/dx=slope
muls.l d0,d3 ; d3.l=slope*xstart
addi.l #$00008000,d3
swap d3
add.w d1,d3 ; d3.w=ystart+xstart*slope
rts
.refsrc:DC.L 0
.refdst:DC.L 0
.vertices:
DC.W 0
.srcvertices:
DC.W 0
.width: DC.W 0
.clipflags:
DC.W 0
; Test if an envmap object can be clipped whole?!?!
; INPUT:
; a0: dst u-fly object
; a1: src u-fly object
; OUTPUT:
; d0.l= size of object
; a0: dst u-fly object
Kaleido.testClip:
; Decode the object..
movem.l a0/a1,-(sp)
lea Kaleido.polyList,a0
lea Kaleido.srcRefTable,a4
bsr.l Kaleido.decodeEnvObject
; Clip all polys..
clr.w .polys
lea Kaleido.srcRefTable,a3
lea Kaleido.dstRefTable,a4
lea Kaleido.polyList,a0
lea Kaleido.clippedPolyList+2,a1
move.w (a0)+,d7
subq.w #1,d7
.clip_loop:
move.l a0,-(sp)
move.l a1,-(sp)
move.w d7,-(sp)
moveq #6,d1 ; d1.w=vertexwidth
bsr.l Kaleido.clipRefPoly
move.w (sp)+,d7
movea.l (sp)+,a1
movea.l (sp)+,a2
; Store (or neglect if culled) the clipped poly...
tst.w d0
bne.s .not_culled
bra.s .end_store_poly
.not_culled:
addq.w #1,.polys
move.w (a0)+,d6
bgt.s .d6_okay
illegal
.d6_okay:
move.w d6,(a1)+
mulu.w #6,d6 ; d6.w=#coords*#vertices
subq.w #1,d6
.store_poly_loop:
move.w (a0)+,(a1)+
dbf d6,.store_poly_loop
.end_store_poly:
; Proceed to next unclipped poly...
move.w (a2)+,d0
mulu.w #6*2,d0
lea (a2,d0.l),a0
dbf d7,.clip_loop
move.w .polys(pc),Kaleido.clippedPolyList
; Encode it to u-fly format again...
movem.l (sp),a0/a3 ; a0: dst u-fly obj, a3: src u-fly obj
lea Kaleido.clippedPolyList,a1
lea Kaleido.dstRefTable,a2
bsr.l Kaleido.encodeEnvObjectEff
; d0.l=size of object
movem.l (sp)+,a0/a3 ; a0: dst u-fly obj, a3: src u-fly obj
rts
.polys: DC.W 0
; INPUT:
; d0.w= x,y,z negation (%000..00zyx)
; a0: object
Kaleido.invertObject:
move.w (a0)+,d7
addq #2,a0
subq.w #1,d7
.loop: btst #0,d0
beq.s .end_x_neg
neg.w (a0)
.end_x_neg:
addq #2,a0
btst #1,d0
beq.s .end_y_neg
neg.w (a0)
.end_y_neg:
addq #2,a0
btst #2,d0
beq.s .end_z_neg
neg.w (a0)
.end_z_neg:
addq #2,a0
dbf d7,.loop
; Test whether to inverse back<->front polys or not..
clr.w d1
lsr.w d0
bcc.s .not1
addq.w #1,d1
.not1: lsr.w d0
bcc.s .not2
addq.w #1,d1
.not2: lsr.w d0
bcc.s .not3
addq.w #1,d1
.not3: btst #0,d1
beq.s .end
; Inverse order polys..
move.w (a0)+,d1
mulu.w #Vertex2d.SIZE,d1
adda.l d1,a0
move.w (a0)+,d7
subq.w #1,d7
moveq #Primitive.TYPESHIFT,d2
.ploop: move.w (a0)+,d6
andi.w #Primitive.TYPEMASK,d6
lsr.w d2,d6
addq.w #1,d6
move.w d6,d5
lea (a0,d6.w*2),a1
movea.l a1,a2
lsr.w d6
subq.w #1,d6
.vloop: move.w -(a1),d1
move.w (a0),(a1)
move.w d1,(a0)+
dbf d6,.vloop
movea.l a2,a0
lea (a0,d5.w*2),a1
movea.l a1,a2
lsr.w d5
subq.w #1,d5
.sloop: move.w -(a1),d1
move.w (a0),(a1)
move.w d1,(a0)+
dbf d5,.sloop
movea.l a2,a0
dbf d7,.ploop
.end: rts
Kaleido.correctNormals:
move.w (a0)+,d7
sub.w (a0)+,d7
move.w d7,d0
mulu.w #Vertex.SIZE,d0
lea (a0,d0.l),a1
subq.w #1,d7
.loop: tst.w (a0)+
bne.s .end_x
clr.w (a1)
.end_x: addq #2,a1
tst.w (a0)+
bne.s .end_y
clr.w (a1)
.end_y: addq #2,a1
tst.w (a0)+
bne.s .end_z
clr.w (a1)
.end_z: addq #2,a1
dbf d7,.loop
rts
IFNE Kaleido.BLOCKCLEARING
; Clears the blockbuffer. Set all blocks to 'unused'.
Kaleido.clearBlockBuffer:
movea.l Kaleido.blockBufferTable,a0
clr.l d0
moveq #25-1,d7
.loop: REPT 10
move.l d0,(a0)+
ENDR
dbf d7,.loop
rts
ENDC
; INPUT:
; a0: rectangle table
Kaleido.clipRectangles:
move.w #199,d1
move.w #319,d2
move.w (a0)+,d7
beq.s .end
subq.w #1,d7
.loop: move.w (a0),d0
bpl.s .ok5
clr.w d0
.ok5: cmp.w d1,d0
blt.s .ok6
move.w d1,d0
.ok6: move.w d0,(a0)+
move.w (a0),d0
bpl.s .ok7
clr.w d0
.ok7: cmp.w d1,d0
blt.s .ok8
move.w d1,d0
.ok8: move.w d0,(a0)+
move.w (a0),d0
bpl.s .ok
clr.w d0
.ok: cmp.w d2,d0
blt.s .ok2
move.w d2,d0
.ok2: move.w d0,(a0)+
move.w (a0),d0
bpl.s .ok3
clr.w d0
.ok3: cmp.w d2,d0
blt.s .ok4
move.w d2,d0
.ok4: move.w d0,(a0)+
dbf d7,.loop
.end: rts
IFNE Kaleido.BLOCKCLEARING
; Mark Rectangle in blockbuffer.
; INPUT:
; d0.w=x1
; d1.w=x2
; d2.w=y1
; d3.w=y2
Kaleido.putRectInBuf:
movea.l Kaleido.blockBufferTable,a0
lsr.w #3,d0
lsr.w #3,d1
lsr.w #3,d2
lsr.w #3,d3
sub.w d0,d1 ; d1.w=dx
sub.w d2,d3 ; d3.w=dy
mulu.w #40,d2
add.w d0,d2
adda.w d2,a0
moveq #$FFFFFFFF,d0
moveq #40-1,d6
sub.w d1,d6 ; d6.w=stride
.yloop: move.w d1,d7
.xloop: move.b d0,(a0)+ ; Mark as 'used'.
dbf d7,.xloop
adda.l d6,a0
dbf d3,.yloop
rts
; Clear blocks on screen as specified by the blockbuffer.
; INPUT:
; a0: screen
Kaleido.clearBlocks:
movea.l Kaleido.blockBufferTable,a1
movea.w #8*2,a5
movea.w #7*320*2,a6
moveq #25-1,d7
clr.l d0
clr.l d1
clr.l d2
clr.l d3
.yloop: moveq #40-1,d6
.xloop: tst.b (a1)+
beq.s .next
movem.l d0-d3,(a0)
movem.l d0-d3,320*2(a0)
movem.l d0-d3,320*4(a0)
movem.l d0-d3,320*6(a0)
movem.l d0-d3,320*8(a0)
movem.l d0-d3,320*10(a0)
movem.l d0-d3,320*12(a0)
movem.l d0-d3,320*14(a0)
.next: adda.l a5,a0
dbf d6,.xloop
adda.l a6,a0
dbf d7,.yloop
rts
ENDC
; Paints 'kaleidoscoped' object in a very lame way. No culling of doubled
; vertices.
; INPUT:
; d0.l= size of object
; a0: u-fly object
Kaleido.paintClippedObject:
movem.l d0/a0,-(sp)
bsr.l ObjectRegistry.clear
movem.l (sp)+,d0/a0
IFNE Kaleido.NORMAL_CORRECTION
movem.l d0/a0,-(sp)
bsr.l Kaleido.correctNormals
movem.l (sp)+,d0/a0
ENDC
movem.l d0/a0,-(sp)
bsr.l ObjectRegistry.set
tst.w d0
bmi return2tos
movem.l (sp)+,d0/a0
; Inverse coords here!
movea.l a0,a6
move.l d0,-(sp)
moveq #%011,d0
bsr.l Kaleido.invertObject
move.l (sp)+,d0
movea.l a6,a0
movem.l d0/a0,-(sp)
bsr.l ObjectRegistry.set
tst.w d0
bmi return2tos
movem.l (sp)+,d0/a0
; Inverse coords here!
movea.l a0,a6
move.l d0,-(sp)
moveq #%010,d0
bsr.l Kaleido.invertObject
move.l (sp)+,d0
movea.l a6,a0
movem.l d0/a0,-(sp)
bsr.l ObjectRegistry.set
tst.w d0
bmi return2tos
movem.l (sp)+,d0/a0
movea.l a0,a6
move.l d0,-(sp)
moveq #%011,d0
bsr.l Kaleido.invertObject
move.l (sp)+,d0
movea.l a6,a0
movem.l d0/a0,-(sp)
bsr.l ObjectRegistry.set
tst.w d0
bmi return2tos
movem.l (sp)+,d0/a0
movea.l a0,a6
move.l d0,-(sp)
moveq #%100,d0
bsr.l Kaleido.invertObject
move.l (sp)+,d0
movea.l a6,a0
movem.l d0/a0,-(sp)
bsr.l ObjectRegistry.set
tst.w d0
bmi return2tos
movem.l (sp)+,d0/a0
movea.l a0,a6
move.l d0,-(sp)
moveq #%011,d0
bsr.l Kaleido.invertObject
move.l (sp)+,d0
movea.l a6,a0
movem.l d0/a0,-(sp)
bsr.l ObjectRegistry.set
tst.w d0
bmi return2tos
movem.l (sp)+,d0/a0
movea.l a0,a6
move.l d0,-(sp)
moveq #%010,d0
bsr.l Kaleido.invertObject
move.l (sp)+,d0
movea.l a6,a0
movem.l d0/a0,-(sp)
bsr.l ObjectRegistry.set
tst.w d0
bmi return2tos
movem.l (sp)+,d0/a0
movea.l a0,a6
move.l d0,-(sp)
moveq #%011,d0
bsr.l Kaleido.invertObject
move.l (sp)+,d0
movea.l a6,a0
movem.l d0/a0,-(sp)
bsr.l ObjectRegistry.set
tst.w d0
bmi return2tos
movem.l (sp)+,d0/a0
movea.l scr,a0
bsr.l Primitive.setScreenbuffer
bsr.l PrimitiveMesh.new
move.w #sintbllen*7/8,d0
move.w #sintbllen/2,d1
move.w #sintbllen/8,d2
bsr getTime
move.w d0,d2
mulu.w #3,d0
lsr.l d0
bsr.l Matrix.generate
move.w #0,d0
move.w #0,d1
move.w #2000,d2
bsr.l Matrix.translate
bsr.l Matrix.push
moveq #TransformObject.BACKFACE_CULLING|TransformObject.PERSPECTIVATE,d0
moveq #0,d1
bsr.l TransformObject.transform
moveq #TransformObject.BACKFACE_CULLING|TransformObject.PERSPECTIVATE,d0
moveq #1,d1
bsr.l TransformObject.transform
moveq #TransformObject.BACKFACE_CULLING|TransformObject.PERSPECTIVATE,d0
moveq #2,d1
bsr.l TransformObject.transform
moveq #TransformObject.BACKFACE_CULLING|TransformObject.PERSPECTIVATE,d0
moveq #3,d1
bsr.l TransformObject.transform
moveq #TransformObject.BACKFACE_CULLING|TransformObject.PERSPECTIVATE,d0
moveq #4,d1
bsr.l TransformObject.transform
moveq #TransformObject.BACKFACE_CULLING|TransformObject.PERSPECTIVATE,d0
moveq #5,d1
bsr.l TransformObject.transform
moveq #TransformObject.BACKFACE_CULLING|TransformObject.PERSPECTIVATE,d0
moveq #6,d1
bsr.l TransformObject.transform
moveq #TransformObject.BACKFACE_CULLING|TransformObject.PERSPECTIVATE,d0
moveq #7,d1
bsr.l TransformObject.transform
bsr.l Matrix.pop
bsr.l PrimitiveMesh.sortZ
bsr.l PrimitiveMesh.complete
IFNE Kaleido.BLOCKCLEARING
movea.l scr,a0
bsr Kaleido.clearBlocks
bsr Kaleido.clearBlockBuffer
ELSE
; moveq #68,d0
; move.l #320-70,d6
; moveq #0,d1
; move.l #200-2,d7
moveq #0,d0
move.l #320,d6
moveq #0,d1
move.l #200,d7
move.l Kaleido.bgColor,d4
bsr.l Viewport.paintRectangle
ENDC
movea.l Kaleido.rectAddressTable,a0
bsr.l PrimitiveMesh.paint
IFNE Kaleido.BLOCKCLEARING
movea.l Kaleido.rectAddressTable,a0
bsr Kaleido.clipRectangles
movea.l Kaleido.rectAddressTable,a0
move.w (a0)+,d7
beq.s .end_put
subq.w #1,d7
.putloop:
movem.w (a0)+,d2-d3
movem.w (a0)+,d0-d1
move.l a0,-(sp)
move.w d7,-(sp)
bsr Kaleido.putRectInBuf
move.w (sp)+,d7
movea.l (sp)+,a0
dbf d7,.putloop
.end_put:
lea Kaleido.blockBufferTable,a0
move.l (a0)+,d0
move.l (a0)+,d1
move.l (a0),-(a0)
move.l d0,4(a0)
move.l d1,-(a0)
ENDC
lea Kaleido.rectAddressTable,a0
move.l (a0)+,d0
move.l (a0)+,d1
move.l (a0),-(a0)
move.l d0,4(a0)
move.l d1,-(a0)
IFNE 0
; just some area measurement..
movea.l Kaleido.rectAddressTable,a0
movea.l a0,a1
move.w (a0)+,d7
beq .end
move.w d7,d5
subq.w #1,d7
.cliploop:
move.w (a0),d0
bpl.s .ok
clr.w d0
.ok: cmpi.w #319,d0
blt.s .ok2
move.w #319,d0
.ok2: move.w d0,(a0)+
move.w (a0),d0
bpl.s .ok3
clr.w d0
.ok3: cmpi.w #319,d0
blt.s .ok4
move.w #319,d0
.ok4: move.w d0,(a0)+
move.w (a0),d0
bpl.s .ok5
clr.w d0
.ok5: cmpi.w #199,d0
blt.s .ok6
move.w #199,d0
.ok6: move.w d0,(a0)+
move.w (a0),d0
bpl.s .ok7
clr.w d0
.ok7: cmpi.w #199,d0
blt.s .ok8
move.w #199,d0
.ok8: move.w d0,(a0)+
dbf d7,.cliploop
tst.w d5
beq.s .end
subq.w #1,d5
clr.l d4
.loop: movem.w (a1)+,d1/d7
.bla2: movem.w (a1)+,d0/d6
sub.w d1,d7
bpl.s .xok
neg.w d7
.xok: sub.w d0,d6
bpl.s .yok
neg.w d6
.yok: mulu.w d6,d7
add.l d7,d4
dbf d5,.loop
.end_restore:
divu.w #64000/320,d4
movea.l scr,a0
subq.w #1,d4
bmi.s .end
moveq #$FFFFFFFF,d0
.clrloop:
move.w d0,(a0)+
dbf d4,.clrloop
ENDC
clr.l Kaleido.bgColor
.end: rts
; This actually 'kaleidoscopes' a clipped object. Works on a normal object
; (no clip), but the results would be quite ordinary.
; INPUT:
; d0.w=coord to mirror
; a0: src u-fly object
; a1: dst u-fly object
; OUTPUT
; d0.l= size of dst object
; PRE: object must have #normals equal to #vertices
; Object must have envmapped polys exclusively!
Kaleido.mirror:
move.w d0,d2 ; d2.w=coord offset.
movea.l a0,a5
movea.l a1,a6
; Step 1 - We mirror vertices in x direction.
; 1a - Clear marks..
lea Kaleido.clipMarkTable,a2 ; a2: marked refs table
moveq #Kaleido.MAX_CVERTICES/4-1,d7
clr.l d0
.clearloop:
move.l d0,(a2)+
dbf d7,.clearloop
; 1b - Copy org vertices and mark x-clipped vertices!
lea Kaleido.clipMarkTable,a2 ; a2: marked refs table
move.w (a0)+,d7
move.w (a0)+,d6
move.w d7,(a1)+
move.w d6,(a1)+
sub.w d6,d7
move.w d7,.orgVertices
subq.w #1,d7
moveq #1,d0
clr.w d1
.copy_v_loop:
tst.w (a0,d2.w)
bne.s .next_v
move.b d0,(a2) ; Mark it.
addq.w #1,d1 ; Increase #marked.
.next_v:addq #1,a2
move.w (a0)+,(a1)+
move.l (a0)+,(a1)+
dbf d7,.copy_v_loop
move.w d1,.culledAmount
; 1c: Make mirrored vertices (not the marked ones!)..
lea Kaleido.clipMarkTable,a2 ; a2: marked refs table
lea 4(a5),a3
move.w .orgVertices(pc),d7
move.w d7,d0
sub.w .culledAmount(pc),d0
move.w d0,.addedVertices
add.w d0,(a6)
add.w d0,(a6)
add.w d0,2(a6)
move.w 2(a6),.dstVertices
ble.s .end_mirror_v
subq.w #1,d7
.mirror_v_loop:
tst.b (a2)+
bne.s .next_mirror_v
move.w (a3),(a1)
move.l 2(a3),2(a1)
neg.w (a1,d2.w) ; Negate coord.
addq #Vertex.SIZE,a1
.next_mirror_v:
addq #Vertex.SIZE,a3
dbf d7,.mirror_v_loop
.end_mirror_v:
; a3: src normals
; 1d: Copy org normals
subq.w #1,d6
.copy_n_loop:
move.l (a0)+,(a1)+
move.w (a0)+,(a1)+
dbf d6,.copy_n_loop
; 1e: Mirror normals (not the marked ones!)..
lea Kaleido.clipMarkTable,a2 ; a2: marked refs table
move.w .orgVertices(pc),d7
ble.s .end_mirror_v
subq.w #1,d7
.mirror_n_loop:
tst.b (a2)+
bne.s .next_mirror_n
move.w (a3),(a1)
move.l 2(a3),2(a1)
neg.w (a1,d2.w)
addq #Vertex.SIZE,a1
.next_mirror_n:
addq #Vertex.SIZE,a3
dbf d7,.mirror_n_loop
.end_mirror_n:
; Copy texturevertices (if any)..
move.w (a0)+,d7
move.w d7,(a1)+
subq.w #1,d7
bmi.s .end_copy_t
.copy_t_loop:
move.l (a0)+,(a1)+
dbf d7,.copy_t_loop
.end_copy_t:
; Intermezzo - Calculate relocation table.
lea Kaleido.clipMarkTable,a2 ; a2: marked refs table
lea Kaleido.clipRelocTable,a3 ; a3: relocation table
move.w .orgVertices(pc),d7
move.w d7,d2
subq.w #1,d7
moveq #-1,d1
clr.w d0
.make_reloc_loop:
move.b (a2)+,d0
bchg #0,d0 ; 1<->0
add.w d0,d1
move.w d2,d3
add.w d1,d3 ; Make ref point to new vertices.
move.w d3,(a3)+ ; Store reference.
dbf d7,.make_reloc_loop
; 2 - Copy polys..
movea.l a0,a3
; 2a - Copy org polys
move.w .addedVertices(pc),d2
moveq #Primitive.TYPESHIFT,d1
move.w (a0)+,d7
move.w d7,(a1)
add.w d7,(a1)+
subq.w #1,d7
.copy_poly_loop:
move.w (a0)+,d0
move.w d0,(a1)+
andi.w #Primitive.TYPEMASK,d0
lsr.w d1,d0
move.w d0,d6
.copy_poly_v_loop:
move.w (a0)+,(a1)+ ; Copy ref.
dbf d0,.copy_poly_v_loop
.copy_poly_s_loop:
move.w (a0)+,d0
add.w d2,d0
move.w d0,(a1)+ ; Copy sref.
dbf d6,.copy_poly_s_loop
dbf d7,.copy_poly_loop
; 2b - Mirror polys.
movea.l a3,a0
lea Kaleido.clipMarkTable,a2 ; a2: marked refs table
lea Kaleido.clipRelocTable,a3 ; a3: relocation table
move.w .dstVertices(pc),d2 ; d2.w=offset to normals
moveq #Primitive.TYPESHIFT,d1
move.w (a0)+,d7
subq.w #1,d7
.mirror_poly_loop:
move.w (a0)+,d0
move.w d0,(a1)+
andi.w #Primitive.TYPEMASK,d0
lsr.w d1,d0
move.w d0,d6
addq.w #1,d6
lea (a1,d6.w*2),a1
lea (a1,d6.w*2),a4
.mirror_poly_v_loop:
move.w (a0)+,d3 ; d3.w=old ref
tst.b (a2,d3.w) ; Check mark.
beq.s .old_vertex
move.w d3,-(a1) ; Store ref.
add.w d2,d3
move.w d3,-(a4) ; Store sref.
bra.s .next_mirror_r
.old_vertex:
move.w (a3,d3.w*2),d3 ; d3.w=relocated ref.
move.w d3,-(a1) ; Store ref.
add.w d2,d3
move.w d3,-(a4) ; Store sref.
.next_mirror_r:
dbf d0,.mirror_poly_v_loop
lea (a4,d6.w*2),a1 ; a1: next dst poly
lea (a0,d6.w*2),a0 ; a0: next src poly
dbf d7,.mirror_poly_loop
; Calc size of new object...
move.l a1,d0
sub.l a6,d0
rts
.culledAmount:
DC.W 0
.orgVertices:
DC.W 0
.dstVertices:
DC.W 0
.addedVertices:
DC.W 0
; Tries to paint 'kaleidoscoped' object in a decent way. Kaleidofucks
; the object and removes doubled vertices at once.
; INPUT:
; d0.l= size of object
; a0: u-fly object
Kaleido.paintClippedObjectOpt:
movem.l d0/a0,-(sp)
movea.l scr,a0
bsr.l Primitive.setScreenbuffer
bsr.l PrimitiveMesh.new
move.w #sintbllen*7/8,d0
move.w #sintbllen/2,d1
move.w #sintbllen/8,d2
bsr getTime
move.w d0,d2
mulu.w #3,d0
lsr.l d0
bsr.l Matrix.generate
move.w #0,d0
move.w #0,d1
move.w #2000,d2
bsr.l Matrix.translate
bsr.l Matrix.push
moveq #TransformObject.BACKFACE_CULLING|TransformObject.PERSPECTIVATE,d0
moveq #0,d1
bsr.l TransformObject.transform
bsr.l Matrix.pop
bsr.l PrimitiveMesh.sortZ
bsr.l PrimitiveMesh.complete
; Parallel shit!
movem.l (sp)+,d0/a0
IFNE Kaleido.NORMAL_CORRECTION
movem.l d0/a0,-(sp)
bsr.l Kaleido.correctNormals
movem.l (sp)+,d0/a0
ENDC
; Mirror in x-direction..
move.l a0,-(sp)
lea Kaleido.mirroredObject,a1
moveq #0,d0
bsr.w Kaleido.mirror
; Mirror in y-direction..
move.l (sp),a1
lea Kaleido.mirroredObject,a0
moveq #2,d0
bsr.w Kaleido.mirror
; Mirror in z-direction..
move.l (sp)+,a0
lea Kaleido.mirroredObject,a1
moveq #4,d0
bsr.w Kaleido.mirror
; d0.l=object size
move.l d0,-(sp)
movea.l Kaleido.rectAddressTable,a0
move.w (a0)+,d7
beq.s .end_restore
subq.w #1,d7
.restore_loop:
move.w d7,-(sp)
movem.w (a0)+,d1/d7
movem.w (a0)+,d0/d6
move.l a0,-(sp)
moveq #$00000000,d4
bsr.l Viewport.paintRectangle
movea.l (sp)+,a0
move.w (sp)+,d7
dbra d7,.restore_loop
.end_restore:
; End of parallel shit!
movea.l Kaleido.rectAddressTable,a0
bsr.l PrimitiveMesh.paint
lea Kaleido.rectAddressTable,a0
move.l (a0)+,d0
move.l (a0)+,d1
move.l (a0),-(a0)
move.l d0,4(a0)
move.l d1,-(a0)
bsr.l ObjectRegistry.clear
movem.l (sp)+,d0
lea Kaleido.mirroredObject,a0
bsr.l ObjectRegistry.set
tst.w d0
bmi return2tos
rts
;******* OBJECT DATA ********
DATA
Kaleido.texture:
INCBIN ENV64.APX
Kaleido.textureTable:
DC.L Kaleido.texture
DC.L Kaleido.texture
DC.L 0
Kaleido.pyramid:
DC.W (.end-.start)/Vertex.SIZE * amount of vertices
DC.W (.end-.normstart)/Vertex.SIZE * amount of normals
.start: DC.W +000,+300,+000
DC.W -300,-300,-300
DC.W +300,-300,-300
DC.W +300,-300,+300
DC.W -300,-300,+300
.normstart:
DC.W +000,+100,+000
DC.W -60,-60,-60
DC.W +60,-60,-60
DC.W +60,-60,+60
DC.W -60,-60,+60
.end:
DC.W 0 ; amount of 2d vertices
DC.W 5 ; amount of primitives
DC.W Polygon.TRI|Polygon.ENVMAPPED|0,+0,2,1,+5,7,6
DC.W Polygon.TRI|Polygon.ENVMAPPED|0,+0,3,2,+5,8,7
DC.W Polygon.TRI|Polygon.ENVMAPPED|0,+0,4,3,+5,9,8
DC.W Polygon.TRI|Polygon.ENVMAPPED|0,+0,1,4,+5,6,9
DC.W Polygon.QUAD|Polygon.ENVMAPPED|0,+1,2,3,4,+5,6,7,8
Kaleido.pyramidEnd:
Kaleido.cube:
DC.W (.end-.start)/Vertex.SIZE * amount of vertices
DC.W (.end-.normstart)/Vertex.SIZE * amount of normals
.start: DC.W -300,-300,-300
DC.W -300,300,-300
DC.W 300,-300,-300
DC.W 300,300,-300
DC.W -300,-300,300
DC.W -300,300,300
DC.W 300,-300,300
DC.W 300,300,300
.normstart:
DC.W -73,-73,-73
DC.W -73,73,-73
DC.W 73,-73,-73
DC.W 73,73,-73
DC.W -73,-73,73
DC.W -73,73,73
DC.W 73,-73,73
DC.W 73,73,73
.end:
DC.W 0 ; amount of 2d vertices
DC.W 6 ; amount of primitives
DC.W Polygon.QUAD|Polygon.ENVMAPPED|0,+0,1,3,2,+8+0,8+1,8+2,8+3
DC.W Polygon.QUAD|Polygon.ENVMAPPED|0,+6,7,5,4,+8+0,8+1,8+2,8+3
DC.W Polygon.QUAD|Polygon.ENVMAPPED|0,+4,5,1,0,+8+0,8+1,8+2,8+3
DC.W Polygon.QUAD|Polygon.ENVMAPPED|0,+2,3,7,6,+8+0,8+1,8+2,8+3
DC.W Polygon.QUAD|Polygon.ENVMAPPED|0,+5,7,3,1,+8+0,8+1,8+2,8+3
DC.W Polygon.QUAD|Polygon.ENVMAPPED|0,+4,0,2,6,+8+0,8+1,8+2,8+3
Kaleido.cubeEnd:
Kaleido.rectAddressTable:
DC.L Kaleido.rectangleTable
DC.L Kaleido.rectangleTable2
DC.L Kaleido.rectangleTable3
IFNE Kaleido.BLOCKCLEARING
Kaleido.blockBufferTable:
DC.L Kaleido.blockBuffer1
DC.L Kaleido.blockBuffer2
DC.L Kaleido.blockBuffer3
ENDC
Kaleido.testPoly:
DC.W 3
DC.W -256,+000,+000
DC.W +256,+256,+000
DC.W +256,-256,+000
DC.W -256,+000,+000 ; wrap first!
DS.W 3*3
;******* OBJECT RESERVES ********
BSS
Kaleido.rectangleTable:
DS.W 1+4*32
Kaleido.rectangleTable2:
DS.W 1+4*32
Kaleido.rectangleTable3:
DS.W 1+4*32
Kaleido.polyTable:
DS.W 1+17*7 ; 17 * (x,y,z,u0,v0,u1,v1)
Kaleido.polyTable2:
DS.W 1+17*7 ; 17 * (x,y,z,u0,v0,u1,v1)
Kaleido.object:
DS.W 10000/2
Kaleido.polyList:
DS.W 10000/2
Kaleido.clippedPolyList:
DS.W 10000/2
Kaleido.srcRefTable:
DS.W 5000
Kaleido.dstRefTable:
DS.W 5000
Kaleido.clippedObject:
DS.W 10000/2
Kaleido.mirroredObject:
DS.W 10000/2
Kaleido.matrix:
DS.B matrixSize
Kaleido.markTable:
DS.B Kaleido.MAX_VERTICES
Kaleido.relocTable:
DS.B Kaleido.MAX_VERTICES
Kaleido.clipMarkTable:
DS.B Kaleido.MAX_CVERTICES
Kaleido.clipRelocTable:
DS.W Kaleido.MAX_CVERTICES
Kaleido.spikey:
DS.W 1000
IFNE Kaleido.BLOCKCLEARING
Kaleido.blockBuffer1:
DS.B 40*25
Kaleido.blockBuffer2:
DS.B 40*25
Kaleido.blockBuffer3:
DS.B 40*25
ENDC