2

我希望利用子弹物理或类似的物理引擎来创建具有两条腿的类人身体的逼真骨架模拟。也就是说,在两条“腿”上创建一个由圆形质量组成的“身体”的模拟,其中每条腿由通过 3 个关节连接的 3 个实体块组成,每个关节都有一定的自由度和有限的运动范围每个方向,类似于人类的臀部、膝盖和脚踝。

我的目标是一个逼真的模型,因此只有当所有关节都正确平衡时它才会“站立”,否则它会倒下。

对现有教程或资源的任何方向、建议或指针表示赞赏!这看起来像是从头开始做的大量工作......

4

4 回答 4

6

查看 OpenSim 项目 (opensim.stanford.edu),该项目被生物力学社区大量用于研究人体运动,例如临床应用。在 OpenSim 中,人体模型通常由肌肉驱动,而不仅仅是关节处的扭矩。

OpenSim 建立在 Simbody 多体动力学库之上。请参阅 Simbody 的此示例,以使用人形模型运行:https ://github.com/simbody/simbody/blob/master/Simbody/examples/JaredsDude.cpp 。

于 2014-03-28T01:12:42.103 回答
4

我目前正在处理类似的代码。我的方法是使用 Bullet Physics Rag Doll Demo 作为起点。它有一个布娃娃,身体各部分由关节连接。

然后我使用 Bullet Physics 动态控制演示来学习弯曲关节。目前具有挑战性的部分是设置所有参数。

我建议你学习如何创建两个通过约束连接的刚体,然后激活约束电机来弯曲关节。

以下是我正在使用的一些代码,用于了解刚体和约束如何在 Bullet Physics 中工作。该代码创建了两个由铰链约束连接的块。随着时间的推移,更新函数会慢慢弯曲铰链约束。

现在我已经有了这个,我将回到布娃娃并调整关节。

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 );  
    }

};
于 2011-07-12T06:28:41.573 回答
1

刚刚发现 Hase & Yamazaki (2002) 的“具有三维全身神经-肌肉-骨骼模型的人体运动的计算机模拟研究”,它提供

提出了一种具有三维全身结构并由神经元系统和肌肉骨骼系统组成的模型,以精确模拟人类步行运动。人体动力学由 14 个刚性连杆系统和 60 个肌肉模型代表

于 2011-12-08T11:35:20.360 回答
0

毫无疑问,从头开始会很困难。我不知道你的目标是什么。但是您不必重新设计轮子。你看过虚幻引擎吗?你可能会在那里找到可以重复使用的东西。许多游戏都是建立在这个引擎之上的。

于 2011-05-13T21:47:44.730 回答