mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 23:29:55 +00:00
3d rotation multiplications now using verafx acceleration
This commit is contained in:
parent
a48ce35f0b
commit
a5cd3728c9
@ -2,16 +2,11 @@
|
||||
%import test_stack
|
||||
%import conv
|
||||
%import math
|
||||
%import verafx
|
||||
|
||||
; TODO add all other Elite's ships, show their name, advance to next ship on keypress
|
||||
|
||||
main {
|
||||
|
||||
; storage for rotated coordinates
|
||||
word[shipdata.totalNumberOfPoints] @split rotatedx
|
||||
word[shipdata.totalNumberOfPoints] @split rotatedy
|
||||
word[shipdata.totalNumberOfPoints] @split rotatedz
|
||||
|
||||
sub start() {
|
||||
uword anglex
|
||||
uword angley
|
||||
@ -24,11 +19,11 @@ main {
|
||||
print_ship_name()
|
||||
|
||||
repeat {
|
||||
rotate_vertices(msb(anglex), msb(angley), msb(anglez))
|
||||
matrix_math.rotate_vertices(msb(anglex), msb(angley), msb(anglez))
|
||||
|
||||
cx16.GRAPH_set_colors(0, 0, 0)
|
||||
; cx16.GRAPH_clear()
|
||||
cx16.GRAPH_draw_rect(32, 10, 256, 220, 0, true)
|
||||
verafx.clear(0, 320*10, 0, 320*(220/4))
|
||||
; cx16.GRAPH_set_colors(0, 0, 0)
|
||||
; cx16.GRAPH_draw_rect(32, 10, 256, 220, 0, true)
|
||||
|
||||
cx16.GRAPH_set_colors(1, 0, 0)
|
||||
draw_lines_hiddenremoval()
|
||||
@ -84,39 +79,6 @@ _ones pla
|
||||
}}
|
||||
}
|
||||
|
||||
sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) {
|
||||
; rotate around origin (0,0,0)
|
||||
|
||||
; set up the 3d rotation matrix values
|
||||
word wcosa = math.cos8(ax)
|
||||
word wsina = math.sin8(ax)
|
||||
word wcosb = math.cos8(ay)
|
||||
word wsinb = math.sin8(ay)
|
||||
word wcosc = math.cos8(az)
|
||||
word wsinc = math.sin8(az)
|
||||
|
||||
word wcosa_sinb = wcosa*wsinb / 128
|
||||
word wsina_sinb = wsina*wsinb / 128
|
||||
|
||||
word Axx = wcosa*wcosb / 128
|
||||
word Axy = (wcosa_sinb*wsinc - wsina*wcosc) / 128
|
||||
word Axz = (wcosa_sinb*wcosc + wsina*wsinc) / 128
|
||||
word Ayx = wsina*wcosb / 128
|
||||
word Ayy = (wsina_sinb*wsinc + wcosa*wcosc) / 128
|
||||
word Ayz = (wsina_sinb*wcosc - wcosa*wsinc) / 128
|
||||
word Azx = -wsinb
|
||||
word Azy = wcosb*wsinc / 128
|
||||
word Azz = wcosb*wcosc / 128
|
||||
|
||||
ubyte @zp i
|
||||
for i in 0 to shipdata.totalNumberOfPoints-1 {
|
||||
; don't normalize by dividing by 128, instead keep some precision for perspective calc later
|
||||
rotatedx[i] = Axx*shipdata.xcoor[i] + Axy*shipdata.ycoor[i] + Axz*shipdata.zcoor[i]
|
||||
rotatedy[i] = Ayx*shipdata.xcoor[i] + Ayy*shipdata.ycoor[i] + Ayz*shipdata.zcoor[i]
|
||||
rotatedz[i] = Azx*shipdata.xcoor[i] + Azy*shipdata.ycoor[i] + Azz*shipdata.zcoor[i]
|
||||
}
|
||||
}
|
||||
|
||||
const uword screen_width = 320
|
||||
const ubyte screen_height = 240
|
||||
|
||||
@ -126,12 +88,12 @@ _ones pla
|
||||
for i in shipdata.totalNumberOfEdges -1 downto 0 {
|
||||
ubyte @zp vFrom = shipdata.edgesFrom[i]
|
||||
ubyte @zp vTo = shipdata.edgesTo[i]
|
||||
word persp1 = 200 + rotatedz[vFrom]/256
|
||||
word persp2 = 200 + rotatedz[vTo]/256
|
||||
cx16.GRAPH_draw_line(rotatedx[vFrom] / persp1 + screen_width/2 as uword,
|
||||
rotatedy[vFrom] / persp1 + screen_height/2 as uword,
|
||||
rotatedx[vTo] / persp2 + screen_width/2 as uword,
|
||||
rotatedy[vTo] / persp2 + screen_height/2 as uword)
|
||||
word persp1 = 200 + matrix_math.rotatedz[vFrom]/256
|
||||
word persp2 = 200 + matrix_math.rotatedz[vTo]/256
|
||||
cx16.GRAPH_draw_line(matrix_math.rotatedx[vFrom] / persp1 + screen_width/2 as uword,
|
||||
matrix_math.rotatedy[vFrom] / persp1 + screen_height/2 as uword,
|
||||
matrix_math.rotatedx[vTo] / persp2 + screen_width/2 as uword,
|
||||
matrix_math.rotatedy[vTo] / persp2 + screen_height/2 as uword)
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +105,7 @@ _ones pla
|
||||
ubyte @zp pointIdx = 0
|
||||
ubyte faceNumber
|
||||
for faceNumber in shipdata.totalNumberOfFaces -1 downto 0 {
|
||||
if facing_away(pointIdx) {
|
||||
if matrix_math.facing_away(pointIdx) {
|
||||
; don't draw this face, fast-forward over the edges and points
|
||||
edgeIdx += 3 ; every face hast at least 3 edges
|
||||
while shipdata.facesEdges[edgeIdx]!=255 {
|
||||
@ -183,6 +145,62 @@ _ones pla
|
||||
}
|
||||
}
|
||||
|
||||
ubyte[shipdata.totalNumberOfEdges] edgestodraw
|
||||
|
||||
sub draw_edge(ubyte edgeidx) {
|
||||
edgestodraw[edgeidx] = false
|
||||
ubyte vFrom = shipdata.edgesFrom[edgeidx]
|
||||
ubyte vTo = shipdata.edgesTo[edgeidx]
|
||||
word persp1 = 170 + matrix_math.rotatedz[vFrom]/256
|
||||
word persp2 = 170 + matrix_math.rotatedz[vTo]/256
|
||||
cx16.GRAPH_draw_line(matrix_math.rotatedx[vFrom] / persp1 + screen_width/2 as uword,
|
||||
matrix_math.rotatedy[vFrom] / persp1 + screen_height/2 as uword,
|
||||
matrix_math.rotatedx[vTo] / persp2 + screen_width/2 as uword,
|
||||
matrix_math.rotatedy[vTo] / persp2 + screen_height/2 as uword)
|
||||
}
|
||||
}
|
||||
|
||||
matrix_math {
|
||||
%option verafxmuls ; accellerate all word-multiplications in this block using Vera FX hardware muls
|
||||
|
||||
; storage for rotated coordinates
|
||||
word[shipdata.totalNumberOfPoints] @split rotatedx
|
||||
word[shipdata.totalNumberOfPoints] @split rotatedy
|
||||
word[shipdata.totalNumberOfPoints] @split rotatedz
|
||||
|
||||
sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) {
|
||||
; rotate around origin (0,0,0)
|
||||
|
||||
; set up the 3d rotation matrix values
|
||||
word wcosa = math.cos8(ax)
|
||||
word wsina = math.sin8(ax)
|
||||
word wcosb = math.cos8(ay)
|
||||
word wsinb = math.sin8(ay)
|
||||
word wcosc = math.cos8(az)
|
||||
word wsinc = math.sin8(az)
|
||||
|
||||
word wcosa_sinb = wcosa*wsinb / 128
|
||||
word wsina_sinb = wsina*wsinb / 128
|
||||
|
||||
word Axx = wcosa*wcosb / 128
|
||||
word Axy = (wcosa_sinb*wsinc - wsina*wcosc) / 128
|
||||
word Axz = (wcosa_sinb*wcosc + wsina*wsinc) / 128
|
||||
word Ayx = wsina*wcosb / 128
|
||||
word Ayy = (wsina_sinb*wsinc + wcosa*wcosc) / 128
|
||||
word Ayz = (wsina_sinb*wcosc - wcosa*wsinc) / 128
|
||||
word Azx = -wsinb
|
||||
word Azy = wcosb*wsinc / 128
|
||||
word Azz = wcosb*wcosc / 128
|
||||
|
||||
ubyte @zp i
|
||||
for i in 0 to shipdata.totalNumberOfPoints-1 {
|
||||
; don't normalize by dividing by 128, instead keep some precision for perspective calc later
|
||||
rotatedx[i] = Axx*shipdata.xcoor[i] + Axy*shipdata.ycoor[i] + Axz*shipdata.zcoor[i]
|
||||
rotatedy[i] = Ayx*shipdata.xcoor[i] + Ayy*shipdata.ycoor[i] + Ayz*shipdata.zcoor[i]
|
||||
rotatedz[i] = Azx*shipdata.xcoor[i] + Azy*shipdata.ycoor[i] + Azz*shipdata.zcoor[i]
|
||||
}
|
||||
}
|
||||
|
||||
sub facing_away(ubyte edgePointsIdx) -> bool {
|
||||
; simplistic visibility determination by checking the Z component of the surface normal
|
||||
; TODO: actually take the line of sight vector into account
|
||||
@ -199,20 +217,6 @@ _ones pla
|
||||
word p3y = rotatedy[p3] / 128
|
||||
return (p2x-p3x)*(p1y-p3y) - (p2y-p3y)*(p1x-p3x) > 0
|
||||
}
|
||||
|
||||
ubyte[shipdata.totalNumberOfEdges] edgestodraw
|
||||
|
||||
sub draw_edge(ubyte edgeidx) {
|
||||
edgestodraw[edgeidx] = false
|
||||
ubyte vFrom = shipdata.edgesFrom[edgeidx]
|
||||
ubyte vTo = shipdata.edgesTo[edgeidx]
|
||||
word persp1 = 170 + rotatedz[vFrom]/256
|
||||
word persp2 = 170 + rotatedz[vTo]/256
|
||||
cx16.GRAPH_draw_line(rotatedx[vFrom] / persp1 + screen_width/2 as uword,
|
||||
rotatedy[vFrom] / persp1 + screen_height/2 as uword,
|
||||
rotatedx[vTo] / persp2 + screen_width/2 as uword,
|
||||
rotatedy[vTo] / persp2 + screen_height/2 as uword)
|
||||
}
|
||||
}
|
||||
|
||||
shipdata {
|
||||
|
@ -3,6 +3,59 @@
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
|
||||
uword anglex
|
||||
uword angley
|
||||
uword anglez
|
||||
|
||||
repeat {
|
||||
matrix_math.rotate_vertices(msb(anglex), msb(angley), msb(anglez))
|
||||
txt.clear_screenchars(' ')
|
||||
draw_edges()
|
||||
anglex+=500
|
||||
angley+=215
|
||||
anglez+=453
|
||||
sys.waitvsync()
|
||||
}
|
||||
}
|
||||
|
||||
sub draw_edges() {
|
||||
|
||||
; plot the points of the 3d cube
|
||||
; first the points on the back, then the points on the front (painter algorithm)
|
||||
|
||||
ubyte @zp i
|
||||
word @zp rz
|
||||
word @zp persp
|
||||
byte sx
|
||||
byte sy
|
||||
|
||||
for i in 0 to len(matrix_math.xcoor)-1 {
|
||||
rz = matrix_math.rotatedz[i]
|
||||
if rz >= 10 {
|
||||
persp = 400 + rz/64
|
||||
sx = matrix_math.rotatedx[i] / persp as byte + txt.DEFAULT_WIDTH/2
|
||||
sy = matrix_math.rotatedy[i] / persp as byte + txt.DEFAULT_HEIGHT/2
|
||||
txt.setcc(sx as ubyte, sy as ubyte, 46, 7)
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0 to len(matrix_math.xcoor)-1 {
|
||||
rz = matrix_math.rotatedz[i]
|
||||
if rz < 10 {
|
||||
persp = 400 + rz/64
|
||||
sx = matrix_math.rotatedx[i] / persp as byte + txt.DEFAULT_WIDTH/2
|
||||
sy = matrix_math.rotatedy[i] / persp as byte + txt.DEFAULT_HEIGHT/2
|
||||
txt.setcc(sx as ubyte, sy as ubyte, 81, 7)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matrix_math {
|
||||
%option verafxmuls ; accellerate all word-multiplications in this block using Vera FX hardware muls
|
||||
|
||||
; vertices
|
||||
word[] @split xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
|
||||
word[] @split ycoor = [ -40, -40, 40, 40, -40, -40, 40, 40 ]
|
||||
@ -13,24 +66,6 @@ main {
|
||||
word[len(ycoor)] @split rotatedy
|
||||
word[len(zcoor)] @split rotatedz
|
||||
|
||||
sub start() {
|
||||
|
||||
uword anglex
|
||||
uword angley
|
||||
uword anglez
|
||||
|
||||
repeat {
|
||||
rotate_vertices(msb(anglex), msb(angley), msb(anglez))
|
||||
txt.clear_screenchars(' ')
|
||||
draw_edges()
|
||||
anglex+=500
|
||||
angley+=215
|
||||
anglez+=453
|
||||
sys.waitvsync()
|
||||
sys.waitvsync()
|
||||
}
|
||||
}
|
||||
|
||||
sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) {
|
||||
; rotate around origin (0,0,0)
|
||||
|
||||
@ -64,35 +99,4 @@ main {
|
||||
}
|
||||
}
|
||||
|
||||
sub draw_edges() {
|
||||
|
||||
; plot the points of the 3d cube
|
||||
; first the points on the back, then the points on the front (painter algorithm)
|
||||
|
||||
ubyte @zp i
|
||||
word @zp rz
|
||||
word @zp persp
|
||||
byte sx
|
||||
byte sy
|
||||
|
||||
for i in 0 to len(xcoor)-1 {
|
||||
rz = rotatedz[i]
|
||||
if rz >= 10 {
|
||||
persp = 400 + rz/64
|
||||
sx = rotatedx[i] / persp as byte + txt.DEFAULT_WIDTH/2
|
||||
sy = rotatedy[i] / persp as byte + txt.DEFAULT_HEIGHT/2
|
||||
txt.setcc(sx as ubyte, sy as ubyte, 46, 7)
|
||||
}
|
||||
}
|
||||
|
||||
for i in 0 to len(xcoor)-1 {
|
||||
rz = rotatedz[i]
|
||||
if rz < 10 {
|
||||
persp = 400 + rz/64
|
||||
sx = rotatedx[i] / persp as byte + txt.DEFAULT_WIDTH/2
|
||||
sy = rotatedy[i] / persp as byte + txt.DEFAULT_HEIGHT/2
|
||||
txt.setcc(sx as ubyte, sy as ubyte, 81, 7)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user