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. |