void handleKeyPress(const int& key) { if (key == osgGA::GUIEventAdapter::KEY_F1) { if (_scene->getNodeMask() == 0x0) _scene->setNodeMask(0xFFFFFFF); else _scene->setNodeMask(0x0); } getMainWindow()->requestPicking(); getMainWindow()->getPickEventHandler()->setHierarchicalPickingEnabled(true); if(key == osgGA::GUIEventAdapter::KEY_F2) { getPhysics()->pause(); for(unsigned int i = 0; i < _rigidBodies.size(); ++i) { removeRigidBody(_rigidBodies[i]); } getPhysics()->resume(); } if(key == osgGA::GUIEventAdapter::KEY_F3) { getPhysics()->pause(); _rigidBodies[0]->setWorldTransform(cefixbt::asBtTransform(osg::Matrix::translate(100,100,100))); getPhysics()->resume(); } if(key == osgGA::GUIEventAdapter::KEY_F4) { bool visible = (_debugNode->getNodeMask() > 0); _debugNode->setNodeMask(0xffff * (!visible)); } }
/** * Adds an Object to the area. * @param object The Object's pointer. * @see removeObject() */ void Area::addObject(Object* object) { //object->setArea(this); DEBUG_M("Entering function..."); GameManager* gm = getGameManager(); if(object->getGameManager() != gm) { DEBUG_A("Different GameMangers..."); object->setGameManager(gm); if(gm) { DEBUG_A("Registering object with gamemanager..."); gm->registerObject(object); } } RigidBody* rb = dynamic_cast<RigidBody*>(object); if(rb) { rb->addBody(getPhysics()); } Light* pl = dynamic_cast<Light*>(object); if(pl) { lights_.push_back(pl); } addChild(object); }
/** * Remove an Object from the area. * @param object The Object's pointer. * @see addObject() */ void Area::removeObject(Object* object) { removeChild(object); RigidBody* rb = dynamic_cast<RigidBody*>(object); if(rb) { rb->removeBody(getPhysics()); } GameManager* gm = getGameManager(); if(gm) { gm->deregisterObject(object); } #warning ['TODO']: Remove lights... }
/** * getProjectionBounds * * Projects this sphere on a given axis. */ void CSphere::getProjectionBounds(const Vector& axis, float& min, float& max) const{ // For any of this to work, we need to have an associated rb const iPhysics* rb = getPhysics(); if (rb) { // Project our sphere onto our axis const Vector& pos = rb->worldCentreOfMass(); float mid = dot(axis, pos) / dot(axis, axis); min = mid - _cinfo.radius; max = mid + _cinfo.radius; } }
/** * getProjectionBounds * * Projects this OBB on a given axis. */ void COBB::getProjectionBounds(const Vector& axis, float& min, float& max) const{ // For any of this to work, we need to have an associated rb const iPhysics* rb = getPhysics(); if (rb) { // Use vertex cache, if possible std::vector<Vector> locCVerts; const std::vector<Vector>* cVerts = NULL; if (_cVerts.size() == 8) { cVerts = &_cVerts; } else { cVerts = &locCVerts; // Fill temporary vertex cache locCVerts.push_back(Vector(_cinfo.radius.x, _cinfo.radius.y, _cinfo.radius.z)); locCVerts.push_back(Vector(_cinfo.radius.x, _cinfo.radius.y, -_cinfo.radius.z)); locCVerts.push_back(Vector(_cinfo.radius.x, -_cinfo.radius.y, _cinfo.radius.z)); locCVerts.push_back(Vector(_cinfo.radius.x, -_cinfo.radius.y, -_cinfo.radius.z)); locCVerts.push_back(Vector(-_cinfo.radius.x, _cinfo.radius.y, _cinfo.radius.z)); locCVerts.push_back(Vector(-_cinfo.radius.x, _cinfo.radius.y, -_cinfo.radius.z)); locCVerts.push_back(Vector(-_cinfo.radius.x, -_cinfo.radius.y, _cinfo.radius.z)); locCVerts.push_back(Vector(-_cinfo.radius.x, -_cinfo.radius.y, -_cinfo.radius.z)); } // Project every vertex in sequence on this axis const Vector& pos = rb->worldCentreOfMass(); const Matrix& rot = rb->rotation(); for (int i = 0; i < 8; i++) { float proj = dot(axis, ((*cVerts)[i] * rot) + pos) / dot(axis, axis); if (i == 0) { min = proj; max = proj; } else { if (proj < min) min = proj; else if (proj > max) max = proj; } } } }
/** 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
void RigidBody::selfAddBody_() { addBody(getPhysics()); }
void RigidBody::selfRemoveBody_() { removeBody(getPhysics()); }
/** 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
/** * clone * * Returns a clone of this object and the attached rb. */ iCollisionGeometry* CSphere::clone() const{ // This is ugly but... iPhysics* rb = const_cast<iPhysics*>(getPhysics()); if (rb) { rb = rb->clone(); } return CreateCSphere(rb, _cinfo.radius); }
osg::Group * createWorld() { setupPerformanceStatistics(); //getPhysics()->setUseFixedTimeSteps(false); //getPhysics()->setMaxSubSteps(5); getPhysics()->addPerformanceStatistics(this); cefix::log::setInfoLevel(osg::ALWAYS); getMainWindow()->getCamera()->setClearColor(osg::Vec4(0.2, 0.2, 0.2, 1.0)); // statistics if (0) { enablePerformanceStatistics(true); get2DLayer()->addChild(getPerformanceStatisticsGroup()); } setUseOptimizerFlag(false); osg::Group* g = new osg::Group(); { //btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),1); cefixbt::StaticPlaneShape* groundShape = new cefixbt::StaticPlaneShape(osg::Vec3(0,0,1),0); cefixbt::MotionState* groundMotionState = new cefixbt::MotionState( btTransform(btQuaternion(0,0,0,1),btVector3(-250,-250,-1)) ); btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0)); osg::ref_ptr<cefixbt::RigidBody> groundRigidBody = new cefixbt::RigidBody(groundRigidBodyCI); groundRigidBody->setContactCallback(new GroundContactCallback()); addRigidBody(groundRigidBody); osg::Geode* groundgeode = new osg::Geode(); groundgeode->addDrawable(new cefix::LineGridGeometry(osg::Vec3(500,500,0))); groundMotionState->addChild(groundgeode); g->addChild(groundMotionState); } for (unsigned int i = 0; i < 00; ++i) { cefixbt::SphereShape* fallShape = new cefixbt::SphereShape(1); cefixbt::MotionState* fallMotionState = new cefixbt::MotionState( btTransform(btQuaternion(0,0,0,1),btVector3(cefix::in_between(-5,5), cefix::in_between(-5,5), cefix::in_between(50,500))) ); btScalar mass = cefix::in_between(1,10); btVector3 fallInertia(0,0,0); fallShape->calculateLocalInertia(mass,fallInertia); btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia); osg::ref_ptr<cefixbt::RigidBody> fallRigidBody = new cefixbt::RigidBody(fallRigidBodyCI); addRigidBody(fallRigidBody); osg::Geode* fallgeode = new osg::Geode(); osg::ShapeDrawable* drawable = new osg::ShapeDrawable(fallShape); drawable->setColor(osg::Vec4(cefix::randomf(1.0),cefix::randomf(1.0),cefix::randomf(1.0),1.0)); fallgeode->addDrawable(drawable); fallMotionState->addChild(fallgeode); g->addChild(fallMotionState); } std::vector<osg::ref_ptr<cefixbt::RigidBody> > boxes; for (unsigned int i = 0; i < 00; ++i) { cefixbt::BoxShape* fallShape = new cefixbt::BoxShape(osg::Vec3(1,1,1)); cefixbt::MotionState* fallMotionState = new cefixbt::MotionState( btTransform(btQuaternion(0,0,0,1),btVector3(cefix::in_between(-5,5), cefix::in_between(-5,5), cefix::in_between(50,500))) ); btScalar mass = cefix::in_between(1,10); btVector3 fallInertia(0,0,0); fallShape->calculateLocalInertia(mass,fallInertia); btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia); osg::ref_ptr<cefixbt::RigidBody> fallRigidBody = new cefixbt::RigidBody(fallRigidBodyCI); addRigidBody(fallRigidBody); osg::Geode* fallgeode = new osg::Geode(); osg::ShapeDrawable* drawable = new osg::ShapeDrawable(fallShape); drawable->setColor(osg::Vec4(cefix::randomf(1.0),cefix::randomf(1.0),cefix::randomf(1.0),1.0)); fallgeode->addDrawable(drawable); fallMotionState->addChild(fallgeode); g->addChild(fallMotionState); boxes.push_back(fallRigidBody); } if (1) { osg::Node* node = osgDB::readNodeFile("w.obj"); osgUtil::Optimizer o; o.optimize(node); cefixbt::ConvexHullShape* fallShape = new cefixbt::ConvexHullShape(node, false); //cefixbt::ConvexTriangleMeshShape* fallShape = new cefixbt::ConvexTriangleMeshShape(node, false); osg::ref_ptr<cefixbt::RigidBody> last(NULL), current(NULL); for (unsigned int i = 0; i < 10; ++i) { cefixbt::MotionState* fallMotionState = new cefixbt::MotionState( btTransform(btQuaternion(0,0,0,1),btVector3(cefix::in_between(-50,50), cefix::in_between(-50,50), cefix::in_between(50,50))) ); btScalar mass = cefix::in_between(1,10); btVector3 fallInertia(0,0,0); fallShape->calculateLocalInertia(mass,fallInertia); btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia); osg::ref_ptr<cefixbt::RigidBody> fallRigidBody = new cefixbt::RigidBody(fallRigidBodyCI); fallRigidBody->setDamping(0.4, 0.4); addRigidBody(fallRigidBody); fallMotionState->addChild(node); fallMotionState->setUserData(new cefixbt::RigidBodyDraggable(fallRigidBody, this)); g->addChild(fallMotionState); last = current; current = fallRigidBody; _rigidBodies.push_back(current); if (last && current) { const int mode(0); switch (mode) { case -1: break; case 0: { cefixbt::Point2PointConstraint* constraint = new cefixbt::Point2PointConstraint(last, current, osg::Vec3(7, 7, 0), osg::Vec3(-7, 0 , 0)); addConstraint(constraint); } break; case 1: { cefixbt::Generic6DofConstraint* constraint = new cefixbt::Generic6DofConstraint( last, current, osg::Matrix::translate(osg::Vec3(5, 0, 0)), osg::Matrix::translate(osg::Vec3(-15, 0 , 0)), true ); constraint->setLinearLowerLimit(btVector3(0.0f, 0.0f, 0.0f)); constraint->setLinearUpperLimit(btVector3(3.0f, 0.0f, 0.0f)); constraint->setAngularLowerLimit(btVector3(0,0,0)); constraint->setAngularUpperLimit(btVector3(0.2,0,0)); addConstraint(constraint); } break; case 2: { cefixbt::Generic6DofSpringConstraint* constraint = new cefixbt::Generic6DofSpringConstraint( last, current, osg::Matrix::translate(osg::Vec3(5, 0, 0)), osg::Matrix::translate(osg::Vec3(-15, 0 , 0)), true ); constraint->setLinearLowerLimit(btVector3(-1.0f, -1.0f, -1.0f)); constraint->setLinearUpperLimit(btVector3(1.0f, 1.0f, 1.0f)); constraint->setAngularLowerLimit(btVector3(-0.5,0,0)); constraint->setAngularUpperLimit(btVector3(0.5,0.0,0)); for(unsigned int i=0; i < 6; ++i) { constraint->enableSpring(i, true); constraint->setStiffness(i, 0.01); constraint->setDamping (i, 0.01); } addConstraint(constraint); } } } } } osg::Group* world = new osg::Group(); world->addChild(g); _scene = g; // debug-world if (1) { _debugNode = getDebugDrawNode( /*cefixbt::DebugPhysicsDrawer::DBG_DrawAabb | */ cefixbt::DebugPhysicsDrawer::DBG_DrawConstraints | cefixbt::DebugPhysicsDrawer::DBG_DrawConstraintLimits | cefixbt::DebugPhysicsDrawer::DBG_DrawFeaturesText | cefixbt::DebugPhysicsDrawer::DBG_DrawContactPoints | cefixbt::DebugPhysicsDrawer::DBG_NoDeactivation | cefixbt::DebugPhysicsDrawer::DBG_NoHelpText | cefixbt::DebugPhysicsDrawer::DBG_DrawText | cefixbt::DebugPhysicsDrawer::DBG_ProfileTimings | cefixbt::DebugPhysicsDrawer::DBG_DrawWireframe ); world->addChild(_debugNode); _debugNode->setNodeMask(0x0); } return world; }