現在、同様のコードに取り組んでいます。私のアプローチは、Bullet Physics Rag Doll Demo を出発点として使用することです。体のパーツがジョイントでつながった縫いぐるみ人形です。
次に、Bullet Physics Dynamic Control Demo を使用して関節の曲げ方を学習します。現時点で難しい部分は、すべてのパラメーターを設定することです。
コンストレイントによって接続された 2 つの剛体を作成し、コンストレイント モーターをアクティブにしてジョイントを曲げる方法を学習することをお勧めします。
以下は、Bullet Physics で剛体と拘束がどのように機能するかを学習するために使用しているコードです。このコードは、ヒンジ制約によって接続された 2 つのブロックを作成します。update 関数は、時間の経過とともにゆっくりとヒンジ制約を曲げます。
これができたので、ラグドールに戻って関節を調整します。
class Simple
{
private:
btScalar targetAngle;
btCollisionShape* alphaCollisionShape;
btCollisionShape* bravoCollisionShape;
btRigidBody* alphaRigidBody;
btRigidBody* bravoRigidBody;
btHingeConstraint* hingeConstraint;
btDynamicsWorld* dynamicsWorld;
public:
~Simple( void )
{
}
btRigidBody* createRigidBody( btCollisionShape* collisionShape,
btScalar mass,
const btTransform& transform ) const
{
// calculate inertia
btVector3 localInertia( 0.0f, 0.0f, 0.0f );
collisionShape->calculateLocalInertia( mass, localInertia );
// create motion state
btDefaultMotionState* defaultMotionState
= new btDefaultMotionState( transform );
// create rigid body
btRigidBody::btRigidBodyConstructionInfo rigidBodyConstructionInfo(
mass, defaultMotionState, collisionShape, localInertia );
btRigidBody* rigidBody = new btRigidBody( rigidBodyConstructionInfo );
return rigidBody;
}
void Init( btDynamicsWorld* dynamicsWorld )
{
this->targetAngle = 0.0f;
this->dynamicsWorld = dynamicsWorld;
// create collision shapes
const btVector3 alphaBoxHalfExtents( 0.5f, 0.5f, 0.5f );
alphaCollisionShape = new btBoxShape( alphaBoxHalfExtents );
//
const btVector3 bravoBoxHalfExtents( 0.5f, 0.5f, 0.5f );
bravoCollisionShape = new btBoxShape( bravoBoxHalfExtents );
// create alpha rigid body
const btScalar alphaMass = 10.0f;
btTransform alphaTransform;
alphaTransform.setIdentity();
const btVector3 alphaOrigin( 54.0f, 0.5f, 50.0f );
alphaTransform.setOrigin( alphaOrigin );
alphaRigidBody = createRigidBody( alphaCollisionShape, alphaMass, alphaTransform );
dynamicsWorld->addRigidBody( alphaRigidBody );
// create bravo rigid body
const btScalar bravoMass = 1.0f;
btTransform bravoTransform;
bravoTransform.setIdentity();
const btVector3 bravoOrigin( 56.0f, 0.5f, 50.0f );
bravoTransform.setOrigin( bravoOrigin );
bravoRigidBody = createRigidBody( bravoCollisionShape, bravoMass, bravoTransform );
dynamicsWorld->addRigidBody( bravoRigidBody );
// create a constraint
const btVector3 pivotInA( 1.0f, 0.0f, 0.0f );
const btVector3 pivotInB( -1.0f, 0.0f, 0.0f );
btVector3 axisInA( 0.0f, 1.0f, 0.0f );
btVector3 axisInB( 0.0f, 1.0f, 0.0f );
bool useReferenceFrameA = false;
hingeConstraint = new btHingeConstraint(
*alphaRigidBody,
*bravoRigidBody,
pivotInA,
pivotInB,
axisInA,
axisInB,
useReferenceFrameA );
// set constraint limit
const btScalar low = -M_PI;
const btScalar high = M_PI;
hingeConstraint->setLimit( low, high );
// add constraint to the world
const bool isDisableCollisionsBetweenLinkedBodies = false;
dynamicsWorld->addConstraint( hingeConstraint,
isDisableCollisionsBetweenLinkedBodies );
}
void Update( float deltaTime )
{
alphaRigidBody->activate();
bravoRigidBody->activate();
bool isEnableMotor = true;
btScalar maxMotorImpulse = 1.0f; // 1.0f / 8.0f is about the minimum
hingeConstraint->enableMotor( isEnableMotor );
hingeConstraint->setMaxMotorImpulse( maxMotorImpulse );
targetAngle += 0.1f * deltaTime;
hingeConstraint->setMotorTarget( targetAngle, deltaTime );
}
};