# Constraint magic - how do you understand them?

Hi, all!

Trying to approach constraints for half a year now, and can’t understand a thing here.
Whatever I do it misbehaves, explodes and malfunction. When I see example made by people it works,
but if I try to modify it it immediately stops working and I can’t understand what leads to that.
I read Bullet docs, but these are very sparse and can’t shed light on anything, so please don’t
reference them to me they won’t help. Please provide humane understanding in the matter.

1. Hinge constraint.
What axes do? What is relation between axes? How the axes relate to rigid bodies?
What are limits? Why whatever I set to limits it doesn’t change anything?
Why the joint tends to keep the same angle regardless of limits?

2. Cone twist constraint
What are axes do? why cones always point rigid bodies up (depending on axes, but always up)? how can I place
it so that it points to direction I need and twists around angle? Looks like this is not related to axes or limits

I was looking for tutorials, but there is basically none, there are a lot of gui tools which use bullet, but
there is no any guide on how to write code to implement constraints.

Is there anyone using constraints here? I’d appreciate any help.

Or is it better to implement custom Verlet integration? Will it be easier to do and understand?

This is what I tried to do.

Things go fine this far:
youtu.be/NX31yE8x1GA

I can’t make constraint to not turn body over. if node with body is rotated it is turn upside down
by constraint. Is it related to axis locations? How can I make it work?
youtu.be/GoUm_ZH0_Ds

Code:

``````Scene@ sc;
Node@ cam_node;
Node@ floorNode;
Node@ box1, box2, box3;
void HandlePostRenderUpdate()
{
renderer.DrawDebugGeometry(false);
sc.physicsWorld.DrawDebugGeometry(true);
}

void Start()
{
graphics.windowTitle = "Pairs";
engine.maxFps = 60.0;
sc = Scene();
sc.CreateComponent("Octree");
sc.CreateComponent("PhysicsWorld");
sc.CreateComponent("DebugRenderer");

cam_node = Node();
Camera@ camera = cam_node.CreateComponent("Camera");
cam_node.worldPosition = Vector3(10.0, 5.0, -10.0);
Quaternion cam_rot;
cam_rot.FromLookRotation(Vector3(0.0, 0.0, 0.0) - cam_node.worldPosition, Vector3(0.0, 1.0, 0.0));
cam_node.worldRotation = cam_rot;
renderer.numViewports = 1;
renderer.viewports[0] = Viewport(sc, camera);
Node@ zoneNode = sc.CreateChild("Zone");
Zone@ zone = zoneNode.CreateComponent("Zone");
zone.boundingBox = BoundingBox(Vector3(-1000.0f,-10000.0, -1000.0f), Vector3(1000, 499, 1000));
zone.ambientColor = Color(0.15f, 0.15f, 0.15f);
zone.fogColor = Color(0.5f, 0.5f, 0.7f);
zone.fogStart = 300.0f;
zone.fogEnd = 300.0f;
Node@ lightNode = sc.CreateChild("DirectionalLight");
lightNode.direction = Vector3(0.0, -1.0f, 0.0f);
Light@ light = lightNode.CreateComponent("Light");
light.lightType = LIGHT_DIRECTIONAL;
light.color = Color(1.0, 1.0, 0.86);

floorNode = sc.CreateChild("Floor");
floorNode.position = Vector3(0.0f, -0.5f, 0.0f);
floorNode.scale = Vector3(400.0f, 1.0f, 400.0f);
StaticModel@ object = floorNode.CreateComponent("StaticModel");
object.model = cache.GetResource("Model", "Models/Box.mdl");
object.material = cache.GetResource("Material", "Materials/Stone.xml");

RigidBody@ body = floorNode.CreateComponent("RigidBody");
// Use collision layer bit 2 to mark world scenery. This is what we will raycast against to prevent camera from going
// inside geometry
body.collisionLayer = 2;
CollisionShape@ shape = floorNode.CreateComponent("CollisionShape");
shape.SetBox(Vector3(1.0f, 1.0f, 1.0f));
/* Creating ragdoll-like structure */
box2 = sc.CreateChild("box2");
box1 = box2.CreateChild("box1");
box3 = box2.CreateChild("box3");
box2.worldPosition = Vector3(0.0, 6, 0.0);
box1.worldPosition = Vector3(0.0, 5, 0.0);
box3.worldPosition = Vector3(0.0, 7, 0.0);
box3.rotation = Quaternion(0.0, 0.0, 180.0);
// Creating boxes
Array<Node@> boxes = {box1, box2, box3};
for (int i = 0; i < boxes.length; i++) {
Node@ box = boxes[i];
RigidBody@ box_body = box.CreateComponent("RigidBody");
box_body.mass = 20;
box_body.collisionLayer = 1;
box_body.friction = 1;
box_body.angularDamping = 0.2f;
box_body.linearDamping = 0.2f;
//        StaticModel@ box_model = box.CreateComponent("StaticModel");
//        box_model.model = cache.GetResource("Model", "Models/Box.mdl");
//        box_model.material = cache.GetResource("Material", "Materials/Stone.xml");
CollisionShape@ box_shape = box.CreateComponent("CollisionShape");
// Offset to look more like bone
box_shape.SetBox(Vector3(1.0, 1.0, 1.0), box.rotation * Vector3(0.0, -0.5, 0.0));
}
Constraint@ box_constraint = box1.CreateComponent("Constraint");
box_constraint.constraintType = CONSTRAINT_HINGE;
box_constraint.otherBody = box2.GetComponent("RigidBody");
// Constraint motion means that body it attaches to moves.
// This way one can offset constraint to the side of body.
box_constraint.worldPosition = box1.worldPosition;
box_constraint.axis = Vector3(1.0, 0.0, 0.0);
box_constraint.otherAxis = Vector3(1.0, 0.0, 0.0);
box_constraint.lowLimit = Vector2(-180.0, 0.0);
box_constraint.highLimit = Vector2(180.0, 0.0);
box_constraint.disableCollision = true;