I've had this sitting around and noticed I never shared it.
Renders a white polygon to an image. (uncomment one of the /////// sections to see the effect of setting various points)
setSyncRate(0, 0)
setVirtualResolution(480, 480) //my setup.agc is set to 480 by 480
global pNm : pNm = 64 //number of points you'll be using
global width : width = 300 //image width
global height : height = 300 //image height
gosub initPolygon
global polySpr : polySpr = createSprite(polyImg)
setSpritePositionByOffset(polySpr, 240, 240)
///////
for i = 0 to pNm-1
p[i].x# = 100*cos(360.0*i/(pNm-1.0))+150
p[i].y# = 100*sin(360.0*i/(pNm-1.0))+150
next i
gosub renderPolygon
setSpriteImage(polySpr, polyImage) //update image
///////
do
///////
/*
for i = 0 to pNm-1
p[i].x# = (1+0.2*sin(timer()*8*i))* 100*cos(360.0*i/(pNm-1.0))+150
p[i].y# = (1+0.2*sin(timer()*8*i))* 100*sin(360.0*i/(pNm-1.0))+150
next i
gosub renderPolygon
setSpriteImage(polySpr, polyImage) //update image
*/
///////
print(screenFPS())
sync()
loop
initPolygon:
type point_UDT
x#
y#
endtype
dim p[pNm] as point_UDT
global mem : mem = createMemblock(12+4*width*height)
setMemblockInt(mem, 0, width)
setMemblockInt(mem, 4, height)
setMemblockInt(mem, 8, 32)
global polyImg : polyImg = createImageFromMemblock(mem) //the image to work with
return
renderPolygon:
//calculate bounds
minID = 0
for i = 0 to pNm-1
if p[i].y# < p[minID].y# then minID = i
next i
maxID = 0
for i = 0 to pNm-1
if p[i].y# > p[maxID].y# then maxID = i
next i
minY = p[minID].y#
maxY = p[maxID].y#
minID = 0
for i = 0 to pNm-1
if p[i].x# < p[minID].x# then minID = i
next i
maxID = 0
for i = 0 to pNm-1
if p[i].x# > p[maxID].x# then maxID = i
next i
minX = p[minID].x#
maxX = p[maxID].x#
if minX < 0 then minX = 0
if minY < 0 then minY = 0
if maxX > width then maxX = width
if maxY > height then maxY = height
if maxX < 0 then maxX = 0
if maxY < 0 then maxY = 0
if minX > width then minX = width
if minY > height then minY = height
dim nodeX[pNm] as float
for pixelY = 0 to minY-1 //set all entirely empty rows to be clear
memIndex = 12+4*pixelY*width
for a = 0 to width-1
memIndex = memIndex+3
setMemblockByte(mem, memIndex, 0) : memIndex = memIndex+1
next a
next pixelY
for pixelY = minY to maxY-1
nodes = 0
j = pNm-1 //build nodes
for i = 0 to pNm-1
if p[i].y# < pixelY and p[j].y# >= pixelY or p[j].y# < pixelY and p[i].y# >= pixelY
nodeX[nodes] = p[i].x#+(pixelY+0.0-p[i].y#)/(p[j].y#-p[i].y#)*(p[j].x#-p[i].x#)
nodes = nodes+1
endif
j = i
next i
i = 0 //sort nodes
while i < nodes-1
if nodeX[i] > nodeX[i+1]
swp# = nodeX[i]
nodeX[i] = nodeX[i+1]
nodeX[i+1] = swp#
if i <> 0 then i = i-1
else
i = i+1
endif
endwhile
memIndex = 12+4*pixelY*width
for a = 0 to width-1 //clear this row to be redrawn (or remove this chunk of code and draw empty parts alongside opaque parts in the code block below it)
memIndex = memIndex+3
setMemblockByte(mem, memIndex, 0) : memIndex = memIndex+1
next a
stop = 0 //draw nodes (if in range)
for i = 0 to nodes-1 step 2
if nodeX[i] > maxX then stop = 1
if stop <> 1 //break if following nodes will exceed range
if nodeX[i+1] > minX
if nodeX[i] < minX then nodeX[i] = minX
if nodeX[i+1] > maxX then nodeX[i+1] = maxX
memIndex = 12+4*pixelY*width+4*trunc(nodeX[i])
top = trunc(nodeX[i+1]-1)+1
if top > width-1 then top = width-1
for a = trunc(nodeX[i]) to top
setMemblockByte(mem, memIndex, 255) : memIndex = memIndex+1
setMemblockByte(mem, memIndex, 255) : memIndex = memIndex+1
setMemblockByte(mem, memIndex, 255) : memIndex = memIndex+1
alpha = 255
if a = trunc(nodeX[i]) then alpha = 255-(nodeX[i]-trunc(nodeX[i]))*255
if a = top then alpha = (nodeX[i+1]-top)*255
if top = width then alpha = 255
setMemblockByte(mem, memIndex, alpha) : memIndex = memIndex+1
next a
endif
endif
next i
next pixelY
for pixelY = maxY to height-1 //set the rest of the rows to be empty
memIndex = 12+4*pixelY*width
for a = 0 to width-1
memIndex = memIndex+3
setMemblockByte(mem, memIndex, 0) : memIndex = memIndex+1
next a
next pixelY
polyImage = createImageFromMemblock(mem)
return
Renders an image from a set of points and another (potentially tileable) image.
setSyncRate(0, 0)
setVirtualResolution(480, 480) //my setup.agc is set to 480 by 480
global pNm : pNm = 64+2 //number of points you'll be using
global sourceImage : sourceImage = loadImage("source.jpg")
global tileRptX : tileRptX = 15 //number of times to repeat in the X direction
global tileRptY : tileRptY = 15 //number of times to repeat in the Y direction
gosub initPolygon
global polySpr : polySpr = createSprite(polyImg)
setSpritePositionByOffset(polySpr, 240, 240)
///////
for i = 0 to pNm-1 -2
p[i].x# = i*10
p[i].y# = 15*sin(4*360*i/(pNm-1.0-2))+300
next i
p[64].x# = (pNm-3)*10
p[64].y# = 480
p[65].y# = 0
p[65].y# = 480
gosub renderPolygon
setSpriteImage(polySpr, polyImage) //update image
///////
do
///////
/*
for i = 0 to pNm-1
p[i].x# = (1+0.2*sin(timer()*8*i))* 100*cos(360.0*i/(pNm-1.0))+150
p[i].y# = (1+0.2*sin(timer()*8*i))* 100*sin(360.0*i/(pNm-1.0))+150
next i
gosub renderPolygon
setSpriteImage(polySpr, polyImage) //update image
*/
///////
/*
for i = 0 to pNm-1
p[i].x# = 100*cos(360*i/(pNm+0.0))+getPointerX()
p[i].y# = 100*sin(360*i/(pNm+0.0))+getPointerY()
next i
gosub renderPolygon
setSpriteImage(polySpr, polyImage) //update image
*/
print(screenFPS())
sync()
loop
initPolygon:
type point_UDT
x#
y#
endtype
dim p[pNm] as point_UDT
global sourceMem : sourceMem = createMemblockFromImage(sourceImage)
global width : width = getMemblockInt(sourceMem, 0)*tileRptX //image width
global height : height = getMemblockInt(sourceMem, 4)*tileRptY //image height
global mem : mem = createMemblock(12+4*width*height)
setMemblockInt(mem, 0, width)
setMemblockInt(mem, 4, height)
setMemblockInt(mem, 8, 32)
global polyImg : polyImg = createImageFromMemblock(mem) //the image to work with
return
renderPolygon:
//calculate bounds
minID = 0
for i = 0 to pNm-1
if p[i].y# < p[minID].y# then minID = i
next i
maxID = 0
for i = 0 to pNm-1
if p[i].y# > p[maxID].y# then maxID = i
next i
minY = p[minID].y#
maxY = p[maxID].y#
minID = 0
for i = 0 to pNm-1
if p[i].x# < p[minID].x# then minID = i
next i
maxID = 0
for i = 0 to pNm-1
if p[i].x# > p[maxID].x# then maxID = i
next i
minX = p[minID].x#
maxX = p[maxID].x#
if minX < 0 then minX = 0
if minY < 0 then minY = 0
if maxX > width then maxX = width
if maxY > height then maxY = height
if maxX < 0 then maxX = 0
if maxY < 0 then maxY = 0
if minX > width then minX = width
if minY > height then minY = height
dim nodeX[pNm] as float
for pixelY = 0 to minY-1 //set all entirely empty rows to be clear
memIndex = 12+4*pixelY*width
for a = 0 to width-1
memIndex = memIndex+3
setMemblockByte(mem, memIndex, 0) : memIndex = memIndex+1
next a
next pixelY
for pixelY = minY to maxY-1
nodes = 0
j = pNm-1 //build nodes
for i = 0 to pNm-1
if p[i].y# < pixelY and p[j].y# >= pixelY or p[j].y# < pixelY and p[i].y# >= pixelY
nodeX[nodes] = p[i].x#+(pixelY+0.0-p[i].y#)/(p[j].y#-p[i].y#)*(p[j].x#-p[i].x#)
nodes = nodes+1
endif
j = i
next i
i = 0 //sort nodes
while i < nodes-1
if nodeX[i] > nodeX[i+1]
swp# = nodeX[i]
nodeX[i] = nodeX[i+1]
nodeX[i+1] = swp#
if i <> 0 then i = i-1
else
i = i+1
endif
endwhile
memIndex = 12+4*pixelY*width
for a = 0 to width-1 //clear this row to be redrawn (or remove this chunk of code and draw empty parts alongside opaque parts in the code block below it)
memIndex = memIndex+3
setMemblockByte(mem, memIndex, 0) : memIndex = memIndex+1
next a
stop = 0 //draw nodes (if in range)
for i = 0 to nodes-1 step 2
if nodeX[i] > maxX then stop = 1
if stop <> 1 //break if following nodes will exceed range
if nodeX[i+1] > minX
if nodeX[i] < minX then nodeX[i] = minX
if nodeX[i+1] > maxX then nodeX[i+1] = maxX
memIndex = 12+4*pixelY*width+4*trunc(nodeX[i])
top = trunc(nodeX[i+1]-1)+1
if top > width-1 then top = width-1
for a = trunc(nodeX[i]) to top
sourceIndex = 12+4*mod(pixelY, getMemblockInt(sourceMem, 4))*getMemblockInt(sourceMem, 0)+4*mod(trunc(a), getMemblockInt(sourceMem, 0))
setMemblockByte(mem, memIndex, getMemblockByte(sourceMem, sourceIndex)) : memIndex = memIndex+1 : sourceIndex = sourceIndex+1
setMemblockByte(mem, memIndex, getMemblockByte(sourceMem, sourceIndex)) : memIndex = memIndex+1 : sourceIndex = sourceIndex+1
setMemblockByte(mem, memIndex, getMemblockByte(sourceMem, sourceIndex)) : memIndex = memIndex+1 : sourceIndex = sourceIndex+1
alpha = 255
if a = trunc(nodeX[i]) then alpha = (1-(nodeX[i]-trunc(nodeX[i])))*getMemblockByte(sourceMem, sourceIndex)
if a = top then alpha = (nodeX[i+1]-top)*255
if top = width then alpha = 255
setMemblockByte(mem, memIndex, alpha) : memIndex = memIndex+1 : sourceIndex = sourceIndex+1
next a
endif
endif
next i
next pixelY
for pixelY = maxY to height-1 //set the rest of the rows to be empty
memIndex = 12+4*pixelY*width
for a = 0 to width-1
memIndex = memIndex+3
setMemblockByte(mem, memIndex, 0) : memIndex = memIndex+1
next a
next pixelY
polyImage = createImageFromMemblock(mem)
return
Once again you can uncomment the divided sections and comment out the others to see some example effects. For the second piece of code I've attached the source image I have been using. It isn't mine, but helps to test.