void StickOnCollision::handleEvent(const CollisionEvent& e) { GameObject obj = e.getOtherObject(); if (obj.getType() == GameObject::Type::TILE) { hookPoint = obj.getPos(); PhysicsComponent * hookPhysics = owner_.getComponent<PhysicsComponent>(); hookPhysics->setVelX(0); hookPhysics->setVelY(0); auto tileCollider = e.getOtherCollider(); auto hookCollider = owner_.getComponent<ColliderComponent>(); float hookBot = hookCollider->getBottom(); float tileBot = tileCollider.getBottom(); float tileTop = tileCollider.getTop(); if (hookBot == tileTop) { isConnected = false; } else { isConnected = true; } //LOG("INFO") << "Hook is connected at " << hookPoint; } }
btScalar ContactCallback::addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap,int partId0,int index0,const btCollisionObjectWrapper* colObj1Wrap,int partId1,int index1) { const btCollisionObject* colObj = colObj0Wrap->getCollisionObject(); PhysicsComponent* physComp = static_cast<PhysicsComponent*>(colObj->getUserPointer()); if(physComp) physComp->OnAddSingleResult(cp,partId0,index0,colObj1Wrap,partId1,index1); return 0; }
void PhysicsComponent::OnAddSingleResult(btManifoldPoint& cp,int partId0,int index0,const btCollisionObjectWrapper* collidedObjWrap,int collidedObjPartId,int collidedObjIndex) { const btCollisionObject* colObj = collidedObjWrap->getCollisionObject(); PhysicsComponent* physComp = static_cast<PhysicsComponent*>(colObj->getUserPointer()); if(physComp) { Entity* entOwner = physComp->GetOwner(); //entOwner->OnHit(); } }
void RenderComponent::VUpdate() { /* All of this code must go!!! This is shit! Rewrite animation system as a seperate component, starting with a virtual base class (AnimationComponent) that can then fork off into a bunch of other more specific animation types (e.g. HumanoidAnimationComponent, MachineAnimationComponent, ParticleAnimationComponent, etc.). */ if(_animated) { PhysicsComponent* physicsComponent = GetOwner()->GetComponent<PhysicsComponent>(COMPONENT_PHYSICS); const uint UP = 1, DOWN = 0, RIGHT = 2, LEFT = 3; int direction = -1;// By default, don't change if(physicsComponent->GetVelocity().x > 0.5) { direction = RIGHT; } else if(physicsComponent->GetVelocity().x < -0.5) { direction = LEFT; } else if(physicsComponent->GetVelocity().y > 0.5) { direction = DOWN; } else if(physicsComponent->GetVelocity().y < -0.5) { direction = UP; } if(direction != -1)// If the texture should change... { _textureY = direction*(_textureHeight/4); _textureX = _currentAnimationFrame*(_textureWidth/3); if(SDL_GetTicks() - _lastAnimationChange >= (100)) { _currentAnimationFrame++; if(_currentAnimationFrame == 3) _currentAnimationFrame = 0; _lastAnimationChange = SDL_GetTicks(); } } else { _textureX = 0; } } }
void Character::Update() { // Update state machine mStateMachine.ProcessStateTransitions(); mStateMachine.UpdateStates(); // Move character const float MAX_SPEED = 100.0f; float currSpeed = mSpeedScale * MAX_SPEED; mPhysicsComponent.SetSpeed(currSpeed); mPhysicsComponent.Move(); printf("Current speed: %f\n", currSpeed); }
void updateCamera() { Actor *actor = game_->findActor("wizard"); if (actor) { PhysicsComponent *component = actor->getPhysicsComponent(); if (component) { b2Body *bodyBody = component->findBody("body"); if (bodyBody) { b2Vec2 position = bodyBody->GetPosition(); cameraPosition_.x = position.x; cameraPosition_.y = position.y; } } } }
PHYSICSDLL_API void OrbitComponent::Update(float dt) { if (targeting_) { Transform* tr = (Transform*)GetSibling(CT_Transform); Vector3 forceVec = current_dir_; Vector3 toTarget = target_ - tr->GetPosition(); float bias = toTarget.Length() / target_dist_; forceVec += toTarget.GetNormalized() * bias; PhysicsComponent* pComp = (PhysicsComponent*)GetSibling(CT_PhysicsComponent); if (pComp) { pComp->GetRigidBody()->AddForce(forceVec); current_dir_ = pComp->GetRigidBody()->GetState().Velocity.GetNormalized(); pComp->GetRigidBody()->GetState().Velocity = pComp->GetRigidBody()->GetState().Velocity.GetNormalized() * 2.0f; } } }
void LocomotionSystem::Update( float i_dt ) { for ( std::map<EntityHandle, Component*>::iterator it = m_components.begin(); it != m_components.end(); it++ ) { LocomotionComponent* pComponent = (LocomotionComponent*) it->second; if ( pComponent ) { if ( pComponent->m_locomotionMode ) { pComponent->m_locomotionMode->Update( i_dt ); } PhysicsComponent* pPhysicsComponent = EntitySystem::GetInstance()->GetComponent<PhysicsComponent>( pComponent->m_entityHandle ); if ( pPhysicsComponent ) { float yVel = pPhysicsComponent->GetVelocity().y; JumpState pJumpState; if ( yVel > 0.5f ) { pJumpState = JumpState::JUMPING; } else if ( yVel < 0.5f ) { pJumpState = JumpState::FALLING; } else if ( yVel == 0.0f ) { pJumpState = JumpState::NOT_JUMPING; } if ( pJumpState == JumpState::FALLING && pComponent->m_jumpState == JumpState::JUMPING ) { EventManager::GetInstance()->SendEvent( "VelocityApexReached", &pComponent->m_entityHandle ); } pComponent->m_jumpState = pJumpState; } } } }
void KeyboardSystem::run(Entity* entity, float time) { PhysicsComponent* physComp = entity->getComponent<PhysicsComponent>(); if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Space)) { physComp->jump(); } if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D)) { physComp->walk(1); } else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A) ) { physComp->walk(-1); } else { physComp->walk(0); } }
void ProjectileCollideSystem::update() { for(int subID = 0; subID < subscribedEntities[0].size(); subID++) { //Get projectile component Entity * projectileEnt = entities[subscribedEntities[0][subID]]; ColliderComponent* projectileCollideComp = static_cast<ColliderComponent*>(projectileEnt->getComponent(ColliderComponent::getStaticID())); WorldComponent * projectileWorldComp = static_cast<WorldComponent*>(projectileEnt->getComponent(WorldComponent::getStaticID())); PhysicsComponent* projectilePhysicsComp = static_cast<PhysicsComponent*>(projectileEnt->getComponent(PhysicsComponent::getStaticID())); //Check projectile for collisions for(int i = 0; i < projectileCollideComp->collisionData.size(); i++) { std::shared_ptr<CollisionPair> collision = projectileCollideComp->collisionData[i]; int projectilePairID = collision->getCollisionPairID(subscribedEntities[0][subID]);//Projectile's CollisionPairID int collidingPairID = collision->getOppositePairID(projectilePairID);//The Colliding Ent's CollisionPairID Entity * collidingEnt = entities[collision->getCollisionEntityID(collidingPairID)]; //The Colliding Entity //Check the type of the collided entity and perform action if(collidingEnt->hasComponent(TerrainComponent::getStaticID())) { deleteEntity(projectileEnt->entityID); } if(collidingEnt->hasComponent(PhysicsComponent::getStaticID()) && !collidingEnt->hasComponent(PlayerComponent::getStaticID())) { glm::vec2 col = collision->getMinimumTranslation(projectilePairID); PhysicsComponent* physicsComp = static_cast<PhysicsComponent*>(collidingEnt->getComponent(PhysicsComponent::getStaticID())); //Should 1. Be conserving energy //Should 2. Be making sure the velocity is transfered correctly //http://gafferongames.com/virtual-go/collision-response-and-coulomb-friction/ float j = -(1+physicsComp->coefficientRestitution)*glm::dot(projectilePhysicsComp->velocity*projectilePhysicsComp->mass,glm::normalize(col)); //projectiles impulse float impulseMag = glm::max(j, 0.0f); //Logger()<<impulseMag<<std::endl; physicsComp->impulse(impulseMag*glm::normalize(-col)); projectilePhysicsComp->impulse(impulseMag*glm::normalize(col)); } } } }
BaseComponent* PhysicsModule::getComponent(Entity* parent, float mass, Shape s, int group, int mask, bool hasTrigger) { PhysicsComponent* component; // checking if component exists if (components.find(parent->getName()) == components.end()) { component = hasTrigger ? new GhostComponent((btScalar) mass, s, group, mask) : new PhysicsComponent((btScalar) mass, s, group, mask); component->setParent(parent); components[parent->getName()] = component; if (hasTrigger) { ghosts[parent->getName()] = (GhostComponent*) component; } } else { component = components[parent->getName()]; } return component; }
int Physics::castRay(float x, float y, float z, float dx, float dy, float dz, float* pos, float* normal) { btCollisionWorld::ClosestRayResultCallback t(btVector3(x,y,z),btVector3(dx,dy,dz)); m_physicsWorld->rayTest(btVector3(x,y,z),btVector3(dx,dy,dz),t); PhysicsComponent* obj = (PhysicsComponent*)(t.m_collisionObject->getUserPointer()); if(obj) { if(pos) { pos[0] = t.m_hitPointWorld.x(); pos[1] = t.m_hitPointWorld.y(); pos[2] = t.m_hitPointWorld.z(); } if(normal) { normal[0] = t.m_hitNormalWorld.x(); normal[1] = t.m_hitNormalWorld.y(); normal[2] = t.m_hitNormalWorld.z(); } return obj->owner()->worldId(); } return 0; }
void RenderSystem::update(float dt, std::vector<GameObject*>* objects) { for (Ite i = objects->begin(); i != objects->end(); i++) { RenderComponent* render = (*i)->getComponent<RenderComponent>(); if (render != nullptr) { RectangleShape shape = *render->getDrawable(); PhysicsComponent* physics = (*i)->getComponent<PhysicsComponent>(); if (physics != nullptr) { Vector2f position = mScale * flipY(physics->getBody()->GetPosition()); shape.setPosition(position); shape.setSize(1.02f * mScale * physics->getSize()); shape.setOrigin(shape.getSize() * 0.5f); // positive direction is opposite in Box2D shape.setRotation(-1.0f * physics->getBody()->GetAngle() * 180 / b2_pi); } mWindow->draw(shape); } } }
void ModelComponent::Update(float dt) { Graphics* gSys = (Graphics*)Engine::GetCore()->GetSystem(ST_Graphics); gSys->AddDebugModel(this); Input* input = (Input*) Engine::GetCore()->GetSystem(ST_Input); InputHandler* handler = input->GetHandler(); Transform* tr = (Transform*)GetSibling(CT_Transform); PhysicsComponent* phys = (PhysicsComponent*) GetSibling(CT_PhysicsComponent); if(handler->Check("MoveRight")) { tr->SetPosition(tr->GetPosition() + Vector3(1.0f,0.0f,0.0f) * dt); phys->Reset(); } Model* newModel = gSys->GetModel(model_); if(newModel && base_ != newModel) { base_->RemoveInstance(this); base_ = newModel; base_->AddInstance(this); } }
void PhysicsComponent::OnHierarchyChange() { // Clear out old data if(absoluteCShape != nullptr) delete absoluteCShape; absoluteMass = mass; if(children.size() == 0) { absoluteCOG = cog; absoluteCShape = cShape; } else { btCompoundShape* compAbsShape = new btCompoundShape(); absoluteCShape = compAbsShape; compAbsShape->addChildShape(btTransform(), cShape); for(auto it = children.begin(); it != children.end(); ++it) { PhysicsComponent* curr = static_cast<PhysicsComponent*>(*it); compAbsShape->addChildShape(curr->getTransform(), curr->absoluteCShape); absoluteMass += curr->absoluteMass; } absoluteCOG.setValue(0.0f, 0.0f, 0.0f); absoluteCOG += cog * (mass / absoluteMass); for(auto it = children.begin(); it != children.end(); ++it) { PhysicsComponent* curr = static_cast<PhysicsComponent*>(*it); absoluteCOG += curr->cog * (curr->absoluteMass / absoluteMass); } } // Allow collision shape to be traced back to us absoluteCShape->setUserPointer(owner); // Only entities with no parents should have rigid bodies. if(parent == nullptr) { //TODO: Update body mass and possibly motionstate // If the body already exists, this entity was already a parent // beforehand. We just need to update it's collision shape // with the new absolute shape. if(body != nullptr) { body->setCollisionShape(absoluteCShape); body->setMassProps(absoluteMass, btVector3()); } // Otherwise we need to instantiate a new rigid body and register // it with the physics world. else { btRigidBody::btRigidBodyConstructionInfo ci(absoluteMass, nullptr, absoluteCShape); body = new btRigidBody(ci); } // Set new center of gravity btTransform comTrans; comTrans.setOrigin(absoluteCOG); body->setCenterOfMassTransform(comTrans); } // If the entitiy is no longer a parent, remove it from the world else if(body != nullptr) { physMan->GetWorld()->removeRigidBody(body); delete body; body = nullptr; } // There is no else. Child objects do not get their own rigid body }
void Client::Play() { OgreEasy::SimpleOgreInit lOgreInit; if(!lOgreInit.initOgre()) { std::cout<<"Could not init ogre"<<std::endl; return; } Ogre::Root* lRoot = lOgreInit.mRoot.get(); Ogre::RenderWindow* lWindow = lOgreInit.mWindow; World* w = new World(); w->SetDebugMode(false); GameObject camObject = w->AddObject("camera"); camObject.AddCameraComponent("camera"); camObject.SetPosition(Ogre::Vector3(0,0,0)); camObject.LookAt(Ogre::Vector3(0,0,0)); GameObject& light2 = w->AddObject("point_light"); light2.AddLightComponent(Ogre::Light::LT_DIRECTIONAL); light2.SetPosition(Ogre::Vector3(0,0,40)); light2.LookAt(Ogre::Vector3(0,100,0)); GameObject& c = w->AddPhysicsObject("esine", "cube/Cube.mesh"); c.SetPosition(Ogre::Vector3(0,0,0)); c.AddBoxCollider(1,1,1); PhysicsComponent phys = c.GetPhysicsComponent(); phys.SetMass(1.0); c.SetMaterial("tex"); GameObject& c2 = w->AddPhysicsObject("esine2", "cube/Cube.mesh"); c2.SetPosition(Ogre::Vector3(1,2,1)); c2.AddBoxCollider(1,1,1); PhysicsComponent phys2 = c2.GetPhysicsComponent(); phys2.SetMass(1.0); c2.SetMaterial("tex"); GameObject& taso = w->AddPhysicsObject("taso", "cube/other/Cube.mesh"); taso.SetPosition(Ogre::Vector3(0, -10, 0)); taso.AddBoxCollider(10,0.1,10); taso.SetMaterial("plane"); PhysicsComponent phys3 = taso.GetPhysicsComponent(); phys3.SetMass(0.0); GameObject& anim = w->AddObject("anim" , "second_anim/Cube.mesh"); anim.SetPosition(Ogre::Vector3(0, -5, 0)); anim.SetMaterial("tex"); lRoot->clearEventTimes(); float f=0.0; unsigned long t=0; double d; Ogre::Timer* a = new Ogre::Timer(); while(!lWindow->isClosed()) { t=a->getMicroseconds(); camObject.SetPosition(Ogre::Vector3(cos(f)*15.0, -5, sin(f)*15.0)); camObject.LookAt(Ogre::Vector3(-0,-10,-0), Ogre::Vector3::UNIT_Y); w->Update(d); f+=d*.5; d = (double)(a->getMicroseconds()-t)/1000000; } delete w; }
void InputModule::moveSphere(Ogre::Vector3 rotation) { PhysicsComponent* component = dynamic_cast<PhysicsComponent*> (ENGINE->getPhysics()->getComponent(ENGINE->getEntity("playerSphere"))); Ogre::Vector3 vect = Ogre::Vector3(rotation.x, rotation.y, rotation.z); component->setComponentGravity(rotation * 10); }
string PhysicsController::run(string myState, float time_since_last_tick) { string game_state_request = " "; for(vector<Entity*>::size_type i = 0; i != controlled_entities.size(); i++) { if(controlled_entities[i]->getGameState()==myState) { if(controlled_entities[i]->getActive()) { //PULL THE MOVING OBJECTS INFORMATION PhysicsComponent* physics = (PhysicsComponent*)controlled_entities[i]->getComponent("Physics"); PositionComponent* position = (PositionComponent*)controlled_entities[i]->getComponent("Position"); //PULLING ALL THE MASS AND FORCE INFORMATION float total_mass = 0 + physics->getMass(); float total_translation [2] = {0,0}; float moment_of_inertia = 0 + physics->getMass(); float total_torque = 0; if( controlled_entities[i]->checkIfHasComponent("Collection")) { CollectionComponent* collection = (CollectionComponent*) controlled_entities[i]->getComponent("Collection"); vector<Entity*> attached_entities = collection->getAttachedEntities(); //Cycling through attached entities for(vector<Entity*>::size_type p = 0; p != attached_entities.size(); p++) { Entity* attached_entity = attached_entities[p]; TetheredComponent* tethered = (TetheredComponent*) attached_entity->getComponent("Tethered"); PhysicsComponent* attached_physics = (PhysicsComponent*) attached_entity->getComponent("Physics"); PositionComponent* attached_position = (PositionComponent*) attached_entity->getComponent("Position"); RocketComponent* rocket = (RocketComponent*) attached_entity->getComponent("Rocket"); float radian_from_center_mass = tethered->getDirectionRadian(); float radian_to_center_mass = radian_from_center_mass + 3.1415926; float t = attached_position->getAngle() - radian_to_center_mass ; tethered->setT(t); //Translational vector<float> attached_vector_forces = attached_physics->getNetTranslationalForce(); total_translation[0] += attached_vector_forces[0]; total_translation[1] += attached_vector_forces[1]; total_mass+= attached_physics->getMass(); //Angular float attached_net_angular_force = attached_physics->getNetAngularForce(); total_torque += attached_net_angular_force; float distance = tethered->getDistance(); moment_of_inertia += attached_physics->getMass()*(distance*distance); } } //Apparently on forces that have a distance can spin it //So after we've pulled all the angular forces we can find the angular acceleration //and then you use torque = I*a physics->setAngularAcceleration(total_torque/moment_of_inertia); //PLANAR MOVEMENT //We already have the tethered objects' forces so now we need the forces affectin the main object itself vector<float> vector_forces = physics->getNetTranslationalForce(); total_translation[0] += vector_forces[0]; total_translation[1] += vector_forces[1]; //Calculating the net acceleration net forces and net mass physics->setAccelerationX(total_translation[0]/total_mass); physics->setAccelerationY(total_translation[1]/total_mass); //Determine its new velocity physics->setVelocityX(physics->getVelocity()[0]+physics->getAcceleration()[0]*time_since_last_tick); physics->setVelocityY(physics->getVelocity()[1]+physics->getAcceleration()[1]*time_since_last_tick); //Determine its new position if its not tethered to something if( !controlled_entities[i]->checkIfHasComponent("Tethered")) { position->setX(position->getPosition()[0]+physics->getVelocity()[0]*time_since_last_tick); position->setY(position->getPosition()[1]+physics->getVelocity()[1]*time_since_last_tick); } //ANGULAR MOVEMENT // Both tethered and collected entities get this because a tethered can be rotating on its own // on top of being rotated by the collectors movement. // On it's own, a tethered object cannot have an angular acceleration, it must be machine assisted. physics->setAngularVelocity(physics->getAngularVelocity()+physics->getAngularAcceleration()*time_since_last_tick); position->setAngle(position->getAngle()+physics->getAngularVelocity()*time_since_last_tick); //To make sure the tethered objects get moved we make sure the collector handles them we he is passed into this controller if( controlled_entities[i]->checkIfHasComponent("Collection")) { CollectionComponent* collection = (CollectionComponent*) controlled_entities[i]->getComponent("Collection"); vector<Entity*> attached_entities = collection->getAttachedEntities(); //Go throuhg all the attached entities and update their tethered position wiht the new positon of the collector for(vector<Entity*>::size_type p = 0; p != attached_entities.size(); p++) { Entity* attached_entity = attached_entities[p]; TetheredComponent* tethered = (TetheredComponent*) attached_entity->getComponent("Tethered"); PhysicsComponent* attached_physics = (PhysicsComponent*) attached_entity->getComponent("Physics"); PositionComponent* attached_position = (PositionComponent*) attached_entity->getComponent("Position"); ////Determine its new position //As the object spins so will all the tethered objects tethered->setDirectionRadian( tethered->getDirectionRadian() + physics->getAngularVelocity()*time_since_last_tick); float radian_from_center_mass = tethered->getDirectionRadian(); float radian_to_center_mass = radian_from_center_mass + 3.1415926; attached_position->setAngle(radian_to_center_mass + tethered->getT()); //Need to update the angle of the rocket as the main ship spins //Set the tethered object to the new position in the new direction attached_position->setX( position->getPosition()[0] + cos(tethered->getDirectionRadian())*tethered->getDistance()); attached_position->setY( position->getPosition()[1] + sin(tethered->getDirectionRadian())*tethered->getDistance()); } } position->calculateBucketPosition(BUCKET_WIDTH); } } } return game_state_request; }
void PhysicsComponent::loadFromXml(const XMLNode* description) { GameLog::logMessage("LOADING BULLET FROM XML"); // Delete old physics representation //release(); Matrix4f objTrans; m_owner->executeEvent(&GameEvent(GameEvent::E_TRANSFORMATION, &GameEventData((float*) objTrans.x, 16), this)); Vec3f t, r, s; objTrans.decompose(t, r, s); // Parse Physics Node Configuration float mass = static_cast<float>(atof(description->getAttribute("mass", "0.0"))); const char* shape = description->getAttribute("shape", "Box"); // create collision shape based on the node configuration if (shape && _stricmp(shape, "Box") == 0) // Bounding Box Shape { float dimX = static_cast<float>(atof(description->getAttribute("x", "1.0"))); float dimY = static_cast<float>(atof(description->getAttribute("y", "1.0"))); float dimZ = static_cast<float>(atof(description->getAttribute("z", "1.0"))); // update box settings with node scaling (TODO is this necessary if we already set the scale by using setLocalScaling?) //m_collisionShape = new btBoxShape(btVector3(dimX * s.x, dimY * s.y, dimZ * s.z)); m_collisionShape = new btBoxShape(btVector3(dimX, dimY, dimZ)); } else if (shape && _stricmp(shape, "Sphere") == 0) // Sphere Shape { float radius = static_cast<float>(atof(description->getAttribute("radius", "1.0"))); m_collisionShape = new btSphereShape(radius); } else if (shape && _stricmp(shape, "Cylinder") == 0) // Cylinder Shape { float radius0 = static_cast<float>(atof(description->getAttribute("radius", "1.0"))); float height = static_cast<float>(atof(description->getAttribute("height", "1.0"))); m_collisionShape = new btCylinderShape(btVector3(radius0, height, radius0)); } else // Mesh Shape { MeshData meshData; GameEvent meshEvent(GameEvent::E_MESH_DATA, &meshData, this); // get mesh data from graphics engine m_owner->executeEvent(&meshEvent); if (meshData.VertexBase && (meshData.TriangleBase32 || meshData.TriangleBase16)) { // Create new mesh in physics engine m_btTriangleMesh = new btTriangleMesh(); int offset = 3; if (meshData.TriangleMode == 5) // Triangle Strip offset = 1; // copy mesh from graphics to physics bool index16 = false; if (meshData.TriangleBase16) index16 = true; for (unsigned int i = 0; i < meshData.NumTriangleIndices - 2; i += offset) { unsigned int index1 = index16 ? (meshData.TriangleBase16[i] - meshData.VertRStart) * 3 : (meshData.TriangleBase32[i] - meshData.VertRStart) * 3; unsigned int index2 = index16 ? (meshData.TriangleBase16[i + 1] - meshData.VertRStart) * 3 : (meshData.TriangleBase32[i + 1] - meshData.VertRStart) * 3; unsigned int index3 = index16 ? (meshData.TriangleBase16[i + 2] - meshData.VertRStart) * 3 : (meshData.TriangleBase32[i + 2] - meshData.VertRStart) * 3; m_btTriangleMesh->addTriangle(btVector3(meshData.VertexBase[index1], meshData.VertexBase[index1 + 1], meshData.VertexBase[index1 + 2]), btVector3(meshData.VertexBase[index2], meshData.VertexBase[index2 + 1], meshData.VertexBase[index2 + 2]), btVector3(meshData.VertexBase[index3], meshData.VertexBase[index3 + 1], meshData.VertexBase[index3 + 2])); } bool useQuantizedAabbCompression = true; if (mass > 0) { //btGImpactMeshShape* shape = new btGImpactMeshShape(m_btTriangleMesh); btGImpactConvexDecompositionShape* shape = new btGImpactConvexDecompositionShape(m_btTriangleMesh, btVector3(1.f, 1.f, 1.f), btScalar(0.1f), true); shape->updateBound(); //btCollisionDispatcher* dispatcher = static_cast<btCollisionDispatcher *>(Physics::instance()->dispatcher()); //btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher); m_collisionShape = shape; //m_collisionShape = new btConvexTriangleMeshShape(m_btTriangleMesh); } else // BvhTriangleMesh can be used only for static objects m_collisionShape = new btBvhTriangleMeshShape(m_btTriangleMesh, useQuantizedAabbCompression); } else { GameLog::errorMessage("The mesh data for the physics representation couldn't be retrieved"); return; } } GameLog::logMessage("PARSED SHAPE FROM XML"); bool kinematic = _stricmp(description->getAttribute("kinematic", "false"), "true") == 0 || _stricmp(description->getAttribute("kinematic", "0"), "1") == 0; bool nondynamic = _stricmp(description->getAttribute("static", "false"), "true") == 0 || _stricmp(description->getAttribute("static", "0"), "1") == 0; bool ragdoll = _stricmp(description->getAttribute("ragdoll", "false"), "true") == 0 || _stricmp(description->getAttribute("ragdoll", "0"), "1") == 0; // Create initial transformation without scale btTransform tr; tr.setIdentity(); tr.setRotation(btQuaternion(r.x, r.y, r.z)); btMatrix3x3 rot = tr.getBasis(); XMLNode offsetXMLNode = description->getChildNode("Offset"); if (!offsetXMLNode.isEmpty()) { lX = static_cast<float>(atof(offsetXMLNode.getAttribute("lX", "0.0"))); lY = static_cast<float>(atof(offsetXMLNode.getAttribute("lY", "0.0"))); lZ = static_cast<float>(atof(offsetXMLNode.getAttribute("lZ", "0.0"))); } btVector3 offset = btVector3(lX * s.x, lY * s.y, lZ * s.z); tr.setOrigin(btVector3(t.x, t.y, t.z) + rot * offset); // Set local scaling in collision shape because Bullet does not support scaling in the world transformation matrices m_collisionShape->setLocalScaling(btVector3(s.x, s.y, s.z)); btVector3 localInertia(0, 0, 0); //rigidbody is dynamic if and only if mass is non zero otherwise static if (mass != 0) m_collisionShape->calculateLocalInertia(mass, localInertia); if (mass != 0 || kinematic) //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects m_motionState = new btDefaultMotionState(tr); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, m_motionState, m_collisionShape, localInertia); rbInfo.m_startWorldTransform = tr; //rbInfo.m_restitution = btScalar( atof(description->getAttribute("restitution", "0")) ); //rbInfo.m_friction = btScalar( atof(description->getAttribute("static_friction", "0.5")) ); // Threshold for deactivation of objects (if movement is below this value the object gets deactivated) //rbInfo.m_angularSleepingThreshold = 0.8f; //rbInfo.m_linearSleepingThreshold = 0.8f; m_rigidBody = new btRigidBody(rbInfo); m_rigidBody->setUserPointer(this); m_rigidBody->setDeactivationTime(2.0f); // Add support for collision detection if mass is zero but kinematic is explicitly enabled if (kinematic && mass == 0 && !nondynamic) { m_rigidBody->setCollisionFlags(m_rigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); m_rigidBody->setActivationState(DISABLE_DEACTIVATION); } if (nondynamic && mass == 0) { m_rigidBody->setCollisionFlags(m_rigidBody->getCollisionFlags() | btCollisionObject::CF_STATIC_OBJECT); } bool isTrigger = _stricmp(description->getAttribute("solid", "true"), "false") == 0 || _stricmp(description->getAttribute("solid", "1"), "0") == 0; if (isTrigger) { setCollisionResponse(true); } GameLog::logMessage("I'm a new Physics body: %s my Motion state: %d", m_owner->id().c_str(), m_motionState); printf("I'm a new Physics body: %s my Motion state: %d\n", m_owner->id().c_str(), m_motionState); if(!ragdoll) Physics::instance()->addObject(this); /*Geometry Proxy*/ XMLNode proxyXMLNode = description->getChildNode("Proxy"); if (proxyXMLNode.isEmpty()) return; m_proxy = GameModules::gameWorld()->entity(proxyXMLNode.getAttribute("name", "")); if (m_proxy) { m_proxy->addListener(GameEvent::E_SET_TRANSFORMATION, this); m_proxy->addListener(GameEvent::E_SET_TRANSLATION, this); m_proxy->addListener(GameEvent::E_SET_ROTATION, this); m_proxy->addListener(GameEvent::E_TRANSLATE_LOCAL, this); m_proxy->addListener(GameEvent::E_TRANSLATE_GLOBAL, this); m_proxy->addListener(GameEvent::E_ROTATE_LOCAL, this); } else printf("No PROXY FOUND with EntityID: %s\n", proxyXMLNode.getAttribute("name", "")); /*Adding constraints*/ XMLNode constraintXMLNode = description->getChildNode("Constraint"); if (constraintXMLNode.isEmpty()) return; const char* constraintType = constraintXMLNode.getAttribute("type", "Hinge"); const char* parentName = constraintXMLNode.getAttribute("parent", ""); PhysicsComponent* parent = getParent(parentName); if (!parent) { printf("NO PARENT FOUND\n"); return; } XMLNode transformXMLNode = constraintXMLNode.getChildNode("TransformA"); float qX = static_cast<float>(atof(transformXMLNode.getAttribute("qx", "1.0"))); float qY = static_cast<float>(atof(transformXMLNode.getAttribute("qy", "1.0"))); float qZ = static_cast<float>(atof(transformXMLNode.getAttribute("qz", "1.0"))); float qW = static_cast<float>(atof(transformXMLNode.getAttribute("qw", "1.0"))); float vX = static_cast<float>(atof(transformXMLNode.getAttribute("vx", "1.0"))); float vY = static_cast<float>(atof(transformXMLNode.getAttribute("vy", "1.0"))); float vZ = static_cast<float>(atof(transformXMLNode.getAttribute("vz", "1.0"))); btTransform transformA; transformA.setIdentity(); printf("%f \t %f \t %f \n ", qX, qY, qZ); transformA.getBasis().setEulerZYX(qZ, qY, qX); // transformA.getBasis().setEulerZYX(M_PI_2,0,0); transformA.setOrigin(btVector3(vX * s.x, vY * s.y, vZ * s.z)); // printf("%f \t %f \t %f \t %s \n ", vX*s.x, vY*s.y, vZ*s.z, m_owner ? m_owner->id().c_str() : "no name"); // btTransform transformA = btTransform(btQuaternion(qX, qY, qZ, qW), btVector3(vX*s.x, vY*s.y, vZ*s.z)); transformXMLNode = constraintXMLNode.getChildNode("TransformB"); qX = static_cast<float>(atof(transformXMLNode.getAttribute("qx", "1.0"))); qY = static_cast<float>(atof(transformXMLNode.getAttribute("qy", "1.0"))); qZ = static_cast<float>(atof(transformXMLNode.getAttribute("qz", "1.0"))); qW = static_cast<float>(atof(transformXMLNode.getAttribute("qw", "1.0"))); vX = static_cast<float>(atof(transformXMLNode.getAttribute("vx", "1.0"))); vY = static_cast<float>(atof(transformXMLNode.getAttribute("vy", "1.0"))); vZ = static_cast<float>(atof(transformXMLNode.getAttribute("vz", "1.0"))); // btTransform transformB = btTransform(btQuaternion(qX, qY, qZ, qW), btVector3(vX*s.x, vY*s.y, vZ*s.z)); btTransform transformB; transformB.setIdentity(); transformB.getBasis().setEulerZYX(qZ, qY, qX); // transformB.getBasis().setEulerZYX(M_PI_2,0,0); transformB.setOrigin(btVector3(vX * s.x, vY * s.y, vZ * s.z)); XMLNode limitXMLNode = constraintXMLNode.getChildNode("Limit"); if (_stricmp(constraintType, "Hinge") == 0) { btHingeConstraint* parentConstraint = new btHingeConstraint(*(parent->rigidBody()), *m_rigidBody, transformA, transformB); float low = static_cast<float>(atof(limitXMLNode.getAttribute("low", "0.0"))); float high = static_cast<float>(atof(limitXMLNode.getAttribute("high", "0.75"))); float softness = static_cast<float>(atof(limitXMLNode.getAttribute("softness", "0.9"))); float biasFactor = static_cast<float>(atof(limitXMLNode.getAttribute("biasFactor", "0.3"))); float relaxationFactor = static_cast<float>(atof(limitXMLNode.getAttribute("relaxationFactor", "1.0"))); parentConstraint->setLimit(low, high, softness, biasFactor, relaxationFactor); m_parentConstraint = parentConstraint; } else if (_stricmp(constraintType, "ConeTwist") == 0) { btConeTwistConstraint* parentConstraint = new btConeTwistConstraint(*(parent->rigidBody()), *m_rigidBody, transformA, transformB); float swingSpan1 = static_cast<float>(atof(limitXMLNode.getAttribute("swingSpan1", "1.0"))); float swingSpan2 = static_cast<float>(atof(limitXMLNode.getAttribute("swingSpan2", "1.0"))); float twistSpan = static_cast<float>(atof(limitXMLNode.getAttribute("twistSpan", "1.0"))); float softness = static_cast<float>(atof(limitXMLNode.getAttribute("softness", "0.9"))); float biasFactor = static_cast<float>(atof(limitXMLNode.getAttribute("biasFactor", "0.3"))); float relaxationFactor = static_cast<float>(atof(limitXMLNode.getAttribute("relaxationFactor", "1.0"))); parentConstraint->setLimit(swingSpan1, swingSpan2, twistSpan, softness, biasFactor, relaxationFactor); m_parentConstraint = parentConstraint; } if(!ragdoll) Physics::instance()->addConstraint(m_parentConstraint); }
void wrapTickCallback(btDynamicsWorld *world, btScalar timeStep) { PhysicsComponent *component = static_cast<PhysicsComponent *>(world->getWorldUserInfo()); component->detectedCollisionsDuringStepSimulation(timeStep); }
string RocketController::run(string myState) { string game_state_request; for(vector<Entity*>::size_type i = 0; i != controlled_entities.size(); i++) { Entity* ent = controlled_entities[i]; if(ent->getGameState() == myState) { if(ent->getActive()) { //SUBTRACT FUEL SpaceshipComponent* spaceship = (SpaceshipComponent*) ent->getComponent("Spaceship"); float current_fuel = spaceship->getCurrentFuel(); CollectionComponent* collection = (CollectionComponent*) ent->getComponent("Collection"); vector<Entity*> attached_entities = collection->getAttachedEntities(); //Cycling through attached entities for(vector<Entity*>::size_type p = 0; p != attached_entities.size(); p++) { Entity* attached_entity = attached_entities[p]; attached_entity->setActive(true); if(attached_entity->checkIfHasComponent("Rocket")) { RocketComponent* rocket = (RocketComponent*) attached_entity->getComponent("Rocket"); TetheredComponent* tethered = (TetheredComponent*) attached_entity->getComponent("Tethered"); PositionComponent* position = (PositionComponent*) attached_entity->getComponent("Position"); PhysicsComponent* physics = (PhysicsComponent*) attached_entity->getComponent("Physics"); physics->clearForces(); if(rocket->getOnOrOff()) { if(spaceship->getCurrentFuel() - rocket->getFuelConsumption() >= 0) { //The rocket is on float force_exerted = rocket->getForceExerted(); float angle = position->getAngle(); float x = rocket->getForceExerted()*cos(angle); float y = rocket->getForceExerted()*sin(angle); physics->addTranslationalForce(x,y); //Angular Forces float distance = tethered->getDistance(); float angular_force = distance * rocket->getForceExerted() * -sin(tethered->getT()); physics->addAngularForce(angular_force); //Burning fuel spaceship->subtractCurrentFuel(rocket->getFuelConsumption()); } } } } } else { CollectionComponent* collection = (CollectionComponent*) ent->getComponent("Collection"); vector<Entity*> attached_entities = collection->getAttachedEntities(); //Cycling through attached entities for(vector<Entity*>::size_type p = 0; p != attached_entities.size(); p++) { attached_entities[p]->setActive(false); } } } } return game_state_request; }
void GhostComponent::checkOverlappingObjects() { int max = ghostObject->getNumOverlappingObjects(); std::set<std::string> currentlyCollidingObjects; for (int i = 0; i < max; i++) { btCollisionObject* collidee = ghostObject->getOverlappingObject(i); PhysicsComponent* component = static_cast<PhysicsComponent*> (collidee->getUserPointer()); std::string colliderName = component->getParent()->getName(); currentlyCollidingObjects.insert(colliderName); std::set<std::string>::iterator colliderIterator = lastKnownColliders.begin(); bool previouslyCollided = false; for (; colliderIterator != lastKnownColliders.end(); colliderIterator++) { if (colliderName == *colliderIterator) { previouslyCollided = true; } } Event* e; if (!previouslyCollided) { e = new Event(Event::COLLISION_ENTER); } else { e = new Event(Event::COLLISION); } e->entity = component->getParent(); this->parent->receiveEvent(e); //delete e; } int setDeltas = lastKnownColliders.size() - currentlyCollidingObjects.size(); if (setDeltas > 0) { // handling exit collisions std::vector<std::string>::iterator it; std::vector<std::string> delta(setDeltas); it = std::set_difference(lastKnownColliders.begin(), lastKnownColliders.end(), currentlyCollidingObjects.begin(), currentlyCollidingObjects.end(), delta.begin()); for (; it != delta.end(); it++) { Entity* exitCollision = ENGINE->getEntity(*it); Event* exitEvent = new Event(Event::COLLISION_EXIT); exitEvent->entity = exitCollision; parent->receiveEvent(exitEvent); delete exitEvent; } //@todo delete events after sending them. Right now they all remain on the heap } lastKnownColliders = currentlyCollidingObjects; }
bool deserialize(JsonNode& root, PhysicsComponent& physics) { physics.set_size(deserialize_vec3f(root["size"]) * TILE_SIZE); return true; }
void InputModule::moveSphere(Ogre::Vector3 direction) { PhysicsComponent* component = dynamic_cast<PhysicsComponent*> (ENGINE->getPhysics() ->getComponent(ENGINE->getEntity("playerSphere"))); component->setComponentGravity((direction) * 10); }
Level* GameInfo::loadLevel(string filename, std::shared_ptr<GenericPool<PhysicsComponent>> physicsPool) { picojson::value v; ifstream levelStream; levelStream.open(filename); int currentTileLayer = 1; std::string tileString = "Tile Layer "; int width = 0; int height = 0; int x = 0; int y = 0; const picojson::array* tileArray = NULL; levelStream >> v; if (levelStream.fail()) { std::cerr << picojson::get_last_error() << std::endl; return NULL; } //std::cout << "---- dump input ----" << std::endl; //std::cout << v << std::endl; //std::cout << "---- analyzing input ----" << std::endl; /*if (v.is<picojson::null>()) { std::cout << "input is null" << std::endl; } else if (v.is<bool>()) { std::cout << "input is " << (v.get<bool>() ? "true" : "false") << std::endl; } else if (v.is<double>()) { std::cout << "input is " << v.get<double>() << std::endl; } else if (v.is<std::string>()) { std::cout << "input is " << v.get<std::string>() << std::endl; } else if (v.is<picojson::array>()) { std::cout << "input is an array" << std::endl; const picojson::array& a = v.get<picojson::array>(); for (picojson::array::const_iterator i = a.begin(); i != a.end(); ++i) { std::cout << " " << *i << std::endl; } }*/ if (v.is<picojson::object>()) { const picojson::object& o = v.get<picojson::object>(); for (picojson::object::const_iterator i = o.begin(); i != o.end(); ++i) { if (i->first == "height") height = (int)i->second.get<double>(); else if (i->first == "width") width = (int)i->second.get<double>(); } } Locator::getLog()->printToFile("GameInfo-LoadLevel", "Width: " + std::to_string(width) + ", Height: " + std::to_string(height)); Level_Tile_3DVector_.resize(MAXTILELAYERS, std::vector<std::vector<int>>(width, std::vector<int>(height, 0))); if (v.is<picojson::object>()) { //std::cout << "input is an object" << std::endl; const picojson::object& o = v.get<picojson::object>(); for (picojson::object::const_iterator i = o.begin(); i != o.end(); ++i) { if (i->second.is<picojson::array>()) { //std::cout << "2nd is an array" << std::endl; const picojson::array& a = i->second.get<picojson::array>(); for (picojson::array::const_iterator i = a.begin(); i != a.end(); ++i) { auto g = *i; if (g.is<std::string>()) { //std::cout << "g is a string" << std::endl; } else if (g.is<picojson::object>()) //gets the objects within the layers array { //std::cout << "g is an object" << std::endl; const picojson::object& q = g.get<picojson::object>(); for (picojson::object::const_iterator p = q.begin(); p != q.end(); ++p) { if (p->first == "name") { if (p->second.is<std::string>()) { std::string tempString = p->second.get<std::string>(); for (int ggg = 0; ggg < MAXTILELAYERS; ggg++) { if (tempString == tileString + std::to_string(ggg + 1)) { currentTileLayer = ggg; } } } } } for (picojson::object::const_iterator p = q.begin(); p != q.end(); ++p) { if (p->first == "data") //tile information { //we found the tiles here! finally! if (p->second.is<picojson::array>()) { //std::cout << "FREAK OUT AGAIN" << std::endl; //tileArray = &p->second.get<picojson::array>(); tileArray = &p->second.get<picojson::array>(); for (picojson::array::const_iterator u = tileArray->begin(); u != tileArray->end(); ++u) { auto l = *u; //if (l.is<std::string>()) std::cout << "l is a string" << std::endl; if (l.is<double>()) { Level_Tile_3DVector_[currentTileLayer][x][y] = (int)l.get<double>(); x++; if (x == width) { x = 0; y++; } if (y == height) { x = 0; y = 0; } //levelTiles_.push_back((int)l.get<double>()); //std::cout << "added: " << currentTileLayer << std::endl; } } //found the array containing the tile data! //const picojson::array& a = p->second.get<picojson::array>(); } } else if (p->first == "objects") //collision objects (or any object) { if (p->second.is<picojson::array>()) //array of actual objects { tileArray = &p->second.get<picojson::array>(); for (picojson::array::const_iterator u = tileArray->begin(); u != tileArray->end(); ++u) { auto l = *u; if (l.is<picojson::object>()) //found an actual collision object now! { const picojson::object& ww = l.get<picojson::object>(); //get the object double h = -1, w = -1, xtemp = -1, ytemp = -1; for (picojson::object::const_iterator qq = ww.begin(); qq != ww.end(); ++qq) //iterate through data { if (qq->first == "height") h = qq->second.get<double>(); else if (qq->first == "width") w = qq->second.get<double>(); else if (qq->first == "x") xtemp = qq->second.get<double>(); else if (qq->first == "y") ytemp = qq->second.get<double>(); } PhysicsComponent* phys = physicsPool->getAvailableElement(); phys->setCoordsAndDimensions(xtemp, ytemp, w, h); phys->setPhysicsType(BLOCK); } } } } } } } } } } //std::cout << "Width: " << width << std::endl; //std::cout << "Height: " << height << std::endl; if (currentLevel_ != nullptr) delete currentLevel_; currentLevel_ = new Level(Level_Tile_3DVector_, physicsPool); currentLevel_->backgroundTex.create(width*TILESIZE, height*TILESIZE); return currentLevel_; }