예제 #1
0
void SkeletonDrawable::adjustVolume(Volume & volume)
{
    Inherited::adjustVolume(volume);

    //Extend the volume by all the Root Joints of Skeleton
    if(getSkeleton() == NULL)
    {
        FWARNING(("SkeletonDrawable::drawPrimitives:: no skeleton!\n"));;
    }
    else
    {
        Pnt3f JointLocation(0.0,0.0,0.0);
        for(UInt32 i(0) ; i<getSkeleton()->getNumJoints() ; ++i)
        {
            JointLocation.setValues(0.0,0.0,0.0);
            if(getDrawPose())
            {
                getSkeleton()->getAbsoluteTransformation(i).mult(Pnt3f(0.0f,0.0f,0.0f),JointLocation);
                volume.extendBy(JointLocation);
            }
            if(getDrawBindPose())
            {
                getSkeleton()->getAbsoluteBindTransformation(i).mult(Pnt3f(0.0f,0.0f,0.0f),JointLocation);
                volume.extendBy(JointLocation);
            }
        }
    }

}
예제 #2
0
void SkeletonDrawable::fill(DrawableStatsAttachment *pStat)
{
    if(pStat == NULL)
    {
        FINFO(("SkeletonDrawable::fill(DrawableStatsAttachment *): "
                          "No attachment given.\n"));
        return;
    }
    if(getSkeleton() == NULL)
    {
        FWARNING(("SkeletonDrawable::fill:: no skeleton!\n"));;
        return;
    }

    UInt32 NumLines(0);
    if(getDrawPose())
    {
        NumLines += getSkeleton()->getNumJoints()-1;
    }
    if(getDrawBindPose())
    {
        NumLines += getSkeleton()->getNumJoints()-1;
    }
    pStat->setLines    (NumLines);
}
예제 #3
0
파일: World.cpp 프로젝트: ehuang3/dart
Eigen::VectorXd World::getState()
{
    Eigen::VectorXd state(mIndices.back() * 2);

    for (unsigned int i = 0; i < getNumSkeletons(); i++)
    {
        int start = mIndices[i] * 2;
        int size = getSkeleton(i)->getNumDofs();
        state.segment(start, size) = getSkeleton(i)->getPose();
        state.segment(start + size, size) = getSkeleton(i)->getPoseVelocity();
    }

    return state;
}
예제 #4
0
파일: Joint.cpp 프로젝트: Shushman/dart
//==============================================================================
size_t Joint::incrementVersion()
{
  if(const auto& skel = getSkeleton())
    return skel->incrementVersion();

  return 0;
}
예제 #5
0
void Model::prepareSkinning()
{
	if( !mesh->isAnimated() ) return;

	size_t numBones = mesh->getSkeleton()->getBones().size();
	bones.resize( numBones );
}
예제 #6
0
파일: Joint.cpp 프로젝트: Shushman/dart
//==============================================================================
size_t Joint::getVersion() const
{
  if(const auto& skel = getSkeleton())
    return skel->getVersion();

  return 0;
}
예제 #7
0
파일: Joint.cpp 프로젝트: jslee02/wafr2016
//==============================================================================
void Joint::notifyPositionUpdate()
{
  if(mChildBodyNode)
  {
    mChildBodyNode->notifyTransformUpdate();
    mChildBodyNode->notifyJacobianUpdate();
    mChildBodyNode->notifyJacobianDerivUpdate();
  }

  mIsLocalJacobianDirty = true;
  mIsLocalJacobianTimeDerivDirty = true;
  mNeedPrimaryAccelerationUpdate = true;

  mNeedTransformUpdate = true;
  mNeedSpatialVelocityUpdate = true;
  mNeedSpatialAccelerationUpdate = true;

  SkeletonPtr skel = getSkeleton();
  if(skel)
  {
    std::size_t tree = mChildBodyNode->mTreeIndex;
    skel->notifyArticulatedInertiaUpdate(tree);
    skel->mTreeCache[tree].mDirty.mExternalForces = true;
    skel->mSkelCache.mDirty.mExternalForces = true;
  }
}
Action::ResultE
CPUSkinningAlgorithm::intersectEnter(Action *action)
{
    Action::ResultE  res     = Action::Continue;
    SkinnedGeometry *skinGeo = getSkin    ();
    Skeleton        *skel    = getSkeleton();
    IntersectAction *iact    =
        boost::polymorphic_downcast<IntersectAction *>(action);

    CPUSkinningDataAttachmentUnrecPtr data = getCPUSkinningData(skinGeo);

    if(data == NULL)
    {
        data = CPUSkinningDataAttachment::create();
        skinGeo->addAttachment(data);
    }

    skel->intersectEnter(action, skinGeo);

    if(data->getDataValid() == false)
    {
        transformGeometry(skinGeo, skel, data);

        data->setDataValid(true);
    }

    intersectGeometry(iact, skinGeo, data);

    return res;
}
Action::ResultE
CPUSkinningAlgorithm::renderEnter(Action *action)
{
    Action::ResultE  res     = Action::Continue;
    SkinnedGeometry *skinGeo = getSkin    ();
    Skeleton        *skel    = getSkeleton();
    RenderAction    *ract    =
        boost::polymorphic_downcast<RenderAction *>(action); 

    OSG_ASSERT(skinGeo != NULL);
    OSG_ASSERT(skel    != NULL);

    CPUSkinningDataAttachmentUnrecPtr data = getCPUSkinningData(skinGeo);

    if(data == NULL)
    {
        data = CPUSkinningDataAttachment::create();
        skinGeo->addAttachment(data);
    }

    skel->renderEnter(action, skinGeo);

    if(data->getDataValid() == false)
    {
        transformGeometry(skinGeo, skel, data);

        data->setDataValid(true);
    }

    renderGeometry(ract, skinGeo, data);

    return res;
}
예제 #10
0
void SkeletonStream::renderSkeleton()
{
    Eigen::Matrix3Xd skeleton;
    if (!getSkeleton(skeleton))
        return;

    renderSkeleton(skeleton);
}
예제 #11
0
파일: model.cpp 프로젝트: whztt07/Magic3D-2
bool Magic3D::Model::update()
{
    bool needUpdate = Scene::getInstance()->getUniqueUpdateFlag() != uniqueUpdate;
    bool result = Object::update();
    if (needUpdate && (isInParentFrustum() || isInEffectFrustum()) && getSkeleton())
    {
        uniqueUpdate = !uniqueUpdate;
        result = getSkeleton()->update() && result;
        if (result)
        {
            result = updateMeshes() && result;
        }
        Object::updateBoundingBox(false);
        box = Object::getBoundingBox();
    }
    return result;
}
예제 #12
0
파일: model.cpp 프로젝트: whztt07/Magic3D-2
Magic3D::XMLElement* Magic3D::Model::save(XMLElement* root)
{
    Object::save(root);

    if (root)
    {
        XMLElement* model = root->GetDocument()->NewElement(M3D_MODEL_XML);
        root->LinkEndChild(model);

        saveString(model, M3D_MODEL_XML_FILE, getFileName());

        if (getSkeleton())
        {
            getSkeleton()->save(model);
        }
    }
    return root;
}
Action::ResultE
SkeletonSkinningAlgorithm::renderLeave(Action *action)
{
    SkinnedGeometry *skinGeo = getSkin();
    Skeleton        *skel    = getSkeleton();

    skel->renderLeave(action, skinGeo);

    return Action::Continue;
}
예제 #14
0
//==============================================================================
void EndEffector::notifyTransformUpdate()
{
  if(!mNeedTransformUpdate)
  {
    const SkeletonPtr& skel = getSkeleton();
    if(skel)
      skel->notifySupportUpdate(getTreeIndex());
  }

  Frame::notifyTransformUpdate();
}
Action::ResultE
GPUSkinningAlgorithm::renderLeave(Action *action)
{
    Action::ResultE  res     = Action::Continue;
    SkinnedGeometry *skinGeo = getSkin();
    Skeleton        *skel    = getSkeleton();

    skel->renderLeave(action, skinGeo);

    res = skinGeo->SkinnedGeometry::Inherited::renderLeave(action);

    return res;
}
예제 #16
0
파일: World.cpp 프로젝트: ehuang3/dart
Eigen::VectorXd World::evalDeriv()
{
    // compute contact forces
    mCollisionHandle->applyContactForces();

    // compute derivatives for integration
    Eigen::VectorXd deriv = Eigen::VectorXd::Zero(mIndices.back() * 2);

    for (unsigned int i = 0; i < getNumSkeletons(); i++)
    {
        // skip immobile objects in forward simulation
        if (mSkeletons[i]->getImmobileState())
            continue;
        int start = mIndices[i] * 2;
        int size = getSkeleton(i)->getNumDofs();

        Eigen::VectorXd qddot = mSkeletons[i]->getInvMassMatrix()
                                * (-mSkeletons[i]->getCombinedVector()
                                   + mSkeletons[i]->getExternalForces()
                                   + mSkeletons[i]->getInternalForces()
                                   + mCollisionHandle->getConstraintForce(i)
                                   );

        //        Eigen::VectorXd qddot = mSkeletons[i]->getMassMatrix().ldlt().solve(
        //                                    -mSkeletons[i]->getCombinedVector()
        //                                    + mSkeletons[i]->getExternalForces()
        //                                    + mSkeletons[i]->getInternalForces()
        //                                    + mCollisionHandle->getConstraintForce(i)
        //                                    );
        
        // set velocities
        deriv.segment(start, size) = getSkeleton(i)->getPoseVelocity() + (qddot * mTimeStep);

        // set qddot (accelerations)
        deriv.segment(start + size, size) = qddot;
    }

    return deriv;
}
예제 #17
0
void Mapper::map(ofxOscMessage &_message) {
	parser.setMessage(_message);

	if(parser.isBody()) {
		Skeleton* skeleton = getSkeleton(parser.parseBodyId());

		if(parser.isJoint()) {
			skeleton->setJoint(parser.parseJoint());
		} else if(parser.isHand()) {
			skeleton->setHand(parser.parseHand());
        }
    }
}
예제 #18
0
파일: frame.cpp 프로젝트: spelteam/spel
 vector <Point2f> Frame::getPartPolygon(int partID) const
 {
   tree <BodyPart> partTree = getSkeleton().getPartTree();
   tree <BodyPart>::iterator i;
   for (i = partTree.begin(); i != partTree.end(); i++)
   {
     if (i->getPartID() == partID)
     {
       return i->getPartPolygon().asVector();
     }
   }
   return vector <Point2f>();
 }
예제 #19
0
//==============================================================================
bool BodyNodeDistanceFilter::needDistance(
    const collision::CollisionObject* object1,
    const collision::CollisionObject* object2) const
{
  if (object1 == object2)
    return false;

  auto shapeNode1 = object1->getShapeFrame()->asShapeNode();
  auto shapeNode2 = object2->getShapeFrame()->asShapeNode();

  if (!shapeNode1 || !shapeNode2)
    return true;
  // We assume that non-ShapeNode is always being checked collision.

  auto bodyNode1 = shapeNode1->getBodyNodePtr();
  auto bodyNode2 = shapeNode2->getBodyNodePtr();

  if (!bodyNode1->isCollidable() || !bodyNode2->isCollidable())
    return false;

  if (bodyNode1->getSkeleton() == bodyNode2->getSkeleton())
  {
    auto skeleton = bodyNode1->getSkeleton();

    if (!skeleton->isEnabledSelfCollisionCheck())
      return false;

    if (!skeleton->isEnabledAdjacentBodyCheck())
    {
      if (areAdjacentBodies(bodyNode1, bodyNode2))
        return false;
    }
  }

  return true;
}
예제 #20
0
파일: model.cpp 프로젝트: whztt07/Magic3D-2
Magic3D::XMLElement* Magic3D::Model::load(XMLElement* root)
{
    if (root)
    {
        XMLElement* model = root->FirstChildElement(M3D_MODEL_XML);

        std::string name = loadString(model, M3D_MODEL_XML_FILE);
        if (name.compare(M3D_XML_NULL) != 0)
        {
            setFileName(name);
        }

        if (getSkeleton())
        {
            getSkeleton()->load(model);
        }
    }

    Object::load(root);

    updateBoundingBox();

    return root;
}
예제 #21
0
void Model::setAttachment(const String& boneName, const EntityPtr& node)
{
	if( !mesh ) return;

	Skeleton* skeleton = mesh->getSkeleton().get();
	assert( skeleton != nullptr );

	Bone* bone = skeleton->findBone(boneName).get();
	if( !bone ) return;

	Attachment* attachment = AllocateThis(Attachment);
	
	attachment->bone = bone;
	attachment->node = node;

	attachments.push_back(attachment);
}
예제 #22
0
HandsHip *moduleCapture::formHandsHip(bool rightHanded)
{
	NUI_SKELETON_DATA *skeleton = getSkeleton(); //Obtiene datos del esqueleto
	if(skeleton == NULL){  // Si no recibimos datos, retorna NULL
		return NULL;
	}
	HandsHip *h = new HandsHip;
	h->hipPosition = skeleton->SkeletonPositions[NUI_SKELETON_POSITION_HIP_CENTER];
	
	// Llenar los campos del handsHip con los datos del esqueleto teniendo en cuenta la lateralidad del usuario
	if(rightHanded){
		h->playingHandPosition = skeleton->SkeletonPositions[NUI_SKELETON_POSITION_WRIST_RIGHT];
		h->chordHandPosition = skeleton->SkeletonPositions[NUI_SKELETON_POSITION_WRIST_LEFT];
	} else {
		h->playingHandPosition = skeleton->SkeletonPositions[NUI_SKELETON_POSITION_WRIST_LEFT];
		h->chordHandPosition = skeleton->SkeletonPositions[NUI_SKELETON_POSITION_WRIST_RIGHT];
	}	
	return h;
}
예제 #23
0
void Game::createScene()
{
	sinbad = new GameObject("sinbad", "Sinbad.mesh", mSceneMgr->getRootSceneNode(), mSceneMgr);

	sinbad->setVelocity(Ogre::Vector3(25, 0, 25));

	auto ent = static_cast<Ogre::Entity*>(sinbad->getNode()->getAttachedObject("sinbad"));
	ent->getSkeleton()->setBlendMode(Ogre::ANIMBLEND_CUMULATIVE);

	const auto setupAnimPair = [&](int i, const std::string& name) {
		animStates[i] = ent->getAnimationState(name + "Base");
		animStates[i + 1] = ent->getAnimationState(name + "Top");
		for (int j = i; j < i + 1; ++j) {
			animStates[j]->setLoop(true);
			animStates[j]->setEnabled(false);
		}
	};
	setupAnimPair(0, "Idle");
	setupAnimPair(2, "Run");
}
예제 #24
0
파일: Box.cpp 프로젝트: ljwdust/fold-hcc
bool Geom::Box::cropByAxisAlignedBox( Box other )
{
	for (int i = 0; i < 3; i++)
	{
		// skeleton along axis[i]
		Segment sklt = getSkeleton(i);
		int other_aid = other.getAxisId(Axis[i]);
		Segment other_sklt = other.getSkeleton(other_aid);

		// point to same direction
		if (dot(sklt.Direction, other_sklt.Direction) < 0)
			other_sklt.flip();

		// projection
		double t0 = other_sklt.getProjCoordinates(sklt.P0);
		double t1 = other_sklt.getProjCoordinates(sklt.P1);
		double t0_crop = Max(-1, t0);
		double t1_crop = Min(1, t1);

		// no overlapping along this direction
		if (t0_crop >= t1_crop) 
		{
			return false;
		}
		// crop along this direction
		else
		{
			// move center
			Vector3 c = other_sklt.getPosition((t0+t1)/2);
			Vector3 c_crop = other_sklt.getPosition((t0_crop+t1_crop)/2);
			Center += c_crop - c;

			// change extent
			Vector3 p0 = other_sklt.getPosition(t0_crop);
			Vector3 p1 = other_sklt.getPosition(t1_crop);
			Extent[i] = (p0 - p1).norm()/2;
		}
	}

	return true;
}
예제 #25
0
void Model::onDebugDraw( DebugDrawer& debug, DebugDrawFlags debugFlags )
{
	const Skeleton* skeleton = mesh->getSkeleton().get();
	if( !skeleton ) return;
	
	if( bones.empty() ) return;

	if( !debugRenderable )
		debugRenderable = createDebugRenderable();

	GeometryBuffer* gb = debugRenderable->getGeometryBuffer().get();

	std::vector<Vector3> pos;
	std::vector<Vector3> colors;

	size_t numBones = skeleton->bones.size();
	
	for( size_t i = 0; i < numBones; ++i )
	{
		Bone* bone = skeleton->bones[i].get();

		Vector3 vertex;
		Vector3 parentVertex;

		if( bone->indexParent == -1 )
			continue;
		
		parentVertex = bones[bone->indexParent]*parentVertex;

		pos.push_back( bones[bone->index]*vertex );
		colors.push_back( Color::Blue );

		pos.push_back( parentVertex);
		colors.push_back( Color::Blue );
	}

	gb->set( VertexAttribute::Position, pos );
	gb->set( VertexAttribute::Color, colors );

	debug.renderables.push_back(debugRenderable.get());
}
예제 #26
0
void SkeletonDrawable::drawPrimitives (DrawEnv *pEnv)
{
    if(getSkeleton() == NULL)
    {
        FWARNING(("SkeletonDrawable::drawPrimitives:: no skeleton!\n"));;
    }
    else
    {

        Pnt3f BoneStart(0.0,0.0,0.0),BoneEnd(0.0,0.0,0.0);
        Int32 ParentIndex;
        glBegin(GL_LINES);
            for(UInt32 i(0) ; i<getSkeleton()->getNumJoints() ; ++i)
            {
                //Draw all Root Joints of Skeleton
                ParentIndex = getSkeleton()->getJointParentIndex(i);
                if(ParentIndex >= 0)
                {
                    if(getDrawPose())
                    {
                        BoneStart.setValues(0.0,0.0,0.0);
                        BoneEnd.setValues(0.0,0.0,0.0);
                        getSkeleton()->getAbsoluteTransformation(i).mult(BoneEnd,BoneEnd);
                        getSkeleton()->getAbsoluteTransformation(ParentIndex).mult(BoneStart,BoneStart);
                        glColor4fv(getPoseColor().getValuesRGBA());
                        glVertex3fv(BoneStart.getValues());
                        glVertex3fv(BoneEnd.getValues());
                    }
                    if(getDrawBindPose())
                    {
                        BoneStart.setValues(0.0f,0.0f,0.0f);
                        BoneEnd.setValues(0.0f,0.0f,0.0f);
                        getSkeleton()->getAbsoluteBindTransformation(i).mult(BoneEnd,BoneEnd);
                        getSkeleton()->getAbsoluteBindTransformation(ParentIndex).mult(BoneStart,BoneStart);
                        glColor4fv(getBindPoseColor().getValuesRGBA());
                        glVertex3fv(BoneStart.getValues());
                        glVertex3fv(BoneEnd.getValues());
                    }
                }
            }
        glEnd();
    }
}
void getSkels(std::vector<mapping_msgs::PolygonalMap> &pmaps, body_msgs::Skeletons &skels){
   XnUserID aUsers[15];
   XnUInt16 nUsers = 15;
   g_UserGenerator.GetUsers(aUsers, nUsers);
   for (int i = 0; i < nUsers; ++i)
   {
      if (g_bDrawSkeleton && g_UserGenerator.GetSkeletonCap().IsTracking(aUsers[i]))
            {
               body_msgs::Skeleton skel;
               getSkeleton(aUsers[i],skel);
               skels.skeletons.push_back(skel);



               mapping_msgs::PolygonalMap pmap;
               getPolygon(aUsers[i], XN_SKEL_HEAD, XN_SKEL_NECK, pmap);
//               printPt(aUsers[i], XN_SKEL_RIGHT_HAND);
               getPolygon(aUsers[i], XN_SKEL_NECK, XN_SKEL_LEFT_SHOULDER, pmap);
               getPolygon(aUsers[i], XN_SKEL_LEFT_SHOULDER, XN_SKEL_LEFT_ELBOW, pmap);
               getPolygon(aUsers[i], XN_SKEL_LEFT_SHOULDER, XN_SKEL_RIGHT_SHOULDER, pmap);
//               ptdist(pmap.polygons.back());
               getPolygon(aUsers[i], XN_SKEL_LEFT_ELBOW, XN_SKEL_LEFT_HAND, pmap);
               getPolygon(aUsers[i], XN_SKEL_NECK, XN_SKEL_RIGHT_SHOULDER, pmap);
               getPolygon(aUsers[i], XN_SKEL_RIGHT_SHOULDER, XN_SKEL_RIGHT_ELBOW, pmap);
               getPolygon(aUsers[i], XN_SKEL_RIGHT_ELBOW, XN_SKEL_RIGHT_HAND, pmap);
               getPolygon(aUsers[i], XN_SKEL_LEFT_SHOULDER, XN_SKEL_TORSO, pmap);
               getPolygon(aUsers[i], XN_SKEL_RIGHT_SHOULDER, XN_SKEL_TORSO, pmap);
               getPolygon(aUsers[i], XN_SKEL_TORSO, XN_SKEL_LEFT_HIP, pmap);
               getPolygon(aUsers[i], XN_SKEL_LEFT_HIP, XN_SKEL_LEFT_KNEE, pmap);
               getPolygon(aUsers[i], XN_SKEL_LEFT_KNEE, XN_SKEL_LEFT_FOOT, pmap);
               getPolygon(aUsers[i], XN_SKEL_TORSO, XN_SKEL_RIGHT_HIP, pmap);
               getPolygon(aUsers[i], XN_SKEL_RIGHT_HIP, XN_SKEL_RIGHT_KNEE, pmap);
               getPolygon(aUsers[i], XN_SKEL_RIGHT_KNEE, XN_SKEL_RIGHT_FOOT, pmap);
               getPolygon(aUsers[i], XN_SKEL_LEFT_HIP, XN_SKEL_RIGHT_HIP, pmap);
//               getSkel(aUsers[i],pmap);
               pmaps.push_back(pmap);
            }
   }

}
예제 #28
0
void Model::setAnimation(Animation* animation)
{
	assert( mesh != nullptr );

	if( !mesh->isAnimated() ) return;

	if( !animation ) return;

	AnimationState state;
	state.animation = animation;
	state.animationTime = 0;

	size_t numBones = mesh->getSkeleton()->getBones().size();
	state.bonesMatrix.resize(numBones);

	if( animations.empty() )
		animations.push_back(state);
	else
		animations[0] = state;

	animationEnabled = true;
}
예제 #29
0
파일: World.cpp 프로젝트: ehuang3/dart
void World::setState(const Eigen::VectorXd& _newState)
{
    for (int i = 0; i < getNumSkeletons(); i++)
    {
        int start = mIndices[i] * 2;
        int size = getSkeleton(i)->getNumDofs();

        VectorXd pose = _newState.segment(start, size);
        VectorXd qDot = _newState.segment(start + size, size);
        getSkeleton(i)->clampRotation(pose, qDot);
        if (getSkeleton(i)->getImmobileState())
        {
            // need to update node transformation for collision
            getSkeleton(i)->setPose(pose, true, false);
        }
        else
        {
            // need to update first derivatives for collision
            getSkeleton(i)->setPose(pose, false, true);
            getSkeleton(i)->computeDynamics(mGravity, qDot, true);
        }

    }
}
예제 #30
0
파일: fbxRNode.cpp 프로젝트: Jeff885/osg
osgDB::ReaderWriter::ReadResult OsgFbxReader::readFbxNode(
    FbxNode* pNode,
    bool& bIsBone, int& nLightCount)
{
    if (FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute())
    {
        FbxNodeAttribute::EType attrType = lNodeAttribute->GetAttributeType();
        switch (attrType)
        {
        case FbxNodeAttribute::eNurbs:
        case FbxNodeAttribute::ePatch:
        case FbxNodeAttribute::eNurbsCurve:
        case FbxNodeAttribute::eNurbsSurface:
        {
            FbxGeometryConverter lConverter(&pSdkManager);
#if FBXSDK_VERSION_MAJOR < 2014
            if (!lConverter.TriangulateInPlace(pNode))
#else
            if (!lConverter.Triangulate(lNodeAttribute,true,false))
#endif
            {
                OSG_WARN << "Unable to triangulate FBX NURBS " << pNode->GetName() << std::endl;
            }
        }
        break;
        default:
            break;
        }
    }

    bIsBone = false;
    bool bCreateSkeleton = false;

    FbxNodeAttribute::EType lAttributeType = FbxNodeAttribute::eUnknown;
    if (pNode->GetNodeAttribute())
    {
        lAttributeType = pNode->GetNodeAttribute()->GetAttributeType();
        if (lAttributeType == FbxNodeAttribute::eSkeleton)
        {
            bIsBone = true;
        }
    }

    if (!bIsBone && fbxSkeletons.find(pNode) != fbxSkeletons.end())
    {
        bIsBone = true;
    }

    unsigned nMaterials = pNode->GetMaterialCount();
    std::vector<StateSetContent > stateSetList;

    for (unsigned i = 0; i < nMaterials; ++i)
    {
        FbxSurfaceMaterial* fbxMaterial = pNode->GetMaterial(i);
        assert(fbxMaterial);
        stateSetList.push_back(fbxMaterialToOsgStateSet.convert(fbxMaterial));
    }

    osg::NodeList skeletal, children;

    int nChildCount = pNode->GetChildCount();
    for (int i = 0; i < nChildCount; ++i)
    {
        FbxNode* pChildNode = pNode->GetChild(i);

        if (pChildNode->GetParent() != pNode)
        {
            //workaround for bug that occurs in some files exported from Blender
            continue;
        }

        bool bChildIsBone = false;
        osgDB::ReaderWriter::ReadResult childResult = readFbxNode(
                    pChildNode, bChildIsBone, nLightCount);
        if (childResult.error())
        {
            return childResult;
        }
        else if (osg::Node* osgChild = childResult.getNode())
        {
            if (bChildIsBone)
            {
                if (!bIsBone) bCreateSkeleton = true;
                skeletal.push_back(osgChild);
            }
            else
            {
                children.push_back(osgChild);
            }
        }
    }

    std::string animName = readFbxAnimation(pNode, pNode->GetName());

    osg::Matrix localMatrix;
    makeLocalMatrix(pNode, localMatrix);
    bool bLocalMatrixIdentity = localMatrix.isIdentity();

    osg::ref_ptr<osg::Group> osgGroup;

    bool bEmpty = children.empty() && !bIsBone;

    switch (lAttributeType)
    {
    case FbxNodeAttribute::eMesh:
    {
        size_t bindMatrixCount = boneBindMatrices.size();
        osgDB::ReaderWriter::ReadResult meshRes = readFbxMesh(pNode, stateSetList);
        if (meshRes.error())
        {
            return meshRes;
        }
        else if (osg::Node* node = meshRes.getNode())
        {
            bEmpty = false;

            if (bindMatrixCount != boneBindMatrices.size())
            {
                //The mesh is skinned therefore the bind matrix will handle all transformations.
                localMatrix.makeIdentity();
                bLocalMatrixIdentity = true;
            }

            if (animName.empty() &&
                    children.empty() &&
                    skeletal.empty() &&
                    bLocalMatrixIdentity)
            {
                return osgDB::ReaderWriter::ReadResult(node);
            }

            children.insert(children.begin(), node);
        }
    }
    break;
    case FbxNodeAttribute::eCamera:
    case FbxNodeAttribute::eLight:
    {
        osgDB::ReaderWriter::ReadResult res =
            lAttributeType == FbxNodeAttribute::eCamera ?
            readFbxCamera(pNode) : readFbxLight(pNode, nLightCount);
        if (res.error())
        {
            return res;
        }
        else if (osg::Group* resGroup = dynamic_cast<osg::Group*>(res.getObject()))
        {
            bEmpty = false;
            if (animName.empty() &&
                    bLocalMatrixIdentity)
            {
                osgGroup = resGroup;
            }
            else
            {
                children.insert(children.begin(), resGroup);
            }
        }
    }
    break;
    default:
        break;
    }

    if (bEmpty)
    {
        osgDB::ReaderWriter::ReadResult(0);
    }

    if (!osgGroup) osgGroup = createGroupNode(pSdkManager, pNode, animName, localMatrix, bIsBone, nodeMap, fbxScene);

    osg::Group* pAddChildrenTo = osgGroup.get();
    if (bCreateSkeleton)
    {
        osgAnimation::Skeleton* osgSkeleton = getSkeleton(pNode, fbxSkeletons, skeletonMap);
        osgSkeleton->setDefaultUpdateCallback();
        pAddChildrenTo->addChild(osgSkeleton);
        pAddChildrenTo = osgSkeleton;
    }

    for (osg::NodeList::iterator it = skeletal.begin(); it != skeletal.end(); ++it)
    {
        pAddChildrenTo->addChild(it->get());
    }
    for (osg::NodeList::iterator it = children.begin(); it != children.end(); ++it)
    {
        pAddChildrenTo->addChild(it->get());
    }


    return osgDB::ReaderWriter::ReadResult(osgGroup.get());
}