Research on Six Degrees of Freedom elastic constraints of Bullet
Research on Six Degrees of Freedom elastic constraints of Bullet
During this time, I planned to integrate the physical engine, so I did some research on the open-source physical engine Bullet. The Bullet research has been around for a while. The Bullet engine has been in touch for a long time, but it has been just an example of running it, and there are no research examples and source code, if you want to integrate it into the rendering engine, it will be spent in the middle of the moon. In March this year, I made a simple example of integrating Bullet. This is the first test of simulated object falling, and wrote the blog "QtQuick + OpenGL + Bullet first test". This example provides a good example. During this time, I began to study other interesting features of Bullet.
The constraint (also called joint) of Bullet is a very interesting part because it represents the physical relationship between two collision objects. For example, if two beads are concatenated by a rope, the rope represents the constraint between the two beads. Of course, you can change the rope into a rubber band or a spring, they all represent different constraints. These constraints all have their names. I recently studied Six Degrees of Freedom elastic constraints.
The best way to study an engine is to study its example. This is also true for Bullet. In the ConstraintDemo provided by Bullet, I have seen some very interesting constraints. So starting from this place is not bad. The example is as follows:
You can use the right-click box to test the effect of constraints on these objects.
This scenario contains multiple constraints. The processing method of each constraint includes the corresponding mechanical formula and its addition. I only studied the Six-Degree-of-Freedom elastic constraint this time, so I pulled it out separately.
A Six-Degree-of-Freedom elastic constraint is a constraint. As its name suggests, it can rotate six dimensions and maintain a certain degree of Elasticity in translation. The yellow and blue squares in the upper right corner form a Six-Degree-of-Freedom elastic constraint. This scenario shows the constraints of Bullet, so that everyone can understand how constraints affect objects.
The Six Degrees of Freedom elastic constraint has the following attributes:
English name |
Chinese name |
RigidBodyA |
Rigid Body A to which this constraint applies |
RigidBodyB |
Rigid Body B to which this constraint applies |
FrameInA |
Transformation from rigid body A to this constraint |
FrameInB |
Transformation from rigid body B to this constraint |
LinearUpperLimit |
Maximum limit of translation (linearity) |
LinearLowerLimit |
Minimum limit of translation (linearity) |
AngularUpperLimit |
Maximum Rotation (angle) Limit |
AngularLowerLimit |
Minimum rotation (angle) Limit |
Spring |
Spring Effect |
Stiffness |
Spring rigidity (stiffness) |
Damping |
Spring Attenuation |
Let's change the default example effect to the spring effect we want:
frameInA.setOrigin(btVector3(btScalar(10), btScalar(0), btScalar(0.))); frameInB.setOrigin(btVector3(btScalar(0), btScalar(0), btScalar(0.))); btGeneric6DofSpringConstraint* pGen6DOFSpring = new btGeneric6DofSpringConstraint(*pBodyA, *pBodyB, frameInA, frameInB, true); pGen6DOFSpring->setLinearUpperLimit(btVector3(0, 0, 0)); pGen6DOFSpring->setLinearLowerLimit(btVector3(0, 0, 0)); pGen6DOFSpring->setAngularLowerLimit(btVector3(-0.17f, -0.17f, -0.17f) ); pGen6DOFSpring->setAngularUpperLimit(btVector3(0.17f, 0.17f, 0.17f) ); pGen6DOFSpring->enableSpring(3, true); pGen6DOFSpring->setStiffness(3, 100.0f); pGen6DOFSpring->setDamping(3, 0.25f); pGen6DOFSpring->enableSpring(4, true); pGen6DOFSpring->setStiffness(4, 100.0f); pGen6DOFSpring->setDamping(4, 0.25f); pGen6DOFSpring->enableSpring(5, true); pGen6DOFSpring->setStiffness(5, 100.0f); pGen6DOFSpring->setDamping(5, 0.25f); pBodyA->addConstraintRef( pGen6DOFSpring ); pBodyB->addConstraintRef( pGen6DOFSpring );
Replace the Code with lines 559 to 576 of ConstraintDemo. cpp and check the effect again. The constraints have changed, for example:
The yellow square turns into a constraint with only-10 ° to 10 ° in each of the six degrees of freedom. Try to use a square to collide with it and find that it will rotate around the constraint.
The next step is the process of imitation. I want to try the example of running the Bullet constraints in Qt Quick + OpenGL, so I did a lot of work in the early stage, the initialization of related classes takes a lot of effort. Because the code is too long, only the important part is posted here:
Void initialize (void) {qDebug ("--- initialize compoundCube physics ---"); btTransform centerOfMassTransform (btTransform: getIdentity (); centerOfMassTransform. setOrigin (btVector3 (0.2, 0.0, 0.2); btTransform tr; tr. setIdentity (); tr. setOrigin (btVector3 (btScalar (-20 .), btScalar (16 .), btScalar (0 .))); tr. getBasis (). values (1.0, 0); btRigidBody * pBodyA = createRigidBody (Cube, btVector3 (1.0, 1.0, 0.0), tr); pBodyA-> setActivationState (DISABLE_DEACTIVATION); tr. setIdentity (); tr. setOrigin (btVector3 (btScalar (-10 .), btScalar (16 .), btScalar (0 .))); tr. getBasis (). values (1.0, 0); btRigidBody * pBodyB = createRigidBody (Cube, btVector3 (1.0, 1.0, 1.0), tr, callback); pBodyB-> setActivationState (DISABLE_DEACTIVATION ); btTransform frameInA, frameInB; frameInA = btTransform: getIdentity (); frameInB = btTransform: getIdentity (); frameInA. setOrigin (btVector3 (btScalar (10), btScalar (0), btScalar (0 .))); frameInB. setOrigin (btVector3 (btScalar (0), btScalar (0), btScalar (0 .))); optional * pGen6DOFSpring = new partition (* pBodyA, * pBodyB, frameInA, frameInB, false); pGen6DOFSpring-> setLinearUpperLimit (btVector3 (0, 0, 0 )); pGen6DOFSpring-> setLinearLowerLimit (btVector3 (0, 0, 0); pGen6DOFSpring-> setAngularLowerLimit (btVector3 (-0.17f,-0.17f,-0.17f )); pGen6DOFSpring-> destroy (btVector3 (0.17f, 0.17f, 0.17f); pGen6DOFSpring-> enableSpring (3, true); pGen6DOFSpring-> setStiffness (3, 100366f ); values-> setDamping (3, 0.25f); pGen6DOFSpring-> enableSpring (4, true); values-> setStiffness (4, 100366f); pGen6DOFSpring-> setDamping (4, 0.25f ); pGen6DOFSpring-> enableSpring (5, true); pGen6DOFSpring-> setStiffness (5, 100366f); response-> setDamping (5, 0.25f); pBodyA-> addConstraintRef (response ); pBodyB-> addConstraintRef (pGen6DOFSpring); // End the newly added m_scene-> physics ()-> world (). addConstraint (pGen6DOFSpring, true); pGen6DOFSpring-> setDbgDrawSize (btScalar (5.f)); m_constraint = pGen6DOFSpring; // Add a new free-body btTransform newTrans; newTrans. setIdentity (); newTrans. setOrigin (btVector3 (-12.0, 60, 0.9); // btQuaternion q; // q. setEuler (0.7, 0.6, 0.7); // newTrans. setRotation (q); btRigidBody * newBody = createRigidBody (Cube, btVector3 (2.0, 6.0, 3.0), 300.0, newTrans); newBody-> setActivationState (DISABLE_DEACTIVATION );} void simulate (void) {// m_constraint-> setEquilibriumPoint (); // qDebug ("--- simulate compoundCube physics ---");} btRigidBody * createRigidBody (ShapeType shapeType, const btVector3 & half, btScalar mass, const btTransform & startTransform, const btTransform & Signature = btTransform: getIdentity () {btCollisionShape * shape = shape; // create a shape switch (shapeType) {case Sphere: // spherical shape = new btSphereShape (half. x (); break; case Cube: // Cube shape = new btBoxShape (half); break; case Capsule: // Capsule shape = new btCapsuleShape (half. x (), half. y (); break; default: qDebug ("This piece is code will never be reached unless bug. "); break;} btMotionState * motionState = new btdefamomotionstate (startTransform, callback); btVector3 inertia (0, 0, 0); shape-> calculateLocalInertia (mass, inertia ); btRigidBody * body = new btRigidBody (mass, motionState, shape, inertia); m_scene-> physics ()-> world (). addRigidBody (body); return body ;}
A simple scenario is created here: there is only one six-degree-of-freedom elastic constraint, two rigid bodies, and a very large object. You can click the button to enable the physical engine, in this way, the object will convert the gravity potential energy into kinetic energy by moving freely into the body and impact this rigid body. Since the rotation elastic factor is set, the rigid body on the other side is constrained to avoid a mass object through rotation, and the object is popped up ......
How can we achieve elasticity by opening the source code? In the past, a classic formula was used: Hu Ke's law. The formula of Hu Ke's law is F = k · x, where k is the stiffness coefficient of the object, which corresponds to stiffness. It seems that to understand the principles of the Bullet library, we need to review a lot of physical knowledge.