Example #1
0
/** Waits till each kart is resting on the ground
 *
 * Does simulation steps still all karts reach the ground, i.e. are not
 * moving anymore
 */
void World::resetAllKarts()
{
    // Reset the physics 'remaining' time to 0 so that the number
    // of timesteps is reproducible if doing a physics-based history run
    getPhysics()->getPhysicsWorld()->resetLocalTime();

    // If track checking is requested, check all rescue positions if
    // they are heigh enough.
    if(UserConfigParams::m_track_debug)
    {
        // Loop over all karts, in case that some karts are dfferent
        for(unsigned int kart_id=0; kart_id<(unsigned int)m_karts.size(); kart_id++)
        {
            for(unsigned int rescue_pos=0;
                rescue_pos<getNumberOfRescuePositions();
                rescue_pos++)
            {
                btTransform t = getRescueTransform(rescue_pos);
                // This will print out warnings if there is no terrain under
                // the kart, or the kart is being dropped on a reset texture
                moveKartTo(m_karts[kart_id], t);

            }   // rescue_pos<getNumberOfRescuePositions

            // Reset the karts back to the original start position.
            // This call is a bit of an overkill, but setting the correct
            // transforms, positions, motion state is a bit of a hassle.
            m_karts[kart_id]->reset();
        }   // for kart_id<m_karts.size()


    }   // if m_track_debug

    m_schedule_pause = false;
    m_schedule_unpause = false;

    //Project karts onto track from above. This will lower each kart so
    //that at least one of its wheel will be on the surface of the track
    for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++)
    {
        Vec3 xyz = (*i)->getXYZ();
        //start projection from top of kart
        Vec3 up_offset(0, 0.5f * ((*i)->getKartHeight()), 0);
        (*i)->setXYZ(xyz+up_offset);

        bool kart_over_ground = m_track->findGround(*i);

        if (!kart_over_ground)
        {
            Log::error("World",
                       "No valid starting position for kart %d on track %s.",
                        (int)(i-m_karts.begin()), m_track->getIdent().c_str());
            if (UserConfigParams::m_artist_debug_mode)
            {
                Log::warn("World", "Activating fly mode.");
                (*i)->flyUp();
                continue;
            }
            else
            {
                exit(-1);
            }
        }
    }

    bool all_finished=false;
    // kart->isInRest() is not fully correct, since it only takes the
    // velocity in count, which might be close to zero when the kart
    // is just hitting the floor, before being pushed up again by
    // the suspension. So we just do a longer initial simulation,
    // which should be long enough for all karts to be firmly on ground.
    for(int i=0; i<60; i++) m_physics->update(1.f/60.f);

    // Stil wait will all karts are in rest (and handle the case that a kart
    // fell through the ground, which can happen if a kart falls for a long
    // time, therefore having a high speed when hitting the ground.
    int count = 0;
    while(!all_finished)
    {
        if (count++ > 100)
        {
            Log::error("World", "Infinite loop waiting for all_finished?");
            break;
        }
        m_physics->update(1.f/60.f);
        all_finished=true;
        for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++)
        {
            if(!(*i)->isInRest())
            {
                Vec3            normal;
                Vec3            hit_point;
                const Material *material;
                // We can't use (*i)->getXYZ(), since this is only defined
                // after update() was called. Instead we have to get the
                // real position of the rigid body.
                btTransform     t;
                (*i)->getBody()->getMotionState()->getWorldTransform(t);
                // This test can not be done only once before the loop, since
                // it can happen that the kart falls through the track later!
                Vec3 to = t.getOrigin()+Vec3(0, -10000, 0);
                m_track->getTriangleMesh().castRay(t.getOrigin(), to,
                                                   &hit_point, &material,
                                                   &normal);
                if(!material)
                {
                    Log::error("World",
                               "No valid starting position for kart %d "
                               "on track %s.",
                               (int)(i-m_karts.begin()),
                               m_track->getIdent().c_str());
                    if (UserConfigParams::m_artist_debug_mode)
                    {
                        Log::warn("World", "Activating fly mode.");
                        (*i)->flyUp();
                        continue;
                    }
                    else
                    {
                        exit(-1);
                    }
                }
                all_finished=false;
                break;
            }
        }
    }   // while

    for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++)
    {
        (*i)->kartIsInRestNow();
    }

    // Initialise the cameras, now that the correct kart positions are set
    for(unsigned int i=0; i<Camera::getNumCameras(); i++)
    {
        Camera::getCamera(i)->setInitialTransform();
    }
}   // resetAllKarts
/** Waits till each kart is resting on the ground
 *
 * Does simulation steps still all karts reach the ground, i.e. are not
 * moving anymore
 */
void World::resetAllKarts()
{
    // Reset the physics 'remaining' time to 0 so that the number
    // of timesteps is reproducible if doing a physics-based history run
    getPhysics()->getPhysicsWorld()->resetLocalTime();

    // If track checking is requested, check all rescue positions if
    // they are heigh enough.
    if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES &&
        UserConfigParams::m_track_debug)
    {
        Vec3 eps = Vec3(0,1.5f*m_karts[0]->getKartHeight(),0);
        for(unsigned int quad=0; quad<QuadGraph::get()->getNumNodes(); quad++)
        {
            const Quad &q   = QuadGraph::get()->getQuadOfNode(quad);
            const Vec3 center = q.getCenter();
            // We have to test for all karts, since the karts have different
            // heights and so things might change from kart to kart.
            for(unsigned int kart_id=0; kart_id<m_karts.size(); kart_id++)
            {
                AbstractKart *kart = m_karts[kart_id];
                kart->setXYZ(center);
    
                btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f),
                                     m_track->getAngle(quad) );
                kart->setRotation(heading);

                btTransform pos;
                pos.setOrigin(center+eps);
                pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f),
                                m_track->getAngle(quad))                 );
                kart->getBody()->setCenterOfMassTransform(pos);
                bool kart_over_ground = m_physics->projectKartDownwards(kart);
                if(kart_over_ground)
                {
                    const Vec3 &xyz = kart->getTrans().getOrigin()
                                    + Vec3(0,0.3f,0);
                    if(dynamic_cast<Kart*>(kart))
                        dynamic_cast<Kart*>(kart)->getTerrainInfo()
                                                 ->update(xyz);
                    const Material *material = kart->getMaterial();
                    if(!material || material->isDriveReset())
                        kart_over_ground = false;
                }
                if(!kart_over_ground)
                {
                    printf("Kart '%s' not over quad '%d'\n",
                        kart->getIdent().c_str(), quad);
                    printf("Center point: %f %f %f\n",
                        center.getX(), center.getY(), center.getZ());

                }
            }   // for kart_id<m_karts.size()
        }   // for quad < quad_graph.getNumNodes

        for(unsigned int kart_id=0; kart_id<m_karts.size(); kart_id++)
        {
            // Reset the karts back to the original start position.
            // This call is a bit of an overkill, but setting the correct
            // transforms, positions, motion state is a bit of a hassle.
            m_karts[kart_id]->reset();
        }

    }   // if m_track_debug


    m_schedule_pause = false;
    m_schedule_unpause = false;
    
    //Project karts onto track from above. This will lower each kart so
    //that at least one of its wheel will be on the surface of the track
    for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++)
    {
        ///start projection from top of kart
        btVector3 up_offset(0, 0.5f * ((*i)->getKartHeight()), 0);
        (*i)->getVehicle()->getRigidBody()->translate (up_offset);

        bool kart_over_ground = m_physics->projectKartDownwards(*i);

        if (!kart_over_ground)
        {
            fprintf(stderr, 
                    "ERROR: no valid starting position for kart %d "
                    "on track %s.\n",
                    (int)(i-m_karts.begin()), m_track->getIdent().c_str());
            if (UserConfigParams::m_artist_debug_mode)
            {
                fprintf(stderr, "Activating fly mode.\n");
                (*i)->flyUp();
                continue;
            }
            else
            {
                exit(-1);
            }
        }
    }

    bool all_finished=false;
    // kart->isInRest() is not fully correct, since it only takes the
    // velocity in count, which might be close to zero when the kart
    // is just hitting the floor, before being pushed up again by
    // the suspension. So we just do a longer initial simulation,
    // which should be long enough for all karts to be firmly on ground.
    for(int i=0; i<60; i++) m_physics->update(1.f/60.f);

    // Stil wait will all karts are in rest (and handle the case that a kart
    // fell through the ground, which can happen if a kart falls for a long
    // time, therefore having a high speed when hitting the ground.
    while(!all_finished)
    {
        m_physics->update(1.f/60.f);
        all_finished=true;
        for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++)
        {
            if(!(*i)->isInRest())
            {
                Vec3            normal;
                Vec3            hit_point;
                const Material *material;
                // We can't use (*i)->getXYZ(), since this is only defined
                // after update() was called. Instead we have to get the
                // real position of the rigid body.
                btTransform     t;
                (*i)->getBody()->getMotionState()->getWorldTransform(t);
                // This test can not be done only once before the loop, since
                // it can happen that the kart falls through the track later!
                Vec3 to = t.getOrigin()+Vec3(0, -10000, 0);
                m_track->getTriangleMesh().castRay(t.getOrigin(), to, 
                                                   &hit_point, &material,
                                                   &normal);
                if(!material)
                {
                    fprintf(stderr, 
                            "ERROR: no valid starting position for "
                            "kart %d on track %s.\n",
                            (int)(i-m_karts.begin()), 
                            m_track->getIdent().c_str());
                    if (UserConfigParams::m_artist_debug_mode)
                    {
                        fprintf(stderr, "Activating fly mode.\n");
                        (*i)->flyUp();
                        continue;
                    }
                    else
                    {
                        exit(-1);
                    }
                }
                all_finished=false;
                break;
            }
        }
    }   // while

    for ( KartList::iterator i=m_karts.begin(); i!=m_karts.end(); i++)
    {
        // Now store the current (i.e. in rest) suspension length for each
        // kart, so that the karts can visualise the suspension. 
        (*i)->setSuspensionLength();
        // Initialise the camera (if available), now that the correct
        // kart position is set
        if((*i)->getCamera())
            (*i)->getCamera()->setInitialTransform();
        // Update the kart transforms with the newly computed position
        // after all karts are reset
        (*i)->setTrans((*i)->getBody()->getWorldTransform());
    }
}   // resetAllKarts