-------------------------------------------------------------------------------- CHARACTER PHYSICS This is a reply I wrote in response to a question asked on the Open Dynamics Engine mailing list. It covers the most important parts of implementing character-environment interaction, in the context of 1st or 3rd person games. It is not specific to ODE, and what's covered here should apply to other physics or game engines roughly the same. -------------------------------------------------------------------------------- On 06/14/2014 07:19 PM, ckoeber wrote: > Hello, > > I apologize in advance if this is a repetitive question, I just couldn't > find the answers anywhere. > > I would like to implement a simple walkable character with Open Dynamics > Engine with custom loaded mesh (the mesh is generally indexed vertices > but there may be unindexed mesh as well). > > So, walking up and down steps and colliding with walls, etc. is a must > with the Open Dynamics Engine. > > I tried the Bullet Physics Engine but I could never get the > btKinematicCharacterController (for those familiar) to work right with > my custom mesh. > > My hope is that there is a simple tutorial somewhere; especially with > the custom mesh. > > Thank you for your time; I tried googling myself but I didn't turn up > much, especially on the custom mesh portion. -------------------------------------------------------------------------------- My response: -------------------------------------------------------------------------------- The general approach to this is to model the player with a capsule geom, suspended over the ground with a downward facing ray geom. The bottom cap of the capsule should roughly be at knee height. The capsule should only collide with walls and ceilings, the ray only with the ground. You may find it necessary to use more than one ray to prevent the character falling into small gaps and getting stuck (e.g. the gap between two planks bridging a trench). If your world is modeled as trimesh, you should not have to many problems using ODE, as capsule-trimesh collisions are pretty robust. Depending on the amount of geometrical detail of the visual world model, and to keep good performance, you'll probably want to create a second, simplified copy of the world geometry for collision purposes. Modern, high performance OpenGL rendering typically requires carefully prepared, aligned, buffered geometry, and ODE eats collision meshes (trimesh) which are often differently structured (no duplicate vertices, per-face normals rather than per-vertex). And since you'll probably buffer the visible geometry on the GPU, you won't typically have a copy in CPU memory anyway, where ODE lives. Separating the visual from physical also gives you various advantages; * Can create simpler, cleaner world collision geometry; prevent players from getting stuck on small details (e.g. window shutters, rain pipes). A picket fence can be modeled by a simple box, resulting in smoother 'wall' contact. A flower should not have collision geometry at all. * Make walking stairs smoother and less problematic, by modeling them as ramps. * Place invisible walls to block players from reaching undesirable areas. If you still want to model stairs as individual steps, you can use the CFM and ERP parameters to make ground (ray) contacts soft, so that the character does not instantly jump up/down with every step (especially important for first-person perspective). One key thing you must know; walking motion should occur in what I call 'ground-space'. You can construct this transform from the ground surface contact normal, and the player forward facing vector (compute tangent, orthogonalize and such). If you do things in the world space, when walking down a slope, the player will continuously lose ground contact with every impulse. This results in stuttering motion. Other problems occur when walking up slopes (capsule may touch ground). At all times, keep aware of whether the player has ground contact. For example, to allow the player to jump only when touching ground, or to unmount while climbing down ladders. Avoid friction. I found it hard to use friction to limit/affect player walking motion in a meaningful/reliable way. Instead, set friction to zero, and use linear damping. Alter damping amount depending on whether the player has ground contact (much damping) or falling through air (less damping). Be careful when applying forces to induce walking motion, the player may 'sink' into obstructions, or even clip through very thin walls. You can make the capsule contacts more soft and fluid for realistic FPS player-world interaction, but hard and rigid contacts tend to feel more responsive, less 'buggy'. If you want the characters to be able to crouch, or crawl under objects you can modify the capsule height on the fly. You'll need to use an up-ward facing ray geom to prevent players getting up under low ceilings (prevent getting the capsule stuck). If there's a need for ladders in you world, you can simulate those by locking the player to the world with a slider joint. You can use rays to detect whether a surface is climbable. Move the player vertically instead of on the ground plane. You can create a table of surface materials, in which you can store some interactivity flags. Some pseudo code: struct colmat { bool noCollide; // no player collisions (e.g. for triggers) bool isLadder; // player can climb this surface bool bulletHit; // bullets may pass through (e.g. chain-link fence) bool isTrigger; // touching this surface triggers event int triggerID; // action ID to trigger misc events int footStepSound; // index of footstep sound (wood, metal, sand etc) int bulletEffect; // metal, glass, wood etc. }; Create a mapping between trimesh face indices and these predefined materials. In the ODE collision callback you can then retrieve the information needed to determine how a contact affects the player (or other colliding objects, projectiles etc). That should cover most of the key aspects. I've implemented a first-person shooter with ODE once, and found it pretty robust for this purpose, although quite a few messy hacks were needed to give the player sufficient physical freedom while making the interaction feel smooth and natural. You'll find your code to be ugly. I've also coded my own coldet/physics engine, while somewhat cleaner than when using ODE, it generally seems player-world interaction code tends to be complex, hacky and fragile. Many popular games have/had issues with this topic: * In Quake3-derived engines, player-world collisions feel very 'boxy', because the player is modeled as an axis-aligned box, rather than a capsule. * Unreal requires very clean collision geometry or the player can get easily stuck on small details. Level designers need to spend much of their time cleaning up and testing. * In Battlefield 2 collisions are very jerky/unclean, easy to get stuck. For example it required the player to jump over obstacles taller than 1-inch! Sidewalk collision meshes for example had little ramps with a special stairs material. More robust collision detection code would have saved artists a lot of time and effort. * In to many games, small objects are insurmountable obstacles. * In virtually all games, when walking under a low sloped ceiling the player gets stuck, rather than crouch. So This is a bit of a black art. There are many aspects to consider. It takes a lot of experimentation. Hope that helps, and good luck. /Martijn -------------------------------------------------------------------------------- See also: http://groups.google.com/group/ode-users --------------------------------------------------------------------------------