//----------------------------
// Function name: read
//----------------------------
//
//Parameters:
//p: Scene &image, const char *fileName
//GlobalVars:
//g:
//Returns:
//r:bool
// Caution
//c:
//Assumations:
//a:
//Describtions:
//d: read the image from the given file
//SeeAlso:
//s:
//
//------------------------------
NodeTransitPtr OBJSceneFileType::read(      std::istream &is,
                                      const Char8        *,
                                            Resolver        ) const
{
    NodeUnrecPtr rootPtr, nodePtr;
    std::string elem;
    std::map<std::string, DataElem>::const_iterator elemI;
    Vec3f vec3r;
    Pnt3f pnt3r;
    Vec2f vec2r;
    Real32 x,y,z;
    GeoPnt3fPropertyUnrecPtr coordPtr    = GeoPnt3fProperty::create();
    GeoVec2fPropertyUnrecPtr texCoordPtr = GeoVec2fProperty::create();
    GeoVec3fPropertyUnrecPtr normalPtr   = GeoVec3fProperty::create();
    GeometryUnrecPtr geoPtr;
    GeoIntegralPropertyUnrecPtr posIndexPtr, texIndexPtr, normalIndexPtr;
    GeoIntegralPropertyUnrecPtr lensPtr;
    GeoIntegralPropertyUnrecPtr typePtr;
    DataElem dataElem;
    DataElem lastDataElem;
    Char8 strBuf[8192], *token, *nextToken;
    Int32 strBufSize = sizeof(strBuf)/sizeof(Char8);
    Int32 index, posIndex = 0, indexType;
    Int32 i,j,n,primCount[3];
    std::list<Mesh> meshList;
    std::map<std::string, SimpleTexturedMaterialUnrecPtr> mtlMap;
    std::map<std::string, SimpleTexturedMaterialUnrecPtr>::iterator mtlI;
    Mesh emptyMesh;
    Face emptyFace;
    TiePoint  emptyTie;
    Int32 indexMask, meshIndexMask;
    std::list<Face>::iterator faceI;
    std::list<Mesh>::iterator meshI;
    bool isSingleIndex;

    // create the first mesh entry
    meshList.push_back(emptyMesh);
    meshI = meshList.begin();

    if(is)
    {
        primCount[0] = 0;
        primCount[1] = 0;
        primCount[2] = 0;

        for(is >> elem; is.eof() == false; is >> elem)
        {
            if(elem[0] == '#' || elem[0] == '$')
            {
                is.ignore(INT_MAX, '\n');
            }
            else
            {
                SceneFileHandler::the()->updateReadProgress();

                elemI = _dataElemMap.find(elem);
                dataElem = ((elemI == _dataElemMap.end()) ?
                        UNKNOWN_DE : elemI->second );
                switch (dataElem)
                {
                    case OBJECT_DE:
                    case GROUP_DE:
                    case SMOOTHING_GROUP_DE:
                        is.ignore(INT_MAX, '\n');
                    break;
                    case VERTEX_DE:
                        primCount[0]++;
                        is >> x >> y >> z;
                        pnt3r.setValues(x,y,z);
                        coordPtr->addValue(pnt3r);
                    break;
                    case VERTEX_TEXTURECOORD_DE:
                        primCount[1]++;
                        is >> x >> y;
                        vec2r.setValues(x,y);
                        texCoordPtr->addValue(vec2r);
                    break;
                    case VERTEX_NORMAL_DE:
                        primCount[2]++;
                        is >> x >> y >> z;
                        vec3r.setValues(x,y,z);
                        normalPtr->addValue(vec3r);
                    break;
                    case LIB_MTL_DE:
                        is >> elem;
                        readMTL ( elem.c_str(), mtlMap );
                        is.ignore(INT_MAX, '\n');
                    break;
                    case USE_MTL_DE:
                        is >> elem;
                        if (meshI->faceList.empty() == false)
                        {
                            meshList.push_front(emptyMesh);
                            meshI = meshList.begin();
                        }
                        mtlI = mtlMap.find(elem);
                        if (mtlI == mtlMap.end())
                        {
                            FFATAL (("Unkown mtl %s\n", elem.c_str()));
                        }
                        else
                        {
                            meshI->mtlPtr = mtlI->second;
                        }
                    break;
                    case FACE_DE:
                        meshI->faceList.push_front(emptyFace);
                        faceI = meshI->faceList.begin();
                        is.get(strBuf,strBufSize);
                        token = strBuf;
                        indexType = 0;
                        while(token && *token)
                        {
                            // some tools use line continuation for long
                            // face definitions - these use a \ at the line
                            // end
                            if(*token == '\\')
                            {
                                is.ignore(1, '\n');
                                is.get(strBuf,strBufSize);
                                token = strBuf;
                                indexType = 0;
                                continue;
                            }
                            for (; *token == '/'; token++)
                                indexType++;
                            for (; isspace(*token); token++)
                                indexType = 0;
                            index = strtol(token, &nextToken, 10);
                            if (token == nextToken)
                                break;
                            if (indexType == 0)
                                faceI->tieVec.push_back(emptyTie);
                            if (index >= 0)
                                index--;
                            else
                                index =  primCount[indexType] + index;
                            faceI->tieVec.back().index[indexType] = index;
                            token = nextToken;
                        }
                    break;

                    case UNKNOWN_DE:
                    default:
                        // don't warn about 3rd tex coord
                        if(lastDataElem != VERTEX_TEXTURECOORD_DE)
                        {
                            FWARNING (( "Unkown obj data elem: %s\n", 
                                        elem.c_str()));
                        }
                        is.ignore(INT_MAX, '\n');
                    break;
                }

                lastDataElem = dataElem;
            }
        }

#if 0
        std::cerr << "------------------------------------------------" << std::endl;
        i = 0;
        for (meshI = meshList.begin(); meshI != meshList.end(); meshI++)
        {
            std::cerr << "Mesh " << i << " faceCount :"
                      << meshI->faceList.size() << std::endl;
            j = 0 ;
            for ( faceI = meshI->faceList.begin(); faceI != meshI->faceList.end();
                  faceI++)
            std::cerr << "MESH " <<  i << "face: " << j++ << "tie num: "
                      << faceI->tieVec.size() << std::endl;
            i++;
        }
        std::cerr << "------------------------------------------------" << std::endl;
#endif

        // create Geometry objects
        for (meshI = meshList.begin(); meshI != meshList.end(); meshI++)
        {
            geoPtr   = Geometry::create();
            posIndexPtr = NULL;
            texIndexPtr = NULL;
            normalIndexPtr = NULL;
            lensPtr  = GeoUInt32Property::create();
            typePtr  = GeoUInt8Property ::create();

            // create and check mesh index mask
            meshIndexMask = 0;
            isSingleIndex = true;
            if ( meshI->faceList.empty() == false)
            {
                for ( faceI = meshI->faceList.begin();
                  faceI != meshI->faceList.end(); faceI++)
                {
                    indexMask = 0;
                    n = UInt32(faceI->tieVec.size());
                    for (i = 0; i < n; i++)
                    {
                        for (j = 0; j < 3; j++)
                        {
                            if ((index = (faceI->tieVec[i].index[j])) >= 0)
                            {
                                indexMask |= (1 << j);
                                if (j)
                                    isSingleIndex &= (posIndex == index);
                                else
                                    posIndex = index;
                            }
                        }
                    }
                    if (meshIndexMask == 0)
                    {
                        meshIndexMask = indexMask;
                    }
                    else if (meshIndexMask != indexMask)
                    {
                        // consider this real-world example:
                       // [...]
                       // f 1603//1747 1679//1744 1678//1743
                       // s 1
                       // f 9/1/10 5/2/9 1680/3/1748 1681/4/174
                       // [...]
                       // Some faces contain texture coords and others do not.
                       // The old version did just skip this geometry.
                       // This version should continue if there's at least
                       // the vertex index
                       // I've seen the change in the maskIndex only after a smooth group,
                       // so it's perhaps smarter to not ignore the smooth group further up in this code
                       if( !(indexMask & 1) )
                       {
                         // if there are vertex indices there's no reason to get in here
                          FFATAL (( "IndexMask unmatch, can not create geo\n"));
                          meshIndexMask = 0;
                          break;
                       }
                       else
                       {
                         // consider the minimum similarities of mesh masks
                         meshIndexMask &= indexMask;
                       }
                    }
                }
            }
            else
            {
                FWARNING (("Mesh with empty faceList\n"));
            }

            // fill the geo properties
            if (meshIndexMask)
            {
                geoPtr->setPositions ( coordPtr );
                posIndexPtr = GeoUInt32Property::create();
                if(!isSingleIndex)
                    geoPtr->setIndex(posIndexPtr, Geometry::PositionsIndex);
                geoPtr->setLengths   ( lensPtr );
                geoPtr->setTypes     ( typePtr );

                if ( (meshIndexMask & 2) && texCoordPtr->size() > 0 )
                {
                    geoPtr->setTexCoords ( texCoordPtr );
                    texIndexPtr = GeoUInt32Property::create();
                    if(!isSingleIndex)
                        geoPtr->setIndex(texIndexPtr, Geometry::TexCoordsIndex);
                }
                else
                {
                    geoPtr->setTexCoords ( NULL );
                }

                if ( (meshIndexMask & 4) && normalPtr->size() > 0 )
                {
                    geoPtr->setNormals   ( normalPtr );
                    normalIndexPtr = GeoUInt32Property::create();
                    if(!isSingleIndex)
                        geoPtr->setIndex(normalIndexPtr, Geometry::NormalsIndex);
                }
                else
                {
                    geoPtr->setNormals   ( NULL );
                }

                if (meshI->mtlPtr == NULL)
                {
                    meshI->mtlPtr = SimpleTexturedMaterial::create();
                    meshI->mtlPtr->setDiffuse( Color3f( .8f, .8f, .8f ) );
                    meshI->mtlPtr->setSpecular( Color3f( 1.f, 1.f, 1.f ) );
                    meshI->mtlPtr->setShininess( 20.f );
                }
                geoPtr->setMaterial  ( meshI->mtlPtr );

                for ( faceI = meshI->faceList.begin();
                      faceI != meshI->faceList.end(); faceI++)
                {
                    n = UInt32(faceI->tieVec.size());

                    // add the lens entry
                    lensPtr->push_back(n);

                    // add the type entry
                    typePtr->push_back(GL_POLYGON);

                    // create the index values
                    for (i = 0; i < n; i++)
                    {
                        if (isSingleIndex)
                        {
                            posIndexPtr->push_back(faceI->tieVec[i].index[0]);
                        }
                        else
                        {
                            posIndexPtr->push_back(faceI->tieVec[i].index[0]);
                            if(texIndexPtr != NULL)
                                texIndexPtr->push_back(faceI->tieVec[i].index[1]);
                            if(normalIndexPtr != NULL)
                                normalIndexPtr->push_back(faceI->tieVec[i].index[2]);
                        }
                    }
                }

                if(isSingleIndex)
                {
                    geoPtr->setIndex(posIndexPtr, Geometry::PositionsIndex);
                    geoPtr->setIndex(posIndexPtr, Geometry::NormalsIndex  );
                    geoPtr->setIndex(posIndexPtr, Geometry::TexCoordsIndex);
                }

                // need to port the geometry functions ...
                createSharedIndex( geoPtr );

                // check if we have normals
                // need to port the geometry functions ...

                if(geoPtr->getNormals() == NULL)
                    calcVertexNormals(geoPtr);

                // create and link the node
                nodePtr = Node::create();
                nodePtr->setCore( geoPtr );

                if (meshList.size() > 1)
                {
                    if (rootPtr == NULL)
                    {
                        rootPtr = Node::create();

                        GroupUnrecPtr tmpPtr = Group::create();

                        rootPtr->setCore ( tmpPtr );
                        rootPtr->addChild(nodePtr);
                    }
                    else
                    {
                        rootPtr->addChild(nodePtr);
                    }
                }
                else
                {
                    rootPtr = nodePtr;
                }
            }
        }
    }

    SceneFileHandler::the()->updateReadProgress(100);

    commitChanges();

    return NodeTransitPtr(rootPtr);
}
int main(int argc, char **argv)
{
    // OSG init
    osgInit(argc,argv);

    // Set up Window
    TutorialWindow = createNativeWindow();
    TutorialWindow->initWindow();

    TutorialWindow->setDisplayCallback(display);
    TutorialWindow->setReshapeCallback(reshape);

    //Add Window Listener
    TutorialKeyListener TheKeyListener;
    TutorialWindow->addKeyListener(&TheKeyListener);
    TutorialMouseListener TheTutorialMouseListener;
    TutorialMouseMotionListener TheTutorialMouseMotionListener;
    TutorialWindow->addMouseListener(&TheTutorialMouseListener);
    TutorialWindow->addMouseMotionListener(&TheTutorialMouseMotionListener);

    // Create the SimpleSceneManager helper
    mgr = new SimpleSceneManager;

    // Tell the Manager what to manage
    mgr->setWindow(TutorialWindow);

    //Print key command info
    std::cout << "\n\nKEY COMMANDS:" << std::endl;
    std::cout << "space   Play/Pause the animation" << std::endl;
    std::cout << "B       Show/Hide the bind pose skeleton" << std::endl;
    std::cout << "SHIFT-B Show/Hide the bind pose mesh" << std::endl;
    std::cout << "P       Show/Hide the current pose skeleton" << std::endl;
    std::cout << "SHIFT-P Show/Hide the current pose mesh" << std::endl;
    std::cout << "CTRL-Q  Exit\n\n" << std::endl;


    //SkeletonDrawer System Material
    LineChunkUnrecPtr ExampleLineChunk = LineChunk::create();
    ExampleLineChunk->setWidth(2.0f);
    ExampleLineChunk->setSmooth(true);

    BlendChunkUnrecPtr ExampleBlendChunk = BlendChunk::create();
    ExampleBlendChunk->setSrcFactor(GL_SRC_ALPHA);
    ExampleBlendChunk->setDestFactor(GL_ONE_MINUS_SRC_ALPHA);

    MaterialChunkUnrecPtr ExampleMaterialChunk = MaterialChunk::create();
    ExampleMaterialChunk->setAmbient(Color4f(1.0f,1.0f,1.0f,1.0f));
    ExampleMaterialChunk->setDiffuse(Color4f(0.0f,0.0f,0.0f,1.0f));
    ExampleMaterialChunk->setSpecular(Color4f(0.0f,0.0f,0.0f,1.0f));

    ChunkMaterialUnrecPtr ExampleMaterial = ChunkMaterial::create();
    ExampleMaterial->addChunk(ExampleLineChunk);
    ExampleMaterial->addChunk(ExampleMaterialChunk);
    ExampleMaterial->addChunk(ExampleBlendChunk);


    //Skeleton
    ExampleSkeleton = SkeletonBlendedGeometry::create();

    //===========================================Joints==================================================================
    Matrix TempMat;
    Matrix InvBind;

    /*================================================================================================*/
    /*                                       Pelvis                                                   */
    Pelvis = Joint::create(); //create a joint called Pelvis 
    TempMat.setTranslate(0.0,7.0,0.0);
    Pelvis->setJointTransformation(TempMat);

    NodeRecPtr PelvisNode = makeNodeFor(Pelvis);

    InvBind = PelvisNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(Pelvis, InvBind);
    setName(Pelvis, "Pelvis Joint");
    setName(PelvisNode, "Pelvis Node");
    
    /*================================================================================================*/
    /*                                       Clavicle                                                   */
    Clavicle = Joint::create(); //create a joint called Clavicle 
    TempMat.setTranslate(0.0,5.0,0.0);
    Clavicle->setJointTransformation(TempMat);

    NodeRecPtr ClavicleNode = makeNodeFor(Clavicle);
    PelvisNode->addChild(ClavicleNode);

    InvBind = ClavicleNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(Clavicle, InvBind);
    setName(Clavicle, "Clavicle Joint");
    setName(ClavicleNode, "Clavicle Node");

    /*================================================================================================*/
    /*                                       Left Shoulder                                                 */
    LeftShoulder = Joint::create(); //create a joint called LeftShoulder 
    TempMat.setTranslate(1.0,-0.5,0.0);
    LeftShoulder->setJointTransformation(TempMat);

    NodeRecPtr LeftShoulderNode = makeNodeFor(LeftShoulder);
    ClavicleNode->addChild(LeftShoulderNode);

    InvBind = LeftShoulderNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(LeftShoulder, InvBind);
    setName(LeftShoulder, "Left Shoulder Joint");
    setName(LeftShoulderNode, "Left Shoulder Node");

    /*================================================================================================*/
    /*                                       Left Elbow                                                 */
    LeftElbow = Joint::create(); //create a joint called LeftElbow 
    TempMat.setTranslate(2.0,0.0,0.0);
    LeftElbow->setJointTransformation(TempMat);

    NodeRecPtr LeftElbowNode = makeNodeFor(LeftElbow);
    LeftShoulderNode->addChild(LeftElbowNode);

    InvBind = LeftElbowNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(LeftElbow, InvBind);
    setName(LeftElbow, "Left Elbow Joint");
    setName(LeftElbowNode, "Left Elbow Node");

    /*================================================================================================*/
    /*                                       Left Hand                                                 */
    LeftHand = Joint::create(); //create a joint called LeftHand 
    TempMat.setTranslate(2.0,0.0,0.0);
    LeftHand->setJointTransformation(TempMat);

    NodeRecPtr LeftHandNode = makeNodeFor(LeftHand);
    LeftElbowNode->addChild(LeftHandNode);

    InvBind = LeftHandNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(LeftHand, InvBind);
    setName(LeftHand, "Left Hand Joint");
    setName(LeftHandNode, "Left Hand Node");
    /*================================================================================================*/
    /*                                       Left Fingers                                                 */
    LeftFingers = Joint::create(); //create a joint called LeftFingers 
    TempMat.setTranslate(1.0,0.0,0.0);
    LeftFingers->setJointTransformation(TempMat);

    NodeRecPtr LeftFingersNode = makeNodeFor(LeftFingers);
    LeftHandNode->addChild(LeftFingersNode);

    InvBind = LeftFingersNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(LeftFingers, InvBind);
    setName(LeftFingers, "Left Fingers Joint");
    setName(LeftFingersNode, "Left Fingers Node");

    /*================================================================================================*/
    /*                                       Right Shoulder                                                 */
    RightShoulder = Joint::create(); //create a joint called RightShoulder 
    TempMat.setTranslate(-1.0,-0.5,0.0);
    RightShoulder->setJointTransformation(TempMat);

    NodeRecPtr RightShoulderNode = makeNodeFor(RightShoulder);
    ClavicleNode->addChild(RightShoulderNode);

    InvBind = RightShoulderNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(RightShoulder, InvBind);
    setName(RightShoulder, "Right Shoulder Joint");
    setName(RightShoulderNode, "Right Shoulder Node");

    /*================================================================================================*/
    /*                                       Right Elbow                                                 */
    RightElbow = Joint::create(); //create a joint called RightElbow 
    TempMat.setTranslate(-2.0,0.0,0.0);
    RightElbow->setJointTransformation(TempMat);

    NodeRecPtr RightElbowNode = makeNodeFor(RightElbow);
    RightShoulderNode->addChild(RightElbowNode);

    InvBind = RightElbowNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(RightElbow, InvBind);
    setName(RightElbow, "Right Elbow Joint");
    setName(RightElbowNode, "Right Elbow Node");

    /*================================================================================================*/
    /*                                       Right Hand                                                 */
    RightHand = Joint::create(); //create a joint called RightHand 
    TempMat.setTranslate(-2.0,0.0,0.0);
    RightHand->setJointTransformation(TempMat);

    NodeRecPtr RightHandNode = makeNodeFor(RightHand);
    RightElbowNode->addChild(RightHandNode);

    InvBind = RightHandNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(RightHand, InvBind);
    setName(RightHand, "Right Hand Joint");
    setName(RightHandNode, "Right Hand Node");

    /*================================================================================================*/
    /*                                       Right Fingers                                                 */
    RightFingers = Joint::create(); //create a joint called RightFingers 
    TempMat.setTranslate(-1.0,0.0,0.0);
    RightFingers->setJointTransformation(TempMat);

    NodeRecPtr RightFingersNode = makeNodeFor(RightFingers);
    RightHandNode->addChild(RightFingersNode);

    InvBind = RightFingersNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(RightFingers, InvBind);
    setName(RightFingers, "Right Fingers Joint");
    setName(RightFingersNode, "Right Fingers Node");

    /*================================================================================================*/
    /*                                       Head                                                 */
    Head = Joint::create(); //create a joint called Head 
    TempMat.setTranslate(0.0,1.0,0.0);
    Head->setJointTransformation(TempMat);

    NodeRecPtr HeadNode = makeNodeFor(Head);
    ClavicleNode->addChild(HeadNode);

    InvBind = HeadNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(Head, InvBind);
    setName(Head, "Head Joint");
    setName(HeadNode, "Head Node");

    /*================================================================================================*/
    /*                                       Left Hip                                                 */
    LeftHip = Joint::create(); //create a joint called LeftHip 
    TempMat.setTranslate(1.0,-1.0,0.0);
    LeftHip->setJointTransformation(TempMat);

    NodeRecPtr LeftHipNode = makeNodeFor(LeftHip);
    PelvisNode->addChild(LeftHipNode);

    InvBind = LeftHipNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(LeftHip, InvBind);
    setName(LeftHip, "Left Hip Joint");
    setName(LeftHipNode, "Left Hip Node");

    /*================================================================================================*/
    /*                                       Left Knee                                                 */
    LeftKnee = Joint::create(); //create a joint called LeftKnee 
    TempMat.setTranslate(0.0,-3.0,0.0);
    LeftKnee->setJointTransformation(TempMat);

    NodeRecPtr LeftKneeNode = makeNodeFor(LeftKnee);
    LeftHipNode->addChild(LeftKneeNode);

    InvBind = LeftKneeNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(LeftKnee, InvBind);
    setName(LeftKnee, "Left Knee Joint");
    setName(LeftKneeNode, "Left Knee Node");

    /*================================================================================================*/
    /*                                       Left Foot                                                 */
    LeftFoot = Joint::create(); //create a joint called LeftFoot 
    TempMat.setTranslate(0.0,-3.0,0.0);
    LeftFoot->setJointTransformation(TempMat);

    NodeRecPtr LeftFootNode = makeNodeFor(LeftFoot);
    LeftKneeNode->addChild(LeftFootNode);

    InvBind = LeftFootNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(LeftFoot, InvBind);
    setName(LeftFoot, "Left Foot Joint");
    setName(LeftFootNode, "Left Foot Node");

    /*================================================================================================*/
    /*                                       Left Toes                                                 */
    LeftToes = Joint::create(); //create a bone called ExampleChildbone
    TempMat.setTranslate(0.0,0.0,1.0);
    LeftToes->setJointTransformation(TempMat);

    NodeRecPtr LeftToesNode = makeNodeFor(LeftToes);
    LeftFootNode->addChild(LeftToesNode);

    InvBind = LeftToesNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(LeftToes, InvBind);
    setName(LeftToes, "Left Toes Joint");
    setName(LeftToesNode, "Left Toes Node");

    /*================================================================================================*/
    /*                                       Right Hip                                                 */
    RightHip = Joint::create(); //create a joint called RightHip 
    TempMat.setTranslate(-1.0,-1.0,0.0);
    RightHip->setJointTransformation(TempMat);

    NodeRecPtr RightHipNode = makeNodeFor(RightHip);
    PelvisNode->addChild(RightHipNode);

    InvBind = RightHipNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(RightHip, InvBind);
    setName(RightHip, "Right Hip Joint");
    setName(RightHipNode, "Right Hip Node");

    /*================================================================================================*/
    /*                                       Right Knee                                                 */
    RightKnee = Joint::create(); //create a joint called RightKnee 
    TempMat.setTranslate(0.0,-3.0,0.0);
    RightKnee->setJointTransformation(TempMat);

    NodeRecPtr RightKneeNode = makeNodeFor(RightKnee);
    RightHipNode->addChild(RightKneeNode);

    InvBind = RightKneeNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(RightKnee, InvBind);
    setName(RightKnee, "Right Knee Joint");
    setName(RightKneeNode, "Right Knee Node");

    /*================================================================================================*/
    /*                                       Right Foot                                                 */
    RightFoot = Joint::create(); //create a joint called RightFoot 
    TempMat.setTranslate(0.0,-3.0,0.0);
    RightFoot->setJointTransformation(TempMat);

    NodeRecPtr RightFootNode = makeNodeFor(RightFoot);
    RightKneeNode->addChild(RightFootNode);

    InvBind = RightFootNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(RightFoot, InvBind);
    setName(RightFoot, "Right Foot Joint");
    setName(RightFootNode, "Right Foot Node");
    
    /*================================================================================================*/
    /*                                       Right Toes                                                 */
    RightToes = Joint::create(); //create a joint called RightToes 
    TempMat.setTranslate(0.0,0.0,1.0);
    RightToes->setJointTransformation(TempMat);

    NodeRecPtr RightToesNode = makeNodeFor(RightToes);
    RightFootNode->addChild(RightToesNode);

    InvBind = RightToesNode->getToWorld();
    InvBind.invert();
    ExampleSkeleton->pushToJoints(RightToes, InvBind);
    setName(RightToes, "Right Toes Joint");
    setName(RightToesNode, "Right Toes Node");


    //Create a geometry to attach to the skeleton (i.e-> skin)
    GeoUInt8PropertyUnrecPtr type = GeoUInt8Property::create();        
        type->push_back(GL_QUADS);

    GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property::create();    
        lens->push_back(72);
    GeoPnt3fPropertyUnrecPtr  pnts  = GeoPnt3fProperty ::create();
        // the points of the Quads

        //Back
        pnts->push_back(Pnt3f(-0.5,  6.0,  0));
        pnts->push_back(Pnt3f( 0.5,  6.0,  0));
        pnts->push_back(Pnt3f( 0.5,  12.0,  0));
        pnts->push_back(Pnt3f(-0.5,  12.0,  0));

        //Head
        pnts->push_back(Pnt3f(-0.5,  12,  0));
        pnts->push_back(Pnt3f( 0.5,  12,  0));
        pnts->push_back(Pnt3f( 0.5,  13,  0));
        pnts->push_back(Pnt3f(-0.5,  13,  0));

        //Left Shoulder
        pnts->push_back(Pnt3f(0.0,  11.5,  0));
        pnts->push_back(Pnt3f(0.0,  12.5,  0));
        pnts->push_back(Pnt3f(1.0,  12.0,  0));
        pnts->push_back(Pnt3f(1.0,  11.0,  0));

        //Left Humerus
        pnts->push_back(Pnt3f(1.0,  11.0,  0));
        pnts->push_back(Pnt3f(1.0,  12.0,  0));
        pnts->push_back(Pnt3f(3.0,  12.0,  0));
        pnts->push_back(Pnt3f(3.0,  11.0,  0));

        //Left Radius
        pnts->push_back(Pnt3f(3.0,  11.0,  0));
        pnts->push_back(Pnt3f(3.0,  12.0,  0));
        pnts->push_back(Pnt3f(5.0,  12.0,  0));
        pnts->push_back(Pnt3f(5.0,  11.0,  0));

        //Left Hand
        pnts->push_back(Pnt3f(5.0,  11.0,  0));
        pnts->push_back(Pnt3f(5.0,  12.0,  0));
        pnts->push_back(Pnt3f(6.0,  12.0,  0));
        pnts->push_back(Pnt3f(6.0,  11.0,  0));

        //Right Shoulder
        pnts->push_back(Pnt3f(0.0,  11.5,  0));
        pnts->push_back(Pnt3f(0.0,  12.5,  0));
        pnts->push_back(Pnt3f(-1.0,  12.0,  0));
        pnts->push_back(Pnt3f(-1.0,  11.0,  0));

        //Right Humerus
        pnts->push_back(Pnt3f(-1.0,  11.0,  0));
        pnts->push_back(Pnt3f(-1.0,  12.0,  0));
        pnts->push_back(Pnt3f(-3.0,  12.0,  0));
        pnts->push_back(Pnt3f(-3.0,  11.0,  0));

        //Right Radius
        pnts->push_back(Pnt3f(-3.0,  11.0,  0));
        pnts->push_back(Pnt3f(-3.0,  12.0,  0));
        pnts->push_back(Pnt3f(-5.0,  12.0,  0));
        pnts->push_back(Pnt3f(-5.0,  11.0,  0));

        //Right Hand
        pnts->push_back(Pnt3f(-5.0,  11.0,  0));
        pnts->push_back(Pnt3f(-5.0,  12.0,  0));
        pnts->push_back(Pnt3f(-6.0,  12.0,  0));
        pnts->push_back(Pnt3f(-6.0,  11.0,  0));

        //Left Hip
        pnts->push_back(Pnt3f(0.0, 6.5,  0));
        pnts->push_back(Pnt3f(0.5, 7.5,  0));
        pnts->push_back(Pnt3f( 1.5,  6.0,  0));
        pnts->push_back(Pnt3f(0.5,  6.0,  0));

        //Left Femur
        pnts->push_back(Pnt3f(0.5,  6.0,  0));
        pnts->push_back(Pnt3f( 1.5,  6.0,  0));
        pnts->push_back(Pnt3f( 1.5,  3.0,  0));
        pnts->push_back(Pnt3f(0.5,  3.0,  0));

        //Left Tibia
        pnts->push_back(Pnt3f(0.5,  3.0,  0));
        pnts->push_back(Pnt3f( 1.5,  3.0,  0));
        pnts->push_back(Pnt3f( 1.5,  0.0,  0));
        pnts->push_back(Pnt3f(0.5,  0.0,  0));

        //Left Foot
        pnts->push_back(Pnt3f(0.5,  0.0,  0));
        pnts->push_back(Pnt3f( 1.5,  0.0,  0));
        pnts->push_back(Pnt3f( 1.5,  0.0,  1.0));
        pnts->push_back(Pnt3f(0.5,  0.0,  1.0));


        //Right Hip
        pnts->push_back(Pnt3f(0.0, 6.5,  0));
        pnts->push_back(Pnt3f(-0.5, 7.5,  0));
        pnts->push_back(Pnt3f( -1.5,  6.0,  0));
        pnts->push_back(Pnt3f(-0.5,  6.0,  0));

        //Right Femur
        pnts->push_back(Pnt3f(-0.5,  6.0,  0));
        pnts->push_back(Pnt3f( -1.5,  6.0,  0));
        pnts->push_back(Pnt3f( -1.5,  3.0,  0));
        pnts->push_back(Pnt3f(-0.5,  3.0,  0));

        //Right Tibia
        pnts->push_back(Pnt3f(-0.5,  3.0,  0));
        pnts->push_back(Pnt3f( -1.5,  3.0,  0));
        pnts->push_back(Pnt3f( -1.5,  0.0,  0));
        pnts->push_back(Pnt3f(-0.5,  0.0,  0));

        //Right Foot
        pnts->push_back(Pnt3f(-0.5,  0.0,  0));
        pnts->push_back(Pnt3f( -1.5,  0.0,  0));
        pnts->push_back(Pnt3f( -1.5,  0.0,  1.0));
        pnts->push_back(Pnt3f(-0.5,  0.0,  1.0));

    //Normals
    GeoVec3fPropertyUnrecPtr  norms = GeoVec3fProperty ::create();
    geo=Geometry::create();
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    //Left Hip
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    //Left Femur
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    //Left Tibia
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    //Left Foot
    norms->push_back(Vec3f( 0.0,1.0,0.0));
    norms->push_back(Vec3f( 0.0,1.0,0.0));
    norms->push_back(Vec3f( 0.0,1.0,0.0));
    norms->push_back(Vec3f( 0.0,1.0,0.0));

    //Right Hip
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    //Right Femur
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    //Right Tibia
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));
    norms->push_back(Vec3f( 0.0,0.0,1.0));

    //Right Foot
    norms->push_back(Vec3f( 0.0,1.0,0.0));
    norms->push_back(Vec3f( 0.0,1.0,0.0));
    norms->push_back(Vec3f( 0.0,1.0,0.0));
    norms->push_back(Vec3f( 0.0,1.0,0.0));

    //Tell the geometry (geo) to use the points and normals we just defined
    geo->setTypes    (type);
    geo->setLengths  (lens);
    geo->setPositions(pnts);
    geo->setNormals(norms);

    // assign a material to the geometry to make it visible. The details
    // of materials are defined later.
    geo->setMaterial(getDefaultMaterial());   

    //Create unbound geometry node (for displaying mesh in its bind pose)
    UnboundGeometry = Node::create();
    UnboundGeometry->setCore(geo);
    UnboundGeometry->setTravMask(0);  //By default, we won't show the mesh's bind pose




    //SkeletonDrawer
    SkeletonDrawableUnrecPtr ExampleSkeletonDrawable = SkeletonDrawable::create();
    ExampleSkeletonDrawable->setSkeleton(ExampleSkeleton);
    ExampleSkeletonDrawable->setMaterial(ExampleMaterial);
    ExampleSkeletonDrawable->setDrawBindPose(false);  //By default, we don't draw the skeleton's bind pose
    ExampleSkeletonDrawable->setBindPoseColor(Color4f(0.0, 1.0, 0.0, 1.0));  //When drawn, the skeleton's bind pose renders green
    ExampleSkeletonDrawable->setDrawPose(true);  //By default, we do draw the skeleton's current pose
    ExampleSkeletonDrawable->setPoseColor(Color4f(0.0, 0.0, 1.0, 1.0));  //The skeleton's current pose renders blue

    //Skeleton Node
    SkeletonNode = Node::create();
    SkeletonNode->setCore(ExampleSkeletonDrawable);




    // Skeleton Blended Geometry
    // Here we are attaching the "skin" to the skeleton so that when the skeleton is animated, the skin moves with it
    ExampleSkeleton->setBaseGeometry(geo);
    //Back
    ExampleSkeleton->addJointBlending(0,Pelvis,1.0f);
    ExampleSkeleton->addJointBlending(1,Pelvis,1.0f);
    ExampleSkeleton->addJointBlending(2,Clavicle,1.0f);
    ExampleSkeleton->addJointBlending(3,Clavicle,1.0f);

    //Head
    ExampleSkeleton->addJointBlending(4,Clavicle,1.0f);
    ExampleSkeleton->addJointBlending(5,Clavicle,1.0f);
    ExampleSkeleton->addJointBlending(6,Head,1.0f);
    ExampleSkeleton->addJointBlending(7,Head,1.0f);

    //Left Shoulder
    ExampleSkeleton->addJointBlending(8,Clavicle,1.0f);
    ExampleSkeleton->addJointBlending(9,Clavicle,1.0f);
    ExampleSkeleton->addJointBlending(10,LeftShoulder,1.0f);
    ExampleSkeleton->addJointBlending(11,LeftShoulder,1.0f);

    //Left Humerus
    ExampleSkeleton->addJointBlending(12,LeftShoulder,1.0f);
    ExampleSkeleton->addJointBlending(13,LeftShoulder,1.0f);
    ExampleSkeleton->addJointBlending(14,LeftElbow,0.8f);
    ExampleSkeleton->addJointBlending(15,LeftElbow,0.8f);
    ExampleSkeleton->addJointBlending(14,LeftHand,0.2f);
    ExampleSkeleton->addJointBlending(15,LeftHand,0.2f);

    //Left Radius
    ExampleSkeleton->addJointBlending(16,LeftElbow,1.0f);
    ExampleSkeleton->addJointBlending(17,LeftElbow,1.0f);
    ExampleSkeleton->addJointBlending(18,LeftHand,1.0f);
    ExampleSkeleton->addJointBlending(19,LeftHand,1.0f);

    //Left Hand
    ExampleSkeleton->addJointBlending(20,LeftHand,1.0f);
    ExampleSkeleton->addJointBlending(21,LeftHand,1.0f);
    ExampleSkeleton->addJointBlending(22,LeftFingers,1.0f);
    ExampleSkeleton->addJointBlending(23,LeftFingers,1.0f);

    //Right Shoulder
    ExampleSkeleton->addJointBlending(24,Clavicle,1.0f);
    ExampleSkeleton->addJointBlending(25,Clavicle,1.0f);
    ExampleSkeleton->addJointBlending(26,RightShoulder,1.0f);
    ExampleSkeleton->addJointBlending(27,RightShoulder,1.0f);

    //Right Humerus
    ExampleSkeleton->addJointBlending(28,RightShoulder,1.0f);
    ExampleSkeleton->addJointBlending(29,RightShoulder,1.0f);
    ExampleSkeleton->addJointBlending(30,RightElbow,1.0f);
    ExampleSkeleton->addJointBlending(31,RightElbow,1.0f);

    //Right Radius
    ExampleSkeleton->addJointBlending(32,RightElbow,1.0f);
    ExampleSkeleton->addJointBlending(33,RightElbow,1.0f);
    ExampleSkeleton->addJointBlending(34,RightHand,1.0f);
    ExampleSkeleton->addJointBlending(35,RightHand,1.0f);

    //Right Hand
    ExampleSkeleton->addJointBlending(36,RightHand,1.0f);
    ExampleSkeleton->addJointBlending(37,RightHand,1.0f);
    ExampleSkeleton->addJointBlending(38,RightFingers,1.0f);
    ExampleSkeleton->addJointBlending(39,RightFingers,1.0f);

    //Left Hip
    ExampleSkeleton->addJointBlending(40,Pelvis,1.0f);
    ExampleSkeleton->addJointBlending(41,Pelvis,1.0f);
    ExampleSkeleton->addJointBlending(42,LeftHip,1.0f);
    ExampleSkeleton->addJointBlending(43,LeftHip,1.0f);

    //Left Femur
    ExampleSkeleton->addJointBlending(44,LeftHip,1.0f);
    ExampleSkeleton->addJointBlending(45,LeftHip,1.0f);
    ExampleSkeleton->addJointBlending(46,LeftKnee,1.0f);
    ExampleSkeleton->addJointBlending(47,LeftKnee,1.0f);

    //Left Tibia
    ExampleSkeleton->addJointBlending(48,LeftKnee,1.0f);
    ExampleSkeleton->addJointBlending(49,LeftKnee,1.0f);
    ExampleSkeleton->addJointBlending(50,LeftFoot,1.0f);
    ExampleSkeleton->addJointBlending(51,LeftFoot,1.0f);

    //Left Foot
    ExampleSkeleton->addJointBlending(52,LeftFoot,1.0f);
    ExampleSkeleton->addJointBlending(53,LeftFoot,1.0f);
    ExampleSkeleton->addJointBlending(54,LeftToes,1.0f);
    ExampleSkeleton->addJointBlending(55,LeftToes,1.0f);

    //Right Hip
    ExampleSkeleton->addJointBlending(56,Pelvis,1.0f);
    ExampleSkeleton->addJointBlending(57,Pelvis,1.0f);
    ExampleSkeleton->addJointBlending(58,RightHip,1.0f);
    ExampleSkeleton->addJointBlending(59,RightHip,1.0f);

    //Right Femur
    ExampleSkeleton->addJointBlending(60,RightHip,1.0f);
    ExampleSkeleton->addJointBlending(61,RightHip,1.0f);
    ExampleSkeleton->addJointBlending(62,RightKnee,1.0f);
    ExampleSkeleton->addJointBlending(63,RightKnee,1.0f);

    //Right Tibia
    ExampleSkeleton->addJointBlending(64,RightKnee,1.0f);
    ExampleSkeleton->addJointBlending(65,RightKnee,1.0f);
    ExampleSkeleton->addJointBlending(66,RightFoot,1.0f);
    ExampleSkeleton->addJointBlending(67,RightFoot,1.0f);

    //Right Foot
    ExampleSkeleton->addJointBlending(68,RightFoot,1.0f);
    ExampleSkeleton->addJointBlending(69,RightFoot,1.0f);
    ExampleSkeleton->addJointBlending(70,RightToes,1.0f);
    ExampleSkeleton->addJointBlending(71,RightToes,1.0f);

    MeshNode = Node::create();
    MeshNode->setCore(ExampleSkeleton);

    //Create scene node 
    NodeUnrecPtr scene = Node::create();
    scene->setCore(Group::create());
    scene->addChild(UnboundGeometry);
    scene->addChild(SkeletonNode);
    scene->addChild(MeshNode);

    mgr->setRoot(scene);

    //Setup the Animation
    setupAnimation();

    //Save to an xml file
    FCFileType::FCPtrStore Containers;
    Containers.insert(ExampleSkeleton);
    Containers.insert(PelvisNode);
    Containers.insert(TheSkeletonAnimation);

    //Use an empty Ignore types vector
    FCFileType::FCTypeVector IgnoreTypes;
    //IgnoreTypes.push_back(Node::getClassType().getId());
    
    //Write the Field Containers to a xml file
    FCFileHandler::the()->write(Containers,BoostPath("./13Output.xml"),IgnoreTypes);

    // Show the whole Scene
    mgr->showAll();


    //Open Window
    Vec2f WinSize(TutorialWindow->getDesktopSize() * 0.85f);
    Pnt2f WinPos((TutorialWindow->getDesktopSize() - WinSize) *0.5);
    TutorialWindow->openWindow(WinPos,
            WinSize,
            "13MeshBlending");

    //Main Loop
    TutorialWindow->mainLoop();


    osgExit();

    return 0;
}
void VTKPolyDataMapper::initGeometries(void)
{
    NodeUnrecPtr pRoot = Node::create();
    
    pRoot->setCore(Group::create());

    setRoot(pRoot);

    for(UInt32 i = 0; i < 4; ++i)
    {
        GeometryUnrecPtr           pGeo      = Geometry::create();
    
        ChunkMaterialUnrecPtr      pMat      = ChunkMaterial::create();
        MaterialChunkUnrecPtr      pMatChunk = MaterialChunk::create();
        
        GeoPnt3fPropertyUnrecPtr   pPoints   = GeoPnt3fProperty  ::create();
        GeoUInt32PropertyUnrecPtr  pLengths  = GeoUInt32Property ::create();
        GeoUInt8PropertyUnrecPtr   pTypes    = GeoUInt8Property  ::create();
        GeoColor4fPropertyUnrecPtr pColors   = GeoColor4fProperty::create();
        GeoVec3fPropertyUnrecPtr   pNormals  = GeoVec3fProperty  ::create();

        if(i < 2)
        {
            pMatChunk->setLit(false);
        }
        
        pMatChunk->setDiffuse  (OSG::Color4f(1.0, 1.0, 1.0, 1.0));
        pMatChunk->setSpecular (OSG::Color4f(0.0, 0.0, 0.0, 1.0));
        pMatChunk->setShininess(10.0f);
        
        pMat->addChunk(pMatChunk);

        TwoSidedLightingChunkUnrecPtr pTSLChunk = 
            TwoSidedLightingChunk::create();
            
        pMat->addChunk(pTSLChunk);

        pGeo->setDlistCache(false   );
        
        pGeo->setMaterial  (pMat    );
        pGeo->setPositions (pPoints );
        pGeo->setLengths   (pLengths);
        pGeo->setTypes     (pTypes  );
        pGeo->setColors    (pColors );

        if(i > 1)
        {
            pGeo->setNormals(pNormals);
        }

        OSG::NodeUnrecPtr pGeoRoot = OSG::Node::create();
        
        pGeoRoot->setCore    (pGeo);
        pGeoRoot->setTravMask(0   );

        pRoot->addChild(pGeoRoot);

        this->pushToGeometries    (pGeo     );
        this->pushToMaterials     (pMat     );
        this->pushToMaterialChunks(pMatChunk);
        this->pushToPositions     (pPoints  );
        this->pushToLength        (pLengths );
        this->pushToTypes         (pTypes   );
        this->pushToColors        (pColors  );
        this->pushToNormals       (pNormals );
        this->pushToGeoRoots      (pGeoRoot );
    }
}
NodeTransitPtr RAWSceneFileType::read(      std::istream &is, 
                                      const Char8        *,
                                            Resolver        ) const
{
    NodeTransitPtr              root;
    GeometryUnrecPtr            geo;
    GeoPnt3fPropertyUnrecPtr    points;
    GeoVec3fPropertyUnrecPtr    normals;
    GeoIntegralPropertyUnrecPtr index;
    GeoIntegralPropertyUnrecPtr lens;
    GeoIntegralPropertyUnrecPtr type;

    Vec3f vec[3];

    UInt32 i = 0, n, triCount = 0;

    Real32 x,y,z;

    if(is)
    {
        root = Node    ::create();
        geo  = Geometry::create();

        root->setCore( geo );

        points = GeoPnt3fProperty::create();

        geo->setPositions(points);

        normals = GeoVec3fProperty::create();

        geo->setNormals(normals);

        triCount = i = 0;


        while(1) 
        {
            is >> x >> y >> z;

            if(is.eof())
            {
                break;
            }
            else 
            {
                points->editFieldPtr()->push_back(Pnt3f(x, y, z));

                vec[i].setValues(x,y,z);

				std::cerr << x << " " << y << " " << z << std::endl;

                if(i == 2) 
                {
                    vec[0] -= vec[1];
                    vec[1] -= vec[2];
                    vec[0].crossThis(vec[1]);
                    vec[0].normalize();

                    normals->editFieldPtr()->push_back(vec[0]);
                    normals->editFieldPtr()->push_back(vec[0]);
                    normals->editFieldPtr()->push_back(vec[0]);

                    i = 0;
                    triCount++;
                }
                else
                {
                    i++;
                }
            }
        }

        if(triCount != 0)
        {
            index = GeoUInt32Property::create();

            geo->setIndex(index, Geometry::PositionsIndex);
            geo->setIndex(index, Geometry::NormalsIndex  );

            n = triCount * 3;

            for(i = 0; i < n; i++)
                index->push_back(i);



            lens = GeoUInt32Property::create();

            geo->setLengths(lens);

            lens->push_back(n);

            type = GeoUInt8Property::create();

            geo->setTypes(type);

            type->push_back(GL_TRIANGLES);
        }

        SimpleMaterialUnrecPtr mat = SimpleMaterial::create();

        mat->setDiffuse  (Color3f(  .8f,  .8f,  .8f));
        mat->setSpecular (Color3f( 1.f,  1.f,  1.f ));
        mat->setShininess(20.f                      );

        geo->setMaterial(mat);
    }

    if(triCount)
    {
        SNOTICE << triCount << " triangle read " << std::endl;
    }

    commitChanges();

    return root;
}