Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement custom shape, Ray #1387

Closed
AndreaCatania opened this issue Oct 17, 2017 · 24 comments
Closed

Implement custom shape, Ray #1387

AndreaCatania opened this issue Oct 17, 2017 · 24 comments

Comments

@AndreaCatania
Copy link
Contributor

What I need:

I'm implementing bullet wrapper for Godot and I need to implement a custom shape "ray". This shape is basically a ray that push the body in the opposite direction where it points.

What I does:

Here a video difference from the Godot shape to the shape that I already implemented:
https://www.youtube.com/watch?v=Ff0qlG55t_E&feature=youtu.be

As you can see the shape can receive lateral forces.

This is how I've implemented it:
Header: https://github.com/AndreaCatania/godot/blob/59ac2999ea4af77cc36c65c9da904616d9eb832b/modules/bullet/btRayShape.h
CPP: https://github.com/AndreaCatania/godot/blob/59ac2999ea4af77cc36c65c9da904616d9eb832b/modules/bullet/btRayShape.cpp

As you can see I've extended the convex shape to implement the RayShape, and this allowed me to easily implement it, but its behaviour is not what I need.

I need that the shape respond to the direction of ray only and for doing this I think that I need to create all algorithms to find the collisions in the narrowphase against all shapes.

My question:

Since do and maintain it could be not so easy, There's a way to customize the shape response in an easier way (in order to clamp forces to ray direction)?


Related godot issue: godotengine/godot#12156

@erwincoumans
Copy link
Member

erwincoumans commented Oct 17, 2017

Such a character controller ray response can be implemented in various ways. One way would be to use a rigid body standing on a little stick/ray, and compute a custom spring/damper force that is applied to the rigid body right before every simulation step (or in the pretick callback). Have you considered that? The ray length can be computed using the Bullet ray test.

@AndreaCatania
Copy link
Contributor Author

This should be a shape that act like a rigid stick with the particularity that it receive only forces along it's direction, So if it's on a downhill it doesn't slide down, but maintain the body standing.

The idea of spring/damper is not wrong, but in Godot is required that it's a regular shape, and it must be rigid.

Exist a way to clamp the received forces for a particular shape?

@AndreaCatania
Copy link
Contributor Author

Hi @erwincoumans it's the time to fix this problem for me so it's very helpful if you can give me an advice about it.

Talking with reduz he said me that probably is possible to implement just one algorithm (something like rayshape vs world). In this case implement and maintain it is very easy.

Thanks in advance for advices.

@erwincoumans
Copy link
Member

erwincoumans commented Oct 26, 2017

Either
(1) you use a rigid body with a stick collision shape, and make sure the friction completely puts the object at rest. Friction should be able to 100% stop the sliding, even on sloped surfaces. Using a custom contact/friction callback, you can customize the friction to allow sliding on certain slopes etc.

(2) create a custom action, similar to the btRaycastVehicle or btKinematicCharacterController: perform a ray cast and apply custom forces to move the object. You can still use a rigid body for the body (like the btRaycastVehicle) or not.

There is no easy way to add non-physical one-way interactions integrate this into the regular Bullet constraint solver, aside from using btRigidBody::setLinearFactor and/or btRigidBody::setAngularFactor (which makes the rigid body infinitely heavy in certain directions.

I would suggest working on (2), a custom character controller with or without rigid body torso.

@erwincoumans
Copy link
Member

In the meanwhile, you got me interested in Godot engine, so I'll try it out soon. I may be able to help a little bit with the character controller.

@reduz
Copy link

reduz commented Oct 28, 2017

@erwincoumans Hi Erwin! Thanks for your interest! Godot uses a really old physics engine I wrote almost a decade ago. As it's quite outdated and working on it is considerable work, @AndreaCatania has been doing a great job of implementing Bullet as a back-end, with success so far.

We already have a nicely working kinematic character controller, so this is mostly OK, but some users prefer to use a Dynamic one.

The most difficult "feature" to port to Bullet is the RayCastShape. In Godot this works using a custom narrowphase that simply does a raycast of a given depth against an object. If the ray hits something, both the hitpoint and the raycast endpoint (origin + direction * depth) are added as a contact pair into the persistent manifold.

This has the effect of immediately separating the body by the ray length with barely any bouncyness. When used together with a sphere or capsule over it, It makes working on dynamic character controllers really easy and straightforward, as characters will do stepping as well as not fall on slopes automatically.

In any case, Godot is more of a high level game engine, and is intended for users where APIs are accessible and easy to use, wrapped for the most common use cases. Because of this, we have no interest in directly exposing the entire Bullet API (like maybe other engine do), but instead make it conform to the higher level abstraction we use. Users that want lower level access have to do their own work in C++.

That mentioned, any help or feedback would be very welcome!

@AndreaCatania
Copy link
Contributor Author

Glad to read that! So I want share my current state of work with RayShape.

I've created GodotRayConvexAlgorithm that extend btConvexConvexAlgorithm.

Then in the process collision I clamp the normals to (0,1,0) in the generated contact manifold.
https://github.com/AndreaCatania/godot/blob/be60233e698ee9bee25962209d51e5f9f9596033/modules/bullet/godot_collision_configuration.cpp#L39-L51

And this works fine.

I did the same thing with GodotRayConcaveAlgorithm that extend btConvexConcaveCollisionAlgorithm.
But here the problem is that the algorithm doesn't catch collision between convex and concave when the point overlap so I get a wrong behaviour.

Bullet physics engine

bulletrayshape

Godot physics engine [EXPECTED]

godotrayshape

Probably I can't use this trick for the concave shapes and I should implement the proper algorithm, what do you think about?

@erwincoumans
Copy link
Member

erwincoumans commented Oct 28, 2017

@reduz Thanks for chiming in! I just noticed Godot 3's renderer explained, the new Godot3 renderer looks great! This client-server approach is very similar to the new Bullet C-API, which is wrapped in Python as pybullet. Please check it out the pybullet quickstart guide.
We are looking for a nice renderer and editor, possibly Godot 3 fits the needs if we can couple its Visual Server with the Bullet Physics Server.

We should be able to use the identical approach in Bullet, doing a ray cast and adding contact points, like Godot does using a regular ray cast. That seems a better way to go than refactoring various collision algorithms. Bullet has 'actions', used in CharacterController and Vehicle. What you describe, we need some custom action that is called during the collision detection and adds contact points to the solver. It may work in a pre-tick callback. If not, we can add it.

This can be done in the regular Bullet 2.x API, but also in the new 'Physics Server' API.

@AndreaCatania Two questions:

Is his custom Ray character controller for Godot 2 or Godot 3?

How can I try out that character controller comparison in Godot and Bullet?

@AndreaCatania
Copy link
Contributor Author

Is his custom Ray character controller for Godot 2 or Godot 3?

Godot 3

How can I try out that character controller comparison in Godot and Bullet?

Note: The red floor is a box shape, while the white floor is trimesh shape

To swap from Bullet to Godot Physics and viceversa

  • Open settings
    untitled

  • General > Physics > 3D > Physics Engine
    untitled

@AndreaCatania
Copy link
Contributor Author

@erwincoumans I'm also checking the actions.

@erwincoumans
Copy link
Member

erwincoumans commented Oct 29, 2017

I could compile Godot and run your tests. First of all, in both modes (GodotDefault and Bullet), the character capsule is sliding, why is there no friction to stop it?

Why don't you use the same logic as GodotDefault for the Bullet RaycastShape as well:

In Godot this works using a custom narrowphase that simply does a raycast of a given depth
against an object. If the ray hits something, both the hitpoint and the raycast endpoint (origin +
direction * depth) are added as a contact pair into the persistent manifold.

In your code, you perform a convex collision check instead of a ray intersection test. This causes a different behaviour. Do you need help to perform the ray check inside your custom collision algorithm?

I cannot reproduce the issue: when selecting Bullet as 3d physics, moving the character forward and backwards works as in this (unlisted) video: https://www.youtube.com/watch?v=KEA1fU5Hhi4

Finally, please share the BulletRayShapeOnSlope project as well.

Thanks for working on this!

@AndreaCatania
Copy link
Contributor Author

I could compile Godot and run your tests. First of all, in both modes (GodotDefault and Bullet), the character capsule is sliding, why is there no friction to stop it?

To move the character was used set velocity each (pre)tick so the friction was always ignored, Now I've changed it. Now I'm setting the impulse only when a button is pressed (WASD).

So please Re-download it please:
AreaBodyCollisionTest.zip

Note: The controller is not implemented in c++ or by Godot, it is a fast implementation in GDScript to test ray shape

In your code, you perform a convex collision check instead of a ray intersection test. This causes a different behaviour. Do you need help to perform the ray check inside your custom collision algorithm?

Initially I was trying to do it in the "standard way", so I tried to use the regular collision algorithm. Now that you told me that use a raycast is enough, I'll implement it ASAP.

I cannot reproduce the issue: when selecting Bullet as 3d physics, moving the character forward and backwards works as in this (unlisted) video: https://www.youtube.com/watch?v=KEA1fU5Hhi4

If you check your video more carefully when you select Bullet physics engine you can see that for some reason you didn't selected Bullet. Let me know if you can't switch engine (that is a weird thing)

Finally, please share the BulletRayShapeOnSlope project as well.

Note: The "controller" is not implemented in this project
BulletRayShapeSlopes.zip

@reduz
Copy link

reduz commented Oct 29, 2017

@erwincoumans The RayCastShape does not rely on friction to stop things. It's just a simple helper to keep objects separated. Using a segment with friction will just make the use case for this a lot more complex for regular users.

I'm not sure what @AndreaCatania tried to do, but the intended behavior is as I described above. It needs to be a custom narrowphase collision that adds endpoint and hitpoint to the persistent manifold.

@reduz
Copy link

reduz commented Oct 29, 2017

Due to the way it works, it just separates objects, so no sliding on slopes will happen by default (contact normal will go upwards) making this function more customizable for users, who don't want sliding to happen and don't want friction bothering their math.

@erwincoumans
Copy link
Member

@reduz So the raycastshape is a stick to push the rigid body upwards. So you add contact points to the constraint solver that only act along the normal direction, without friction constraints, right? What prevents the rigid body from falling over and rotation if you strafe along walls?

@AndreaCatania I re-uploaded a new video,I cannot see a difference in behavour using Bullet:
See video here: https://www.youtube.com/watch?v=clYY3ifr-xs

I was trying to do it in the "standard way"

There is no "standard" way to add custom contact points, (1) computed using a ray cast and (2) without friction constraints. Once it is crystal clear why you/Godot tries to achieve with the character controller, we can find a way to fit this custom action into Bullet. Regular 'actions' may not be fully suitable yet.

@erwincoumans
Copy link
Member

erwincoumans commented Oct 29, 2017

@reduz Every time I play 'start', a new window pops open in the right left hand corner, mostly invisible, so I have to drag it into view. See this video: https://www.youtube.com/watch?v=clYY3ifr-xs

Isn't there an option to pop up at a fully visible location?
Why not add an option to integrate the play window within the current editor, like Unity does?

@reduz
Copy link

reduz commented Oct 29, 2017

@erwincoumans It's meant for bodies that can't rotate, so there is no chance of them falling over. Again, not looking for a custom way to add contact points, just custom narrow phase code which can do that logic instead of the classical Bullet GJKEPA.

@reduz
Copy link

reduz commented Oct 29, 2017

@erwincoumans regarding the demo and Bullet branch, I don't know exactly how it's put together, you'll have to ask @AndreaCatania .

Godot uses a different approach to Unity, as the game runs in a separate process. This allows editing the scene in the editor and have changes reflect in the game while allowing you to save your changes (this is not possible in Unity). It also makes running the game faster (as Unity, using the same process, has to unload current state, load game, unload game, reload state.. which is pretty inefficient).

If I knew how to put a separate process embedded into an OpenGL texture I would gladly do it, but this seems incredibly difficult in most operating systems. That said, users dont really care much about this.

@erwincoumans
Copy link
Member

erwincoumans commented Oct 29, 2017

@reduz Yes, using shared memory would be one way to do it, and upload the contents of the shared memory to OpenGL in the editor process, and read/copy the OpenGL content to shared memory in the game process. I'm using shared memory for the physics client-server intra-process communication a lot, on Windows/Mac and Linux. Since this is a lot of work (user input transfer from editor to game process through shared memory etc), let's ignore it for now.

For the current solution, main issue is that the window starts mostly out-of-view. Is there an option to automatically (re)position that game play window so it is fully visible? Can some script line reposition the window to say (10,10) at absolute screen coordinates?

@AndreaCatania
Copy link
Contributor Author

I've implemented the ray shape by creating a custom narrow phase algorithm that use raycast as suggested.

This is the algorithm: https://github.com/godotengine/godot/blob/ce367016f4d1d97d998049287e70fe694377c061/modules/bullet/godot_ray_world_algorithm.cpp

Thanks you both @reduz @erwincoumans !!

Tell me if I can close it

@AndreaCatania
Copy link
Contributor Author

@erwincoumans also is interesting that you was able to climb the trimesh collision with old implementation. Is probably your "IOS" the reason of this difference?

@erwincoumans
Copy link
Member

erwincoumans commented Oct 30, 2017

Great, thanks @AndreaCatania!

You included btDiscreteDynamicsWorld.h in that algorithm, which usually is too big of a dependency. In Bullet we avoid circular dependencies by enforcing that high level classes such as btDynamicsWorld can include low level classes such as btVector3, btCollisionShape, but low-level classes should never include high-level classes. Since there is no low-level rayTestSingleInternal at the btCollisionShape/btCollisionObject level, this cannot be easily avoided so it is OK. Ideally we re-factoring the code in btCollisionWorld:::rayTestSingleInternal in a separate utility. I'll keep it in mind.

to climb the trimesh collision

@AndreaCatania well, if the contact normal is always along the ray, there won't be sliding indeed.

I assume you add the ray-shape contact points with zero friction? It could be useful to allow to add those rayshape contacts WITH friction as an option: then the character will follow moving platforms automatically due to friction, and you can tune friction so it will slide down (if you pass the actual contact normal, instead of ray normal). But I agree with @reduz that the default should be easy and customized. So an option for friction and surface normal (instead of ray normal) may be nice as option, but disabled by default in GoDot?

I added a whole series of comments in the GoDot tracker, please check it:
godotengine/godot#10013 (comment)

Yes, feel free to close this issue, if it works OK.

@AndreaCatania
Copy link
Contributor Author

Ideally we re-factoring the code in btCollisionWorld:::rayTestSingleInternal in a separate utility. I'll keep it in mind.

Very good, just let me know when you do it so I can improve the algorithm.

I assume you add the ray-shape contact points with zero friction? It could be useful to allow to add those rayshape contacts WITH friction as an option: then the character will follow moving platforms automatically due to friction, and you can tune friction so it will slide down (if you pass the actual contact normal, instead of ray normal). But I agree with @reduz that the default should be easy and customized. So an option for friction and surface normal (instead of ray normal) may be nice as option, but disabled by default in GoDot?

Currently I didn't touch the friction that is managed outside the narrowphase algorithm (correct me if I'm wrong).

So basically the friction is considered and this is a prove:
bulletrayshape

However your idea is not wrong, someone could need that ray shape slides on slopes, so I'll make a PR to add a check box in the Godot shape to control this behaviour.

I added a whole series of comments in the GoDot tracker, please check it:

I waited to fix the RayShape, I'll respond soon

@reduz
Copy link

reduz commented Oct 30, 2017

@erwincoumans in general friction is a hassle for dynamic character controllers. In our examples we just take the velocity from the floor collider at that point and apply it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants