Page 2 of 2
Re: Pixel precise object picking
Posted: Fri Oct 05, 2012 8:52 pm
by GarbagePillow
Xgoff wrote:yes, that's a drawback. however, you'd probably need to implement it anyway as a fallback since not everybody's hardware can use canvases, and apparently some can't use shaders either
Good point. Is there some data structure that you would recommend for doing it this way? Something where you could get a list of all the rectangles overlapping a certain point and maybe their draw order too? Also, do you know how common it is for canvases and pixel shaders to not be supported?
Ref wrote:image_data = love.image.newImageData( "images/"..file )
img = G.newImage( image_data )
Thank you, I know how to do that, I was just having trouble visualizing Xgoff's solution.
Re: Pixel precise object picking
Posted: Sat Oct 06, 2012 12:18 am
by Xgoff
GarbagePillow wrote:Xgoff wrote:yes, that's a drawback. however, you'd probably need to implement it anyway as a fallback since not everybody's hardware can use canvases, and apparently some can't use shaders either
Good point. Is there some data structure that you would recommend for doing it this way? Something where you could get a list of all the rectangles overlapping a certain point and maybe their draw order too? Also, do you know how common it is for canvases and pixel shaders to not be supported?
tbqh i'd just take the lazy route and iterate through all of them... for something like picking objects i wouldn't think the performance would be an issue. having to read pixel information from the graphics card like you're doing now is probably much slower
otherwise, maybe a spatial hash would help a little.
hardoncollider conveniently has a separate module for that. i don't know if it handles ordering though
Re: Pixel precise object picking
Posted: Tue Oct 09, 2012 2:57 am
by Ref
GarbagePillow wrote:Xgoff wrote:yes, that's a drawback. however, you'd probably need to implement it anyway as a fallback since not everybody's hardware can use canvases, and apparently some can't use shaders either
Good point. Is there some data structure that you would recommend for doing it this way? Something where you could get a list of all the rectangles overlapping a certain point and maybe their draw order too? Also, do you know how common it is for canvases and pixel shaders to not be supported?
Ref wrote:image_data = love.image.newImageData( "images/"..file )
img = G.newImage( image_data )
Thank you, I know how to do that, I was just having trouble visualizing Xgoff's solution.
Probably missing the point but don't see why this is so complex.
Find attached an old script I wrote for Lua and translated to Love.
May be relivant or not?
Re: Pixel precise object picking
Posted: Wed Oct 10, 2012 7:24 am
by T-Bone
Couldn't you do something like this:
Start by creating a 2D table, each location represents a pixel on screen. Call this "pixels".
Create a table containing information about all images. Call this "images".
For each image, go through the image and for each pixel in the image see if it's transparent or not. If it's not transparent, put a 1 in the "pixels" table in the corresponding position.
If images are moved, recalculate the "pixels" table (don't do this on every love.update, only when you finally place the image down).
If a new image is added, you don't need to recalculate the entire "pixels" table, just add 1:s where needed.
When you press your mouse, you can instantly look up if there's a picture there or not by checking the "pixels" table.
Re: Pixel precise object picking
Posted: Wed Oct 10, 2012 12:39 pm
by GarbagePillow
Ref wrote:GarbagePillow wrote:Xgoff wrote:yes, that's a drawback. however, you'd probably need to implement it anyway as a fallback since not everybody's hardware can use canvases, and apparently some can't use shaders either
Good point. Is there some data structure that you would recommend for doing it this way? Something where you could get a list of all the rectangles overlapping a certain point and maybe their draw order too? Also, do you know how common it is for canvases and pixel shaders to not be supported?
Ref wrote:image_data = love.image.newImageData( "images/"..file )
img = G.newImage( image_data )
Thank you, I know how to do that, I was just having trouble visualizing Xgoff's solution.
Probably missing the point but don't see why this is so complex.
Find attached an old script I wrote for Lua and translated to Love.
May be relivant or not?
That solution does work. The only thing is that it's inefficient for scenes with many objects that don't overlap each other. You end up doing a linear search through a list of objects where most of them wont overlap the point you are querying. It probably doesn't matter if you are doing a picking test every mouseclick. It might not work well if you are doing a picking test every update and have thousands of objects to look through.
Re: Pixel precise object picking
Posted: Wed Oct 10, 2012 12:58 pm
by GarbagePillow
T-Bone wrote:Couldn't you do something like this:
Start by creating a 2D table, each location represents a pixel on screen. Call this "pixels".
Create a table containing information about all images. Call this "images".
For each image, go through the image and for each pixel in the image see if it's transparent or not. If it's not transparent, put a 1 in the "pixels" table in the corresponding position.
If images are moved, recalculate the "pixels" table (don't do this on every love.update, only when you finally place the image down).
If a new image is added, you don't need to recalculate the entire "pixels" table, just add 1:s where needed.
When you press your mouse, you can instantly look up if there's a picture there or not by checking the "pixels" table.
This is basically the solution I am doing, using a canvas instead of a pixel table, and storing object IDs instead of just marking a pixel as not transparent.
Re: Pixel precise object picking
Posted: Fri Oct 12, 2012 6:21 am
by BlackBulletIV
This code comes to mind (not tested):
Code: Select all
function love.load()
img = {}
img.data = love.image.newImageData("image.png") -- ImageData for pixel checking
img.image = love.graphics.newImage(img.data) -- Image object to draw to the screen
img.x = 200 -- example coordinates
img.y = 100
img.width = img.image:getWidth() -- bounding box info; you could use values other than the image's width and height, of course
img.height = img.image:getHeight()
end
function love.mousepressed(x, y, button)
if button == "l" then
-- point-to-rectangle collision detection, determining whether mouse is within the image's bounds
if x >= img.x and y >= img.y and x <= img.x + img.width and y <= img.y + img.height then
local r, g, b, a = img.data:getPixel(x - img.x, y - img.y) -- get the pixel the mouse is pointing at
-- if alpha is over 0, this is a visible pixel; 0 could be replaced with a higher number if you wish
if a > 0 then imageClicked() end
end
end
end
I've commented it for you. Take note that this approach doesn't work if the image is scaled; if it is, you'd probably just have to scale the mouse coordinates to fit.
Re: Pixel precise object picking
Posted: Fri Oct 12, 2012 4:44 pm
by Ref
Ah!
I second BlackBulletIV's suggestion as that is essentually what I did in the above demo (drag_image.love) which does include size change.
Have subsiquently modified it to also include ability to rotate the image & and bounding box.
Re: Pixel precise object picking
Posted: Fri Oct 12, 2012 4:58 pm
by GarbagePillow
Hey guys. I've tested out the imagedata and linear search solution you suggested and you were totally right. It's definitely fast enough for any normal use of object picking. I guess I have a tendency to over engineer solutions sometimes.
Here's the test I did picking through 10,000 objects. It's based on BlackBulletIV's code.
Re: Pixel precise object picking
Posted: Sat Oct 13, 2012 1:23 am
by BlackBulletIV
Glad it worked out for you.