Example #1
0
bool Collision::AABB_vs_AABB(const AABB& a, const AABB& b, Vector *v)
{
    const Vector a_upleft = a.upleft();
    const Vector a_downright = a.downright();
    const Vector b_upleft = b.upleft();
    const Vector b_downright = b.downright();

    bool c =  !(a_downright.y < b_upleft.y
             || a_upleft.y    > b_downright.y
             || a_downright.x < b_upleft.x
             || a_upleft.x    > b_downright.x);

    if(c && v)
    {
        AABB ov = a.getOverlap(b);
        *v = ov.getCenter();
    }

    return c;
}
Example #2
0
// If AABB intersects the frustum, an output clip mask is returned as well
(indicating which
// planes are crossed by the AABB). This information can be used to optimize
testing of
// child nodes or objects inside the nodes (pass value as 'inClipMask').

bool intersectAABBFrustum (const AABB& a, const Vector4* p, unsigned int&
outClipMask, unsigned int inClipMask)
{
Vector3 m = a.getCenter(); // center of AABB
Vector3 d = a.getMax() - m; // half-diagonal
unsigned int mk = 1;
outClipMask = 0; // init outclip mask
while (mk <= inClipMask){ // loop while there are active planes..
if (inClipMask&mk){ // if clip plane is active...
float NP = (float)(d.x*fabs(p->x)+d.y*fabs(p->y)+d.z*fabs(p->z));
float MP = m.x*p->x+m.y*p->y+m.z*p->z+p->w;
if ((MP+NP) < 0.0f) return false; // behind clip plane
if ((MP-NP) < 0.0f) outClipMask |= mk;
}
mk+=mk; // mk = (1<<iter)
p++; // next plane
}
return true; // AABB intersects frustum
}
Example #3
0
PhysicsInterface::BodyObject Bullet::createBoundingBoxBody(const AABB& aabb, float mass, bool fixed,
                                                           const Entity* entity,
                                                           const SimpleTransform& initialTransform)
{
    auto collisionShape = new btBoxShape(toBullet((aabb.getMaximum() - aabb.getMinimum()) * 0.5f));

    // Calculate inertia
    auto localInertia = btVector3(0.0f, 0.0f, 0.0f);
    if (!fixed)
        collisionShape->calculateLocalInertia(mass, localInertia);

    // Motion state for this body
    auto motionState = new btDefaultMotionState(toBullet(initialTransform),
                                                btTransform(btQuaternion::getIdentity(), toBullet(aabb.getCenter())));

    // Create Bullet rigid body
    auto bulletBody = new btRigidBody(
        btRigidBody::btRigidBodyConstructionInfo(fixed ? 0.0f : mass, motionState, collisionShape, localInertia));

    bulletBody->setDamping(DefaultLinearDamping, DefaultAngularDamping);
    bulletBody->setSleepingThresholds(DefaultLinearSleepingThreshold, DefaultAngularSleepingThreshold);
    bulletBody->setRestitution(0.0f);

    // Add body to the simulation
    dynamicsWorld_->addRigidBody(bulletBody);

    // Create local body
    auto body = new Body(bulletBody, entity, fixed);
    bodies_.append(body);

    body->ownedCollisionShape = collisionShape;

    bulletBody->setUserPointer(body);

    return body;
}
Example #4
0
void Transform::setByBounds(AABB bounds) {
    pos = bounds.getCenter();
    scale = bounds.getSize();
    needUpdate = true;
}
Example #5
0
void wiSPTree::getVisible(Node* node, AABB& frustum, CulledList& objects, SortType sort, CullStrictness type){
	if(!node) return;
	int contain_type = frustum.intersects(node->box);
	if(!contain_type) 
		return;
	else{
		for(Cullable* object : node->objects)
			if(
				type==SP_TREE_LOOSE_CULL || 
				(type==SP_TREE_STRICT_CULL &&
					contain_type==AABB::INSIDE ||
					(contain_type==INTERSECTS && frustum.intersects(object->bounds))
				)
			){

#ifdef SORT_SPTREE_CULL
				object->lastSquaredDistMulThousand=(long)(wiMath::Distance(object->bounds.getCenter(),frustum.getCenter())*1000);
				if (sort == SP_TREE_SORT_PAINTER)
					object->lastSquaredDistMulThousand *= -1;
#endif

				objects.insert(object);
			}
		if(node->count){
			for (unsigned int i = 0; i<node->children.size(); ++i)
				getVisible(node->children[i],frustum,objects, sort,type);
		}
	}
}
Example #6
0
//Now that the cells are created, associate each model to one or more cells of the scene.
void PVSGenerator::addModelsToCells(const vector<shared_ptr<Cell>>& cells, VoxelContainer& voxelContainer, const AABB sceneAABB)
{
	const Vector3f voxelSize = voxelContainer.getVoxelSize();
	vector<Point3i> cellExternalIndices;
	vector<Triangle> triangles;
	AABB voxelAABB;
	Vector3f voxelMidPoint;
	float boxHalfSize[3];
	float triverts[3][3];
	float boxCenter[3];

	for( unsigned int c = 0 ; c < cells.size() ; ++c)
	{

		Point3i minIndex = cells[c]->minPoint;
		Point3i maxIndex = cells[c]->maxPoint;

		//Convert the AABB to world space.
		AABB cellAABB(  Vector3f (
								minIndex.x * voxelSize.x + sceneAABB.minPoint.x,
								minIndex.y * voxelSize.y + sceneAABB.minPoint.y,
								minIndex.z * voxelSize.z + sceneAABB.minPoint.z	),
						Vector3f (
								maxIndex.x * voxelSize.x + sceneAABB.minPoint.x + voxelSize.x,
								maxIndex.y * voxelSize.y + sceneAABB.minPoint.y + voxelSize.y,
								maxIndex.z * voxelSize.z + sceneAABB.minPoint.z + voxelSize.z));
		AABB modelAABB;

		//For each Occludee
		for( int i = 0; i < scene.getModelInstancesCount() ; ++i)
		{
			//TODO: very heavy operation, try to cache it somewhere.
			modelAABB = scene.getModelInstance(i).getModelAABB();

			//Check if model is inside the cell. If so, add it to the cell model list.
			if( scene.getModelInstance(i).getModelType() == OCCLUDEE)
			{
				if( CollisionUtils::boxBoxOverlapTest( modelAABB.minPoint.vec,  modelAABB.maxPoint.vec,  cellAABB.minPoint.vec,  cellAABB.maxPoint.vec))
					cells[c]->addModelId( scene.getModelInstance(i).getModelId() );
			}
		}


		//Calculate the occluders.
		//Occluders are treated differently from the occludees. Occluders don't collide with cells directly because they are where solid voxels are.
		//Because of this, we have to test the cell external voxels against the actual occluder geometry.
		
		//Get all the external voxels of the cell.
		cellExternalIndices.clear();
		getCellExternalVoxels( *(cells[c]), cellExternalIndices);

		//Calculate the voxel's half size in x, y and z.
		boxHalfSize[0] = voxelSize.x / 2.0f;
		boxHalfSize[1] = voxelSize.y / 2.0f;
		boxHalfSize[2] = voxelSize.z / 2.0f;

		//For each external voxel of this cell, see if there is any occluder that collides with it.
		for( unsigned int i = 0 ; i < cellExternalIndices.size() ; ++i)
		{
			//Only consider solid external voxels because they have geometry there.
			if( voxelContainer.voxelAt(cellExternalIndices[i]).getStatus() != Voxel::SOLID )
				continue;

			//Go for each occluder and test for collision.
			for( int k = 0; k < scene.getModelInstancesCount() ; ++k)
			{
				//If it is occluder and it is not yet associated with the cell...
				if( scene.getModelInstance(k).getModelType() == OCCLUDER &&
					cells[c]->isModelIdInCell(scene.getModelInstance(k).getModelId()) == false  )
				{
					//TODO: very heavy operation, try to cache it somewhere.
					modelAABB = scene.getModelInstance(k).getModelAABB();
					voxelAABB = voxelContainer.getVoxelAABBFromIndex(cellExternalIndices[i], sceneAABB);

					//If collides with AABB of the voxel then we can test at polygon level.
					if( CollisionUtils::boxBoxOverlapTest( modelAABB.minPoint.vec,  modelAABB.maxPoint.vec,  voxelAABB.minPoint.vec,  voxelAABB.maxPoint.vec))
					{
						
						triangles.clear();

						//Transform the model space triangle to world space.
						scene.getModelInstance(k).getModelTrianglesWorldSpace(triangles);

						voxelMidPoint = voxelAABB.getCenter();
												
						boxCenter[0] = voxelMidPoint.x;
						boxCenter[1] = voxelMidPoint.y;
						boxCenter[2] = voxelMidPoint.z;

						for( unsigned int t = 0 ; t < triangles.size() ; ++t)
						{

							//Store the triangle in a format that the colission algorithm can receive.
							triverts[0][0] = triangles[t].a.x;
							triverts[0][1] = triangles[t].a.y;
							triverts[0][2] = triangles[t].a.z;

							triverts[1][0] = triangles[t].b.x;
							triverts[1][1] = triangles[t].b.y;
							triverts[1][2] = triangles[t].b.z;

							triverts[2][0] = triangles[t].c.x;
							triverts[2][1] = triangles[t].c.y;
							triverts[2][2] = triangles[t].c.z;

							//Test for intersection between the triangle and the voxel's AABB.
							if(CollisionUtils::triBoxOverlap(boxCenter, boxHalfSize, triverts) == 1)
							{
								cells[c]->addModelId( scene.getModelInstance(k).getModelId() );
								break;
							}
						}
					}
				}
			}
		}
		
		//Log progress
		if( c % ( (cells.size() / 10)  + 1) == 0 ) //Show 10% increments.
		{
			std::stringstream str;
			str << "Models to Cells %: " << ((float) c / cells.size()) * 100.0f;
			Logger::Log( str.str() );
		}
	}
}
Example #7
0
bool OBB::collision(const CollisionObject * pCollisionObject, bool calculateNormal)
{
	if(pCollisionObject->getCollisionType()==CollisionType_OBB)
	{
		OBB * pOBB = (OBB*) pCollisionObject;
		
		for(unsigned int aIndex=0; aIndex<3; aIndex++)
	    {
			  D3DXVECTOR3 axis = mAxis[aIndex];

              float min1 = 1000000.0f;
              float max1 = -1000000.0f;
              float min2 = 1000000.0f;
              float max2 = -1000000.0f;
              
              for(unsigned int cIndex=0; cIndex<8; cIndex++)
              {
				  float pos = D3DXVec3Dot(&axis, &mCorners[cIndex]);// axis.x * mCorners[cIndex].x + axis.y * mCorners[cIndex].y + axis.z * mCorners[cIndex].z;    
                     
                     if(pos < min1)
                     {
                          min1 = pos;  
                     }
                     else if(pos > max1)     
                     {
                          max1 = pos;
                     }                   
              }
              
              for(unsigned int cIndex=0; cIndex<8; cIndex++)
              {
					 D3DXVECTOR3 corner = pOBB->getCorner(cIndex);

                     float pos = D3DXVec3Dot(&axis, &corner);//axis.x * corner.x + axis.y * corner.y  + axis.z * corner.z;    
                     
                     if(pos < min2)
                     {
                          min2 = pos;  
                     }
                     else if(pos > max2)     
                     {
                          max2 = pos;
                     }                   
              }
              
              if(max1 < min2 ||  min1 > max2)
              {
                     return false;       
              }          
        }

		for(unsigned int aIndex=0; aIndex<3; aIndex++)
	    {
			  D3DXVECTOR3 axis = pOBB->getAxis(aIndex);

              float min1 = 1000000.0f;
              float max1 = -1000000.0f;
              float min2 = 1000000.0f;
              float max2 = -1000000.0f;
              
              for(unsigned int cIndex=0; cIndex<8; cIndex++)
              {
                     float pos = D3DXVec3Dot(&axis, &mCorners[cIndex]);//axis.x * mCorners[cIndex].x + axis.y * mCorners[cIndex].y + axis.z * mCorners[cIndex].z;    
                     
                     if(pos < min1)
                     {
                          min1 = pos;  
                     }
                     else if(pos > max1)     
                     {
                          max1 = pos;
                     }                   
              }
              
              for(unsigned int cIndex=0; cIndex<8; cIndex++)
              {
					 D3DXVECTOR3 corner = pOBB->getCorner(cIndex);

                     float pos = D3DXVec3Dot(&axis, &corner);//axis.x * corner.x + axis.y * corner.y  + axis.z * corner.z;    
                     
                     if(pos < min2)
                     {
                          min2 = pos;  
                     }
                     else if(pos > max2)     
                     {
                          max2 = pos;
                     }                   
              }
              
              if(max1 < min2 ||  min1 > max2)
              {
                     return false;       
              }          
        }
        
		if(calculateNormal)
		{
			setCollisionNormal(pOBB->getCenter() - mCenter);
			pOBB->setCollisionNormal(mCenter - pOBB->getCenter());
		}

        return true; 

	}
	else if(pCollisionObject->getCollisionType()==CollisionType_AABB)
	{
		AABB * pAABB = (AABB*) pCollisionObject;
		
		D3DXVECTOR3 aabbAxis[3];

		aabbAxis[0] = D3DXVECTOR3(1,0,0);
		aabbAxis[1] = D3DXVECTOR3(0,1,0);
		aabbAxis[2] = D3DXVECTOR3(0,0,1);
		
		for(int aIndex=0;aIndex<3;aIndex++)
		{
              float min1 = 1000000;
              float max1 = -1000000;
              float min2 = 1000000;
              float max2 = -1000000;
              
              for(int cIndex=0;cIndex<8;cIndex++)
              {
					 //D3DXVECTOR3 corner = pAABB->getCorner(cIndex);

                     //float pos = mAxis[aIndex].x * mCorners[cIndex].x + mAxis[aIndex].y * mCorners[cIndex].y + mAxis[aIndex].z * mCorners[cIndex].z;
					 float pos = D3DXVec3Dot(&mAxis[aIndex], &mCorners[cIndex]);
                     
                     if(pos < min1)
                     {
                          min1 = pos;  
                     }
                     else if(pos > max1)     
                     {
                          max1 = pos;
                     }                   
              }
              
              for(int cIndex=0;cIndex<8;cIndex++)
              {
					 D3DXVECTOR3 corner = pAABB->getCorner(cIndex);

                     //float pos = mAxis[aIndex].x * aabbCorners[cIndex].x + mAxis[aIndex].y * aabbCorners[cIndex].y  + mAxis[aIndex].z * aabbCorners[cIndex].z;
				     float pos = D3DXVec3Dot(&mAxis[aIndex], &corner);
                     
                     if(pos < min2)
                     {
                          min2 = pos;  
                     }
                     else if(pos > max2)     
                     {
                          max2 = pos;
                     }                   
              }
              
              if(max1 < min2 || max2 < min1)
              {
                     return false;       
              }           
        }

		for(int aIndex=0;aIndex<3;aIndex++)
		{
              float min1 = 1000000;
              float max1 = -1000000;
              float min2 = 1000000;
              float max2 = -1000000;
            
              for(int cIndex=0;cIndex<8;cIndex++)
              {
					 //D3DXVECTOR3 corner = pAABB->getCorner(cIndex);

                     //float pos = aabbAxis[aIndex].x * mCorners[cIndex].x + aabbAxis[aIndex].y * mCorners[cIndex].y + aabbAxis[aIndex].z * mCorners[cIndex].z;
					 float pos = D3DXVec3Dot(&aabbAxis[aIndex], &mCorners[cIndex]);
                     
                     if(pos < min1)
                     {
                          min1 = pos;  
                     }
                     else if(pos > max1)     
                     {
                          max1 = pos;
                     }                   
              }
              
              for(int cIndex=0;cIndex<8;cIndex++)
              {
					 D3DXVECTOR3 corner = pAABB->getCorner(cIndex);

                     //float pos = aabbAxis[aIndex].x * aabbCorners[cIndex].x + aabbAxis[aIndex].y * aabbCorners[cIndex].y  + aabbAxis[aIndex].z * aabbCorners[cIndex].z;  
				     float pos = D3DXVec3Dot(&aabbAxis[aIndex], &corner);
                     
                     if(pos < min2)
                     {
                          min2 = pos;  
                     }
                     else if(pos > max2)     
                     {
                          max2 = pos;
                     }                   
              }
              
              if(max1 < min2 || max2 < min1)
              {
                     return false;       
              }           
        }

		if(calculateNormal)
		{
			setCollisionNormal(pAABB->getCenter() - mCenter);
			pAABB->setCollisionNormal(mCenter - pAABB->getCenter());
		}
        
        return true;

	}
	else if(pCollisionObject->getCollisionType()==CollisionType_Sphere)
	{
		Sphere * pSphere = (Sphere*) pCollisionObject;

		for(int aIndex=0;aIndex<3;aIndex++)
	    {
              float min1 = 1000000;
			  float max1 = -1000000;
			  float min2 = 1000000;
              float max2 = -1000000;
              
              for(int cIndex=0;cIndex<8;cIndex++)
              {
                     float pos = mAxis[aIndex].x * mCorners[cIndex].x + mAxis[aIndex].y * mCorners[cIndex].y + mAxis[aIndex].z * mCorners[cIndex].z;    
                     
                     if(pos < min1)
                     {
                          min1 = pos;  
                     }
                     else if(pos > max1)     
                     {
                          max1 = pos;
                     }
              }
              
			  min2 = mAxis[aIndex].x * pSphere->getX() + mAxis[aIndex].y * pSphere->getY() + mAxis[aIndex].z * pSphere->getZ() - pSphere->getR();
			  max2 = mAxis[aIndex].x * pSphere->getX() + mAxis[aIndex].y * pSphere->getY() + mAxis[aIndex].z * pSphere->getZ() + pSphere->getR();
              
              if(max1 < min2 ||  min1 > max2)
              {
                     return false;       
              }          
        }
		
		D3DXVECTOR3 obbToSphere = D3DXVECTOR3(pSphere->getX(),pSphere->getY(),pSphere->getZ());
		obbToSphere -= mCenter;

		float length = obbToSphere.x * obbToSphere.x + obbToSphere.y * obbToSphere.y + obbToSphere.z * obbToSphere.z;
		length = sqrt(length);

		obbToSphere /= length;

		float min1 = 1000000;
		float max1 = -1000000;
		float min2 = 1000000;
        float max2 = -1000000;

		for(int cIndex=0;cIndex<8;cIndex++)
        {
             float pos = obbToSphere.x * mCorners[cIndex].x + obbToSphere.y * mCorners[cIndex].y + obbToSphere.z * mCorners[cIndex].z;    
                     
             if(pos < min1)
             {
                   min1 = pos;  
             }
             else if(pos > max1)     
             {
                   max1 = pos;
             }
        }
              
	    min2 = obbToSphere.x * pSphere->getX() + obbToSphere.y * pSphere->getY() + obbToSphere.z * pSphere->getZ() - pSphere->getR();
	    max2 = obbToSphere.x * pSphere->getX() + obbToSphere.y * pSphere->getY() + obbToSphere.z * pSphere->getZ() + pSphere->getR();
              
        if(max1 < min2 ||  min1 > max2)
        {
              return false;       
        }

		if(calculateNormal)
		{
			D3DXVECTOR3 sphereCenter = D3DXVECTOR3(pSphere->getX(), pSphere->getY(), pSphere->getZ());

			setCollisionNormal(sphereCenter - mCenter);
			pSphere->setCollisionNormal(mCenter - sphereCenter);
		}
        
        return true;
	}

	return false;
}