Camera aligned with ray

Hello !

I am casting a ray from a mesh toward the camera, once the ray hits the ground the camera radius is changed to the hit point distance, then a check for intersections is done between a sphere (which has the same position as the camera but it’s distant from the ray) and all the meshes of the scene.

It seems to work fine if I move the camera slowly with the mouse, however, if I move the camera too fast, sometimes, the sphere and the ground will actually intersect.

What can be done to have the sphere always aligned with the ray, so that the sphere wouldn’t actually hit the ground before the ray?

Here’s the PG:
https://www.babylonjs-playground.com/#1VITHH#19

Try to move the camera toward the ground by moving the mouse slowly/quickly, intersections will be logged in the console.

I am quite new to any of this. I am sorry if this was already covered in another question.
Many thanks for any help you can provide.

Hello and welcome!

what you could would be to use camera.onAfterCheckInputsObservable to check if the position of the camera is intersecting and then restore previously known position?

Hi @Deltakosh
Thanks for the welcome and for the help you have provided!

I have tried to use onAfterCheckInputsObservable as you suggested, however without success (most likely because I am not applying logic correctly)

Here’s what I did:
Added a variable that would hold the camera safe position, the safe position changes only when the sphereCollision is not intersecting with anything. Once the sphereCollision intersects with something, the camera and the sphereCollision would be moved to the safe position. All of this happens inside onAfterCheckInputsObservable.

Here’s the PG:
https://www.babylonjs-playground.com/#1VITHH#20

I was wondering if maybe there’s a different way to do what I am trying to achieve. Basically the idea is to make a camera that orbits around the character, however, I don’t want it to slowdown on collisions, get stuck around obstacles or pass thru other meshes.

In my mind this could be achieved by attaching various ray pointing to the camera, then check if the camera is colliding with anything, if so, move the camera to the ray that has the shortest distance from the character. This way the camera would always be fast and rotate without worrying of obstacles or clipping effects.

Any suggestions are very welcome!
Thank you again for the help!

The problem is inertia. The camera to get its smooth movement uses inertia and thus even if you restore the position of the camera, it will keep moving along its inertia vector

To check if this is the case you can set camera.inertia = 0

The problem persists even after setting the inertia to 0.

I made another attempt, this time I did the following:

  • Set sphereOrigin as parent of sphereCollision
  • Set sphereCollision as parent of camera
  • Add code to control the sphereOrigin rotation with the mouse/pointer
  • Detatch the camera controls from the canvas
  • Use the ray hit distance to change the z position of sphereCollision (to simulate the camera radius)

The issue still remains (moving the pointer too fast will result in sphereCollision hitting the ground)

I have also tried to save the rotation of sphereOrigin while sphereCollision is not intersecting with the ground. When sphereCollision intersects with the ground, sphereOrigin rotation is changed with the previously saved position.

Despite all this, sphereCollision still hits the ground.

Here’s the PG:
https://www.babylonjs-playground.com/#1VITHH#21

I’m on my phone right now but can you confirm that if you slow down the camera the problem does not happen?

In this case it means the camera (somehow) is not checked at the right moment

We can try other observables like scene.onAfterRender for instance

As for the original PG: changing the camera speed doesn’t seem to have an impact, however by increasing the angular sensitivity, or by moving the mouse slowly, the issue does not happen.

About the second PG: increasing angual sensitivty or moving the mouse slowly doesn’t not show the issue, however at high speeds the position doesn’t seem to “reset” to a safe one (this is most likely a fault in my code)

Regarding the latest PG: similar to the other two cases, moving slowly or reducing the mesh rotation will not show the issue, however at high speeds sphereCollision still hits the ground and the rotation is not “reset”.

I did try y our last PG but maybe I’m not understanding the issue but I cannot seem to get the problem

what should I look at?

The sphere on the right (the one that gets closer to the sphere on the left when the ray hits) goes below the ground before actually moving to the ray distance. On my side, it visibly goes below the ground for a split second, then moves back to where the ray hits (even though it should move to a safe position before the the actual frame rendering), however I am starting to think that perhaps what I want to achieve should be done in a different way, such as using the built in babylon camera collision system.

Maybe a screenshot?

I have recorded a small clip from the latest PG that I made (the one where the mouse controls the rotation of sphereOrigin, which is the parent of sphereCollision)

This is the clip at normal speed, you can see when I move the mouse quickly the sphere on the right (sphereCollision) goes below the ground, however (toward the end) if I move the mouse slowly, it stays aligned with the ray.

Clip at normal speed (60fps):

Then there’s a piece of the same clip, however slowed down from 60 to 10fps
This clip shows how much the ray lags behind the actual mesh (ray and sphereCollision are parented to sphereOrigin)

Clip at slower speed (10fps):

Screenshot:
Issue

I wonder if maybe there’s something going on with the ray not picking fast enough. The ray should always be under sphereCollision.

sphereCollision should never go thru the ground since the ray should always hit the ground before sphereCollision, right ?

Far cleaner! Here is a try:
https://www.babylonjs-playground.com/#1VITHH#22

The playground doesn’t seem to work:

sorry: https://www.babylonjs-playground.com/#1VITHH#23

Same issue on my side

Edit: Could the issue be only on my side ?

Edit 2:

Edit 3:
The same issue happens with the version 4.2.0-alpha.30 (Latest in the playground)

OK I think I finally got it :smiley:
https://www.babylonjs-playground.com/#1VITHH#24

The reason is that the rayHelper is updating the ray based on mesh AFTER the mesh has moved thus introducing a difference of a frame between the moment the pick was done and the update of the ray :slight_smile:

3 Likes

Yes, you did it !! :partying_face:

I was losing my mind over it ahah !

Massive thanks, I feel like I can continue the project now !

1 Like