void getUnitMeterScalingAndUpAxisTransform(TiXmlDocument& doc, btTransform& tr, float& unitMeterScaling) { TiXmlElement* unitMeter = doc.RootElement()->FirstChildElement("asset")->FirstChildElement("unit"); if (unitMeter) { const char* meterText = unitMeter->Attribute("meter"); printf("meterText=%s\n", meterText); unitMeterScaling = atof(meterText); } TiXmlElement* upAxisElem = doc.RootElement()->FirstChildElement("asset")->FirstChildElement("up_axis"); if (upAxisElem) { std::string upAxisTxt = upAxisElem->GetText(); if (upAxisTxt == "X_UP") { btQuaternion y2x(btVector3(0,0,1),SIMD_HALF_PI); tr.setRotation(y2x); } if (upAxisTxt == "Y_UP") { //assume Y_UP for now, to be compatible with assimp? } if (upAxisTxt == "Z_UP") { btQuaternion y2z(btVector3(1,0,0),-SIMD_HALF_PI); tr.setRotation(y2z); } } }
//**************************************************************************************************************************pose2DtoTf() void PSMpositionNode::pose2DToTf(const geometry_msgs::Pose2D& pose, btTransform& t) { t.setOrigin(btVector3(pose.x, pose.y, 0.0)); btQuaternion q; q.setRPY(0, 0, pose.theta); t.setRotation(q); }
//------------------------------------------------------------------------------------------------------- void Road::updateTriggerPosition(btTransform& trans) { trans.setIdentity(); trans.setOrigin(GameState::ogreVecToBullet(mPosition)); Ogre::Quaternion rotation = Ogre::Vector3::UNIT_Z.getRotationTo(mDirection); trans.setRotation(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w)); }
void fbMotionState::getWorldTransform(btTransform& worldTrans) const { assert(mVisualObj); worldTrans.setIdentity(); worldTrans.setRotation(FBToBullet(mVisualObj->GetRot())); worldTrans.setOrigin(FBToBullet(mVisualObj->GetPos())); }
void MotionState::getWorldTransform(btTransform &transform) const { lua_rawgeti(L, LUA_REGISTRYINDEX, component_ref); lua_getfield(L, -1, "transform"); lua_remove(L, -2); // the stack now contains just the transform component // get the origin { lua_getfield(L, -1, "pos"); double x, y, z; l_tovect(L, -1, &x, &y, &z); lua_pop(L, 1); transform.setOrigin(btVector3(x, y, z)); } // get the rotation { lua_getfield(L, -1, "orientation"); double w, x, y, z; l_toquaternion(L, -1, &w, &x, &y, &z); lua_pop(L, 1); transform.setRotation(btQuaternion(x, y, z, w)); } lua_pop(L, 1); }
// This callback is invoked by the physics simulation in two cases: // (1) when the RigidBody is first added to the world // (irregardless of PhysicsMotionType: STATIC, DYNAMIC, or KINEMATIC) // (2) at the beginning of each simulation step for KINEMATIC RigidBody's -- // it is an opportunity for outside code to update the object's simulation position void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { BT_PROFILE("getWorldTransform"); if (!_entity) { return; } assert(entityTreeIsLocked()); if (_motionType == MOTION_TYPE_KINEMATIC) { BT_PROFILE("kinematicIntegration"); uint32_t thisStep = ObjectMotionState::getWorldSimulationStep(); if (hasInternalKinematicChanges()) { // ACTION_CAN_CONTROL_KINEMATIC_OBJECT_HACK: This kinematic body was moved by an Action // and doesn't require transform update because the body is authoritative and its transform // has already been copied out --> do no kinematic integration. clearInternalKinematicChanges(); _lastKinematicStep = thisStep; return; } // This is physical kinematic motion which steps strictly by the subframe count // of the physics simulation and uses full gravity for acceleration. _entity->setAcceleration(_entity->getGravity()); float dt = (thisStep - _lastKinematicStep) * PHYSICS_ENGINE_FIXED_SUBSTEP; _lastKinematicStep = thisStep; _entity->stepKinematicMotion(dt); // and set the acceleration-matches-gravity count high so that if we send an update // it will use the correct acceleration for remote simulations _accelerationNearlyGravityCount = (uint8_t)(-1); } worldTrans.setOrigin(glmToBullet(getObjectPosition())); worldTrans.setRotation(glmToBullet(_entity->getWorldOrientation())); }
// This callback is invoked by the physics simulation in two cases: // (1) when the RigidBody is first added to the world // (irregardless of PhysicsMotionType: STATIC, DYNAMIC, or KINEMATIC) // (2) at the beginning of each simulation step for KINEMATIC RigidBody's -- // it is an opportunity for outside code to update the object's simulation position void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { BT_PROFILE("getWorldTransform"); if (!_entity) { return; } assert(entityTreeIsLocked()); if (_motionType == MOTION_TYPE_KINEMATIC) { BT_PROFILE("kinematicIntegration"); // This is physical kinematic motion which steps strictly by the subframe count // of the physics simulation and uses full gravity for acceleration. _entity->setAcceleration(_entity->getGravity()); uint32_t thisStep = ObjectMotionState::getWorldSimulationStep(); float dt = (thisStep - _lastKinematicStep) * PHYSICS_ENGINE_FIXED_SUBSTEP; _entity->stepKinematicMotion(dt); // bypass const-ness so we can remember the step const_cast<EntityMotionState*>(this)->_lastKinematicStep = thisStep; // and set the acceleration-matches-gravity count high so that if we send an update // it will use the correct acceleration for remote simulations _accelerationNearlyGravityCount = (uint8_t)(-1); } worldTrans.setOrigin(glmToBullet(getObjectPosition())); worldTrans.setRotation(glmToBullet(_entity->getRotation())); }
// virtual void AvatarMotionState::getWorldTransform(btTransform& worldTrans) const { worldTrans.setOrigin(glmToBullet(getObjectPosition())); worldTrans.setRotation(glmToBullet(getObjectRotation())); if (_body) { _body->setLinearVelocity(glmToBullet(getObjectLinearVelocity())); _body->setAngularVelocity(glmToBullet(getObjectAngularVelocity())); } }
virtual void getWorldTransform(btTransform& tform) const { const auto& p = m_part->dummy->getDefaultTranslation(); const auto& o = glm::toQuat(m_part->dummy->getDefaultRotation()); tform.setOrigin(btVector3(p.x, p.y, p.z)); tform.setRotation(btQuaternion(o.x, o.y, o.z, o.w)); tform = m_object->collision->getBulletBody()->getWorldTransform() * tform; }
void EntityMotionState::getWorldTransform(btTransform& transform) const { if(!owner) { transform = original_transform; return; } const float* position = owner->getPosition(); transform.setOrigin(btVector3(position[0], position[1], position[2])); const float* rotation = owner->getQuaternionRotation(); transform.setRotation(btQuaternion(rotation[0], rotation[1], rotation[2], rotation[3])); }
/// btMotionState override. Called when Bullet wants us to tell the body's initial transform void getWorldTransform(btTransform &worldTrans) const { if (placeable.Expired()) return; float3 position = placeable->WorldPosition(); Quat orientation = placeable->WorldOrientation(); worldTrans.setOrigin(position); worldTrans.setRotation(orientation); }
void DiBone::GetOffsetTransform(btTransform& t) const { DiVec3 locScale = GetDerivedScale() * mBindDerivedInverseScale; DiQuat locRotate = GetDerivedOrientation() * mBindDerivedInverseOrientation; DiVec3 locTranslate = GetDerivedPosition() + locRotate * (locScale * mBindDerivedInversePosition); t.setOrigin(btVector3(locTranslate.x,locTranslate.y,locTranslate.z)); btQuaternion qt; qt.setValue(locRotate.x,locRotate.y,locRotate.z,locRotate.w); t.setRotation(qt); t.setBasis(t.getBasis().scaled(btVector3(locScale.x, locScale.y, locScale.z))); }
void RigidBody::getWorldTransform(btTransform& worldTrans) const { // We may be in a pathological state where a RigidBody exists without a scene node when this callback is fired, // so check to be sure if (node_) { lastPosition_ = node_->GetWorldPosition(); lastRotation_ = node_->GetWorldRotation(); worldTrans.setOrigin(ToBtVector3(lastPosition_ + lastRotation_ * centerOfMass_)); worldTrans.setRotation(ToBtQuaternion(lastRotation_)); } }
bool ROSURDFImporter::getJointInfo(int urdfLinkIndex, btTransform& parent2joint, btVector3& jointAxisInJointSpace, int& jointType, btScalar& jointLowerLimit, btScalar& jointUpperLimit) const { jointLowerLimit = 0.f; jointUpperLimit = 0.f; if ((*m_data->m_links[urdfLinkIndex]).parent_joint) { my_shared_ptr<Joint> pj =(*m_data->m_links[urdfLinkIndex]).parent_joint; const urdf::Vector3 pos = pj->parent_to_joint_origin_transform.position; const urdf::Rotation orn = pj->parent_to_joint_origin_transform.rotation; jointAxisInJointSpace.setValue(pj->axis.x,pj->axis.y,pj->axis.z); parent2joint.setOrigin(btVector3(pos.x,pos.y,pos.z)); parent2joint.setRotation(btQuaternion(orn.x,orn.y,orn.z,orn.w)); switch (pj->type) { case Joint::REVOLUTE: jointType = URDFRevoluteJoint; break; case Joint::FIXED: jointType = URDFFixedJoint; break; case Joint::PRISMATIC: jointType = URDFPrismaticJoint; break; case Joint::PLANAR: jointType = URDFPlanarJoint; break; case Joint::CONTINUOUS: jointType = URDFContinuousJoint; break; default: { printf("Error: unknown joint type %d\n", pj->type); btAssert(0); } }; if (pj->limits) { jointLowerLimit = pj->limits.get()->lower; jointUpperLimit = pj->limits.get()->upper; } return true; } else { parent2joint.setIdentity(); return false; } }
void ROSURDFImporter::getMassAndInertia(int linkIndex, btScalar& mass,btVector3& localInertiaDiagonal, btTransform& inertialFrame) const { if ((*m_data->m_links[linkIndex]).inertial) { mass = (*m_data->m_links[linkIndex]).inertial->mass; localInertiaDiagonal.setValue((*m_data->m_links[linkIndex]).inertial->ixx,(*m_data->m_links[linkIndex]).inertial->iyy,(*m_data->m_links[linkIndex]).inertial->izz); inertialFrame.setOrigin(btVector3((*m_data->m_links[linkIndex]).inertial->origin.position.x,(*m_data->m_links[linkIndex]).inertial->origin.position.y,(*m_data->m_links[linkIndex]).inertial->origin.position.z)); inertialFrame.setRotation(btQuaternion((*m_data->m_links[linkIndex]).inertial->origin.rotation.x,(*m_data->m_links[linkIndex]).inertial->origin.rotation.y,(*m_data->m_links[linkIndex]).inertial->origin.rotation.z,(*m_data->m_links[linkIndex]).inertial->origin.rotation.w)); } else { mass = 1.f; localInertiaDiagonal.setValue(1,1,1); inertialFrame.setIdentity(); } }
// This callback is invoked by the physics simulation in two cases: // (1) when the RigidBody is first added to the world // (irregardless of MotionType: STATIC, DYNAMIC, or KINEMATIC) // (2) at the beginning of each simulation frame for KINEMATIC RigidBody's -- // it is an opportunity for outside code to update the object's simulation position void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { if (_isKinematic) { // This is physical kinematic motion which steps strictly by the subframe count // of the physics simulation. uint32_t substep = PhysicsEngine::getNumSubsteps(); float dt = (substep - _lastKinematicSubstep) * PHYSICS_ENGINE_FIXED_SUBSTEP; _entity->simulateKinematicMotion(dt); _entity->setLastSimulated(usecTimestampNow()); // bypass const-ness so we can remember the substep const_cast<EntityMotionState*>(this)->_lastKinematicSubstep = substep; } worldTrans.setOrigin(glmToBullet(_entity->getPositionInMeters() - ObjectMotionState::getWorldOffset())); worldTrans.setRotation(glmToBullet(_entity->getRotation())); }
// This callback is invoked by the physics simulation in two cases: // (1) when the RigidBody is first added to the world // (irregardless of MotionType: STATIC, DYNAMIC, or KINEMATIC) // (2) at the beginning of each simulation step for KINEMATIC RigidBody's -- // it is an opportunity for outside code to update the object's simulation position void EntityMotionState::getWorldTransform(btTransform& worldTrans) const { if (!_entity) { return; } assert(entityTreeIsLocked()); if (_motionType == MOTION_TYPE_KINEMATIC) { // This is physical kinematic motion which steps strictly by the subframe count // of the physics simulation. uint32_t thisStep = ObjectMotionState::getWorldSimulationStep(); float dt = (thisStep - _lastKinematicStep) * PHYSICS_ENGINE_FIXED_SUBSTEP; _entity->simulateKinematicMotion(dt); // bypass const-ness so we can remember the step const_cast<EntityMotionState*>(this)->_lastKinematicStep = thisStep; } worldTrans.setOrigin(glmToBullet(getObjectPosition())); worldTrans.setRotation(glmToBullet(_entity->getRotation())); }
bool parseTransform(btTransform& tr, TiXmlElement* xml, ErrorLogger* logger) { tr.setIdentity(); { const char* xyz_str = xml->Attribute("xyz"); if (xyz_str) { parseVector3(tr.getOrigin(),std::string(xyz_str),logger); } } { const char* rpy_str = xml->Attribute("rpy"); if (rpy_str != NULL) { btVector3 rpy; if (parseVector3(rpy,std::string(rpy_str),logger)) { double phi, the, psi; double roll = rpy[0]; double pitch = rpy[1]; double yaw = rpy[2]; phi = roll / 2.0; the = pitch / 2.0; psi = yaw / 2.0; btQuaternion orn( sin(phi) * cos(the) * cos(psi) - cos(phi) * sin(the) * sin(psi), cos(phi) * sin(the) * cos(psi) + sin(phi) * cos(the) * sin(psi), cos(phi) * cos(the) * sin(psi) - sin(phi) * sin(the) * cos(psi), cos(phi) * cos(the) * cos(psi) + sin(phi) * sin(the) * sin(psi)); orn.normalize(); tr.setRotation(orn); } } } return true; }
void DynamicsMotionState::getWorldTransform(btTransform& transform) const { // DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__); // get node's world position and rotation Vector3 position; Quaternion rotation; Vector3 axis; float angle( 0.0f ); mDynamicsBody.GetNodePositionAndRotation(position, rotation); rotation.ToAxisAngle( axis, angle ); // modify parameters transform.setIdentity(); transform.setOrigin(btVector3(position.x, position.y, position.z)); if( axis != Vector3::ZERO ) { transform.setRotation( btQuaternion(btVector3(axis.x, axis.y, axis.z), btScalar(angle)) ); } }
int main(int argc, char** argv) { //*** init Bullet Physics btQuaternion qtn; btCollisionShape *shape; btDefaultMotionState *motionState; btDefaultCollisionConfiguration *collisionCfg = new btDefaultCollisionConfiguration(); btAxisSweep3 *axisSweep = new btAxisSweep3(btVector3(-100,-100,-100), btVector3(100,100,100), 128); dynamicsWorld = new btDiscreteDynamicsWorld(new btCollisionDispatcher(collisionCfg), axisSweep, new btSequentialImpulseConstraintSolver, collisionCfg); dynamicsWorld->setGravity(btVector3(0, -10, 0)); //*** box1 - STATIC / mass=btScalar(0.0) shape = new btBoxShape(btVector3(20,20,20)); trans.setIdentity(); qtn.setEuler(0, 0.0, 0.0); trans.setRotation(qtn); trans.setOrigin(btVector3(0, -20, 0)); motionState = new btDefaultMotionState(trans); btRigidBody::btRigidBodyConstructionInfo boxRigidBodyCI(btScalar(0.0), motionState, shape, btVector3(0,0,0)); boxRigidBodyCI.m_friction = 0.4; box1 = new btRigidBody(boxRigidBodyCI); box1->setCollisionFlags( box1->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); box1->setActivationState(DISABLE_DEACTIVATION); dynamicsWorld->addRigidBody(box1); //*** box3 - STATIC / mass=btScalar(0.0) shape = new btBoxShape(btVector3(15,15,15)); trans.setIdentity(); qtn.setEuler(0, 0.0, 0.0); trans.setRotation(qtn); trans.setOrigin(btVector3(-35, -35, 0)); motionState = new btDefaultMotionState(trans); btRigidBody::btRigidBodyConstructionInfo boxRigidBodyCI3(btScalar(0.0), motionState, shape, btVector3(0,0,0)); boxRigidBodyCI3.m_friction = 0.4; box3 = new btRigidBody(boxRigidBodyCI3); dynamicsWorld->addRigidBody(box3); //*** box2 - DYNAMIC / mass=btScalar(1.0) shape = new btBoxShape(btVector3(5,5,5)); trans.setIdentity(); qtn.setEuler(0.8, 0.7, 0.4); trans.setRotation(qtn); trans.setOrigin(btVector3(-10, 50, 0)); motionState = new btDefaultMotionState(trans); btScalar mass = 1; btVector3 Intertia(0,0,0); shape->calculateLocalInertia(mass, Intertia); btRigidBody::btRigidBodyConstructionInfo *boxRigidBodyCI2; boxRigidBodyCI2 = new btRigidBody::btRigidBodyConstructionInfo(mass, motionState, shape, Intertia); boxRigidBodyCI2->m_restitution = 0.4; box2 = new btRigidBody(*boxRigidBodyCI2); box2->setActivationState(DISABLE_DEACTIVATION); //box2->setLinearFactor(btVector3(1,1,0)); //box2->setAngularFactor(btVector3(0,0,1)); dynamicsWorld->addRigidBody(box2); //*** init GLUT glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("Jump you little bastard"); glutDisplayFunc(draw); glutIdleFunc(tim); glutKeyboardFunc(keyPress); //*** init OpenGL glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); glEnable(GL_COLOR_MATERIAL); glMatrixMode(GL_PROJECTION); gluPerspective( 90.0, 1.0, 1.0, 1000.0); glMatrixMode(GL_MODELVIEW); gluLookAt(0.0, 5.0, 60.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glutMainLoop(); //*** EXIT delete shape; delete motionState; delete collisionCfg; delete axisSweep; }
// virtual void DetailedMotionState::getWorldTransform(btTransform& worldTrans) const { worldTrans.setOrigin(glmToBullet(getObjectPosition())); worldTrans.setRotation(glmToBullet(getObjectRotation())); }
void MotionState::getWorldTransform(btTransform& worldTrans) const { worldTrans.setOrigin(vec3_cast<btVector3>(rigidbody->GetOwner()->transform->GetWorldPosition())); worldTrans.setRotation(quat_cast<btQuaternion>(rigidbody->GetOwner()->transform->GetRotationQuat())); }
void PhysicsCamera::getWorldTransform(btTransform &worldTrans) const { worldTrans.setOrigin(GLToBtVector(parent->position)); worldTrans.setRotation(GLToBtQuat(parent->orientation)); }
void getUnitMeterScalingAndUpAxisTransform(TiXmlDocument& doc, btTransform& tr, float& unitMeterScaling, int clientUpAxis) { ///todo(erwincoumans) those up-axis transformations have been quickly coded without rigorous testing TiXmlElement* unitMeter = doc.RootElement()->FirstChildElement("asset")->FirstChildElement("unit"); if (unitMeter) { const char* meterText = unitMeter->Attribute("meter"); printf("meterText=%s\n", meterText); unitMeterScaling = atof(meterText); } TiXmlElement* upAxisElem = doc.RootElement()->FirstChildElement("asset")->FirstChildElement("up_axis"); if (upAxisElem) { switch (clientUpAxis) { case 1: { std::string upAxisTxt = upAxisElem->GetText(); if (upAxisTxt == "X_UP") { btQuaternion x2y(btVector3(0,0,1),SIMD_HALF_PI); tr.setRotation(x2y); } if (upAxisTxt == "Y_UP") { //assume Y_UP for now, to be compatible with assimp? //client and COLLADA are both Z_UP so no transform needed (identity) } if (upAxisTxt == "Z_UP") { btQuaternion z2y(btVector3(1,0,0),-SIMD_HALF_PI); tr.setRotation(z2y); } break; } case 2: { std::string upAxisTxt = upAxisElem->GetText(); if (upAxisTxt == "X_UP") { btQuaternion x2z(btVector3(0,1,0),-SIMD_HALF_PI); tr.setRotation(x2z); } if (upAxisTxt == "Y_UP") { btQuaternion y2z(btVector3(1,0,0),SIMD_HALF_PI); tr.setRotation(y2z); } if (upAxisTxt == "Z_UP") { //client and COLLADA are both Z_UP so no transform needed (identity) } break; } case 0: default: { //we don't support X or other up axis btAssert(0); } }; } }
void PlayerMotionState::getWorldTransform(btTransform &worldTrans) const { worldTrans.setOrigin(toBt(gameObject.getPosition())); worldTrans.setRotation(toBt(glm::quat())); }
/** Sets the rotation of this moveable. */ void setRotation(const btQuaternion&a) { m_transform.setRotation(a); if(m_motion_state) m_motion_state->setWorldTransform(m_transform); }
void AvMotionState::getWorldTransform(btTransform &worldTrans) const { worldTrans.setOrigin( toBtVec(_transform->position) ); worldTrans.setRotation( toBtQuat(_transform->rotation) ); }
void KinematicMotionState::getWorldTransform(btTransform &worldTrans) const { worldTrans.setOrigin(GLToBtVector(owner->transform->position)); worldTrans.setRotation(GLToBtQuat(owner->transform->orientation)); }
virtual void getWorldTransform(btTransform& worldTrans) const { worldTrans.setOrigin(OgreBulletCollisions::OgreBtConverter::to(mObject->getWorldPosition())); worldTrans.setRotation(OgreBulletCollisions::OgreBtConverter::to(mObject->getWorldOrientation())); }
void BulletTestApp::update() { // Run next test if ( mTest != mTestPrev ) { mTestPrev = mTest; initTest(); } mFrameRate = getAverageFps(); // Update light mLight->update( mCamera ); if ( mTest < 3 ) { // Set box rotation float rotation = math<float>::sin( ( float )getElapsedSeconds() * 0.3333f ) * 0.35f ; mGroundTransform.setRotation( btQuaternion( 0.25f, 0.0f, 1.0f + rotation * 0.1f, rotation ) ); mGroundTransform.setOrigin( btVector3( 0.0f, -60.0f, 0.0f ) ); // Apply rotation to box btRigidBody* body = bullet::toBulletRigidBody( mGround ); body->getMotionState()->setWorldTransform( mGroundTransform ); body->setWorldTransform( mGroundTransform ); } else if ( mTest == 6 ) { // Read data Channel32f& input = mTerrain->getData(); // Get image dimensions int32_t height = input.getHeight(); int32_t width = input.getWidth(); // Create output channel Channel32f output = Channel32f( width, height ); // Move pixel value over by one for ( int32_t y = 0; y < height; y++ ) { for ( int32_t x = 0; x < width; x++ ) { float value = input.getValue( Vec2i( x, y ) ); Vec2i position( ( x + 1 ) % width, ( y + 1 ) % height ); output.setValue( position, value ); } } // Copy new data back to original input.copyFrom( output, output.getBounds() ); // Shift texture coordinates to match positions vector<Vec2f>& texCoords = mTerrain->getTexCoords(); Vec2f delta( 1.0f / (float)width, 1.0f / (float)height ); for ( vector<Vec2f>::iterator uv = texCoords.begin(); uv != texCoords.end(); ++uv ) { *uv -= delta; } // Update terrain VBO mTerrain->updateVbo(); } else if ( mTest == 7 ) { bool init = !mSurface; if ( mCapture.isCapturing() && mCapture.checkNewFrame() ) { mSurface = mCapture.getSurface(); ip::flipVertical( &mSurface ); if ( init ) { mTerrain = new DynamicTerrain( Channel32f( 160, 160 ), -1.0f, 1.0f, Vec3f( 2.0f, 70.0f, 2.0f ), 0.0f ); mWorld->pushBack( mTerrain ); btRigidBody* terrain = ( btRigidBody* )mTerrain->getBulletBody(); terrain->setAngularFactor( 0.6f ); terrain->setFriction( 0.6f ); } else { mTerrain->getData().copyFrom( Channel32f( mSurface ), Area( 0, 0, 160, 160 ) ); mTerrain->updateVbo(); } } } // Update dynamics world mWorld->update( mFrameRate ); /*if ( mGround ) { Iter iter = mWorld->find( mGround ); OutputDebugStringA( toString( iter->getPosition().x ).c_str() ); OutputDebugStringA( "\n" ); }*/ // Remove out of bounbds objects for ( bullet::Iter object = mWorld->begin(); object != mWorld->end(); ) { if ( object != mWorld->begin() && object->getPosition().y < -800.0f ) { object = mWorld->erase( object ); } else { ++object; } } // Remove objects when count is too high uint32_t max = mTest >= 4 ? MAX_OBJECTS_TERRAIN : MAX_OBJECTS; if ( mWorld->getNumObjects() > max + 1 ) { for ( uint32_t i = 1; i < mWorld->getNumObjects() - MAX_OBJECTS_TERRAIN; i++ ) { mWorld->erase( mWorld->begin() + 1 ); } } }