Пример #1
0
void CameraOrbit(KFbxScene* pScene, KFbxVector4 lOrigCamPos, double OrigRoll, int dX, int dY)
{
	KFbxCamera* lCamera = GetCurrentCamera(pScene);
	if (!lCamera) return;
	KFbxGlobalCameraSettings& lGlobalCameraSettings = pScene->GlobalCameraSettings();
	if (lCamera != lGlobalCameraSettings.GetCameraProducerPerspective()) return;
	if (lCamera->LockMode.Get()) return;
	if (dX == 0 && dY == 0) return;

	KFbxVector4 lRotationVector, lNewPosition, lCurPosition;
	KFbxXMatrix lRotation;
	KFbxVector4 lCenter = lCamera->InterestPosition.Get();

	KFbxVector4 lPosition = lCamera->Position.Get();
	lCurPosition = lPosition-lCenter;

	lNewPosition = lOrigCamPos-lCenter;

	int rotX;
	if (lNewPosition[2] == 0) {
		rotX = 90;
	} else {
		rotX = (int) (180.0* atan((double)lNewPosition[0]/(double)lNewPosition[2]) / 3.14159);
	}
	bool bRoll = (((int)OrigRoll % 360) != 0);
	if (   (lNewPosition[2] < 0 && !bRoll)
			|| (lNewPosition[2] > 0 && bRoll) ) {
		dY = -dY;
	}
	if (bRoll) dX = -dX;

	lRotationVector[1] = -rotX;
	lRotation.SetR(lRotationVector);
	lNewPosition = lRotation.MultT(lNewPosition);
	lRotationVector[1] = 0;
	lRotationVector[0] = dY;
	lRotation.SetR(lRotationVector);
	lNewPosition = lRotation.MultT(lNewPosition);
	lRotationVector[0] = 0;
	lRotationVector[1] = rotX;
	lRotation.SetR(lRotationVector);
	lNewPosition = lRotation.MultT(lNewPosition);
	lRotationVector[1] = -dX;
	lRotation.SetR(lRotationVector);
	lNewPosition = lRotation.MultT(lNewPosition);

	if (   lNewPosition[0]*lCurPosition[0] < 0 
			&& lNewPosition[2]*lCurPosition[2] < 0) {
		double lRoll = lCamera->Roll.Get();
		lRoll = 180.0-lRoll;
		lCamera->Roll.Set(lRoll);
	}

	lNewPosition = lNewPosition + lCenter;
	lCamera->Position.Set(lNewPosition);
}
// Get the geometry deformation local to a node. It is never inherited by the
// children.
KFbxXMatrix GetGeometry(KFbxNode* pNode) {
	KFbxVector4 lT, lR, lS;
	KFbxXMatrix lGeometry;

	lT = pNode->GetGeometricTranslation(KFbxNode::eSOURCE_SET);
	lR = pNode->GetGeometricRotation(KFbxNode::eSOURCE_SET);
	lS = pNode->GetGeometricScaling(KFbxNode::eSOURCE_SET);

	lGeometry.SetT(lT);
	lGeometry.SetR(lR);
	lGeometry.SetS(lS);

	return lGeometry;
}
Пример #3
0
        KFbxXMatrix FilmboxNode::GetGeometricTransform() const
        {
            KFbxXMatrix value;
            value.SetIdentity();

            if( m_node )
            {
                KFbxVector4 translation = m_node->GeometricTranslation.Get();
                KFbxVector4 rotation    = m_node->GeometricRotation.Get();
                KFbxVector4 scale       = m_node->GeometricScaling.Get();

                value.SetS( scale );
                value.SetR( rotation );
                value.SetT( translation );
            }

            return value;
        }
Пример #4
0
        KFbxXMatrix FilmboxNode::GetParentWorldTransform( int frame ) const
        {
            KFbxXMatrix value;
            value.SetIdentity();

            if( m_node )
            {
                KFbxNode* fbx_parent_node = m_node->GetParent();

                if( fbx_parent_node )
                {
                    MCE::FBX::FilmboxNode mce_parent_node( fbx_parent_node );
                    value = mce_parent_node.GetWorldTransform( frame );
                }
            }

            return value;
        }
Matrix FBXModel::convert(const KFbxXMatrix& matrix)
{
	Matrix m;

	for (int row = 0; row < 4; ++row)
		for (int col = 0; col < 4; ++col)
			m[row * 4 + col] = (float)matrix.Get(row, col);

	return m;
}
Пример #6
0
// Set the view to the current camera settings.
void SetCamera(KFbxScene* pScene, 
		KTime& pTime, 
		KFbxAnimLayer* pAnimLayer,
		KArrayTemplate<KFbxNode*>& pCameraArray)
{
	KFbxCamera* lCamera = GetCurrentCamera(pScene, pTime, pCameraArray);
	KFbxNode*   lCameraNode = lCamera ? lCamera->GetNode() : NULL;

	KFbxVector4 lEye(0,0,1);
	KFbxVector4 lCenter(0,0,0);
	KFbxVector4 lUp(0,1,0);
	KFbxVector4 lForward, lRight;

	if (lCamera)
	{
		lEye = lCamera->Position.Get();
		lUp = lCamera->UpVector.Get();
	}

	if (lCameraNode && lCameraNode->GetTarget())
	{
		lCenter = GetGlobalPosition(lCameraNode->GetTarget(), pTime).GetT();
	}
	else
	{
		if (!lCameraNode || IsProducerCamera(pScene, lCamera))
		{
			if (lCamera)
				lCenter = lCamera->InterestPosition.Get();
		}
		else
		{
			KFbxXMatrix lGlobalRotation;
			KFbxVector4 lRotationVector(GetGlobalPosition(lCameraNode, pTime).GetR());
			lGlobalRotation.SetR(lRotationVector);

			KFbxVector4 lInterestPosition(lCamera->InterestPosition.Get());
			KFbxVector4 lCameraGlobalPosition(GetGlobalPosition(lCameraNode, pTime).GetT());
			double      lLength = (KFbxVector4(lInterestPosition - lCameraGlobalPosition).Length());

			lRotationVector = KFbxVector4(1.0,0,0);
			lCenter = lGlobalRotation.MultT(lRotationVector);
			lCenter *= lLength;
			lCenter += lEye;

			lRotationVector = KFbxVector4(0,1.0,0);
			lUp = lGlobalRotation.MultT(lRotationVector);
		}
	}

	lForward = lCenter - lEye;
	lForward.Normalize();
	lRight = lForward.CrossProduct(lUp);
	lRight.Normalize();
	lUp = lRight.CrossProduct(lForward);
	lUp.Normalize();

	double lRadians = 0;

	if (lCamera)
		lRadians = 3.1416 * lCamera->Roll.Get() / 180.0;
	lUp *= cos(lRadians);
	lRight *= sin(lRadians);
	lUp = lUp + lRight;

	double lNearPlane = 0.01;
	if (lCamera)
		lNearPlane = lCamera->GetNearPlane();
	double lFarPlane = 1000.0;
	if (lCamera)
		lFarPlane = lCamera->GetFarPlane();

	if (lCamera && lCamera->ProjectionType.Get() == KFbxCamera::ePERSPECTIVE)
	{
		double lFieldOfViewY=0.0;
		double lAspect = lCamera->GetApertureWidth() * lCamera->GetSqueezeRatio() / lCamera->GetApertureHeight();

		if (lCamera->GetApertureMode() == KFbxCamera::eHORIZONTAL 
				|| lCamera->GetApertureMode() == KFbxCamera::eVERTICAL) {
			lFieldOfViewY = lCamera->FieldOfView.Get();
			if (lCamera->GetApertureMode() == KFbxCamera::eHORIZONTAL)
				lFieldOfViewY /= lAspect;
		} else if (lCamera->GetApertureMode() == KFbxCamera::eFOCAL_LENGTH) {
			lFieldOfViewY = lCamera->ComputeFieldOfView(lCamera->FocalLength.Get());
			lFieldOfViewY /= lAspect;
		} else if (lCamera->GetApertureMode() == KFbxCamera::eHORIZONTAL_AND_VERTICAL) {
			lFieldOfViewY = lCamera->FieldOfViewY.Get();
		}

		GlSetCameraPerspective(lFieldOfViewY,
				lAspect,
				lNearPlane,
				lFarPlane,
				lEye,
				lCenter,
				lUp);
	}
	else
	{
		double lPixelRatio = 1.0;
		if (lCamera)
			lPixelRatio = lCamera->GetPixelRatio();  

		int lWidth, lHeight;
		double lLeftPlane, lRightPlane, lBottomPlane, lTopPlane;

		GlGetWindowSize(lWidth, lHeight);

		if(lWidth < lHeight) 
		{   
			lLeftPlane   = -gsOrthoCameraScale * lPixelRatio;
			lRightPlane  =  gsOrthoCameraScale * lPixelRatio;
			lBottomPlane = -gsOrthoCameraScale * lHeight / lWidth;
			lTopPlane    =  gsOrthoCameraScale * lHeight / lWidth;               
		} 
		else 
		{
			lWidth *= (int) lPixelRatio;
			lLeftPlane   = -gsOrthoCameraScale * lWidth / lHeight;
			lRightPlane  =  gsOrthoCameraScale * lWidth / lHeight;
			lBottomPlane = -gsOrthoCameraScale;
			lTopPlane    =  gsOrthoCameraScale;
		}

		GlSetCameraOrthogonal(lLeftPlane,
				lRightPlane,
				lBottomPlane,
				lTopPlane,
				lNearPlane,
				lFarPlane,
				lEye,
				lCenter,
				lUp);
	}
}
Пример #7
0
        KFbxXMatrix FilmboxNode::GetWorldTransform( int frame ) const
        {
            KFbxXMatrix value;
            value.SetIdentity();

            if( m_node )
            {
                KFbxScene*         scene     = m_node->GetScene();
                KFbxAnimEvaluator* evaluator = scene->GetEvaluator();
                
                KTime frame_time;

                if( frame == 0xFFFFFFFF )
                {
                    frame_time = KTIME_INFINITE;
                }
                else
                {
                    frame_time.SetTime( 0, 0, 0, frame );
                }

                value = evaluator->GetNodeGlobalTransform( m_node, frame_time );

                if( m_type == MCE::FBX::SceneObjectType::CAMERA )
                {
                    KFbxNode* fbx_target_node = m_node->GetTarget();

                    if( fbx_target_node )
                    {
                        // For target cameras we need to manually replace the rotation to point towards the target
                        KFbxVector4 camera_position = value.GetT();

                        MCE::FBX::FilmboxNode mce_target_node( fbx_target_node );

                        KFbxXMatrix target_transform = mce_target_node.GetWorldTransform( frame );
                        KFbxVector4 target_position  = target_transform.GetT();

                        KFbxVector4 up_vector( 0.0, 1.0, 0.0, 0.0 );

                        KFbxVector4 look_axis = -( target_position - camera_position );
                        look_axis.Normalize();

                        KFbxVector4 right_axis = up_vector.CrossProduct( look_axis );
                        KFbxVector4 up_axis    = look_axis.CrossProduct( right_axis );

                        KFbxMatrix rotation_matrix;
                        rotation_matrix.SetRow( 0, right_axis );
                        rotation_matrix.SetRow( 1, up_axis );
                        rotation_matrix.SetRow( 2, look_axis );
                        rotation_matrix.SetRow( 3, KFbxVector4( 0.0, 0.0, 0.0, 1.0 ) );

                        KFbxQuaternion camera_rotation;
                        double determinant;
                        rotation_matrix.GetElements( KFbxVector4(), camera_rotation, KFbxVector4(), KFbxVector4(), determinant );

                        KFbxVector4 camera_scale( 1.0, 1.0, 1.0, 0.0 );
                        value.SetTQS( camera_position, camera_rotation, camera_scale );
                    }
                    else
                    {
                        // Even though the SDK docs say that GetNodeGlobalTransform takes all transforms into account
                        // For cameras it appears that you have to manually apply post-rotation
                        KFbxVector4 post_rotation = m_node->GetPostRotation( KFbxNode::eSOURCE_SET );

                        KFbxXMatrix fbx_to_mce_camera;
                        fbx_to_mce_camera.SetR( post_rotation );

                        value *= fbx_to_mce_camera;
                    }
                }
            }

            return value;
        }
Пример #8
0
osgDB::ReaderWriter::ReadResult OsgFbxReader::readMesh(
    KFbxNode* pNode,
    KFbxMesh* fbxMesh,
    std::vector<StateSetContent>& stateSetList,
    const char* szName)
{
    GeometryMap geometryMap;

    osg::Geode* pGeode = new osg::Geode;
    pGeode->setName(szName);

    const KFbxLayerElementNormal* pFbxNormals = 0;
    const KFbxLayerElementVertexColor* pFbxColors = 0;
    const KFbxLayerElementMaterial* pFbxMaterials = 0;

    const KFbxVector4* pFbxVertices = fbxMesh->GetControlPoints();

    // scan layers for Normals, Colors and Materials elements (this will get the first available elements)...
    for (int cLayerIndex = 0; cLayerIndex < fbxMesh->GetLayerCount(); cLayerIndex++)
    {
        const KFbxLayer* pFbxLayer = fbxMesh->GetLayer(cLayerIndex);
        if (!pFbxLayer)
            continue;

        // get normals, colors and materials...
        if (!pFbxNormals)
            pFbxNormals = pFbxLayer->GetNormals();
        if (!pFbxColors)
            pFbxColors = pFbxLayer->GetVertexColors();
        if (!pFbxMaterials)
            pFbxMaterials = pFbxLayer->GetMaterials();
    }

    // look for UV elements (diffuse, opacity, reflection, emissive, ...) and get their channels names...
    std::string diffuseChannel = getUVChannelForTextureMap(stateSetList, KFbxSurfaceMaterial::sDiffuse);
    std::string opacityChannel = getUVChannelForTextureMap(stateSetList, KFbxSurfaceMaterial::sTransparentColor);
    std::string emissiveChannel = getUVChannelForTextureMap(stateSetList, KFbxSurfaceMaterial::sEmissive);
    // look for more UV elements here...

    // UV elements...
    const KFbxLayerElementUV* pFbxUVs_diffuse = getUVElementForChannel(diffuseChannel, KFbxLayerElement::eDIFFUSE_TEXTURES, fbxMesh);
    const KFbxLayerElementUV* pFbxUVs_opacity = getUVElementForChannel(opacityChannel, KFbxLayerElement::eTRANSPARENT_TEXTURES, fbxMesh);
    const KFbxLayerElementUV* pFbxUVs_emissive = getUVElementForChannel(emissiveChannel, KFbxLayerElement::eEMISSIVE_TEXTURES, fbxMesh);
    // more UV elements here...

    // check elements validity...
    if (!layerElementValid(pFbxNormals)) pFbxNormals = 0;
    if (!layerElementValid(pFbxColors)) pFbxColors = 0;

    if (!layerElementValid(pFbxUVs_diffuse)) pFbxUVs_diffuse = 0;
    if (!layerElementValid(pFbxUVs_opacity)) pFbxUVs_opacity = 0;
    if (!layerElementValid(pFbxUVs_emissive)) pFbxUVs_emissive = 0;
    // more here...

    int nPolys = fbxMesh->GetPolygonCount();

    int nDeformerCount = fbxMesh->GetDeformerCount(KFbxDeformer::eSKIN);
    int nDeformerBlendShapeCount = fbxMesh->GetDeformerCount(KFbxDeformer::eBLENDSHAPE);

    GeometryType geomType = GEOMETRY_STATIC;

    //determine the type of geometry
    if (nDeformerCount)
    {
        geomType = GEOMETRY_RIG;
    }
    else if (nDeformerBlendShapeCount)
    {
        geomType = GEOMETRY_MORPH;
    }

    FbxToOsgVertexMap fbxToOsgVertMap;
    OsgToFbxNormalMap osgToFbxNormMap;

    // First add only triangles and quads (easy to split into triangles without
    // more processing)
    // This is the reason we store polygons references:

    PolygonRefList polygonRefList;

    for (int i = 0, nVertex = 0; i < nPolys; ++i)
    {
        int lPolygonSize = fbxMesh->GetPolygonSize(i);

        int materialIndex = getPolygonIndex(pFbxMaterials, i);

        osg::Geometry* pGeometry = getGeometry(pGeode, geometryMap,
            stateSetList, geomType, materialIndex,
            pFbxNormals != 0,
            pFbxUVs_diffuse != 0,
            pFbxUVs_opacity != 0,
            pFbxUVs_emissive != 0,
            // more UV elements here...
            pFbxColors != 0,
            options,
            lightmapTextures);

        osg::Array* pVertices = pGeometry->getVertexArray();
        osg::Array* pNormals = pGeometry->getNormalArray();

        // get texture coordinates...
        osg::Array* pTexCoords_diffuse = pGeometry->getTexCoordArray(StateSetContent::DIFFUSE_TEXTURE_UNIT);
        osg::Array* pTexCoords_opacity = pGeometry->getTexCoordArray(StateSetContent::OPACITY_TEXTURE_UNIT);
        osg::Array* pTexCoords_emissive = pGeometry->getTexCoordArray(StateSetContent::EMISSIVE_TEXTURE_UNIT);
        // more texture coordinates here...

        osg::Array* pColors = pGeometry->getColorArray();

        if (lPolygonSize == 3)
        {
            // Triangle
            readMeshTriangle(fbxMesh, i,
                0, 1, 2,
                nVertex, nVertex+1, nVertex+2,
                fbxToOsgVertMap, osgToFbxNormMap,
                pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors,
                pGeometry,
                pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors);
            nVertex += 3;
        }
        else if (lPolygonSize == 4)
        {
            // Quad - Convert to triangles
            // Use some fast specialized code to see how the should be decomposed
            // Two cases : Split at '02' (012 and 023), or split at '13 (013 and 123)
            bool split02 = quadSplit02(fbxMesh, i, 0, 1, 2, 3, pFbxVertices);
            int p02 = split02 ? 2 : 3; // Triangle 0, point 2
            int p10 = split02 ? 0 : 1; // Triangle 1, point 0
            readMeshTriangle(fbxMesh, i,
                0, 1, p02,
                nVertex, nVertex+1, nVertex+p02,
                fbxToOsgVertMap, osgToFbxNormMap,
                pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors,
                pGeometry,
                pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors);
            readMeshTriangle(fbxMesh, i,
                p10, 2, 3,
                nVertex+p10, nVertex+2, nVertex+3,
                fbxToOsgVertMap, osgToFbxNormMap,
                pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors,
                pGeometry,
                pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors);
            nVertex += 4;
        }
        else if (tessellatePolygons)
        {
            // Polygons - Store to add after triangles
            polygonRefList.push_back(PolygonRef(pGeometry, i, nVertex));
            nVertex += lPolygonSize;
        }
        else
        {
            int nVertex0 = nVertex;
            nVertex += (std::min)(2, lPolygonSize);

            for (int j = 2; j < lPolygonSize; ++j, ++nVertex)
            {
                readMeshTriangle(fbxMesh, i,
                    0, j - 1, j,
                    nVertex0, nVertex - 1, nVertex,
                    fbxToOsgVertMap, osgToFbxNormMap,
                    pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors,
                    pGeometry,
                    pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors);
            }
        }
    }

    for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i)
    {
        osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry();
        osg::DrawArrays* pDrawArrays = new osg::DrawArrays(
            GL_TRIANGLES, 0, pGeometry->getVertexArray()->getNumElements());
        pGeometry->addPrimitiveSet(pDrawArrays);
    }

    // Now add polygons - Convert to triangles
    // We put vertices in their own PrimitiveSet with Mode=POLYGON; then run the
    // Tessellator on the Geometry which should tessellate the polygons
    // automagically.
    for (PolygonRefList::iterator it = polygonRefList.begin(), itEnd=polygonRefList.end();
        it != itEnd; ++it)
    {
        int i = it->numPoly;
        int lPolygonSize = fbxMesh->GetPolygonSize(i);
        //int materialIndex = getPolygonIndex(pFbxMaterials, i);
        osg::Geometry* pGeometry = it->pGeometry;

        osg::Array* pVertices = pGeometry->getVertexArray();
        osg::Array* pNormals = pGeometry->getNormalArray();
        osg::Array* pTexCoords_diffuse = pGeometry->getTexCoordArray(StateSetContent::DIFFUSE_TEXTURE_UNIT);
        osg::Array* pTexCoords_opacity = pGeometry->getTexCoordArray(StateSetContent::OPACITY_TEXTURE_UNIT);
        osg::Array* pTexCoords_emissive = pGeometry->getTexCoordArray(StateSetContent::EMISSIVE_TEXTURE_UNIT);
        osg::Array* pColors = pGeometry->getColorArray();
        // Index of the 1st vertex of the polygon in the geometry
        int osgVertex0 = pVertices->getNumElements();

        for (int j = 0, nVertex = it->nVertex; j<lPolygonSize; ++j, ++nVertex)
        {
            int v0 = fbxMesh->GetPolygonVertex(i, j);
            fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v0, GIPair(pGeometry, pVertices->getNumElements())));
            addVec3ArrayElement(*pVertices, pFbxVertices[v0]);
            if (pNormals)
            {
                int n0 = getVertexIndex(pFbxNormals, fbxMesh, i, j, nVertex);
                osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->getNumElements()), n0));
                addVec3ArrayElement(*pNormals, pFbxNormals->GetDirectArray().GetAt(n0));
            }

            // add texture maps data (avoid duplicates)...
            if (pTexCoords_diffuse)
            {
                addVec2ArrayElement(*pTexCoords_diffuse, getElement(pFbxUVs_diffuse, fbxMesh, i, j, nVertex));
            }
            if (pTexCoords_opacity && (pTexCoords_opacity != pTexCoords_diffuse))
            {
                addVec2ArrayElement(*pTexCoords_opacity, getElement(pFbxUVs_opacity, fbxMesh, i, j, nVertex));
            }

            // Only spherical reflection maps are supported (so do not add coordinates for the reflection map)

            if (pTexCoords_emissive && (pTexCoords_emissive != pTexCoords_opacity) && (pTexCoords_emissive != pTexCoords_diffuse))
            {
                addVec2ArrayElement(*pTexCoords_emissive, getElement(pFbxUVs_emissive, fbxMesh, i, j, nVertex));
            }
            // add more texture maps here...

            if (pColors)
            {
                addColorArrayElement(*pColors, getElement(pFbxColors, fbxMesh, i, j, nVertex));
            }
        }

        osg::DrawArrays* pDrawArrays = new osg::DrawArrays(
            GL_POLYGON, osgVertex0, pGeometry->getVertexArray()->getNumElements() - osgVertex0);
        pGeometry->addPrimitiveSet(pDrawArrays);
    }

    for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i)
    {
        osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry();

        // Now split polygons if necessary
        osgUtil::Tessellator tessellator;
        tessellator.retessellatePolygons(*pGeometry);

        if (pGeode->getNumDrawables() > 1)
        {
            std::stringstream ss;
            ss << pGeode->getName() << " " << i + 1;
            pGeometry->setName(ss.str());
        }
        else
        {
            pGeometry->setName(pGeode->getName());
        }
    }

    if (geomType == GEOMETRY_RIG)
    {
        typedef std::map<osg::ref_ptr<osg::Geometry>,
            osg::ref_ptr<osgAnimation::RigGeometry> > GeometryRigGeometryMap;
        GeometryRigGeometryMap old2newGeometryMap;

        for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i)
        {
            osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry();

            osgAnimation::RigGeometry* pRig = new osgAnimation::RigGeometry;
            pRig->setSourceGeometry(pGeometry);
            pRig->copyFrom(*pGeometry);
            old2newGeometryMap.insert(GeometryRigGeometryMap::value_type(
                pGeometry, pRig));
            pRig->setDataVariance(osg::Object::DYNAMIC);
            pRig->setUseDisplayList( false );
            pGeode->setDrawable(i, pRig);

            pRig->setInfluenceMap(new osgAnimation::VertexInfluenceMap);
            pGeometry = pRig;
        }

        for (int i = 0; i < nDeformerCount; ++i)
        {
            KFbxSkin* pSkin = (KFbxSkin*)fbxMesh->GetDeformer(i, KFbxDeformer::eSKIN);
            int nClusters = pSkin->GetClusterCount();
            for (int j = 0; j < nClusters; ++j)
            {
                KFbxCluster* pCluster = (KFbxCluster*)pSkin->GetCluster(j);
                //assert(KFbxCluster::eNORMALIZE == pCluster->GetLinkMode());
                KFbxNode* pBone = pCluster->GetLink();

                KFbxXMatrix transformLink;
                pCluster->GetTransformLinkMatrix(transformLink);
                KFbxXMatrix transformLinkInverse = transformLink.Inverse();
                const double* pTransformLinkInverse = transformLinkInverse;
                osg::Matrix bindMatrix(pTransformLinkInverse);

                int nIndices = pCluster->GetControlPointIndicesCount();
                int* pIndices = pCluster->GetControlPointIndices();
                double* pWeights = pCluster->GetControlPointWeights();

                for (int k = 0; k < nIndices; ++k)
                {
                    int fbxIndex = pIndices[k];
                    float weight = static_cast<float>(pWeights[k]);

                    for (FbxToOsgVertexMap::const_iterator it =
                        fbxToOsgVertMap.find(fbxIndex);
                        it != fbxToOsgVertMap.end() &&
                        it->first == fbxIndex; ++it)
                    {
                        GIPair gi = it->second;
                        osgAnimation::RigGeometry& rig =
                            dynamic_cast<osgAnimation::RigGeometry&>(
                            *old2newGeometryMap[gi.first]);
                        addBindMatrix(boneBindMatrices, pBone, bindMatrix, &rig);
                        osgAnimation::VertexInfluenceMap& vim =
                            *rig.getInfluenceMap();
                        osgAnimation::VertexInfluence& vi =
                            getVertexInfluence(vim, pBone->GetName());
                        vi.push_back(osgAnimation::VertexIndexWeight(
                            gi.second, weight));
                    }
                }
            }
        }
    }
    else if (geomType == GEOMETRY_MORPH)
    {
        for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i)
        {
            osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry();

            osgAnimation::MorphGeometry& morph = dynamic_cast<osgAnimation::MorphGeometry&>(*pGeometry);

            pGeode->addUpdateCallback(new osgAnimation::UpdateMorph(morph.getName()));

            //read morph geometry
            for (int nBlendShape = 0; nBlendShape < nDeformerBlendShapeCount; ++nBlendShape)
            {
                KFbxBlendShape* pBlendShape = KFbxCast<KFbxBlendShape>(fbxMesh->GetDeformer(nBlendShape, KFbxDeformer::eBLENDSHAPE));
                const int nBlendShapeChannelCount = pBlendShape->GetBlendShapeChannelCount();

                for (int nBlendShapeChannel = 0; nBlendShapeChannel < nBlendShapeChannelCount; ++nBlendShapeChannel)
                {
                    KFbxBlendShapeChannel* pBlendShapeChannel = pBlendShape->GetBlendShapeChannel(nBlendShapeChannel);
                    if (!pBlendShapeChannel->GetTargetShapeCount()) continue;

                    //Assume one shape
                    if (pBlendShapeChannel->GetTargetShapeCount() > 1)
                    {
                        OSG_WARN << "Multiple FBX Target Shapes, only the first will be used" << std::endl;
                    }
                    const KFbxGeometryBase* pMorphShape = pBlendShapeChannel->GetTargetShape(0);

                    const KFbxLayerElementNormal* pFbxShapeNormals = 0;
                    if (const KFbxLayer* pFbxShapeLayer = pMorphShape->GetLayer(0))
                    {
                        pFbxShapeNormals = pFbxShapeLayer->GetNormals();
                        if (!layerElementValid(pFbxShapeNormals)) pFbxShapeNormals = 0;
                    }

                    osg::Geometry* pMorphTarget = new osg::Geometry(morph);
                    pMorphTarget->setVertexArray(static_cast<osg::Array*>(
                        pMorphTarget->getVertexArray()->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));
                    if (pFbxShapeNormals)
                    {
                        if (osg::Array* pNormals = pMorphTarget->getNormalArray())
                        {
                            pMorphTarget->setNormalArray(static_cast<osg::Array*>(
                                pNormals->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));
                        }
                    }
                    pMorphTarget->setName(pMorphShape->GetName());
                    morph.addMorphTarget(pMorphTarget, 0.0f);

                    readAnimation(pNode, fbxScene, morph.getName(), pAnimationManager, fbxMesh,
                        nBlendShape, nBlendShapeChannel, (int)morph.getMorphTargetList().size() - 1);
                }
            }
        }

        int nMorphTarget = 0;
        for (int nBlendShape = 0; nBlendShape < nDeformerBlendShapeCount; ++nBlendShape)
        {
            KFbxBlendShape* pBlendShape = KFbxCast<KFbxBlendShape>(fbxMesh->GetDeformer(nBlendShape, KFbxDeformer::eBLENDSHAPE));
            const int nBlendShapeChannelCount = pBlendShape->GetBlendShapeChannelCount();

            for (int nBlendShapeChannel = 0; nBlendShapeChannel < nBlendShapeChannelCount; ++nBlendShapeChannel)
            {
                KFbxBlendShapeChannel* pBlendShapeChannel = pBlendShape->GetBlendShapeChannel(nBlendShapeChannel);
                if (!pBlendShapeChannel->GetTargetShapeCount()) continue;

                //Assume one shape again
                const KFbxGeometryBase* pMorphShape = pBlendShapeChannel->GetTargetShape(0);

                const KFbxLayerElementNormal* pFbxShapeNormals = 0;
                if (const KFbxLayer* pFbxShapeLayer = pMorphShape->GetLayer(0))
                {
                    pFbxShapeNormals = pFbxShapeLayer->GetNormals();
                    if (!layerElementValid(pFbxShapeNormals)) pFbxShapeNormals = 0;
                }

                const KFbxVector4* pControlPoints = pMorphShape->GetControlPoints();
                int nControlPoints = pMorphShape->GetControlPointsCount();
                for (int fbxIndex = 0; fbxIndex < nControlPoints; ++fbxIndex)
                {
                    osg::Vec3d vPos = convertVec3(pControlPoints[fbxIndex]);
                    for (FbxToOsgVertexMap::const_iterator it =
                        fbxToOsgVertMap.find(fbxIndex);
                        it != fbxToOsgVertMap.end() &&
                        it->first == fbxIndex; ++it)
                    {
                        GIPair gi = it->second;
                        osgAnimation::MorphGeometry& morphGeom =
                            dynamic_cast<osgAnimation::MorphGeometry&>(*gi.first);
                        osg::Geometry* pGeometry = morphGeom.getMorphTarget(nMorphTarget).getGeometry();

                        if (pGeometry->getVertexArray()->getType() == osg::Array::Vec3dArrayType)
                        {
                            osg::Vec3dArray* pVertices = static_cast<osg::Vec3dArray*>(pGeometry->getVertexArray());
                            (*pVertices)[gi.second] = vPos;
                        }
                        else
                        {
                            osg::Vec3Array* pVertices = static_cast<osg::Vec3Array*>(pGeometry->getVertexArray());
                            (*pVertices)[gi.second] = vPos;
                        }

                        if (pFbxShapeNormals && pGeometry->getNormalArray())
                        {
                            if (pGeometry->getNormalArray()->getType() == osg::Array::Vec3dArrayType)
                            {
                                osg::Vec3dArray* pNormals = static_cast<osg::Vec3dArray*>(pGeometry->getNormalArray());
                                (*pNormals)[gi.second] = convertVec3(
                                    pFbxShapeNormals->GetDirectArray().GetAt(osgToFbxNormMap[gi]));
                            }
                            else
                            {
                                osg::Vec3Array* pNormals = static_cast<osg::Vec3Array*>(pGeometry->getNormalArray());
                                (*pNormals)[gi.second] = convertVec3(
                                    pFbxShapeNormals->GetDirectArray().GetAt(osgToFbxNormMap[gi]));
                            }
                        }
                    }
                }

                //don't put this in the for loop as we don't want to do it if the loop continues early
                ++nMorphTarget;
            }
        }
    }

    KFbxXMatrix fbxGeometricTransform;
    fbxGeometricTransform.SetTRS(
        pNode->GeometricTranslation.Get(),
        pNode->GeometricRotation.Get(),
        pNode->GeometricScaling.Get());
    const double* pGeometricMat = fbxGeometricTransform;
    osg::Matrix osgGeometricTransform(pGeometricMat);

    if (geomType == GEOMETRY_RIG)
    {
        KFbxSkin* pSkin = (KFbxSkin*)fbxMesh->GetDeformer(0, KFbxDeformer::eSKIN);
        if (pSkin->GetClusterCount())
        {
            KFbxXMatrix fbxTransformMatrix;
            pSkin->GetCluster(0)->GetTransformMatrix(fbxTransformMatrix);
            const double* pTransformMatrix = fbxTransformMatrix;
            osgGeometricTransform.postMult(osg::Matrix(pTransformMatrix));
        }
    }

    osg::Node* pResult = pGeode;

    if (!osgGeometricTransform.isIdentity())
    {
        osg::MatrixTransform* pMatTrans = new osg::MatrixTransform(osgGeometricTransform);
        pMatTrans->addChild(pGeode);
        pResult = pMatTrans;
    }

    if (geomType == GEOMETRY_RIG)
    {
        //Add the geometry to the skeleton ancestor of one of the bones.
        KFbxSkin* pSkin = (KFbxSkin*)fbxMesh->GetDeformer(0, KFbxDeformer::eSKIN);
        if (pSkin->GetClusterCount())
        {
            osgAnimation::Skeleton* pSkeleton = getSkeleton(
                pSkin->GetCluster(0)->GetLink(), fbxSkeletons, skeletonMap);
            pSkeleton->addChild(pResult);
            return osgDB::ReaderWriter::ReadResult::FILE_LOADED;
        }
    }

    return osgDB::ReaderWriter::ReadResult(pResult);
}