【问题标题】:Bullet physics with OpenGL使用 OpenGL 的子弹物理
【发布时间】:2012-01-06 11:52:15
【问题描述】:

我在我的 opengl 游戏中实现子弹物理时遇到了一些问题。问题是它不想持续更新我的 translatef 值,而只是在最后。 项目符号的代码如下所示:

void CGL::initPhysics( void ) {
broadphase = new btDbvtBroadphase();
collisionConfiguration = new btDefaultCollisionConfiguration();
dispatcher = new btCollisionDispatcher(collisionConfiguration);
solver = new btSequentialImpulseConstraintSolver;
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,broadphase,solver,collisionConfiguration);

dynamicsWorld->setGravity(btVector3(0,-10,0));


ballShape = new btSphereShape(1);
pinShape = new btCylinderShape(btVector3(1,1,1));
pinShape->setMargin(0.04);

fallMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,10,0)));
btScalar mass = 1;
btVector3 fallInertia(0,0,0);
ballShape->calculateLocalInertia(mass,fallInertia);

btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),1);

btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0)));
btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));
btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);
dynamicsWorld->addRigidBody(groundRigidBody);

btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,ballShape,fallInertia);
btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI);
dynamicsWorld->addRigidBody(fallRigidBody);

for (int i=0 ; i<300 ; i++) {
    dynamicsWorld->stepSimulation(1/60.f,10);

    btTransform trans;
    fallRigidBody->getMotionState()->getWorldTransform(trans);

    fallY = trans.getOrigin().getY();
}
state_list.remove( STATE_FALL_BALL );
printf("stoped\n");

}

而开头调用的绘图函数是这样的:

void CGL::fallingBall( void ) {
glPushMatrix();

float colBall2[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
glMaterialfv( GL_FRONT, GL_AMBIENT, colBall2);

glTranslatef(0.0f,fallY,0.0f);

printf("fallY: %f\n",fallY);

glutSolidSphere(1.0f,20,20);

glPopMatrix();

}

问题是它在这个函数的 printf 中显示了正确的值,但是翻译只在开始时被调用,我的意思是我只能看到最后一个状态。

编辑

这是改变的函数和循环。收集我认为它现在应该工作的所有信息,但它没有。它不画任何东西。

initPhysics(){
    for (int i=0 ; i<500 ; i++) 
    {
        draw();

    }
    state_list.remove( STATE_FALL_BALL );
    printf("stoped\n");
}

void CGL::draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            current_time = getTime();
            since_update = current_time - last_update;
            printf("time: %f\n",since_update);
            if(since_update>timestep)
            {
                dynamicsWorld->stepSimulation(timestep,10);
                last_update = current_time;
            }
            btTransform trans;
            fallRigidBody->getMotionState()->getWorldTransform(trans);

            fallY = trans.getOrigin().getY();
            fallingBall();
            printf("fallY: %f\n",fallY);
glFlush();
    }

开始的变量声明看起来像这样:

last_update = 0;
timestep = 100;
current_time = 0;
since_update = 0;

【问题讨论】:

  • 跟opengl没关系,跟for循环有关。你运行你的循环 300 次,但你从来没有告诉它重画子弹?
  • @deanWombournefallingBall() 函数一直在运行,因此它至少应该在彼此相邻的地方绘制 300 个球。但事实并非如此。
  • 它是否“一直在运行”在同一个线程上?如果您没有在后台线程上进行计算,那么它将等到循环完成后才会有机会运行。

标签: c++ opengl bulletphysics


【解决方案1】:

看起来有点杂乱无章。我想在不深入研究多线程的情况下解决当前问题的基本错误是这样做:

//pseudo-code to get the idea
void draw(){
    // clear Buffers and setup matricies
    ....
    //calculate the time that has pased since the last time that the physics have been calculated
    time_t current_time = getCurrentTime();
    time_t since_update = current_time - last_update;

    //if enough time has passed since the last redraw calculate physics
    if(since_update>timestep)
    {
        dynamicsWorld->stepSimulation(timestep,10);
        last_update = current_time;
    }
    btTransform trans;
    fallRigidBody->getMotionState()->getWorldTransform(trans);

    fallY = trans.getOrigin().getY();

    //draw various object
    ....
    fallingBall();
    //swap buffers or flush()
    glSwapBuffers();
}

除非有明确的原因直接使用 OpenGL,否则我建议您使用更高级别的工具包。还有通常的免责声明,即您当前使用的是旧版本的 OpenGL。

【讨论】:

  • 该项目是用OpenGL开发的,所以我必须使用它。看起来不错,但我有一个问题——这个 drwa 函数是在这个 for 循环中使用或实现的,还是在哪里?
  • 是的,除非您使用单独的线程来计算物理,否则您应该检查每一帧(在您绘制循环内)是否应该推进物理并在足够的时间过去后推进它们。
  • @sebap123 我认为您对绘制循环是什么以及如何使用它们有一些基本的误解?你在哪里使用glClear(...)glFlush()glSwapBuffers(),在你尝试整合物理之前你有没有打电话给他们?
  • 也许我不了解绘制循环的全部概念,但我从未使用过它们。 glClear(...) 和 glFlush 在 draw 函数中。我忘了粘贴它们。现在它们在代码中。
  • @sebap123 您是否在应用程序中使用了 glut,或者在集成物理之前如何调用绘图代码?你能澄清一下the fallingBall() function is running all the time吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多