子弹头车轮落后和错误的底盘俯仰方向

Posted

技术标签:

【中文标题】子弹头车轮落后和错误的底盘俯仰方向【英文标题】:Bullet vehicle wheels fall behind and wrong chassis pitch direction 【发布时间】:2013-12-09 22:54:40 【问题描述】:

我已经创建了一个在顶部带有炮塔的子弹车,如下所示:

    gEngineForce = 0.f;
    gBreakingFrontForce = 0.f;
    gBreakingBackForce = 0.f;

    maxEngineForce = 20000.f;
    minEngineForce = -2000.f;
    maxBreakingFrontForce = 4000.f;
    maxBreakingBackForce = 600.f;

    gVehicleSteering = 0.f;
    steeringIncrement = 0.002f;
    steeringClamp = 0.6f;
    wheelRadius = 0.5f;
    wheelWidth = 0.4f;
    wheelFriction = 50;
    suspensionStiffness = 10.f;
    suspensionDamping = 1.3f;
    suspensionCompression = 4.4f;
    rollInfluence = 0.1f;//1.0f

    btScalar suspensionRestLength(0.6);
    btVector3 wheelDirectionCS0(0, -1, 0);
    btVector3 wheelAxleCS(-1, 0, 0);




    btTransform tr;
    tr.setIdentity();

    chassisShape = new btBoxShape(btVector3(1.f, 0.5f, 2.f));
    bulletCollisionShapes.push_back(chassisShape);

    compound = new btCompoundShape();
    bulletCollisionShapes.push_back(compound);

    btTransform chassisTrans;
    chassisTrans.setIdentity();
    //localTrans effectively shifts the center of mass with respect to the chassis
    chassisTrans.setOrigin(btVector3(0, 1.3, 0));
    compound->addChildShape(chassisTrans, chassisShape);

    tr.setOrigin(btVector3(0, 0.f, 0));
    //m_carChassis = CreateRigidBody(2000, tr, compound);
    //m_carChassis->setDamping(0.2,0.2);
    m_wheelShape = new btCylinderShapeX(btVector3(wheelWidth, wheelRadius, wheelRadius));

    m_carChassis = CreateRigidBody(2000, tr, compound);


    // create turret
    turretShape = new btBoxShape(btVector3(0.4f, 0.2f, 0.8f));
    bulletCollisionShapes.push_back(turretShape);
    btTransform turretTrans;
    turretTrans.setIdentity();
    turretTrans.setOrigin(btVector3(0.0f, 0.7f, 0.0f));
    turretBody = CreateRigidBody(1, turretTrans, turretShape);

    // add some data to build constraint frames
    btVector3 axisA(0.f, 1.f, 0.f);
    btVector3 axisB(0.f, 0.f, 0.f);
    btVector3 pivotA(0.f, 1.f, 0.f);
    btVector3 pivotB(0.f, 0.f, 0.f);
    hinge = new btHingeConstraint(*m_carChassis, *turretBody, pivotA, pivotB, axisA, axisB);
    //hinge->setLimit(-SIMD_HALF_PI * 0.5f, SIMD_HALF_PI * 0.5f);
    hinge->enableAngularMotor(true, 0, 1);

    // add constraint to world
    bt_dynamicsWorld->addConstraint(hinge, true);

    
        btTransform something;
        something.setIdentity();
        something.setOrigin(btVector3(0, 10, 0));
        m_carChassis->setWorldTransform(something);

        m_vehicleRayCaster = new btDefaultVehicleRaycaster(bt_dynamicsWorld);
        m_vehicle = new btRaycastVehicle(m_tuning, m_carChassis, m_vehicleRayCaster);

        m_carChassis->setActivationState(DISABLE_DEACTIVATION);

        bt_dynamicsWorld->addVehicle(m_vehicle);

        float connectionHeight = 1.2f;


        //choose coordinate system
        m_vehicle->setCoordinateSystem(rightIndex, upIndex, forwardIndex);

        bool isFrontWheel = true;
        btVector3 connectionPointCS0(1 - (-0.8*wheelWidth), connectionHeight, 3 * 1 - wheelRadius);
        m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);

        connectionPointCS0 = btVector3(-1 + (-0.8*wheelWidth), connectionHeight, 3 * 1 - wheelRadius);
        m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);

        isFrontWheel = false;
        connectionPointCS0 = btVector3(-1 + (-0.8*wheelWidth), connectionHeight, -3 * 1 + wheelRadius);
        m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);

        connectionPointCS0 = btVector3(1 - (-0.8*wheelWidth), connectionHeight, -3 * 1 + wheelRadius);
        m_vehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, m_tuning, isFrontWheel);

        for (int i = 0; i < m_vehicle->getNumWheels(); i++)
        
            btWheelInfo& wheel = m_vehicle->getWheelInfo(i);
            wheel.m_suspensionStiffness = suspensionStiffness;
            wheel.m_wheelsDampingRelaxation = suspensionDamping;
            wheel.m_wheelsDampingCompression = suspensionCompression;
            wheel.m_frictionSlip = wheelFriction;
            wheel.m_rollInfluence = rollInfluence;
        
    

    int wheelIndex = 2;
    m_vehicle->applyEngineForce(gEngineForce, wheelIndex);
    m_vehicle->setBrake(gBreakingBackForce, wheelIndex);
    wheelIndex = 3;
    m_vehicle->applyEngineForce(gEngineForce, wheelIndex);
    m_vehicle->setBrake(gBreakingBackForce, wheelIndex);

    wheelIndex = 0;
    m_vehicle->setSteeringValue(gVehicleSteering, wheelIndex);
    m_vehicle->setBrake(gBreakingFrontForce, wheelIndex);
    wheelIndex = 1;
    m_vehicle->setSteeringValue(gVehicleSteering, wheelIndex);
    m_vehicle->setBrake(gBreakingFrontForce, wheelIndex);

这是我渲染车辆的方式:

   // render wheels
   btScalar mwheel[16];
   for (int i = 0; i<m_vehicle->getNumWheels(); i++)
      //synchronize the wheels with the (interpolated) chassis worldtransform
      m_vehicle->updateWheelTransform(i, true);
      //draw wheels
      m_vehicle->getWheelInfo(i).m_worldTransform.getOpenGLMatrix(mwheel);
      RenderWheel(m_wheelShape, mwheel);
   


   // render car chassis
   btScalar mchassis[16];
   m_vehicle->getChassisWorldTransform().getOpenGLMatrix(mchassis);
   RenderBox(chassisShape, mchassis);


   // render turret
   btScalar mturret[16];
   // get chassis and turret transforms
   btTransform chassisTransform = m_vehicle->getChassisWorldTransform();
   //btTransform turretTransform = compound->getChildTransform(1);
   btTransform turretTransform = turretBody->getWorldTransform();
   // multiply transforms to get updated turret transform
   //turretTransform *= chassisTransform;
   turretTransform.getOpenGLMatrix(mturret);
   RenderBox(turretShape, mturret);

使用箭头键,我可以像这样施加中断或加速力:

  bullet.gEngineForce = bullet.maxEngineForce;
  bullet.gBreakingFrontForce = 0.f;
  bullet.gBreakingBackForce = 0.f;

等等

摄像头安装在汽车顶部的炮塔上,因此安装在汽车本身上。

问题在于,当汽车开始行驶并加速时,车轮似乎落后而底盘向前移动。我想让***和底盘更紧,但玩弄汽车悬架设置并没有帮助。

这是一个演示此行为的视频:click

我还注意到另一个与汽车在移动、刹车和转弯时的倾斜方式有关的奇怪行为。

增加重力会加重这种行为。当我加速时,底盘向前倾斜,当我刹车时,它向后倾斜。这显然是错误的,因为它应该是相反的。左转时也会发生同样的情况,汽车向左而不是向右倾斜,反之亦然。

这是另一个演示此行为的视频:click

【问题讨论】:

你解决问题了吗? 【参考方案1】:

我遇到了这种问题。事实证明,车轮是使用变换渲染的,而不是来自与底盘相同的框架。即从框架 n-1 开始,而底盘使用框架 n。

事情并不明显,因为车轮网格是底盘节点的子节点,因为它是我在渲染引擎中实现的方式,而在子弹物理中,车轮坐标是全局的,底盘也是如此。 但这还不是全部,当将车轮坐标从全局转换为局部车辆空间时,会出现精度损失,这仍然会导致问题。它是通过将车轮网格作为全局节点来修复的。

【讨论】:

以上是关于子弹头车轮落后和错误的底盘俯仰方向的主要内容,如果未能解决你的问题,请参考以下文章

三轴速率陀螺装在俯仰轴上,怎么计算方位速率

子弹不向方向旋转

如何根据玩家的方向偏移子弹对象

子弹物理和 OpenGL 将方向转换为前、上和右

弹丸/子弹方向 Cocos2d

在pygame中向鼠标方向射击子弹