03-03-2024, 10:49 AM
I wrote a quick prototype of drawing images with arbitrary rotation and scaling in n7. The code may look a bit too complicated for just drawing a transformed image. But when I add this stuff to the core (implement it in C and add new commands to n7), I will also let you draw textured polygons with any number of points. Here I just draw a textured rectangle, four points.
It's slow, but it's gonna get a lot faster, of course.
I'm already thinking about adding support for z coordinates and perspective correct interpolation (for polygons). Would be fun to allow some 3d rendering as in naalaa 5.
It's slow, but it's gonna get a lot faster, of course.
I'm already thinking about adding support for z coordinates and perspective correct interpolation (for polygons). Would be fun to allow some 3d rendering as in naalaa 5.
Code:
include "list.n7"
'#win32
#dbg
visible vPoints = fill([x: 0, y: 0, u: 0, v: 0], 4)
visible vXval = List()
vXval.Add([0, 0, 0])
vXval.Add([0, 0, 0])
set window "test", 640, 480
set redraw off
img = loadimage("logo.png")
pln width(img) + ", " + height(img)
a = 0
while not keydown(KEY_ESCAPE, true)
a = (a + 1)%360
set color 0, 0, 0
cls
set color 255, 255, 255, 0
' DrawImageTransformed(image, x, y, scale_x, scaleY, angle, pivot_x, pivot_y)
' draw scaled and centered (= pivot at center of image).
DrawImageTransformed(img, 120, 240, 2, 2, 0, width(img)/2, height(img)/2)
' draw rotated and centered
DrawImageTransformed(img, 320, 240, 1, 1, rad(a), width(img)/2, height(img)/2)
' draw rotated and scaled but put pivot at top left corner of image.
DrawImageTransformed(img, 520, 240, 4, 4, rad(a), 0, 0)
redraw
fwait 60
wend
function DrawImageTransformed(img, drawX, drawY, scaleX, scaleY, angle, pivotX, pivotY)
srcX = 0
srcY = 0
srcW = width(img)
srcH = height(img)
xLeft = -pivotX*scaleX
xRight = (srcW - pivotX)*scaleX
yTop = -pivotY*scaleY
yBottom = (srcH - pivotY)*scaleY
vPoints[0].x = xLeft; vPoints[0].y = yTop; vPoints[0].u = 0; vPoints[0].v = 0
vPoints[1].x = xRight; vPoints[1].y = yTop; vPoints[1].u = 1; vPoints[1].v = 0
vPoints[2].x = xRight; vPoints[2].y = yBottom; vPoints[2].u = 1; vPoints[2].v = 1
vPoints[3].x = xLeft; vPoints[3].y = yBottom; vPoints[3].u = 0; vPoints[3].v = 1
for i = 0 to sizeof(vPoints) - 1
x = vPoints[i].x*cos(angle) - vPoints[i].y*sin(angle)
y = vPoints[i].y*cos(angle) + vPoints[i].x*sin(angle)
vPoints[i].x = round(drawX + x)
vPoints[i].y = round(drawY + y)
if i = 0
minX = vPoints[i].x
maxX = vPoints[i].x
minY = vPoints[i].y
maxY = vPoints[i].y
else
minX = min(vPoints[i].x, minX)
maxX = max(vPoints[i].x, maxX)
minY = min(vPoints[i].y, minY)
maxY = max(vPoints[i].y, maxY)
endif
next
if maxX < 0 or minX >= width(primary) or maxY < 0 or minY >= height(primary) return
set color 255, 255, 255, 0
for y = minY to maxY
numx = 0
for i = 0 to sizeof(vPoints) - 1
p0 = vPoints[i]
p1 = vPoints[(i + 1)%sizeof(vPoints)]
if p0.y <= y and p1.y > y or
p0.y > y and p1.y <= y
dy = p1.y - p0.y
if dy = 0
vXval[numx][0] = p0.x; vXval[numx][1] = p0.u; vXval[numx][2] = p0.v
numx = numx + 1
vXval[numx][0] = p1.x; vXval[numx][1] = p1.u; vXval[numx][2] = p1.v
numx = numx + 1
else
f = (y - p0.y)/(p1.y - p0.y)
vXval[numx][0] = p0.x + f*(p1.x - p0.x)
vXval[numx][1] = p0.u + f*(p1.u - p0.u)
vXval[numx][2] = p0.v + f*(p1.v - p0.v)
numx = numx + 1
endif
endif
next
if numx
vXval.size = numx
vXval.SortByField(0, vXval.ASCENDING)
for i = 0 to vXval.size - 2 step 2
draw hraster img, y, vXval[i][0], vXval[i + 1][0],
vXval[i][1], vXval[i][2], vXval[i + 1][1], vXval[i + 1][2]
next
endif
next
draw poly vPoints, false
endfunc