psyrendust

Pixi.js v4 get globally translated vertices for collision detection

Recommended Posts

Hi, I'm running into an issue regarding collision detection against adjacent DisplayObjects. Let's say I have sibling objects that are a child of a Container that has been rotated. If I use getBounds() on the siblings they return a bounding box that is oriented to cardinal north. Using those bounds for collision detection may result in false positives, because the given bounds may not follow the actual shape and orientation of the DisplayObject. I created a codepen to illustrate the point: 

When you toggle the "rotate" buttons at the bottom of the pen you will see the purple box morphing to the shape of the bounds for "shape" and "label". The text will change from red to green if the collision detection returns positive.

I would like to do a more robust collision detection algorithm (possibly based on Separating Axis Theorem), but I would need to grab the vertices for each shape correctly translated to the global coordinates regardless of their nesting within the scene graph (accounting for scale, rotation, and translation from the shape and all parent transforms). The case being that the collision detection that I would like to do may not be only between direct siblings within the scene graph.

Is there a nested property that would give me what I'm looking for, or will I need to grab the graphics data and apply all of the recursive parent transforms myself for each vertex?

 

Here is a fork of a codepen that demonstrates the Separating Axis Theorem: 

 

Share this post


Link to post
Share on other sites

The codepens above are really cool!
With my game https://www.hookem.io, I had to do all of my collision detections on the server.
The server in my case has no awareness of the canvas, but it tracks all of the objects states (shape dimensions, positions, velocity etc) in memory.
Since most of my objects are circles I use the below function to detect its collision to 'something else':

/* 
In Circle?
   @x is the x-point to test
   @y is the y-point to test
   @cx is the circles center x-point
   @cy is the circles center y-center
   @radius is circle radius 

   returns boolean
*/

function pointInCircle(x, y, cx, cy, radius)
{
  var distancesquared = (x - cx) * (x - cx) + (y - cy) * (y - cy);
  return distancesquared <= radius * radius;
}

Considering all sprites frames are rectangles, maybe if you keep your inner sprites vectors waypoints in memory and detect against those instead?  

PIXI has a 'draw outline' filter which detects all the points around a shape and draws an outline around it, maybe you could reuse that logic to get the waypoints to compare against? 

(sorry if I'm way off) 

Share this post


Link to post
Share on other sites

Thanks for the tip @ivan.popelyshev. I'm now able to get the correct bounding box I want by grabbing the 4 vertices of the local bounds and applying the world transform to each vertex. You can see my latest update here: 

My next step is to improve the collision detection method based on the new vertex bounding box. I'll post the final result when I get to it.

Share this post


Link to post
Share on other sites

Thanks @OSUblake for the SAT link. I'll have to check it out. I was able to get collision detection going by calculating all of the vertices for a bounding box that has been oriented to the global coordinate space, then doing line intersection on each of the four line segments that make up each vertex bounding box. I'm able to show the coordinate of the first intersection found for two elements (bails out quickly for perf) (highlighted by a green dot). I'll have to take a look at the SAT example to see if there is any optimization that I can do, or if I'm better off working with SAT.js.

 
In my real world use case I'll be running this collision detection algorithm against a few hundred siblings on each requestAnimationFrame. The codepens are a bastardized version of the potential scene graph. Each EntityLabel is a Container that holds a "marker" that is a Graphics element which represents the anchor of the Container. The "marker" has a sibling that is another Container called "label", which is another Container, that holds a Text object. The label is offset from the marker as shown in the pens. With that said, I'm not sure if "PIXI.Polygon().contains()" will suit my needs because I won't be able to infer just a point that I can pass into the "PIXI.Polygon().contains()" method, which is why I chose to run my algorithm against line intersections.
Edited by psyrendust
My codepen example was broken because of missing files from a codepen project that was deleted. I recreated the example on codesandbox.io.

Share this post


Link to post
Share on other sites

Interesting topic. Could you do a scaling from the center of the inner box or child box? Currently you are scaling them from the top left point. I would like to know how to do the scaling from the center of the box and hope it won't affect other things on canvas.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.