transparent png to polygon converter - solved
Monkey Forums/Monkey Programming/transparent png to polygon converter - solved
| ||
| edit: solved and created a module here: http://www.monkey-x.com/Community/posts.php?topic=9748 H! I'm now using a simple RectColl() detection but for several objects in my game I need a other Coll detection. For example, take this road sign picture: The mouse over is only allowed when the cursor is on the sign, and not outside it. (with a rect detection it's not oke) There are several options to solve this problem, and I thought this is the best that I need. - Load the image in monkey and create a polygon outline using the png alpha. Then after that, store that polygon inside the memory and use that when needed, for example to check if the mouse is inside the polygon. I'm searching and find some java things, but I don't understand how to convert that to monkey code. Here is the fastest example. (it don't have to be accurate) http://stackoverflow.com/questions/7052422/image-graphic-into-a-shape http://stackoverflow.com/questions/15342083/algorithm-to-make-a-polygon-from-transparent-png-sprite When the polygon is inside the memory, than its possible to rotate/scale it with the image if needed :) I'm wondering if this is possible in monkey. |
| ||
| You can bake SVG polygons using a vector trace algo built into a program like Illustrator, then do some fudging with the data to bake polygons from it. This can be automated into your build chain using an illustrator script or something of that nature. I'm not sure how it's done in other programs, but once you have that data, it can be used in your other projects. That's a lot of effort, however. Since you're only looking for mouse hover data, it sounds like you only need to text against one pixel for a collision mask. If that's the case, a polygon type collission is not necessary -- you can do a pixel test on the mouse's underlying pixel either by siphoning raw alpha data from the image (say using nDrawExts2), or by baking raw alpha masks from your sprites and incorporating that into your build chain. The latter would allow you to do a threshold test without any serious magic voodoo, just load the raw data into a DataBuffer and use ReadByte() to test if the value is >0. (Signed ints mean this is a simple >127 alpha threshold) |
| ||
| you talk voodoo to me haha, I know the only fact is that I want to extract/use the alpha to be ignored when mouse over. So its possible to read bytes() to detect if its transparent ? every byte is a pixel I assume ? I will check you nDrawExts2 later, to figure this out. Thanks for the info. SVG polygons sounds overkill indeed, and I don't want to use extra program's if not needed. Btw is nDrawExts2 for desktop/ios and android ? |
| ||
| desktop, ios, and android yes. All OpenGL targets. I do not provide support for this module, however. You can read bytes from a specially-crafted alpha mask. You have to create it yourself using photoshop or another tool, or pull the alpha bits directly from the image at runtime using something like nDrawExts2. I recommend not creating the mask at runtime, since it could be slow depending on how many pixels you'd have to read. |
| ||
| I did this once, for a mini HOG. What I did? I took all images, opened them up in PSP7, and with the drawing tool I plotted a polygon on top of it, keeping nots of every x,y pair I placed a vertex. Then, used those vertex in code, and with a "point inside polygon" function checked the collision. Worked well and it was fast enough on the dev-side for me :) If you don't want to do it manually, just write a tool to do that instead - should be simple to record MouseHit() and record positions. |
| ||
| You could try my pixel perfect collision detection module "Collision Mask Module": http://www.loadcode.co.uk/software/monkey-x-software/collision-mask-module/ |
| ||
| Maybe this can help you: http://www.monkey-x.com/Community/posts.php?topic=2571 |
| ||
| @Powelly That was the first 'thing' I found, but first i'm trying to do this in monkey only with-out extra tools @Jesse I will have a look |
| ||
| Update. 2 hours later I think its fast and possible to create this using monkey. What my code does: - scanning an image from top left to bottom right - when its alpha is 0 then it remembers the x,y coordinate till the alpha is not 0 - so at the end I have some outlines - part 2 is to compress the data and create only the necessary x,y dots (the green dots) - part 3 is to display a polygon using that coordinates (fails here) I have all the coordinates (green dots) from top left to bottom right and create the polygon like this ' to poly verts ' Function DrawPoly:Int( verts:Float[] ) Local tmpI:Int = 0 For Local point:Point = Eachin points2 verts[tmpI] = point.x tmpI=tmpI+1 verts[tmpI] = point.y tmpI=tmpI+1 Next See what happens. http://postimg.org/image/5ihhjt6mx/ http://postimg.org/image/5sh1n60x3/ Using this image: ![]() All this is possible using gless and using parts from the nDrawExts2 class (thanks Nobuyuki)
Strict
Import mojo
Import opengl.gles11
Function Main:Int()
New MyApp()
Return 0
End
Class MyApp Extends App
Field thing:Sprite
Method OnCreate:Int()
SetUpdateRate(60)
thing = New Sprite()
Return 0
End
Method OnUpdate:Int()
Return 0
End
Method OnRender:Int()
Cls(255,255,255)
thing.Draw(0,0)
Return 0
End
End
Class Sprite
Field image:Image
Field tmp:Image
Field points:Stack<Point> = New Stack<Point>()
Field points2:Stack<Point> = New Stack<Point>()
Field verts:Float[60]
Method New()
image = LoadImage("test-col.png")
Local size:Int[2]
Local data:Int[] = PixelArray.Get("test-col.png", size)
tmp = CreateImage(size[0], size[1])
Local x:Int = 0
Local y:Int = 0
Local prevX:Int = -1
Local prevY:Int = -1
Local testVertical:Bool = False
Local testHorzontal:Bool = True
For Local j:Int = 0 Until data.Length
Local color:Int[] = PixelArray.GetARGB(data[j])
If color[0]>0 Then
Local r:Int = 0
Local g:Int = 0
Local b:Int = 255
Local a:Int = 255
Local color:Int
color |= (a & $FF) Shl 24
color |= (r & $FF) Shl 16
color |= (g & $FF) Shl 8
color |= (b & $FF)
data[j] = color
' transparant END
If testHorzontal Then
points.Push(New Point(x,y))
testVertical = True
testHorzontal = False
end
Else
' transparant START
If testVertical Then
points.Push(New Point(x-1,y))
testVertical = False
testHorzontal = True
End
End
If x=size[0]-1 Then
x = 0
y = y+1
Else
x = x+1
End
Next
' REMOVE STRAIGT LINES...
Local xyMap:FloatMap<Float> = New FloatMap<Float>()
Local endedWithTheSame:Bool = False
Local lastY:Float
Local xMap:FloatMap<Float> = New FloatMap<Float>()
For Local point:Point = Eachin points
If xyMap.Contains(point.x) Then
xMap.Add(point.x,point.y)
endedWithTheSame = True
lastY = point.y
Else
For Local it:=EachIn xMap
Print it.Key+","+it.Value
points2.Push(New Point(it.Key,lastY))
Next
xyMap.Add(point.x,point.y)
points2.Push(New Point(point.x,point.y))
xMap.Clear()
Print ""
End
Next
If endedWithTheSame Then
For Local it:=EachIn xMap
points2.Push(New Point(it.Key,lastY))
Next
End
' to poly verts
' Function DrawPoly:Int( verts:Float[] )
Local tmpI:Int = 0
For Local point:Point = Eachin points2
verts[tmpI] = point.x
tmpI=tmpI+1
verts[tmpI] = point.y
tmpI=tmpI+1
Next
' Print size[1]
tmp.WritePixels(data, 0, 0, size[0], size[1])
End
Method Draw:Void(px:Float, py:Float)
DrawImage(tmp,250,250)
SetColor(255,0,0)
For Local point:Point = Eachin points
DrawPoint(point.x,point.y)
Next
SetColor(0,255,0)
For Local point:Point = Eachin points2
DrawCircle(point.x,point.y,3)
Next
DrawPoly(verts)
End
End
Class Point
Field x:Float
Field y:Float
Method New(_x:Float,_y:Float)
x=_x
y=_y
End
End
Class PixelArray
'Summary: Loads an ARGB image into an array of ints.
Function Get:Int[] (path:String, info:Int[])
Local data:Int[]
Local db:DataBuffer = LoadImageData("monkey://data/" + path, info)
'Local timeSpent:Int = Millisecs()
'Copy the data buffer into an array.
data = data.Resize(db.Length / 4) '32-bits = 4 bytes
'We need to swap bytes of R and B channels around.
For Local i:Int = 0 Until db.Length Step 4
Local j:Int = db.PeekInt(i)
data[i / 4] = (j & $ff000000) | ((j & $00ff0000) Shr 16) | (j & $0000ff00) | ((j & $000000ff) Shl 16)
Next
'Print "Operation took " + (Millisecs() -timeSpent) + "ms"
Return data
End Function
'Summary: Loads a section of an ARGB image into an array of ints.
Function Get:Int[] (path:String, startX:Int, startY:Int, w:Int, h:Int)
Local data:Int[]
Local info:Int[2]
Local db:DataBuffer = LoadImageData("monkey://data/" + path, info)
'Local timeSpent:Int = Millisecs()
'Copy the data buffer into an array.
data = data.Resize(w * h)
'We need to swap bytes of R and B channels around.
For Local y:Int = 0 Until h
For Local x:Int = 0 Until w
Local j:Int = db.PeekInt( ( (startY + y) * info[0] + (startX + x)) * 4)
data[y * w + x] = (j & $ff000000) | ( (j & $00ff0000) Shr 16) | (j & $0000ff00) | ( (j & $000000ff) Shl 16)
Next
Next
'Print "Operation took " + (Millisecs() -timeSpent) + "ms"
Return data
End Function
'Summary: Crops a 1d pixel array to the specified rectangle. Width of image in data must be specified.
Function Crop:Int[] (pixeldata:Int[], strideWidth:Int, startX:Int, startY:Int, w:Int, h:Int)
Local output:Int[w * h]
For Local y:Int = 0 Until h
For Local x:Int = 0 Until w
output[y * w + x] = pixeldata[ (y + startY) * strideWidth + (x + startX)]
Next
Next
Return output
End Function
'Summary: Grabs a color from an ARGB value and returns an array [A,R,G,B].
Function GetARGB:Int[] (argb:Int)
Local out:Int[4]
out[3] = (argb) & $FF
out[2] = (argb Shr 8) & $FF
out[1] = (argb shr 16) & $FF
out[0] = (argb shr 24) & $FF
Return out
End Function
'Summary: Returns an ARGB value from the colors specified.
'' Function ToARGB:Int(a, r, g, b)
'' Return (r Shl 24) + (g Shl 16) + (b Shl 8) + a
' Local color:Int
'' color |= (a & $FF) Shl 24
'' color |= (r & $FF) Shl 16
'' color |= (g & $FF) Shl 8
'' color |= (b & $FF)
'' Return color
'' End Function
Function ToARGB:Int(color:Int[])
Local out:Int
out |= (color[0] & $FF) Shl 24
out |= (color[1] & $FF) Shl 16
out |= (color[2] & $FF) Shl 8
out |= (color[3] & $FF)
Return color
End Function
End Class
|
| ||
| Dunno if you saw this: http://www.monkey-x.com/Community/posts.php?topic=8626 |
| ||
| nope haha, but where can i find your code ? |
| ||
| Doh! Haha, I thought I had posted it up back then! I'll see if I can find it and get it on that thread. |
