/*!
  * \brief Create a new BoundingVolume object.
  *
  * This method creates and returns a new BoundingVolume object, according to
  * the preferred BoundingVolume-type settings.
  *
  * \param parent The BvhNode that the BoundingVolume should be in. See \ref
  * setHierarchyNode.
  *
  * \return A new BoundingVolume object. The caller is responsible for
  * deleting it.
  */
 BoundingVolume* BoundingVolume::createBoundingVolume(World* world, BvhNode* parent) {
     if (!world) {
         throw NullPointerException("Parameter world");
     }
     BoundingVolume* bv = 0;
     switch (getCreateRigidBoundingVolumeType(world)) {
         case BV_TYPE_AABB:
             bv = new Aabb();
             break;
         case BV_TYPE_KDOP:
             bv = new Kdop();
             break;
         case BV_TYPE_SPHERE:
             bv = new BoundingSphere();
             break;
         case BV_TYPE_OBB:
             bv = new Obb();
             break;
         default:
             // TODO: exception!!
             std::cerr << dc_funcinfo << "FATAL ERROR: bounding volume type " << getCreateRigidBoundingVolumeType(world) << " not supported" << std::endl;
             exit(1);
             return 0;
     }
     bv->setHierarchyNode(parent);
     return bv;
 }
Exemple #2
0
		BoundingVolume Grid::boundingVolume(const Math::Transformation &transformation) const
		{
			BoundingVolume volume;
			for (const Vertex &vertex : mVertices) {
				volume.expand(transformation * vertex.point);
			}

			return volume;
		}
Exemple #3
0
		/*!
		 * \brief Tests for intersection with another Aabb
		 * \return TRUE If this Aabb intersects with \p other. Otherwise FALSE.
		 * 
		 * TODO: Implement correct/faster collision detection methods for
		 *       collisions between different types of bounding volumes.
		 */
		bool Aabb::collidesWith(const BoundingVolume& other) const {
			if (other.getVolumeType() == getVolumeType()) {
				const BoundingVolume* otherPointer = &other;
				const Aabb* aabbPointer = static_cast<const Aabb*>(otherPointer);
				return collidesWithInternal(*aabbPointer);
			}
			return collidesWithInternal(Aabb(other.getSurroundingAabbMin(),
											 other.getSurroundingAabbMax()));
		}
Exemple #4
0
bool Physics::willObjectsCollide(CollidableObject* coA, CollidableObject* coB)
{
	PhysicalProperties* pp = coA->getPhysicalProperties();
	BoundingVolume* bv = coA->getBoundingVolume();
	float widthA = bv->getWidth();
	float heightA = bv->getHeight();
	float xA = pp->getX() + bv->getX();
	float yA = pp->getY() + bv->getY();
	float velXA = pp->getVelocityX();
	float velYA = pp->getVelocityY();
	float minXA = xA-(widthA/2);
	float maxXA = xA+(widthA/2);
	float minYA = yA-(heightA/2);
	float maxYA = yA+(heightA/2);

	if(velXA >= 0)
		maxXA += velXA; 
	if(velXA < 0)
		minXA += velXA; 
	if(velYA >= 0)
		maxYA += velYA; 
	if(velYA < 0)
		minYA += velYA; 

	pp = coB->getPhysicalProperties();
	bv = coB->getBoundingVolume();
	float widthB = bv->getWidth();
	float heightB = bv->getHeight();
	float xB = pp->getX() + bv->getX();
	float yB = pp->getY() + bv->getY();
	float velXB = pp->getVelocityX();
	float velYB = pp->getVelocityY();
	float minXB = xB-(widthB/2);
	float maxXB = xB+(widthB/2);
	float minYB = yB-(heightB/2);
	float maxYB = yB+(heightB/2);

	if(velXB >= 0)
		maxXB += velXB; 
	if(velXB < 0)
		minXB += velXB; 
	if(velYB >= 0)
		maxYB += velYB; 
	if(velYB < 0)
		minYB += velYB; 

	if( !(maxXB < minXA || minXB > maxXA || maxYB < minYA || minYB > maxYA))
		return true;
	return false;
}
Exemple #5
0
void BoundingVolume::transform(const BoundingVolume &in_volume,
        glm::mat4 matrix) {
    // Make sure the bounding volume itself is cleared before transformation
    reset();

    glm::vec4 min_corner(in_volume.min_corner(), 1.0f);
    glm::vec4 max_corner(in_volume.max_corner(), 1.0f);
    glm::vec4 transformed_min_corner = matrix * min_corner;
    glm::vec4 transformed_max_corner = matrix * max_corner;

    glm::vec3 transformed_min(transformed_min_corner.x, transformed_min_corner.y,
            transformed_min_corner.z);
    glm::vec3 transformed_max(transformed_max_corner.x, transformed_max_corner.y,
            transformed_max_corner.z);

    // expand with the new corners
    expand(transformed_min);
    expand(transformed_max);
}
/*
	clone - this method makes another BackAndForthBot object, but does
	not completely initialize it with similar data to this. Most of the 
	object, like velocity and position, are left uninitialized.
*/
Bot* BackAndForthBot::clone()
{
	BackAndForthBot *botClone = new BackAndForthBot();
	PhysicalProperties* pp = this->getPhysicalProperties();
	PhysicalProperties* bp = botClone->getPhysicalProperties();
	BoundingVolume* pV = this->getBoundingVolume();
	BoundingVolume* bV = botClone->getBoundingVolume();
	botClone->setEnemy(enemy);
	botClone->setItem(item);
	botClone->setPortal(portal);
	botClone->setSpriteType(this->getSpriteType());
	botClone->setAlpha(this->getAlpha());
	botClone->setDead(false);
	bp->setCollidable(pp->isCollidable());
	bp->setGravAffected(pp->isGravAffected());
	bV->setHeight(pV->getHeight());
	bV->setWidth(pV->getWidth());
	bV->setX(pV->getX());
	bV->setY(pV->getY());
	return botClone;
}
/*
 * Uses the technique described here:
 * http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
 */
void BoundingVolume::transform(const BoundingVolume &in_volume, glm::mat4 matrix) {
    // Make sure the bounding volume itself is cleared before transformation
    reset();

    glm::vec3 center = (in_volume.min_corner() + in_volume.max_corner()) / 2.0f;
    glm::vec3 extent = (in_volume.max_corner() - in_volume.min_corner()) / 2.0f;

    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            scratch_abs_matrix[i, j] = abs(matrix[i, j]);
        }
    }

    glm::vec4 new_center = matrix * glm::vec4(center, 1.0f);
    glm::vec4 new_extent = scratch_abs_matrix * glm::vec4(extent, 0.0f);

    glm::vec4 bb_min = new_center - new_extent;
    glm::vec4 bb_max = new_center + new_extent;

    expand(glm::vec3(bb_min.x, bb_min.y, bb_min.z));
    expand(glm::vec3(bb_max.x, bb_max.y, bb_max.z));
}
    /*!
     * TODO: Implement correct/faster collision detection methods for
     *       collisions between different types of bounding volumes.
     */
    bool BoundingSphere::collidesWith(const BoundingVolume& other) const {
        if (other.getVolumeType() == BV_TYPE_SPHERE) {
            const BoundingSphere& otherSphere = (const BoundingSphere&) other;

            real distance = (getCenterVector() - otherSphere.getCenterVector()).dotProduct();
            real radii = (mRadius + otherSphere.getRadius()) * (mRadius + otherSphere.getRadius());

            //std::cout << "2. Distanz : " << distance << "     2. radius: " << radii << std::endl;
            
            if (distance > radii) {
                return 0;
            } else {
                //std::cout << "Kollision" << std::endl;
                return 1;
            }
        } else {
            Aabb thisAabb(getSurroundingAabbMin(), getSurroundingAabbMax());
            return
                thisAabb.collidesWith(
                    Aabb(other.getSurroundingAabbMin(),
                         other.getSurroundingAabbMax()));
        }
    }
    /*!
     * \overload
     *
     * This method creates a new BoundingVolume as a copy of \p copy.
     */
    BoundingVolume* BoundingVolume::createBoundingVolume(World* world, const BoundingVolume* copy, BvhNode* parent) {
        if (!copy) {
            return createBoundingVolume(world, parent);
        }

        if (copy->getVolumeType() != getCreateRigidBoundingVolumeType(world)) {
            std::stringstream errormessage;
            errormessage << "ERROR: requested a copy of BV type "
                    << copy->getVolumeType()
                    << ", but expected type " << getCreateRigidBoundingVolumeType(world)
                    << std::endl;
            throw TypeMismatchException(errormessage.str());
        }

        BoundingVolume* bv = 0;
        switch (getCreateRigidBoundingVolumeType(world)) {
            case BV_TYPE_AABB:
                bv = new Aabb(*static_cast<const Aabb*>(copy));
                break;
            case BV_TYPE_KDOP:
                bv = new Kdop(*static_cast<const Kdop*>(copy));
                break;
            case BV_TYPE_SPHERE:
                bv = new BoundingSphere(*static_cast<const BoundingSphere*>(copy));
                break;
            case BV_TYPE_OBB:
                bv = new Obb(*static_cast<const Obb*>(copy));
                break;
            default:
                // TODO: exception!!
                std::cerr << dc_funcinfo << "FATAL ERROR: bounding volume type " << getCreateRigidBoundingVolumeType(world) << " not supported" << std::endl;
                exit(1);
                return 0;
        }
        bv->setHierarchyNode(parent);
        return bv;
    }
Exemple #10
0
	bool EDBVH::Collide(const BoundingVolume& boundingVolume, unsigned int& triIndex, EDCollision::Contact* contact)
	{
		Aabb bvAabb = boundingVolume.GetAabb();

		EDCollision::Contact newContact;
		newContact.numPoints = 0;
		newContact.PenetrationDepth = -FLT_MAX;

		BVtoBVH( boundingVolume, bvAabb, rootPtr, this, newContact, triIndex );

		if( newContact.PenetrationDepth > 0.0f )
		{
			if( contact )
				*contact = newContact;

			return true;
		}

		return false;
	}
Exemple #11
0
void Physics::collideTestWithTiles(CollidableObject *c,TiledLayer *tL, list<Collision*> *collisions)
{
	BoundingVolume *bv = c->getBoundingVolume();
	float toRight= bv->getWidth()/2;
	float toBottom = bv->getHeight()/2;

	PhysicalProperties *pp = c->getPhysicalProperties();
	float x = pp->getX()+bv->getX();
	float y = pp->getY()+bv->getY();
	float xVel = pp->getVelocityX();
	float yVel = pp->getVelocityY();
	float minX = x - toRight;
	float maxX = x + toRight;
	float minY = y - toBottom;
	float maxY = y + toBottom;

	if(xVel > 0)
		maxX += xVel;
	else
		minX += xVel;
	if(yVel > 0)
		maxY += yVel;
	else
		minY += yVel;

	 int tW = tL->getTileWidth();
	 int tH = tL->getTileHeight();

	int firstCol = minX/tW;
	int lastCol = maxX/tW;
	int firstRow = minY/tH;
	int lastRow = maxY/tH;

	if(firstCol < 0)
		firstCol = 0;
	if(firstRow < 0)
		firstRow = 0;
	if(lastCol >= tL->getColumns())
		lastCol = tL->getColumns() - 1;
	if(lastRow >= tL->getRows())
		lastRow = tL->getRows() - 1;

	for(int i = firstRow; i <= lastRow; i++)
	{
		for(int j = firstCol; j <= lastCol; j++)
		{
			Tile* current = tL->getTile(i,j);
			if(current->collidable == true)
			{
				if( !( (i+1)*tH < minY || i*tH > maxY || (j+1)*tW < minX || j*tW > maxX)  )
				{
					CollidableObject* tileCO = coStack[coStackCounter];
					coStackCounter --;
					BoundingVolume *bv = tileCO->getBoundingVolume();
					bv->setWidth(tW);
					bv->setHeight(tH);
					bv->setX(tW/2);
					bv->setY(tW/2);
					pp = tileCO->getPhysicalProperties();
					pp->setPosition(j*tW,i*tH);
					

					/*
					Collision* currentCollision = collisionStack.top();
					collisionStack.pop();*/
					Collision* currentCollision = collisionStack[collisionStackCounter];
					collisionStackCounter --;


					currentCollision->setCO1(c);
					currentCollision->setCO2(tileCO);
					currentCollision->calculateTimes();

					collisions->push_back(currentCollision);
				}
			}
		}
	}
	
}
Exemple #12
0
//----------------------------------------------------------------------------
Bool RenderText::Append(const Char* pText, Float x, Float y)
{
	if (!pText)
	{
		return true;
	}

	VertexBuffer* pVertexBuffer = GetMesh()->GetVertexBuffer();
	WIRE_ASSERT(pVertexBuffer && pVertexBuffer->GetAttributes().HasTCoord());
	const UInt offset = GetMesh()->GetIndexCount()/6;

	const UInt maxLength = pVertexBuffer->GetQuantity() / 4;
	UInt indexCount = 0;

	BoundingVolume* pModelBound = GetMesh()->GetModelBound();
	WIRE_ASSERT(pModelBound);
	Vector2F min(System::MAX_FLOAT, System::MAX_FLOAT);
	Vector2F max(System::MIN_FLOAT, System::MIN_FLOAT);
	Float radius = pModelBound->GetRadius();
	Vector3F center3 = pModelBound->GetCenter();
	if (radius != 0)
	{
		min = Vector2F(center3.X() - radius, center3.Y() - radius);
		max = Vector2F(center3.X() + radius, center3.Y() + radius);
	}

	for (UInt j = 0; pText[j]; j++)
	{
		if ((offset+indexCount) >= maxLength)
		{
			break;
		}

		UInt c = static_cast<UInt>(pText[j]);
		if (c == ' ')
		{
			x+= mWhitespaceWidth;
			continue;
		}

		if (c >= mCharSizes.GetQuantity())		
		{
			return false;
		}

		UInt i = (indexCount + offset) * 4;
		Float cWidth = mCharSizes[c].X();
		Float cHeight = mCharSizes[c].Y();
		Float cStride = mCharSizes[c].Z();
		if ((x+cStride) >= mLineWidth || c == '\n')
		{
			x = 0.0F;
			y -= mFontHeight;

			if (c == '\n')
			{
				continue;
			}
		}

		Float cy = y - mCharSizes[c].W();
		const Float x1 = x + cWidth;
		const Float cy1 = cy + cHeight;

		min.X() = min.X() > x ? x : min.X();
		max.X() = max.X() < x1 ? x1 : max.X();
		min.Y() = min.Y() > cy1 ? cy : min.Y();
		max.Y() = max.Y() < cy1 ? cy1 : max.Y();

		pVertexBuffer->Position3(i) = Vector3F(x, cy1, 0);
		pVertexBuffer->Color4(i) = mColor;
		pVertexBuffer->Position3(i+1) = Vector3F(x1, cy1, 0);
		pVertexBuffer->Color4(i+1) = mColor;
		pVertexBuffer->Position3(i+2) = Vector3F(x1, cy, 0);
		pVertexBuffer->Color4(i+2) = mColor;
		pVertexBuffer->Position3(i+3) = Vector3F(x, cy, 0);
		pVertexBuffer->Color4(i+3) = mColor;

		UInt c4 = c*4;
		pVertexBuffer->TCoord2(i) = mUvs[c4];
		pVertexBuffer->TCoord2(i+1) = mUvs[c4+1];
		pVertexBuffer->TCoord2(i+2) = mUvs[c4+2];
		pVertexBuffer->TCoord2(i+3) = mUvs[c4+3];

		x+= cStride;
		indexCount++;
	}

	GetMesh()->SetIndexCount(GetMesh()->GetIndexCount() + indexCount*6);
	mIsPdrBufferOutOfDate = true;

	Vector2F center((max.X()+min.X()) * 0.5F, (max.Y()+min.Y()) * 0.5F);
	pModelBound->SetCenter(Vector3F(center.X(), center.Y(), 0));
	pModelBound->SetRadius((center - min).Length());

	mPenX = x;
	mPenY = y;

	return true;
}
Exemple #13
0
/*
 * expand the volume by the incoming volume
 */
void BoundingVolume::expand(const BoundingVolume &volume) {
    expand(volume.min_corner());
    expand(volume.max_corner());
}
Exemple #14
0
Plane
findPlane(Axis a, BoundingVolume const &bv)
{
    int off{ 0 };
    int smallest{ std::numeric_limits<int>::max() };
    Vec3 min{ bv.min() };
    Vec3 max{ bv.min() + bv.extent() };

    // move candidate plane along axis
    switch (a)
    {
    case Axis::X:   
    {
        svt::accum_delta next_offset(min.x, svt::delta.x);
        int pp{ next_offset() };
        while (pp < max.x) {
            int diff{ 
                diffSides(
                    min, 
                    { min.x+pp, max.y, max.z },
                    { min.x+pp, min.y, min.z },
                    max
                ) };

            std::cout << "X pp: " << pp << " diff: " << diff << "\n-----\n" ;
            //TODO: handle diff==smallest separately
            if (diff <= smallest) {
                smallest = diff;
                off = pp;
            }
            pp = next_offset();
        } //for

        return Plane{ { min.x + off, min.y, min.z },
                      { min.x + off, max.y, max.z } };
    }

    case Axis::Y:   
    {
        svt::accum_delta next_offset(min.y, svt::delta.y);
        int pp{ next_offset() };
        while(pp < max.y) {
            int diff{
                diffSides( 
                    min, 
                    { max.x, min.y+pp, max.z },
                    { min.x, min.y+pp, min.z },
                    max 
                ) };

            std::cout << "Y pp: " << pp << " diff: " << diff << "\n-----\n" ;
            //TODO: handle diff==smallest separately
            if (diff <= smallest) {
                smallest = diff;
                off = pp;
            }
            pp = next_offset();
        } //for

        return Plane{ { min.x, min.y + off, min.z },
                      { max.x, min.y + off, max.z } };
    }

    case Axis::Z:   
    {
        svt::accum_delta next_offset(min.z, svt::delta.z);
        int pp{ next_offset() };
        while (pp < max.z) {
            int diff{
                diffSides(
                    min, 
                    { max.x, max.y, min.z+pp },
                    { min.x, min.y, min.z+pp },
                    max
                ) };

            std::cout << "Z pp: " << pp << " diff: " << diff << "\n-----\n" ;
            //TODO: handle diff==smallest separately
            if (diff <= smallest) {
                smallest = diff;
                off = pp;
            }
            pp = next_offset();
        } //for

        return Plane{ { min.x, min.y, min.z + off },
                      { max.x, max.y, min.z + off } };
    }

    default: break;
    }

    return Plane{ { -1,-1,-1 }, { -1,-1,-1 } };  // The most interesting case.
}
void MeshSkin::computeBounds()
{
    // Find the offset of the blend indices and blend weights within the mesh vertices
    int blendIndexOffset = -1;
    int blendWeightOffset = -1;
    for (unsigned int i = 0, count = _mesh->getVertexElementCount(); i < count; ++i)
    {
        const VertexElement& e = _mesh->getVertexElement(i);
        switch (e.usage)
        {
        case BLENDINDICES:
            blendIndexOffset = i;
            break;
        case BLENDWEIGHTS:
            blendWeightOffset = i;
            break;
        }
    }
    if (blendIndexOffset == -1 || blendWeightOffset == -1)
    {
        // Need blend indices and blend weights to calculate skinned bounding volume
        return;
    }

    LOG(2, "Computing bounds for skin of mesh: %s\n", _mesh->getId().c_str());

    // Get the root joint
	if (_joints.size() == 0)
		return;
    Node* rootJoint = _joints[0];
    Node* parent = rootJoint->getParent();
    while (parent)
    {
        // Is this parent in the list of joints that form the skeleton?
        // If not, then it's simply a parent node to the root joint
        if (find(_joints.begin(), _joints.end(), parent) != _joints.end())
        {
            rootJoint = parent;
        }
        parent = parent->getParent();
    }

    // If the root joint has a parent node, temporarily detach it so that its transform is
    // not included in the bounding volume calculation below
    Node* rootJointParent = rootJoint->getParent();
    if (rootJointParent)
    {
        rootJointParent->removeChild(rootJoint);
    }

    unsigned int jointCount = _joints.size();
    unsigned int vertexCount = _mesh->getVertexCount();

    LOG(3, "  %u joints found.\n", jointCount);

    std::vector<AnimationChannel*> channels;
    std::vector<Node*> channelTargets;
    std::vector<Curve*> curves;
    std::vector<Vector3> vertices;
    _jointBounds.resize(jointCount);

    // Construct a list of all animation channels that target the joints affecting this mesh skin
    LOG(3, "  Collecting animations...\n");
    LOG(3, "  0%%\r");
    for (unsigned int i = 0; i < jointCount; ++i)
    {
        Node* joint = _joints[i];

        // Find all animations that target this joint
        Animations* animations = GPBFile::getInstance()->getAnimations();
        for (unsigned int j = 0, animationCount = animations->getAnimationCount(); j < animationCount; ++j)
        {
            Animation* animation = animations->getAnimation(j);
            for (unsigned int k = 0, channelCount = animation->getAnimationChannelCount(); k < channelCount; ++k)
            {
                AnimationChannel* channel = animation->getAnimationChannel(k);
                if (channel->getTargetId() == joint->getId())
                {
                    if (find(channels.begin(), channels.end(), channel) == channels.end())
                    {
                        channels.push_back(channel);
                        channelTargets.push_back(joint);
                    }
                }
            }
        }

        // Calculate the local bounding volume for this joint
        vertices.clear();
        BoundingVolume jointBounds;
        jointBounds.min.set(FLT_MAX, FLT_MAX, FLT_MAX);
        jointBounds.max.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
        for (unsigned int j = 0; j < vertexCount; ++j)
        {
            const Vertex& v = _mesh->getVertex(j);

            if ((v.blendIndices.x == i && !ISZERO(v.blendWeights.x)) ||
                (v.blendIndices.y == i && !ISZERO(v.blendWeights.y)) ||
                (v.blendIndices.z == i && !ISZERO(v.blendWeights.z)) ||
                (v.blendIndices.w == i && !ISZERO(v.blendWeights.w)))
            {
                vertices.push_back(v.position);
                // Update box min/max
                if (v.position.x < jointBounds.min.x)
                    jointBounds.min.x = v.position.x;
                if (v.position.y < jointBounds.min.y)
                    jointBounds.min.y = v.position.y;
                if (v.position.z < jointBounds.min.z)
                    jointBounds.min.z = v.position.z;
                if (v.position.x > jointBounds.max.x)
                    jointBounds.max.x = v.position.x;
                if (v.position.y > jointBounds.max.y)
                    jointBounds.max.y = v.position.y;
                if (v.position.z > jointBounds.max.z)
                    jointBounds.max.z = v.position.z;
            }
        }
        if (vertices.size() > 0)
        {
            // Compute center point
            Vector3::add(jointBounds.min, jointBounds.max, &jointBounds.center);
            jointBounds.center.scale(0.5f);
            // Compute radius
            for (unsigned int j = 0, jointVertexCount = vertices.size(); j < jointVertexCount; ++j)
            {
                float d = jointBounds.center.distanceSquared(vertices[j]);
                if (d > jointBounds.radius)
                    jointBounds.radius = d;
            }
            jointBounds.radius = sqrt(jointBounds.radius);
        }
        _jointBounds[i] = jointBounds;

        LOG(3, "  %d%%\r", (int)((float)(i+1) / (float)jointCount * 100.0f));
    }
    LOG(3, "\n");

    unsigned int channelCount = channels.size();

    // Create a Curve for each animation channel
    float maxDuration = 0.0f;
    LOG(3, "  Building animation curves...\n");
    LOG(3, "  0%%\r");
    for (unsigned int i = 0; i < channelCount; ++i)
    {
        AnimationChannel* channel = channels[i];

        const std::vector<float>& keyTimes = channel->getKeyTimes();
        unsigned int keyCount = keyTimes.size();
        if (keyCount == 0)
            continue;

        // Create a curve for this animation channel
        Curve* curve = NULL;
        switch (channel->getTargetAttribute())
        {
        case Transform::ANIMATE_SCALE_ROTATE_TRANSLATE:
            curve = new Curve(keyCount, 10);
            curve->setQuaternionOffset(3);
            break;
        }
        if (curve == NULL)
        {
            // Unsupported/not implemented curve type 
            continue;
        }

        // Copy key values into a temporary array
        unsigned int keyValuesCount = channel->getKeyValues().size();
        float* keyValues = new float[keyValuesCount];
        for (unsigned int j = 0; j < keyValuesCount; ++j)
            keyValues[j] = channel->getKeyValues()[j];

        // Determine animation duration
        float startTime = keyTimes[0];
        float duration = keyTimes[keyCount-1] - startTime;
        if (duration > maxDuration)
            maxDuration = duration;

        if (duration > 0.0f)
        {
            // Set curve points
            float* keyValuesPtr = keyValues;
            for (unsigned int j = 0; j < keyCount; ++j)
            {
                // Store time normalized, between 0-1
                float t = (keyTimes[j] - startTime) / duration;

                // Set the curve point
                // TODO: Handle other interpolation types
                curve->setPoint(j, t, keyValuesPtr, gameplay::Curve::LINEAR);

                // Move to the next point on the curve
                keyValuesPtr += curve->getComponentCount();
            }
            curves.push_back(curve);
        }

        delete[] keyValues;
        keyValues = NULL;

        LOG(3, "  %d%%\r", (int)((float)(i+1) / (float)channelCount * 100.0f));
    }
    LOG(3, "\n");

    // Compute a total combined bounding volume for the MeshSkin that contains all possible
    // vertex positions for all animations targeting the skin. This rough approximation allows
    // us to store a volume that can be used for rough intersection tests (such as for visibility
    // determination) efficiently at runtime.

    // Backup existing node transforms so we can restore them when we are finished
    Matrix* oldTransforms = new Matrix[jointCount];
    for (unsigned int i = 0; i < jointCount; ++i)
    {
        memcpy(oldTransforms[i].m, _joints[i]->getTransformMatrix().m, 16 * sizeof(float));
    }

    float time = 0.0f;
    float srt[10];
    Matrix temp;
    Matrix* jointTransforms = new Matrix[jointCount];
    _mesh->bounds.min.set(FLT_MAX, FLT_MAX, FLT_MAX);
    _mesh->bounds.max.set(-FLT_MAX, -FLT_MAX, -FLT_MAX);
    _mesh->bounds.center.set(0, 0, 0);
    _mesh->bounds.radius = 0;
    Vector3 skinnedPos;
    Vector3 tempPos;
    LOG(3, "  Evaluating joints...\n");
    LOG(3, "  0%%\r");
    BoundingVolume finalBounds;
    while (time <= maxDuration)
    {
        // Evaluate joint transforms at this time interval
        for (unsigned int i = 0, curveCount = curves.size(); i < curveCount; ++i)
        {
            Node* joint = channelTargets[i];
            Curve* curve = curves[i];

            // Evalulate the curve at this time to get the new value
            float tn = time / maxDuration;
            if (tn > 1.0f)
                tn = 1.0f;
            curve->evaluate(tn, srt);

            // Update the joint's local transform
            Matrix::createTranslation(srt[7], srt[8], srt[9], temp.m);
            temp.rotate(*((Quaternion*)&srt[3]));
            temp.scale(srt[0], srt[1], srt[2]);
            joint->setTransformMatrix(temp.m);
        }

        // Store the final matrix pallette of resovled world space joint matrices
        std::vector<Matrix>::const_iterator bindPoseItr = _bindPoses.begin();
        for (unsigned int i = 0; i < jointCount; ++i, bindPoseItr++)
        {
            BoundingVolume bounds = _jointBounds[i];
            if (ISZERO(bounds.radius))
                continue;

            Matrix& m = jointTransforms[i];
            Matrix::multiply(_joints[i]->getWorldMatrix().m, bindPoseItr->m, m.m);
            Matrix::multiply(m.m, _bindShape, m.m);

            // Get a world-space bounding volume for this joint
            bounds.transform(m);
            if (ISZERO(finalBounds.radius))
                finalBounds = bounds;
            else
                finalBounds.merge(bounds);
        }

        // Increment time by 1/30th of second (~ 33 ms)
        if (time < maxDuration && (time + 33.0f) > maxDuration)
            time = maxDuration;
        else
            time += 33.0f;

        LOG(3, "  %d%%\r", (int)(time / maxDuration * 100.0f));
    }
    LOG(3, "\n");

    // Update the bounding sphere for the mesh
    _mesh->bounds = finalBounds;

    // Restore original joint transforms
    for (unsigned int i = 0; i < jointCount; ++i)
    {
        _joints[i]->setTransformMatrix(oldTransforms[i].m);
    }

    // Cleanup
    for (unsigned int i = 0, curveCount = curves.size(); i < curveCount; ++i)
    {
        delete curves[i];
    }
    delete[] oldTransforms;
    delete[] jointTransforms;

    // Restore removed joints
    if (rootJointParent)
    {
        rootJointParent->addChild(rootJoint);
    }
}
Exemple #16
0
int main(int argc, char* argv[]) {
  cout << "HELLO WORLD" << endl;
  //if (argc == 2) return -1;

  int currentArg = 1;

  ProgramSettings* settings = new ProgramSettings();

  // take in arguements and settings
  while (currentArg != argc) {
    char* arg = argv[currentArg];

    if (strcmp(arg, "--in") == 0) {
      settings->mesh = string(argv[++currentArg]);
    } else if (strcmp(arg, "--out") == 0) {
      cout << "FOUND OUTPUT:: " << endl;
      settings->outputMesh = string(argv[++currentArg]);
    } else if (strcmp(arg, "--config") == 0) {
      settings->config = string(argv[++currentArg]);
      cout << "FOUND FORCE FILE" << endl;
    } else if (strcmp(arg, "--force") == 0) {
      settings->outputForce = string(argv[++currentArg]);
    } else if (strcmp(arg, "--corner") == 0) {
      settings->corner = atoi(argv[++currentArg]);
    } else if (strcmp(arg, "--cubeAlign") == 0) {
      settings->needsAlignment = true;
      settings->cubeAlign = true;
      settings->depth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--topCubeAlign") == 0) {
      settings->needsAlignment = true;
      settings->topCubeAlign = true;
      settings->depth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--botCubeAlign") == 0) {
      settings->needsAlignment = true;
      settings->botCubeAlign = true;
      settings->depth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--rightCubeAlign") == 0) {
      settings->needsAlignment = true;
      settings->rightCubeAlign = true;
      settings->depth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--leftCubeAlign") == 0) {
      settings->needsAlignment = true;
      settings->leftCubeAlign = true;
      settings->depth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--frontCubeAlign") == 0) {
      settings->needsAlignment = true;
      settings->frontCubeAlign = true;
      settings->depth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--backCubeAlign") == 0) {
      settings->needsAlignment = true;
      settings->backCubeAlign = true;
      settings->depth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--maxForce") == 0) {
      settings->needsForce = true;
      cout << "FOUND MAX FORCE" << endl;
      settings->maxForce = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--constant") == 0) {
      settings->needsForce = true;
      settings->constantForce = true;
      settings->maxForce = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--impulse") == 0) {
      settings->needsForce = true;
      settings->impulseForce = true;
      settings->maxForce = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--bezierFile") == 0) {
      settings->bezierForce = true;
      settings->bezierForceFile = string(argv[++currentArg]);
    } else if (strcmp(arg, "--topCubeForce") == 0) {
      settings->topCubeForce = true;
      settings->forceDepth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--botCubeForce") == 0) {
      settings->botCubeForce = true;
      settings->forceDepth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--rightCubeForce") == 0) {
      settings->rightCubeForce = true;
      settings->forceDepth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--leftCubeForce") == 0) {
      settings->leftCubeForce = true;
      settings->forceDepth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--frontCubeForce") == 0) {
      settings->frontCubeForce = true;
      settings->forceDepth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--backCubeForce") == 0) {
      settings->backCubeForce = true;
      settings->forceDepth = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--domainMinX") == 0) {
      settings->domainForce = true;
      settings->domainX[0] = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--domainMaxX") == 0) {
      settings->domainForce = true;
      settings->domainX[1] = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--domainMinY") == 0) {
      settings->domainForce = true;
      settings->domainY[0] = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--domainMaxY") == 0) {
      settings->domainForce = true;
      settings->domainY[1] = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--domainMinZ") == 0) {
      settings->domainForce = true;
      settings->domainZ[0] = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--domainMaxZ") == 0) {
      settings->domainForce = true;
      settings->domainZ[1] = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--domainBezier") == 0) {
      settings->domainBezier = true;
    } else if (strcmp(arg, "--domainDirX") == 0) {
      settings->domainForce = true;
      settings->direction[0] = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--domainDirY") == 0) {
      settings->domainForce = true;
      settings->direction[1] = atof(argv[++currentArg]);
    } else if (strcmp(arg, "--domainDirZ") == 0) {
      settings->domainForce = true;
      settings->direction[2] = atof(argv[++currentArg]);
    }

    currentArg++;
  }

  // stages of the program
  // read in all the verts and faces
  cout << "Making Mesh" << endl;
  Mesh* mesh = new Mesh(settings->mesh);
  cout << "Made Mesh" << endl;
  // calculate the bounding shape based on the verts
  BoundingVolume* volume = 0x0;
  //if (settings->needsAlignment) {
  if (true) {
    // initialize bounding volume
    //if (settings->cubeAlign) volume = mesh->createCubeBound(settings->depth);
    //else if (settings->topCubeAlign) volume = mesh->createTopBound(settings->depth);
    //else if (settings->botCubeAlign) volume = mesh->createBotBound(settings->depth);
    //else if (settings->rightCubeAlign) volume = mesh->createRightBound(settings->depth);
    //else if (settings->leftCubeAlign) volume = mesh->createLeftBound(settings->depth);
    //else if (settings->frontCubeAlign) volume = mesh->createFrontBound(settings->depth);
    //else if (settings->backCubeAlign) volume = mesh->createBackBound(settings->depth);
    cout << "Creating Fixed Volume" << endl;
    volume = mesh->createLeftBound(0.0);
    cout << "Created Fixed Volume" << endl;
    // translate the object to the origin
    //vec3 newOrigin = volume->getNewOrigin(settings->corner);
    cout << "Getting Origin" << endl;
    dvec3 newOrigin = volume->getNewOrigin(1);
    cout << "ORIGIN:: " << newOrigin[0] << " " << newOrigin[1] << " " << newOrigin[2] << endl;
    //mesh->translate(-newOrigin[0], -newOrigin[1], -newOrigin[2]);
    mesh->translate(-mesh->xExtremes[0], -mesh->yExtremes[1], -mesh->zExtremes[1]);
    cout << "Making Fixed" << endl;
    volume->makeFixed();
  }
  // calculate the force bounds and calculate all forces within it
  BoundingVolume* forceVolume = 0x0;
  //if (settings->needsForce
  cout << "Calculating Force Volume" << endl;
  if (true)
  {
    // initialize force bounding volume
    //if (settings->topCubeForce) forceVolume = mesh->createTopBound(settings->forceDepth);
    //else if (settings->botCubeForce) forceVolume = mesh->createBotBound(settings->forceDepth);
    //else if (settings->rightCubeForce) forceVolume = mesh->createRightBound(settings->forceDepth);
    //else if (settings->leftCubeForce) forceVolume = mesh->createLeftBound(settings->forceDepth);
    //else if (settings->frontCubeForce) forceVolume = mesh->createFrontBound(settings->forceDepth);
    //else if (settings->backCubeForce) forceVolume = mesh->createBackBound(settings->forceDepth);
    cout << "FIXED BOUNDS :: " << volume->verts.size() << endl;
    cout << "Creating Line Bound" << endl;
    cout << "MESH XBNDS :: " << mesh->xBnds()[0] << " " << mesh->xBnds()[1] << endl;
    cout << "MESH YBNDS :: " << mesh->yBnds()[0] << " " << mesh->yBnds()[1] << endl;
    cout << "MESH ZBNDS :: " << mesh->zBnds()[0] << " " << mesh->zBnds()[1] << endl;
    forceVolume = mesh->createLineBound(mesh->xBnds()[1], 0.0, mesh->zBnds()[1], false, true, false);
    // distribute force per vert in volume
    cout << "Distributing Max Force" << endl;
    cout << "MAX FORCE :: " << settings->maxForce << endl;
    forceVolume->distributeForce(settings->maxForce);
  }
  // print all verts with forces into the data file
  cout << "Writing All Files" << endl;
  mesh->writeToFile(settings);
  cout << "Cleaning Up" << endl;
  // clean up
  if (forceVolume) delete forceVolume;
  if (volume) delete volume;
  delete mesh;
  delete settings;
}
Exemple #17
0
void Physics::resolveCollision(Game* game, Collision* currentCollision)
{
	CollidableObject* co1 = currentCollision->getCO1();
	CollidableObject* co2 = currentCollision->getCO2();
	PhysicalProperties* pp;
	BoundingVolume* bv;
	AnimatedSprite* player = game->getGSM()->getSpriteManager()->getPlayer();
	
	if(co2->isStaticObject() == true)
	{
		pp = co2->getPhysicalProperties();
		bv = co2->getBoundingVolume();
		float tX = pp->getX();
		float tY = pp->getY();
		float tXR = tX + bv->getWidth();
		float tYB = tY + bv->getHeight();

		pp = co1->getPhysicalProperties();
		bv = co1->getBoundingVolume();
		float x = pp->getX() + bv->getX() - (bv->getWidth()/2);
		float y = pp->getY() + bv->getY() - (bv->getHeight()/2);
		float xR = x+bv->getWidth();
		float yB = y+bv->getHeight();
		//pp->setVelocity(0, 0);

		/*if(x < tX)
			pp->setX(pp->getX() - 0.1);
		if(x > tX)
			pp->setX(pp->getX() + 0.1);*/
		if(x >= tXR)
		{
			pp->setX(pp->getX() + 0.1);
			pp->setVelocity(0, pp->getVelocityY());
		}
		if(xR <= tX)
		{
			pp->setX(pp->getX() - 0.1);
			pp->setVelocity(0, pp->getVelocityY());
		}
		if(y >= tYB)
		{
			pp->setY(pp->getY() + 0.1);
			pp->setVelocity(pp->getVelocityX(), 0);
		}
		if(yB <= tY)
		{
			pp->setY(pp->getY() - 0.1);
				if(co1 == player)
				{
					pp->setJumped(false);
					pp->setDoubleJumped(false);
					pp->setStunned(false);
				}
				pp->setVelocity(pp->getVelocityX(), 0);
		}

		//if(currentCollision->getTOC() == currentCollision->getSYC())
		//{
		//	/*if(pp->getVelocityY() < 0)
		//	{
		//		pp->setY(pp->getY() + 0.1);
		//	}
		//	else
		//	{
		//		pp->setY(pp->getY() - 0.1);
		//		if(co1 == player)
		//		{
		//			pp->setJumped(false);s
		//			pp->setDoubleJumped(false);
		//			if(player->getCurrentState().compare(L"JUMP_STATE") == 0 
		//				|| player->getCurrentState().compare(L"JUMPL_STATE") == 0)
		//			{
		//				player->setCurrentState(L"IDLE_STATE");
		//			}
		//		}
		//	}*/
		//	if(y < tY)
		//	{
		//		pp->setY(pp->getY() - 0.1);
		//		if(co1 == player)
		//		{
		//			pp->setJumped(false);
		//			pp->setDoubleJumped(false);
		//			/*if(player->getCurrentState().compare(L"JUMP_STATE") == 0 
		//				|| player->getCurrentState().compare(L"JUMPL_STATE") == 0)
		//			{
		//				player->setCurrentState(L"IDLE_STATE");
		//			}*/
		//		}
		//	}
		//	if(y > tY)
		//	{
		//		pp->setY(pp->getY() + 0.1);
		//		
		//	}
		//	pp->setVelocity(pp->getVelocityX(), 0);
		//	
		//	
		//}
		//else if(currentCollision->getTOC() == currentCollision->getSXC())
		//{
		//	/*if(pp->getVelocityX() < 0)
		//	{
		//		pp->setX(pp->getX() + 0.1);
		//	}
		//	else
		//	{
		//		pp->setX(pp->getX() - 0.1);
		//	}*/
		//	/*if(x < tX)
		//	pp->setX(pp->getX() - 0.1);
		//	if(x > tX)
		//	pp->setX(pp->getX() + 0.1);*/
		//	pp->setVelocity(0, pp->getVelocityY());
		//}
		//else
		//{
		//	/*if(pp->getVelocityY() < 0)
		//		pp->setY(pp->getY() + 0.1);
		//	else
		//		pp->setY(pp->getY() - 0.1);

		//	if(pp->getVelocityX() < 0)
		//		pp->setX(pp->getX() + 0.1);
		//	else
		//		pp->setX(pp->getX() - 0.1);*/

		//	pp->setVelocity(0,0);
		//}
	}
	else
	{

		pp = co1->getPhysicalProperties();
		bv = co1->getBoundingVolume();
		float x = pp->getX()+ bv->getX() - (bv->getWidth()/2);
		float y = pp->getY()+ bv->getY() - (bv->getHeight()/2);
		float xR = x + bv->getWidth();
		float yB = y + bv->getHeight();

		PhysicalProperties* p2 = co2->getPhysicalProperties();
		bv = co2->getBoundingVolume();
		float tX = p2->getX() + bv->getX() - (bv->getWidth()/2);
		float tY = p2->getY() + bv->getY() - (bv->getHeight()/2);
		float tXR = tX+bv->getWidth();
		float tYB = tY+bv->getHeight();
		//pp->setVelocity(0, 0);

		if(x >= tXR)
		{
			if(co1->isMobile())
				pp->setX(pp->getX() + 0.1);
			if(co2->isMobile())
				p2->setX(p2->getX() - 0.1);

		}
		if(xR <= tX)
		{
			if(co1->isMobile())
				pp->setX(pp->getX() - 0.1);
			if(co2->isMobile())
				p2->setX(p2->getX() + 0.1);
		}
		if(y >= tYB)
		{
			if(co1->isMobile())
				pp->setY(pp->getY() + 0.1);
			if(co2->isMobile())
				p2->setY(p2->getY() - 0.1);
		}
		if(yB <= tY)
		{
			if(co1->isMobile())
				pp->setY(pp->getY() - 0.1);
			if(co2->isMobile())
				p2->setY(p2->getY() + 0.1);
		}
	}
}