/** 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