void NxMeshManager::SetPivotTransform( Ogre::MeshPtr mesh, const Nx::Vector3 & Position, const Nx::Quaternion & Rotation, const Nx::Vector3 & Scale )
{
	//from mesh magick / mit licence
	 Nx::Matrix4 transform = Nx::Matrix4::IDENTITY;
	 Nx::Vector3 translate =  Nx::Vector3::ZERO;
	// Apply current transform to the mesh, to get the bounding box to
	// base te translation on.
	AxisAlignedBox aabb = getMeshAabb( mesh, transform);
	//if (alignment == "left")
	//{
	// 	translate = Vector3(-aabb.getMinimum().x, 0, 0);
	//}
	//else if (alignment == "center")
	//{
	//	translate = Vector3(-aabb.getCenter().x, 0, 0);
	//}
	//else if (alignment == "right")
	//{
	//	translate = Vector3(-aabb.getMaximum().x, 0, 0);
	//}

	//Position .. only support pivot down / centered
	//translate = Vector3(0, -aabb.getMinimum().y, 0);// pivot down

	translate = Position;
	 
	transform = Nx::Matrix4::getTrans(translate) * transform;

	//rotation
	transform = Nx::Matrix4(Rotation) * transform;

	//scale
	transform = Nx::Matrix4::getScale(Scale) * transform;

    // Check whether we have to flip vertex winding.
    // We do have to, if we changed our right hand base.
    // We can test it by using the cross product from X and Y and see, if it is a non-negative
    // projection on Z. Actually it should be exactly Z, as we don't do non-uniform scaling yet,
    // but the test is cheap either way.
    Nx::Matrix3 m3;
    transform.extract3x3Matrix(m3);

    if (m3.GetColumn(0).crossProduct(m3.GetColumn(1)).dotProduct(m3.GetColumn(2)) < 0)
    {
		LogMsg("SetPivotPosition : Flipping vertex winding ... "   );
    	mFlipVertexWinding = true;
    }

	//mTransform = transform;

	NxMat4toOgre( mTransform, transform ) ;


	mBoundingBox.setNull();

    if( mesh->sharedVertexData != NULL)
    {
        processVertexData( mesh->sharedVertexData);
	}else
	{
		LogMsg("mesh->sharedVertexData NULL");
	}

    for( int i = 0; i < mesh->getNumSubMeshes(); i++ )
    {
        SubMesh* submesh = mesh->getSubMesh(i);
        if( submesh->vertexData != NULL )
        {
			LogMsg("SetPivotPosition : Processing vertex data ... "   );
            processVertexData(submesh->vertexData);
		}else
		{
			LogMsg("submesh->vertexData NULL");
		}

        if (submesh->indexData != NULL)
        {
			LogMsg("SetPivotPosition : Processing Index data .."   );
        	processIndexData(submesh->indexData);
		}else
		{
			LogMsg("submesh->indexData NULL");
		}
    }

	//process pose
    for( unsigned short i = 0; i < mesh->getPoseCount(); ++i )
    {
		Ogre::Pose * pose =  mesh->getPose(i);
		Ogre::Matrix3 m3x3;
		mTransform.extract3x3Matrix(m3x3);

		Pose::VertexOffsetIterator it = pose->getVertexOffsetIterator();
		while (it.hasMoreElements()) {
			Ogre::Vector3 offset = it.peekNextValue();
			Ogre::Vector3 newOffset = m3x3 * offset;
			*it.peekNextValuePtr() = newOffset;
			it.moveNext();
		}
    }

	mesh->_setBounds( mBoundingBox, false );
  
}
Esempio n. 2
0
std::pair<bool, Real>
rayCollide(const Ogre::Ray& ray,
           Ogre::MovableObject* movable,
           bool accurate,
           CullingMode cullingMode,
           bool allowAnimable)
{
    // Get local space axis aligned bounding box
    const Ogre::AxisAlignedBox& aabb = movable->getBoundingBox();

    // Matrix4 to transform local space to world space
    const Ogre::Matrix4& localToWorld = movable->_getParentNodeFullTransform();

    // Matrix4 to transform world space to local space
    Ogre::Matrix4 worldToLocal = localToWorld.inverse();

    // Matrix3 to transform world space normal to local space
    Ogre::Matrix3 worldToLocalN;
    worldToLocal.extract3x3Matrix(worldToLocalN);

    // Convert world space ray to local space ray
    // Note:
    //      By preserving the scale between world space and local space of the
    //      direction, we don't need to recalculate the distance later.
    Ogre::Ray localRay;
    localRay.setOrigin(worldToLocal * ray.getOrigin());
    localRay.setDirection(worldToLocalN * ray.getDirection());

    // Intersect with axis aligned bounding box, but because we transformed
    // ray to local space of the bounding box, so this test just like test
    // with oriented bounding box.
    std::pair<bool, Real> ret = localRay.intersects(aabb);

    // Do accurate test if hitted bounding box and user required.
    if (ret.first && accurate)
    {
        if (movable->getMovableType() == Ogre::EntityFactory::FACTORY_TYPE_NAME ||
            allowAnimable && movable->getMovableType() == Ogre::AutoAnimationEntityFactory::FACTORY_TYPE_NAME)
        {
            Ogre::Entity* entity = static_cast<Ogre::Entity*>(movable);
            if (!entity->_isAnimated())
            {
                // Static entity

                // Get the entity mesh
                const Ogre::MeshPtr& mesh = entity->getMesh();

                // Get the collision mode
                CollisionModelPtr collisionModel = CollisionModelManager::getSingleton().getCollisionModel(mesh);

                ret = doPicking(localRay, *collisionModel, cullingMode);
            }
            else if (allowAnimable)
            {
                // Animation entity

                bool addedSoftwareAnimation = false;
                if (entity->getSoftwareAnimationRequests() <= 0)
                {
                    entity->addSoftwareAnimationRequest(false);
                    entity->_updateAnimation();
                    addedSoftwareAnimation = true;
                }

                CollisionModel collisionModel;
                collisionModel.addEntity(entity);
                collisionModel.build(true);

                ret = doPicking(localRay, collisionModel, cullingMode);

                if (addedSoftwareAnimation)
                {
                    entity->removeSoftwareAnimationRequest(false);
                }
            }
        }
    }

    return ret;
}