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