Пример #1
0
    void PhysicsWorld::update(Scene * scene, unsigned dt){
        /*std::cout << "<---- physics update ----> \n";
        std::cout << "<---- collisons loop ----> \n";*/
            
		/*std::cout << "i= "<< i << " | id = " << objectList[i]->getId() << " \n";
		std::cout << "pos: (" << objectList[i]->getPosition().x << ", " << objectList[i]->getPosition().y << " )\n";
		std::cout << "rigid body pos: (" << objectList[i]->getRigidBody()->getPosition().x << ", " << objectList[i]->getRigidBody()->getPosition().y << " )\n";
		std::cout << "width: " << objectList[i]->getWidth() << "| height: " << objectList[i]->getHeight() << "\n";*/
        this->collisions.clear();
		scene->getCollisionLayer()->foreachPair(dt, [=](CollisionObject * a, CollisionObject * b, unsigned dt) {
			
            glm::vec2 mtv = a->getCollisionShape()->checkCollision(b->getCollisionShape());
            if(mtv != glm::vec2()){
                this->collisions.push_back(CollisionEvent(a,b,mtv));
                this->resolveCollision(a,b,mtv);
            }
		});
 
		scene->getCollisionLayer()->foreachObject(dt, [=](CollisionObject * collisionObject, unsigned dt) {
            if(!(collisionObject->getCollisionShape()->getIsStatic())) {
                collisionObject->getCollisionShape()->getRigidBody()->setForce(glm::vec2());
                applyForce(collisionObject->getCollisionShape()->getRigidBody() ,this->gravity);
                collisionObject->step(dt);
            }
			
		});
    }
Пример #2
0
inline
void
CollisionBox<ScalarT, dimN>::queueCellChanges(
    typename CollisionBox<ScalarT, dimN>::Particle* particle,
    const typename CollisionBox<ScalarT, dimN>::Point& newPosition,
    typename CollisionBox<ScalarT, dimN>::Scalar timeStep,
    typename CollisionBox<ScalarT, dimN>::CollisionQueue& collisionQueue)
{
    /* Check for crossing of any cell borders: */
    GridCell* cell=particle->cell;
    Scalar cellChangeTime=timeStep;
    int cellChangeDirection=-1;
    for (int i=0;i<dimension;++i) {
        if (newPosition[i]<cell->boundaries.min[i]) {
            Scalar collisionTime=particle->timeStamp+(cell->boundaries.min[i]-particle->position[i])/particle->velocity[i];
            if (cellChangeTime>collisionTime) {
                cellChangeTime=collisionTime;
                cellChangeDirection=2*i+0;
            }
        } else if (newPosition[i]>cell->boundaries.max[i]) {
            Scalar collisionTime=particle->timeStamp+(cell->boundaries.max[i]-particle->position[i])/particle->velocity[i];
            if (cellChangeTime>collisionTime) {
                cellChangeTime=collisionTime;
                cellChangeDirection=2*i+1;
            }
        }
    }
    if (cellChangeDirection>=0) {
        collisionQueue.insert(CollisionEvent(cellChangeTime,particle,cellChangeDirection));
    }
}
Пример #3
0
inline
void
CollisionBox<ScalarT, dimN>::queueCollisionsInCell(
    typename CollisionBox<ScalarT, dimN>::GridCell* cell,
    typename CollisionBox<ScalarT, dimN>::Particle* particle1,
    typename CollisionBox<ScalarT, dimN>::Scalar timeStep,
    bool symmetric,
    typename CollisionBox<ScalarT, dimN>::Particle* otherParticle,
    typename CollisionBox<ScalarT, dimN>::CollisionQueue& collisionQueue)
{
    /* Calculate all intersections between two particles: */
    for (Particle* particle2=cell->particlesHead;particle2!=0;particle2=particle2->cellSucc)
    {
        if (particle2!=particle1 && particle2!=otherParticle && (symmetric||particle2>particle1))
        {
            /* Calculate any possible intersection time between the two particles: */
            Vector d=particle1->position-particle2->position;
            d-=particle1->velocity*particle1->timeStamp;
            d+=particle2->velocity*particle2->timeStamp;
            Vector vd=particle1->velocity-particle2->velocity;
            Scalar vd2=Geometry::sqr(vd);
            if (vd2>Scalar(0)) // Are the two particles' velocities different?
            {
                /* Solve the quadratic equation determining possible collisions: */
                Scalar ph=(d*vd)/vd2;
                Scalar q=(Geometry::sqr(d)-Scalar(4)*particleRadius2)/vd2;
                Scalar det=Math::sqr(ph)-q;
                if (det>=Scalar(0)) // Are there any solutions?
                {
                    /* Calculate the first solution (only that can be valid): */
                    Scalar collisionTime=-ph-Math::sqrt(det);

                    /* If the collision is valid, i.e., occurs past the last update of both particles, queue it: */
                    if (collisionTime>particle1->timeStamp && collisionTime>particle2->timeStamp && collisionTime<=timeStep)
                        collisionQueue.insert(CollisionEvent(collisionTime,particle1,particle2));
                }
            }
        }
    }
}
Пример #4
0
void PhysicsComponent::callOnCollision(GameObject& other, Scene& scene)
{
	ColliderComponent* otherCollider = other.getComponent<ColliderComponent>(); 
	owner_.broadcastEvent(CollisionEvent(scene, other, *otherCollider));
	other.broadcastEvent(CollisionEvent(scene, owner_, *collider_));
}
Пример #5
0
inline
void
CollisionBox<ScalarT, dimN>::queueCollisions(
    typename CollisionBox<ScalarT, dimN>::Particle* particle1,
    typename CollisionBox<ScalarT, dimN>::Scalar timeStep,
    bool symmetric,
    typename CollisionBox<ScalarT, dimN>::Particle* otherParticle,
    typename CollisionBox<ScalarT, dimN>::CollisionQueue& collisionQueue)
{
    /* Calculate the particle's position at the end of this time step: */
    Point newPosition=particle1->position+particle1->velocity*(timeStep-particle1->timeStamp);
    
    /* Check for crossing of cell borders: */
    queueCellChanges(particle1,newPosition,timeStep,collisionQueue);
    
    /* Check for collision with any of the collision box's walls: */
    for (int i=0;i<dimension;++i) {
        if (newPosition[i]<boundaries.min[i]+particleRadius) {
            Scalar collisionTime=particle1->timeStamp+(boundaries.min[i]+particleRadius-particle1->position[i])/particle1->velocity[i];
            if (collisionTime<particle1->timeStamp)
                collisionTime=particle1->timeStamp;
            else if (collisionTime>timeStep)
                collisionTime=timeStep;
            Vector wallNormal=Vector::zero;
            wallNormal[i]=Scalar(1);
            collisionQueue.insert(CollisionEvent(collisionTime,particle1,wallNormal));
        }
        else if (newPosition[i]>boundaries.max[i]-particleRadius) {
            Scalar collisionTime=particle1->timeStamp+(boundaries.max[i]-particleRadius-particle1->position[i])/particle1->velocity[i];
            if (collisionTime<particle1->timeStamp)
                collisionTime=particle1->timeStamp;
            else if (collisionTime>timeStep)
                collisionTime=timeStep;
            Vector wallNormal=Vector::zero;
            wallNormal[i]=Scalar(-1);
            collisionQueue.insert(CollisionEvent(collisionTime,particle1,wallNormal));
        }
    }
    
    /* Check for collision with the spherical obstacle: */
    Vector d=particle1->position-spherePosition;
    d-=particle1->velocity*particle1->timeStamp;
    d+=sphereVelocity*sphereTimeStamp;
    Vector vd=particle1->velocity-sphereVelocity;
    Scalar vd2=Geometry::sqr(vd);
    if (vd2>Scalar(0)) { // Are the two particles' velocities different?
        /* Solve the quadratic equation determining possible collisions: */
        Scalar ph=(d*vd)/vd2;
        Scalar q=(Geometry::sqr(d)-Math::sqr(particleRadius+sphereRadius))/vd2;
        Scalar det=Math::sqr(ph)-q;
        if (det>=Scalar(0)) { // Are there any solutions?
            /* Calculate the first solution (only that can be valid): */
            Scalar collisionTime=-ph-Math::sqrt(det);

            /* If the collision is valid, i.e., occurs past the last update of both particles, queue it: */
            if (collisionTime>particle1->timeStamp && collisionTime>sphereTimeStamp && collisionTime<=timeStep) {
                collisionQueue.insert(CollisionEvent(collisionTime,particle1,sphereTimeStamp));
            }
        }
    }
    
    /* Check for collision with any other particle: */
    GridCell* baseCell=particle1->cell;
    for (int i=0;i<numNeighbors;++i)
    {
        GridCell* cell=baseCell+neighborOffsets[i];
        queueCollisionsInCell(cell,particle1,timeStep,symmetric,otherParticle,collisionQueue);
    }
}
void BulletOpenGLApplication::CheckForCollisionEvents() {
	// keep a list of the collision pairs we
	// found during the current update
	CollisionPairs pairsThisUpdate;

	// iterate through all of the manifolds in the dispatcher
	for (int i = 0; i < m_pDispatcher->getNumManifolds(); ++i) {
		
		// get the manifold
		btPersistentManifold* pManifold = m_pDispatcher->getManifoldByIndexInternal(i);
		
		// ignore manifolds that have 
		// no contact points.
		if (pManifold->getNumContacts() > 0) {
			// get the two rigid bodies involved in the collision
			const btRigidBody* pBody0 = static_cast<const btRigidBody*>(pManifold->getBody0());
			const btRigidBody* pBody1 = static_cast<const btRigidBody*>(pManifold->getBody1());
    
			// always create the pair in a predictable order
			// (use the pointer value..)
			bool const swapped = pBody0 > pBody1;
			const btRigidBody* pSortedBodyA = swapped ? pBody1 : pBody0;
			const btRigidBody* pSortedBodyB = swapped ? pBody0 : pBody1;
			
			// create the pair
			CollisionPair thisPair = std::make_pair(pSortedBodyA, pSortedBodyB);
			
			// insert the pair into the current list
			pairsThisUpdate.insert(thisPair);

			// if this pair doesn't exist in the list
			// from the previous update, it is a new
			// pair and we must send a collision event
			if (m_pairsLastUpdate.find(thisPair) == m_pairsLastUpdate.end()) {
				CollisionEvent((btRigidBody*)pBody0, (btRigidBody*)pBody1);
			}
		}
	}
	
	// create another list for pairs that
	// were removed this update
	CollisionPairs removedPairs;
	
	// this handy function gets the difference beween
	// two sets. It takes the difference between
	// collision pairs from the last update, and this 
	// update and pushes them into the removed pairs list
	std::set_difference( m_pairsLastUpdate.begin(), m_pairsLastUpdate.end(),
	pairsThisUpdate.begin(), pairsThisUpdate.end(),
	std::inserter(removedPairs, removedPairs.begin()));
	
	// iterate through all of the removed pairs
	// sending separation events for them
	for (CollisionPairs::const_iterator iter = removedPairs.begin(); iter != removedPairs.end(); ++iter) {
		SeparationEvent((btRigidBody*)iter->first, (btRigidBody*)iter->second);
	}
	
	// in the next iteration we'll want to
	// compare against the pairs we found
	// in this iteration
	m_pairsLastUpdate = pairsThisUpdate;
}