Pixel precise object picking

General discussion about LÖVE, Lua, game development, puns, and unicorns.
GarbagePillow
Prole
Posts: 41
Joined: Wed Sep 26, 2012 9:19 pm

Re: Pixel precise object picking

Post 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.
User avatar
Xgoff
Party member
Posts: 211
Joined: Fri Nov 19, 2010 4:20 am

Re: Pixel precise object picking

Post 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
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: Pixel precise object picking

Post 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?
Attachments
drag_image.love
simple image dragging demo
(103.27 KiB) Downloaded 130 times
User avatar
T-Bone
Inner party member
Posts: 1492
Joined: Thu Jun 09, 2011 9:03 am

Re: Pixel precise object picking

Post 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.
GarbagePillow
Prole
Posts: 41
Joined: Wed Sep 26, 2012 9:19 pm

Re: Pixel precise object picking

Post 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.
GarbagePillow
Prole
Posts: 41
Joined: Wed Sep 26, 2012 9:19 pm

Re: Pixel precise object picking

Post 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.
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Re: Pixel precise object picking

Post 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.
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: Pixel precise object picking

Post 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.
GarbagePillow
Prole
Posts: 41
Joined: Wed Sep 26, 2012 9:19 pm

Re: Pixel precise object picking

Post 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. :oops:

Here's the test I did picking through 10,000 objects. It's based on BlackBulletIV's code.
Attachments
PickingTest.love
(123.2 KiB) Downloaded 148 times
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Re: Pixel precise object picking

Post by BlackBulletIV »

Glad it worked out for you. :)
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 7 guests