Ejemplo n.º 1
0
void QuadTree::draw(Core::Engine& engine){
    glm::vec4 farbe(0,0,0,0);
    if(level_ == 0){
        farbe = glm::vec4(0,0,0,1);
    }
    else if(level_ == 1){
        farbe = glm::vec4(0,0,255,1);
    }
    else if(level_ == 2){
        farbe = glm::vec4(255,0,0,1);
    }
    else if(level_ == 3){
        farbe = glm::vec4(0,255,0,1);
    }
    else if(level_ == 4){
        farbe = glm::vec4(255,255,0,1);
    }
    if(nodes_.size() > 0){
        for(int i = 0; i < nodes_.size(); ++i){
            nodes_.at(i)->draw(engine);
        }
    }
    engine.renderSystem().renderPrimitive(EL_STROKE_QUAD, glm::vec2(bounds_.x, bounds_.y), glm::vec2(bounds_.w, bounds_.h), farbe, 0);

    for(int i = 0; i < collisionBoxes_.size(); ++i){
        CollisionBox *cb = collisionBoxes_.at(i);
        Util::Struct::FloatRect bounds = cb->bounds();
        engine.renderSystem().renderPrimitive(EL_STROKE_QUAD, glm::vec2(cb->parent().parent().pos().x + bounds.x,
                                                                        cb->parent().parent().pos().y + bounds.y),
                                                    glm::vec2(bounds.w, bounds.h), farbe, 0);
    }
}
Ejemplo n.º 2
0
precision CollisionBox::projectToAxis(CollisionBox b, const Vector& axis)
{
	// Find all the component contributions in the direction of
	// the given axis
	return (b.halfLength.x * std::abs(b.getAxis(0).scalarProduct(axis))) +
		(b.halfLength.y * std::abs(b.getAxis(1).scalarProduct(axis)))+
		(b.halfLength.z * std::abs(b.getAxis(2).scalarProduct(axis)));
}
Ejemplo n.º 3
0
static inline real transformToAxis(
    const CollisionBox &box,
    const Vector3 &axis
    )
{
    return
        box.halfSize.x * real_abs(axis * box.getAxis(0)) +
        box.halfSize.y * real_abs(axis * box.getAxis(1)) +
        box.halfSize.z * real_abs(axis * box.getAxis(2));
}
// TODO: Test!
// REALLY TODO: TEST. There definitely is a bug in here.
void CollisionSphere::genContactsB(const CollisionBox& b, std::vector<std::shared_ptr<IContact>>& o) const
{
	// Get the sphere position in local coordinates of the box.

	Vect3 transformedSpherePosition = b.getTransformMatrix().getInverse() * this->getPos();

	// If the sphere is further away than the magnitude of the furthest distance
	//  a corner can be, early out:
	if (transformedSpherePosition.squareMagnitude() > b.getSize().squareMagnitude())
		return;

	// Otherwise, find the closest point on the cube.
	//  For any axis, it will be the cube half length on that side if
	//  the sphere's position is further than the half length. If not, it'll
	//  just be the component on that side.
	Vect3 closestBoxPoint = transformedSpherePosition;
	closestBoxPoint._x = CLAMP(closestBoxPoint._x, -b.getSize()._x, b.getSize()._x);
	closestBoxPoint._y = CLAMP(closestBoxPoint._y, -b.getSize()._y, b.getSize()._y);
	closestBoxPoint._z = CLAMP(closestBoxPoint._z, -b.getSize()._z, b.getSize()._z);

	// Now we have the closest point on the box.
	//  If it's closer than the radius, we have a contact
	if ((closestBoxPoint - transformedSpherePosition).squareMagnitude() < this->getRadius() * this->getRadius()
		&& ((closestBoxPoint - transformedSpherePosition).squareMagnitude() > 0.f))
	{
		// Box contact data: Contact is under the surface of the sphere, pointing directly out.
		Vect3Normal d = (closestBoxPoint - transformedSpherePosition);
		Vect3 collisionPoint_l = transformedSpherePosition + d * _radius;
		Vect3 penetration_l = closestBoxPoint - collisionPoint_l;
		Vect3 collisionPoint_w = b.getTransformMatrix() * collisionPoint_l;
		Vect3 penetration_w = b.getTransformMatrix().transformDirn(penetration_l);
		/*Vect3 collisionPoint_l = (Vect3Normal(closestBoxPoint - this->GetPos()) * this->GetRadius()) + this->GetPos();
		Vect3 collisionPoint_w = b.GetTransformMatrix() * (closestBoxPoint - transformedSpherePosition);
		Vect3 penetration_w = (Vect3Normal(collisionPoint_w - this->GetPos()) * this->GetRadius()) - collisionPoint_w;*/
		o.push_back(this->summonDemons(
			collisionPoint_w,
			penetration_w,
			penetration_w.magnitude(),
			b.getAttachedObjectPtr(), _attachedObject));

		// Sphere contact data: Exact opposite of the box contact.
		penetration_w *= -1.f;
		o.push_back(this->summonDemons(
			collisionPoint_w,
			penetration_w,
			penetration_w.magnitude(),
			this->getAttachedObjectPtr(), b.getAttachedObjectPtr()));
	}
}
Ejemplo n.º 5
0
unsigned CollisionDetector::boxAndPoint(
    const CollisionBox &box,
    const Vector3 &point,
    CollisionData *data
    )
{
    // Transform the point into box coordinates
    Vector3 relPt = box.transform.transformInverse(point);

    Vector3 normal;

    // Check each axis, looking for the axis on which the
    // penetration is least deep.
    real min_depth = box.halfSize.x - real_abs(relPt.x);
    if (min_depth < 0) return 0;
    normal = box.getAxis(0) * ((relPt.x < 0)?-1:1);

    real depth = box.halfSize.y - real_abs(relPt.y);
    if (depth < 0) return 0;
    else if (depth < min_depth)
    {
        min_depth = depth;
        normal = box.getAxis(1) * ((relPt.y < 0)?-1:1);
    }

    depth = box.halfSize.z - real_abs(relPt.z);
    if (depth < 0) return 0;
    else if (depth < min_depth)
    {
        min_depth = depth;
        normal = box.getAxis(2) * ((relPt.z < 0)?-1:1);
    }

    // Compile the contact
    Contact* contact = data->contacts;
    contact->contactNormal = normal;
    contact->contactPoint = point;
    contact->penetration = min_depth;

    // Note that we don't know what rigid body the point
    // belongs to, so we just use NULL. Where this is called
    // this value can be left, or filled in.
    contact->setBodyData(box.body, NULL,
        data->friction, data->restitution);

    data->addContacts(1);
    return 1;
}
Ejemplo n.º 6
0
bool CollisionBox::didCollide(const CollisionBox& b) const
{
	vec3 v1=b.getPoint1()-this->getPoint2();
	vec3 v2=b.getPoint2()-this->getPoint1();

	if((v1.x>0)!=(v2.x>0)){
		if((v1.y>0)!=(v2.y>0)){
			if((v1.z>0)!=(v2.z>0)){
				//std::cout<<"TEST"<<std::endl;
				return true;
			}
		}
	}

	return false;
}
Ejemplo n.º 7
0
/**
 * Checks if two collidables intersects with each other
 *
 */
bool CollisionBox::Intersects(const CollisionBox& other)
{
	Vector3D<float>* otherPos = other.GetPosition();
	Vector3D<float>& otherBounds = other.GetBounds();
	
	if( _LeftCollision(otherPos, otherBounds)
		&& _RightCollision(otherPos, otherBounds)
		&& _TopCollision(otherPos, otherBounds)
		&& _BottomCollision(otherPos, otherBounds)
		&& _FrontCollision(otherPos, otherBounds)
		&& _BackCollision(otherPos, otherBounds) )
	{
  		return true;
	}
	return false;
}
Ejemplo n.º 8
0
void fillPointFaceBoxBox(
    const CollisionBox &one,
    const CollisionBox &two,
    const Vector3 &toCentre,
    CollisionData *data,
    unsigned best,
    real pen
    )
{
    // This method is called when we know that a vertex from
    // box two is in contact with box one.

    Contact* contact = data->contacts;

    // We know which axis the collision is on (i.e. best),
    // but we need to work out which of the two faces on
    // this axis.
    Vector3 normal = one.getAxis(best);
    if (one.getAxis(best) * toCentre > 0)
    {
        normal = normal * -1.0f;
    }

    // Work out which vertex of box two we're colliding with.
    // Using toCentre doesn't work!
    Vector3 vertex = two.halfSize;
    if (two.getAxis(0) * normal < 0) vertex.x = -vertex.x;
    if (two.getAxis(1) * normal < 0) vertex.y = -vertex.y;
    if (two.getAxis(2) * normal < 0) vertex.z = -vertex.z;

    // Create the contact data
    contact->contactNormal = normal;
    contact->penetration = pen;
    contact->contactPoint = two.getTransform() * vertex;
    contact->setBodyData(one.body, two.body,
        data->friction, data->restitution);
}
Ejemplo n.º 9
0
bool IntersectionTests::boxAndHalfSpace(
    const CollisionBox &box,
    const CollisionPlane &plane
    )
{
    // Work out the projected radius of the box onto the plane direction
    real projectedRadius = transformToAxis(box, plane.direction);

    // Work out how far the box is from the origin
    real boxDistance =
        plane.direction *
        box.getAxis(3) -
        projectedRadius;

    // Check for the intersection
    return boxDistance <= plane.offset;
}
bool CollisionSphere::isTouchingB(const CollisionBox& b) const
{
	// Get the sphere position in local coordinates of the box.
	Vect3 transformedSpherePosition = b.getTransformMatrix().getInverse() * this->getPos();

	// If the sphere is further away than the magnitude of the furthest distance
	//  a corner can be, early out:
	if (transformedSpherePosition.squareMagnitude() > b.getSize().squareMagnitude())
		return false;

	// Otherwise, find the closest point on the cube.
	//  For any axis, it will be the cube half length on that side if
	//  the sphere's position is further than the half length. If not, it'll
	//  just be the component on that side.
	Vect3 closestBoxPoint = transformedSpherePosition;
	closestBoxPoint._x = CLAMP(closestBoxPoint._x, -b.getSize()._x, b.getSize()._x);
	closestBoxPoint._y = CLAMP(closestBoxPoint._y, -b.getSize()._y, b.getSize()._y);
	closestBoxPoint._z = CLAMP(closestBoxPoint._z, -b.getSize()._z, b.getSize()._z);

	// Now we have the closest points on the box.
	//  If it's closer than the radius, we have a contact.
	return ((closestBoxPoint - transformedSpherePosition).squareMagnitude() <= this->getRadius() * this->getRadius());
}
Ejemplo n.º 11
0
unsigned CollisionDetector::boxAndBox(
    const CollisionBox &one,
    const CollisionBox &two,
    CollisionData *data
    )
{
    //if (!IntersectionTests::boxAndBox(one, two)) return 0;

    // Find the vector between the two centres
    Vector3 toCentre = two.getAxis(3) - one.getAxis(3);

    // We start assuming there is no contact
    real pen = REAL_MAX;
    unsigned best = 0xffffff;

    // Now we check each axes, returning if it gives us
    // a separating axis, and keeping track of the axis with
    // the smallest penetration otherwise.
    CHECK_OVERLAP(one.getAxis(0), 0);
    CHECK_OVERLAP(one.getAxis(1), 1);
    CHECK_OVERLAP(one.getAxis(2), 2);

    CHECK_OVERLAP(two.getAxis(0), 3);
    CHECK_OVERLAP(two.getAxis(1), 4);
    CHECK_OVERLAP(two.getAxis(2), 5);

    // Store the best axis-major, in case we run into almost
    // parallel edge collisions later
    unsigned bestSingleAxis = best;

    CHECK_OVERLAP(one.getAxis(0) % two.getAxis(0), 6);
    CHECK_OVERLAP(one.getAxis(0) % two.getAxis(1), 7);
    CHECK_OVERLAP(one.getAxis(0) % two.getAxis(2), 8);
    CHECK_OVERLAP(one.getAxis(1) % two.getAxis(0), 9);
    CHECK_OVERLAP(one.getAxis(1) % two.getAxis(1), 10);
    CHECK_OVERLAP(one.getAxis(1) % two.getAxis(2), 11);
    CHECK_OVERLAP(one.getAxis(2) % two.getAxis(0), 12);
    CHECK_OVERLAP(one.getAxis(2) % two.getAxis(1), 13);
    CHECK_OVERLAP(one.getAxis(2) % two.getAxis(2), 14);

    // Make sure we've got a result.
    assert(best != 0xffffff);

    // We now know there's a collision, and we know which
    // of the axes gave the smallest penetration. We now
    // can deal with it in different ways depending on
    // the case.
    if (best < 3)
    {
        // We've got a vertex of box two on a face of box one.
        fillPointFaceBoxBox(one, two, toCentre, data, best, pen);
        data->addContacts(1);
        return 1;
    }
    else if (best < 6)
    {
        // We've got a vertex of box one on a face of box two.
        // We use the same algorithm as above, but swap around
        // one and two (and therefore also the vector between their
        // centres).
        fillPointFaceBoxBox(two, one, toCentre*-1.0f, data, best-3, pen);
        data->addContacts(1);
        return 1;
    }
    else
    {
        // We've got an edge-edge contact. Find out which axes
        best -= 6;
        unsigned oneAxisIndex = best / 3;
        unsigned twoAxisIndex = best % 3;
        Vector3 oneAxis = one.getAxis(oneAxisIndex);
        Vector3 twoAxis = two.getAxis(twoAxisIndex);
        Vector3 axis = oneAxis % twoAxis;
        axis.normalise();

        // The axis should point from box one to box two.
        if (axis * toCentre > 0) axis = axis * -1.0f;

        // We have the axes, but not the edges: each axis has 4 edges parallel
        // to it, we need to find which of the 4 for each object. We do
        // that by finding the point in the centre of the edge. We know
        // its component in the direction of the box's collision axis is zero
        // (its a mid-point) and we determine which of the extremes in each
        // of the other axes is closest.
        Vector3 ptOnOneEdge = one.halfSize;
        Vector3 ptOnTwoEdge = two.halfSize;
        for (unsigned i = 0; i < 3; i++)
        {
            if (i == oneAxisIndex) ptOnOneEdge[i] = 0;
            else if (one.getAxis(i) * axis > 0) ptOnOneEdge[i] = -ptOnOneEdge[i];

            if (i == twoAxisIndex) ptOnTwoEdge[i] = 0;
            else if (two.getAxis(i) * axis < 0) ptOnTwoEdge[i] = -ptOnTwoEdge[i];
        }

        // Move them into world coordinates (they are already oriented
        // correctly, since they have been derived from the axes).
        ptOnOneEdge = one.transform * ptOnOneEdge;
        ptOnTwoEdge = two.transform * ptOnTwoEdge;

        // So we have a point and a direction for the colliding edges.
        // We need to find out point of closest approach of the two
        // line-segments.
        Vector3 vertex = contactPoint(
            ptOnOneEdge, oneAxis, one.halfSize[oneAxisIndex],
            ptOnTwoEdge, twoAxis, two.halfSize[twoAxisIndex],
            bestSingleAxis > 2
            );

        // We can fill the contact.
        Contact* contact = data->contacts;

        contact->penetration = pen;
        contact->contactNormal = axis;
        contact->contactPoint = vertex;
        contact->setBodyData(one.body, two.body,
            data->friction, data->restitution);
        data->addContacts(1);
        return 1;
    }
    return 0;
}
Ejemplo n.º 12
0
bool CollisionBox::earlyOut(CollisionBox b1, CollisionBox b2)
{
	Vector centre = b2.centre - b1.centre;
	return !(
		overlaps(b1, b2, b1.getAxis(0)) &&
		overlaps(b1, b2, b1.getAxis(1)) &&
		overlaps(b1, b2, b1.getAxis(2)) &&
		
		overlaps(b1, b2, b2.getAxis(0)) &&
		overlaps(b1, b2, b2.getAxis(1)) &&
		overlaps(b1, b2, b2.getAxis(2)) &&

		overlaps(b1, b2, b1.getAxis(0) % b2.getAxis(0)) &&
		overlaps(b1, b2, b1.getAxis(0) % b2.getAxis(1)) &&
		overlaps(b1, b2, b1.getAxis(0) % b2.getAxis(2)) &&
		overlaps(b1, b2, b1.getAxis(1) % b2.getAxis(0)) &&
		overlaps(b1, b2, b1.getAxis(1) % b2.getAxis(1)) &&
		overlaps(b1, b2, b1.getAxis(1) % b2.getAxis(2)) &&
		overlaps(b1, b2, b1.getAxis(2) % b2.getAxis(0)) &&
		overlaps(b1, b2, b1.getAxis(2) % b2.getAxis(1)) &&
		overlaps(b1, b2, b1.getAxis(2) % b2.getAxis(2))
		);
}
Ejemplo n.º 13
0
bool CollisionBox::isZCollision(const CollisionBox &box) {
   return !(_max(2) < box.getMinZ() || box.getMaxZ() < _min(2));
}
Ejemplo n.º 14
0
bool CollisionBox::isXCollision(const CollisionBox &box) {
   return !(_max(0) < box.getMinX() || box.getMaxX() < _min(0));
}
Ejemplo n.º 15
0
bool Monster::checkBoxes(std::vector<CollisionBox>* boxes, float p_x, float p_y){
	CollisionBox box;

	Point2D A = Point2D(this->getX(), this->getY());
	Point2D B;
	for (int i = 0; i < boxes->size(); i++){
		box = boxes->at(i);


		if (box.getRight() < this->getBox().getLeft())
			B.setX(box.getRight());
		else if (box.getLeft() > this->getBox().getRight())
			B.setX(box.getLeft());
		else
			B.setX(this->getX());

		if (box.getTop() < this->getBox().getBottom())
			B.setY(box.getTop());
		else if (box.getBottom() > this->getBox().getTop())
			B.setY(box.getBottom());
		else
			B.setY(this->getY());


		float difx = (B.getX() - A.getX()) * (B.getX() - A.getX());
		float dify = (B.getY() - A.getY()) * (B.getY() - A.getY());

		float dist = difx + dify;
		if (dist <= this->getRadius() * this->getRadius()){


			if ((this->getBox().getBottom() > box.getTop() ||
				this->getBox().getTop() < box.getBottom())
				){
				if (this->getBox().getBottom() > box.getTop()){
					if (p_x == this->getX()){
						this->angle = 0;
					}

					else if (p_x > this->getX()){

						if (this->getY() < p_y)
							this->angle = 8;
						else
							this->angle = 0;

					}
					else {

						if (this->getY() < p_y)
							this->angle = 172;
						else
							this->angle = 180;
					}

				}
				else if (this->getBox().getTop() < box.getBottom()){
					if (p_x == this->getX()){
						this->angle = 0;
					}

					else if (p_x > this->getX()){
						if (this->getY() > p_y)
							this->angle = 352;
						else
							this->angle = 0;

					}
					else{
						if (this->getY() > p_y)
							this->angle = 188;
						else
							this->angle = 180;
					}
				}

			}
			else if ((this->getBox().getRight() < box.getLeft() || this->getBox().getLeft() > box.getRight())
				){

				float up = box.getTop() - this->getY();
				float down = this->getY() - box.getBottom();

				if (this->getBox().getRight() < box.getLeft()){
					if (p_y == this->getY()){
						this->angle = 90;
					}
					else if (p_y > this->getY()){
						if (this->getX() > p_x)
							this->turn(this->getX() - 16, box.getTop() + 32);
						else
							this->turn(this->getX(), box.getTop() + 32);
					}
					else{
						if (this->getX() > p_x)
							this->turn(this->getX() - 16, box.getBottom() - 32);
						else
							this->turn(this->getX(), box.getBottom() - 32);
					}

				}
				else if (this->getBox().getLeft() > box.getRight()){

					if (p_y == this->getY()){
						this->angle = 90;
					}
					else if (p_y > this->getY()){
						if (this->getX() < p_x)
							this->turn(this->getX() + 16, box.getTop() + 32);
						else
							this->turn(this->getX(), box.getTop() + 32);
					}
					else{
						if (this->getX() < p_x)
							this->turn(this->getX() + 16, box.getBottom() - 32);
						else
							this->turn(this->getX(), box.getBottom() - 32);
					}
				}
			}
			return true;
		}
		else
			continue;
	}
	return false;
}
Ejemplo n.º 16
0
bool IntersectionTests::boxAndBox(
    const CollisionBox &one,
    const CollisionBox &two
    )
{
    // Find the vector between the two centres
    Vector3 toCentre = two.getAxis(3) - one.getAxis(3);

    return (
        // Check on box one's axes first
        TEST_OVERLAP(one.getAxis(0)) &&
        TEST_OVERLAP(one.getAxis(1)) &&
        TEST_OVERLAP(one.getAxis(2)) &&

        // And on two's
        TEST_OVERLAP(two.getAxis(0)) &&
        TEST_OVERLAP(two.getAxis(1)) &&
        TEST_OVERLAP(two.getAxis(2)) &&

        // Now on the cross products
        TEST_OVERLAP(one.getAxis(0) % two.getAxis(0)) &&
        TEST_OVERLAP(one.getAxis(0) % two.getAxis(1)) &&
        TEST_OVERLAP(one.getAxis(0) % two.getAxis(2)) &&
        TEST_OVERLAP(one.getAxis(1) % two.getAxis(0)) &&
        TEST_OVERLAP(one.getAxis(1) % two.getAxis(1)) &&
        TEST_OVERLAP(one.getAxis(1) % two.getAxis(2)) &&
        TEST_OVERLAP(one.getAxis(2) % two.getAxis(0)) &&
        TEST_OVERLAP(one.getAxis(2) % two.getAxis(1)) &&
        TEST_OVERLAP(one.getAxis(2) % two.getAxis(2))
    );
}
Ejemplo n.º 17
0
bool CollisionBox::isXZCollision(const CollisionBox &box) {
   return !(maxX < box.getMinX() || box.getMaxX() < minX || maxZ < box.getMinZ() || box.getMaxZ() < minZ);
}