lovr
lovr copied to clipboard
add Shape:queryOverlapping to query overlppaing shapes
Currently, if we want to get overlapping shapes of a shape, we have to record when world:update
. This logic is too complicated.
As a sensor, it functions exactly like a tag marked as non-collisionable. This function will allow users to skip the complicated collision resolver logic and get the overlapping shapes directly.
Thanks for the PR! It would be really helpful to see the use case you had for it. While trying to make sure this function makes sense in the context of the other collision functions, I'm trying to go over various use cases, and knowing yours would help. Based on previous discussion I'm assuming you have a MeshShape for a sword slash and are trying to check all the shapes it intersects.
What's the purpose of setting tag filter to false? I guess there are 3 options for the tag filtering:
- The query does not use tags. If you want to respect tags, you have to do a check with
World:isCollisionEnabledBetween
. - The query does use tags. If you didn't want this, you have to set up your tags differently, or temporarily remove and re-add tags.
- Make it configurable, like in the PR.
Some other very random design brainstorming while thinking about this:
-
Shape:isTouching(otherShape)
? -
Collider:isTouching(otherCollider)
? -
World:queryShape
vs.Shape:queryOverlapping
is an interesting decision. - Calling this "overlaps" is confusing because it checks for actual contacts, not overlaps like
World:getOverlaps
. - If this is meant to be an alternative to
World:overlaps
because it sucks, thenWorld:overlaps
should be removed (and maybe replaced with a more conventional contact filter callbackWorld:get/setCollisionFilter
) instead of having 2 ways of doing things.
This is another case, I have a skill that needs to cause damage to units in an area (fire breathing effect, I just use a simple box) every second. Based on this requirement, I created a sensor. And I used the world tag to set that only the specified tag will be in contact. I use a simple timer to query the units in this area when the time point is reached, and then apply the damage.
In Lovr, in order to achieve the above effect, it is necessary to continuously record all the units in contact with the sensor in the resolver and keep updating, or calculate aabb and then queryBox, and finally perform collision detection by itself. I don't want to do the above events, I just want to simply get all the shapes that the current shape can touch when needed (by default, things whose collider's tag is set to be untouchable should not be found). Maybe the tagFilter switch is not necessary, it can be achieved by setting collider:setTag(nil), but it is necessary based on the collider tag, because it must conform to the real performance of the current shape in the world.
In addition, for Lovr's current physics, too many things have not been exported. The collision query that is simply implemented in ode is completely absent in lovr, and all of them need to be implemented by themselves. Like this function, whether it is Love2d or other game engines, an API will be provided to query the units touched by the collision
isTouching is useless, it only needs to know the situation of the two to detect. If there are 1000 objects in your world and you don’t know all the touching units, it is impossible to test them one by one.
It is usually required when a more accurate detection is required after querying the possible collisions nearby through the AABB
World:queryShape and Shape:queryOverlapping, I think they can exist at the same time. World:queryShap executes a one-off query without a shape/collider, create -> query -> destroy. Moreover, for this kind of query, basically there is no need to care about whether there is a collider, and naturally there is no need for a tag filter. And shape:queryOverlapping uses shapes that already exist in the world to perform multiple queries, so it needs to perform tag filter.
By the way, Love2d's World:setCallbacks( beginContact, endContact, preSolve, postSolve ) is very useful, I don't know if ODE has a callback like this. Now I want to monitor the events of units entering and leaving the area. I can only compare the units of the previous frame and the current frame, and then detect which ones are new and which ones are leaving. This function is also relatively general.
Then, I actually feel that collider:getOverlapping
is better, but to remove duplicates, I feel a bit complicated to write this in C, so I can only write a simple shape:getOverlapping
By the way, Love2d's World:setCallbacks( beginContact, endContact, preSolve, postSolve ) is very useful, I don't know if ODE has a callback like this.
ODE doesn't have these callbacks
Ok thanks for the info. I think my current preference would be a World:queryShape(shape, callback)
function. The shape must be attached to a collider in the world, and it does not use tags, to keep it similar to getContacts and the other query functions. Basically what you have now, but put on World instead of Shape and no tag filter. It's not perfect, but good enough and adds an important missing feature. Does that seem good?
For pure shape, I don't think tag is necessary. But for a collider‘s shape, tag is necessary. On the one hand, if collider:addShape(shape)
has been explicitly executed in lua, then the shape needs to be configured according to the collider. On the other hand, for a sensor, it should be the same as the perceived result.
For the current Lovr, Sensor is basically the same as nothing.
Because if the resolver function is not written, it is equivalent to a tag, if it is written, its function is simply not to call collide, but it is equivalent to simply adding an if shape.is_sensor then goto next_shape end
in the resolver. I think that the sensor needs to know which objects it has collided with at any time, and the related collision events (begin/end colliding)
This is stale, and I will be adding it soon to Jolt backend. But thank you for starting the discussion about it.