Urho3D integrates the Bullet physics engine: http://bulletphysics.org/
Each node in Urho can be set up to be a static (non moving) or dynamic (moved by physic and gravity) physical object:
body->SetMass(50.0); // set to 0 (default) for static objects
body->SetLinearDamping(0.2f); // air friction body->SetAngularDamping(0.2f); // rotaion damping
body->SetFriction(0.6); // friction with other objects (like the ground) // it's also possible to restrict the rotation. Like if you want the object // to be always upwards (rotation only around the Y-axis, left and right). // (This could also be used to have different resistances.) body->SetAngularFactor(Vector3(0,1,0));
// optional, some actions like raycast, can be set to only be on one layer // and then only affect physical objects on that layer. // In USP the play is on layer 1 and everything else on level 2. body->SetCollisionLayer(2); // box shaped collider, the first vector is the size // and the second an optional positon offset CollisionShape* shape=node->CreateComponent<CollisionShape>();
shape->SetBox(Vector3(0.7,1.47,0.7),Vector3(0,1.47/2,0)); // or capsule collider shape->SetCapsule(1.3,2,Vector3(0,1.05,0)); // could also be a triangle mesh: //shape->SetTriangleMesh(cache->GetResource<Model>("level1.mdl")); // or a convex hull or one of the other types //shape->SetConvexHull(cache->GetResource<Model>("Models/rock.mdl"));
Note: triangle mesh on triangle mesh collisions are disabled per default. See PhysicsWorld::SetInternalEdge(bool enable) http://urho3d.github.io/documentation/1.32/class_urho3_d_1_1_physics_world.html.
Physical nodes are moved by applying forces. You can give it an impulse (changes the speed depending on impulse strength and object weight) with
or you can set the speed/velocity directly:
You can also still set the position directly The same goes for the rotation.
Example of an physical raycast Edit
Ray ray(pos,Vector3(0,-1,0)); // the given vector is the direction
physical_world->SphereCast(result,ray,2,100); // a sphere cast has a volume
if(result.distance_<=1000) // if hit something
Characters (at least humanoids) are typically made with a capsule collider.
In USP the player has a capsule collider whose rotation is ignored, because it was turning weirdly when moving. The player has two nodes, one is controlled by the physics and one contains the model. The one with the model is set to the position of the physical one and the rotation is set by either the camera when in first person view (to looking direction) or to the movement direction when in third person mode (so that the player is always running forward and never sideways or backwards).
Also the friction has two different values. 2.0 when the player is not pressing any movement keys and 0.4 when he is. This was done because the physical object was sliding down even slight slopes with a low value like below 0.6 and values above that made direction changes quite slow.
Avoiding the High Speed Glitch Edit
When something moves fast enough towards a collider so that the objects are not colliding at the two frame around the collision, the collision will be undetected. [I know that there is a specific term for this but I can't find it.]
To avoid this there is typically a raycast done between the two positions there the moving object was at the current and the last frame:
// player center of current frame Vector3 player_pos=body->GetPosition()+Vector3(0,1,0); PhysicsRaycastResult result; // pos_last is the same position in the last frame Ray ray(pos_last,player_pos-pos_last); // prepare a raycast between the two points float l=(player_pos-pos_last).Length(); // distance between points physical_world->SphereCast(result,ray,0.2,l,2); // if something has been passed between the frame if(result.distance_<=l) // set the object to the last position (could be also set to // the point of the impact of the raycast) body->SetPosition(pos_last); pos_last=body->GetPosition()+Vector3(0,1,0);