Jump to content

moveWithCollisions, obtain normal at collision point


HoratioHuffnagel
 Share

Recommended Posts

Hi,

I am currently working on a game where I want to avoid using heavy physics systems. Mainly because I have size restrictions on downloads, and the physics requires a movement style like asteroids, but with no friction and a capped speed. Something that gets a little tricky with physics engines.

So - Babylons's inbuilt physics system looks perfect - I can move the player with my own calculations, and just detect the collisions and react to that.

Only problem is I'm not sure how to get the intersection point (i need to reflect the characters velocity when it hits a wall).

let result = player.mesh.intersectsMesh(wall.mesh, true);

So for instance - this is great... but only returns a boolean. I COULD cast a ray along the direction of travel, but that wont help if I clip the corner of an object. Any thoughts?

Cheers.

Link to comment
Share on other sites

Here are some 'meteors(?)' colliding in a box  https://www.babylonjs-playground.com/#CBYLEW

The physics of collisions is based on the mathematics of spheres colliding. Each meteor is a sphere with vertices moved randomly by a small amount based on Temechon's work on tree generation.

More on the mathematics of collisions used can be found here http://doc.babylonjs.com/samples unfortunately on these pages the diagrams to help are missing. I have now submitted the images but they will only be available on the next deployment of the documention.

As this uses the SPS system all meteors are identical in shape except for some random scaling along the x, y and z axis. However the same process can be done with individual meshes.

Hope this helps

Link to comment
Share on other sites

[EDIT: I have added a new post, because I realised the error was wetware - I really should have seen this problem myself. ]

Thanks guys - this is somewhat helpful (it has shown me a lot of promising possibilities for sure!), but every path I follow isn't quite there. All I want is a collision event, and a normal. This is insanely difficult to do apparently... grr.

 

let mesh1 = player.mesh;
let mesh2 = wall1.mesh;

mesh1.actionManager = new BABYLON.ActionManager(renderer.scene);
mesh1.actionManager.registerAction(new BABYLON.SetValueAction( { trigger: BABYLON.ActionManager.OnIntersectionEnterTrigger, parameter: mesh2 }, "scaling", new BABYLON.Vector3(1.2, 1.2, 1.2)));

// This is directly from the documentation but results in the following error
// babylon.js:25 Uncaught TypeError: t.split is not a function
// This is being thrown from the registerAction method by the looks

 

Does anyone have any idea what this error may be caused by?

Edited by HoratioHuffnagel
I made a stupid error. ;)
Link to comment
Share on other sites

Okay - so the secret is to rant on a forum, then the answer will come immediately too you. My error was to pass a new SetValueAction instead of ExecuteCodeAction. Wow - I really should have seen that!

So - thank you very much guys - it's been a couple of days of digging through documentation, but you both gave me some excellent resources to read!

However - I do now have one last question - I have this collision event - but I can't seem to find what would constitute the normal of the collision? Any ideas?

Link to comment
Share on other sites

For a wall and a sphere the collision normal is the normal of the wall.

For two spheres the collision normal is the line joining their centres. My meteor PG assumes a bounding sphere for the meteors.

For other shapes things get really complicated. Take to meshes A and B made up of triangular facets with facets FA and FB in contact. If FA and FB are parallel (unlikely) then the collision normal is the normal of the two facets. If they are not parallel then some other decisions on how to interpret what is happening at the collision area need to be made, for example use the line joining the Barycentres of the facets FA and FB.

Alternatively you could use a bounding ellipsoid for the the two meshes A and B

An ellipsoid with centre at the origin and in alignment to the axes will have an equation of the form ax2 + bx2 + cx2 = d

When P = (p, q, r) is on the surface of the ellipsoid then the normal at P will have the form (ap, bq, cr).

When two ellipsoids C and D meet in space let Q = (s, t, u) be the point of contact. Now for the ellipsoid to be where they are they will have undergone rotation and translation. Let T be the transformation matrix applied to C then CT -1 will return the ellipsoid C back to centre origin and in alignment with the axes and QT -1 will be the point on the surface where contact was made on the ellipsoid CT -1. Using the x, y, z values for the point QT -1 with the equation of CT -1 will give you the  normal N and so NT will be the collision normal for the two ellipsoids.

Which is why I stuck to spheres.

 

Link to comment
Share on other sites

Yes, I know it is the normal of the wall - the question is how do I obtain it?

If I have a set of walls in an environment, I have successfully coded number of ways to determine if there is a collision, using OnIntersectionEnterTrigger, or intersectMesh - each time I find myself stuck with either not enough, or too much information. Now - I know that is user error more than anything - it's just that I am up against the clock and have to get something working soon. 

I should also mention - this is an environment that will have walls - in a maze like layout - think Pacman - player can navigate freely through the environment, and collide with walls, rebounding off them - and there will be no friction (so they need to rebound constantly).

So this is where I am at:

  1. I am choosing to use moveWithCollision (so I can just write my own movement routines)
  2. I have settled on OnIntersectionEnterTrigger to get the collision event
  3. At this point I have an enormous data structure (returned in the callback for OnIntersectionEnter) and I can't tell what is actually useful for getting the normal of the face I hit.
  4. I will also like need to the collision point, as I will need to reposition the player outside the wall (as they may continue to apply force in the direction of the collision)

One way would be to use a ray test - but it seems the collision event SHOULD have the data in there somewhere? 

 

Thanks :)

Link to comment
Share on other sites

I've had a look at that code before - it doesn't need or consume the face normals. The reason I need normals is because the user can move with continuous velocity in a single direction. When they hit the wall, they must 'reflect' off the wall. Basically like pong.

The only problem is, unlike pong, I don't know the orientation of the wall ahead of time. While many games wont require it, it's common enough to need to know (i.e. projectile hits wall, what direction should particles spray out etc).

Link to comment
Share on other sites

i'm working on a steering library, i used this to bounce off walls:

if(this.player.intersectsMesh(obstacle)){
this.player.position = BABYLON.Vector3.Lerp(this.player.position, new BABYLON.Vector3(obstacle.position.x, 0, obstacle.position.z).scale(100).negate(), this.alpha);

this.player.position.scale(this.radius).normalize();
}

But if you intend to use raycaster, you can use the same approach.

Link to comment
Share on other sites

I think I have it - thanks for the advice everyone. I will do up a playground to demonstrate the result once I have had some sleep. But the basics are:

  1. Use moveWithCollisions to do movement
  2. Setup AABB boxes as children of the obstacles (use this to detect collisions)
  3. Setup OnIntersectionEnterTrigger actions on the player object
  4. When a collision is detected, do a ray cast (up, down, left, right) to determine where the collision was using intersectsMeshes
  5. The object that is returned will let me get the normal using .getNormal

@huntsYour solution also looks completely valid - I might give that a go too to see what is more performant.

Thanks again.

Cheers!

Link to comment
Share on other sites

Nice work, HH, and thx for the promise of the demo PG.  We will look forward to that.

I have a dumb question (I'm not noob to collisions, but I DO forget everything I've EVER learned... once per month) ;) ...

If you were to constantly "record" the lastPlayerMovementDirection... so you could "have" the direction of impact that caused collision... then couldn't that, and the wall's y-rotation (and a bit of simple math)... be used to derive a rebound direction?

Sorry about being simpleton.  I'm more polyhedrArtist (TinkerToy Engineer) than mathematician or programmer.  :)

Link to comment
Share on other sites

When a wall is created and positioned can you not make the normal a property of the wall. 

You could also check this out http://doc.babylonjs.com/how_to/how_to_use_facetdata

In particular getFacetsAtLocalCoordinates

and getFacetNormal

EDIT Started this answer a couple of hours ago on my mobile while waiting for an appointment. Finished it when I got home before checking for replies. Answer is probably now redundant.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...