mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +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 test_stack
|
||||||
%import conv
|
%import conv
|
||||||
%import math
|
%import math
|
||||||
|
%import verafx
|
||||||
|
|
||||||
; TODO add all other Elite's ships, show their name, advance to next ship on keypress
|
; TODO add all other Elite's ships, show their name, advance to next ship on keypress
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
; storage for rotated coordinates
|
|
||||||
word[shipdata.totalNumberOfPoints] @split rotatedx
|
|
||||||
word[shipdata.totalNumberOfPoints] @split rotatedy
|
|
||||||
word[shipdata.totalNumberOfPoints] @split rotatedz
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
uword anglex
|
uword anglex
|
||||||
uword angley
|
uword angley
|
||||||
@ -24,11 +19,11 @@ main {
|
|||||||
print_ship_name()
|
print_ship_name()
|
||||||
|
|
||||||
repeat {
|
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)
|
verafx.clear(0, 320*10, 0, 320*(220/4))
|
||||||
; cx16.GRAPH_clear()
|
; cx16.GRAPH_set_colors(0, 0, 0)
|
||||||
cx16.GRAPH_draw_rect(32, 10, 256, 220, 0, true)
|
; cx16.GRAPH_draw_rect(32, 10, 256, 220, 0, true)
|
||||||
|
|
||||||
cx16.GRAPH_set_colors(1, 0, 0)
|
cx16.GRAPH_set_colors(1, 0, 0)
|
||||||
draw_lines_hiddenremoval()
|
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 uword screen_width = 320
|
||||||
const ubyte screen_height = 240
|
const ubyte screen_height = 240
|
||||||
|
|
||||||
@ -126,12 +88,12 @@ _ones pla
|
|||||||
for i in shipdata.totalNumberOfEdges -1 downto 0 {
|
for i in shipdata.totalNumberOfEdges -1 downto 0 {
|
||||||
ubyte @zp vFrom = shipdata.edgesFrom[i]
|
ubyte @zp vFrom = shipdata.edgesFrom[i]
|
||||||
ubyte @zp vTo = shipdata.edgesTo[i]
|
ubyte @zp vTo = shipdata.edgesTo[i]
|
||||||
word persp1 = 200 + rotatedz[vFrom]/256
|
word persp1 = 200 + matrix_math.rotatedz[vFrom]/256
|
||||||
word persp2 = 200 + rotatedz[vTo]/256
|
word persp2 = 200 + matrix_math.rotatedz[vTo]/256
|
||||||
cx16.GRAPH_draw_line(rotatedx[vFrom] / persp1 + screen_width/2 as uword,
|
cx16.GRAPH_draw_line(matrix_math.rotatedx[vFrom] / persp1 + screen_width/2 as uword,
|
||||||
rotatedy[vFrom] / persp1 + screen_height/2 as uword,
|
matrix_math.rotatedy[vFrom] / persp1 + screen_height/2 as uword,
|
||||||
rotatedx[vTo] / persp2 + screen_width/2 as uword,
|
matrix_math.rotatedx[vTo] / persp2 + screen_width/2 as uword,
|
||||||
rotatedy[vTo] / persp2 + screen_height/2 as uword)
|
matrix_math.rotatedy[vTo] / persp2 + screen_height/2 as uword)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +105,7 @@ _ones pla
|
|||||||
ubyte @zp pointIdx = 0
|
ubyte @zp pointIdx = 0
|
||||||
ubyte faceNumber
|
ubyte faceNumber
|
||||||
for faceNumber in shipdata.totalNumberOfFaces -1 downto 0 {
|
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
|
; don't draw this face, fast-forward over the edges and points
|
||||||
edgeIdx += 3 ; every face hast at least 3 edges
|
edgeIdx += 3 ; every face hast at least 3 edges
|
||||||
while shipdata.facesEdges[edgeIdx]!=255 {
|
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 {
|
sub facing_away(ubyte edgePointsIdx) -> bool {
|
||||||
; simplistic visibility determination by checking the Z component of the surface normal
|
; simplistic visibility determination by checking the Z component of the surface normal
|
||||||
; TODO: actually take the line of sight vector into account
|
; TODO: actually take the line of sight vector into account
|
||||||
@ -199,20 +217,6 @@ _ones pla
|
|||||||
word p3y = rotatedy[p3] / 128
|
word p3y = rotatedy[p3] / 128
|
||||||
return (p2x-p3x)*(p1y-p3y) - (p2y-p3y)*(p1x-p3x) > 0
|
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 {
|
shipdata {
|
||||||
|
@ -3,6 +3,59 @@
|
|||||||
|
|
||||||
main {
|
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
|
; vertices
|
||||||
word[] @split xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
|
word[] @split xcoor = [ -40, -40, -40, -40, 40, 40, 40, 40 ]
|
||||||
word[] @split ycoor = [ -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(ycoor)] @split rotatedy
|
||||||
word[len(zcoor)] @split rotatedz
|
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) {
|
sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) {
|
||||||
; rotate around origin (0,0,0)
|
; 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