GeometryRefPtr buildTerrain(Vec2f Dimensions, UInt32 XSubdivisions, UInt32 YSubdivisions)
{
    GeoUInt8PropertyRefPtr type = GeoUInt8Property::create();        
    type->addValue(GL_TRIANGLES);

    GeoPnt3fPropertyRefPtr  pnts  = GeoPnt3fProperty ::create();
    GeoVec3fPropertyRefPtr  norms = GeoVec3fProperty ::create();
    Real32 ZScale(8.0);
    for(UInt32 i(0) ; i<XSubdivisions ; ++i)
    {
        for(UInt32 j(0) ; j<YSubdivisions ; ++j)
        {
            Real32 Theta(5*3.14159*(static_cast<Real32>(i)/static_cast<Real32>(XSubdivisions))),
                   ThetaNext(5*3.14159*(static_cast<Real32>(i+1)/static_cast<Real32>(XSubdivisions)));
            // the points of the Tris
            pnts->addValue(Pnt3f(-Dimensions.x()/2.0+i*(Dimensions.x()/static_cast<Real32>(XSubdivisions)),  Dimensions.y()/2.0-j*(Dimensions.y()/static_cast<Real32>(YSubdivisions)),  ZScale*osgCos(Theta)));
            norms->addValue(Vec3f( 0.0,0.0,1.0));
            pnts->addValue(Pnt3f(-Dimensions.x()/2.0+i*(Dimensions.x()/static_cast<Real32>(XSubdivisions)),  Dimensions.y()/2.0-(j+1)*(Dimensions.y()/static_cast<Real32>(YSubdivisions)),  ZScale*osgCos(Theta)));
            norms->addValue(Vec3f( 0.0,0.0,1.0));
            pnts->addValue(Pnt3f(-Dimensions.x()/2.0+(i+1)*(Dimensions.x()/static_cast<Real32>(XSubdivisions)),  Dimensions.y()/2.0-j*(Dimensions.y()/static_cast<Real32>(YSubdivisions)),  ZScale*osgCos(ThetaNext)));
            norms->addValue(Vec3f( 0.0,0.0,1.0));

            pnts->addValue(Pnt3f(-Dimensions.x()/2.0+i*(Dimensions.x()/static_cast<Real32>(XSubdivisions)),  Dimensions.y()/2.0-(j+1)*(Dimensions.y()/static_cast<Real32>(YSubdivisions)),  ZScale*osgCos(Theta)));
            norms->addValue(Vec3f( 0.0,0.0,1.0));
            pnts->addValue(Pnt3f(-Dimensions.x()/2.0+(i+1)*(Dimensions.x()/static_cast<Real32>(XSubdivisions)),  Dimensions.y()/2.0-(j+1)*(Dimensions.y()/static_cast<Real32>(YSubdivisions)),  ZScale*osgCos(ThetaNext)));
            norms->addValue(Vec3f( 0.0,0.0,1.0));
            pnts->addValue(Pnt3f(-Dimensions.x()/2.0+(i+1)*(Dimensions.x()/static_cast<Real32>(XSubdivisions)),  Dimensions.y()/2.0-j*(Dimensions.y()/static_cast<Real32>(YSubdivisions)),  ZScale*osgCos(ThetaNext)));
            norms->addValue(Vec3f( 0.0,0.0,1.0));
        }
    }


    GeoUInt32PropertyUnrecPtr lens = GeoUInt32Property::create();    
    lens->addValue(pnts->size());

    GeometryRefPtr Terrain = Geometry::create();
    Terrain->setTypes    (type);
    Terrain->setLengths  (lens);
    Terrain->setPositions(pnts);
    Terrain->setNormals(norms);

    calcVertexNormals(Terrain);

    return Terrain;
}
void
OgreMeshReader::readSubMesh(SubMeshStore       &subMeshInfo,
                            VertexElementStore &sharedVertexElements,
                            bool                skelAnim             )
{
    OSG_OGRE_LOG(("OgreMeshReader::readSubMesh\n"));

    subMeshInfo.push_back((SubMeshInfo()));
    SubMeshInfo &smInfo = subMeshInfo.back();

    smInfo.matName       = readString(_is);
    smInfo.sharedVertex  = readBool  (_is);
    UInt32      idxCount = readUInt32(_is);
    bool        idx32Bit = readBool  (_is);

    OSG_OGRE_LOG(("OgreMeshReader::readSubMesh: matName '%s' sharedVert '%d' "
                  "idxCount '%d' idx32Bit '%d'\n",
                  smInfo.matName.c_str(), smInfo.sharedVertex, idxCount, idx32Bit));

    smInfo.skelAnim = skelAnim;
    smInfo.meshOp   = SMO_TRIANGLE_LIST;

    if(idx32Bit == true)
    {
        GeoUInt32PropertyUnrecPtr pi = GeoUInt32Property::create();
        pi->resize(idxCount);

        _is.read(reinterpret_cast<Char8 *>(&pi->editField().front()),
                 idxCount * sizeof(UInt32));

        smInfo.propIdx = pi;
    }
    else
    {
        GeoUInt16PropertyUnrecPtr pi = GeoUInt16Property::create();
        pi->resize(idxCount);

        _is.read(reinterpret_cast<Char8 *>(&pi->editField().front()),
                 idxCount * sizeof(UInt16));

        smInfo.propIdx = pi;
    }

    Int16 boneIdxVE    = -1;
    Int16 boneWeightVE = -1;
    bool  stop         = false;

    while(_is)
    {
        readChunkHeader(_is);

        switch(_header.chunkId)
        {
        case CHUNK_GEOMETRY:
            readGeometry(smInfo.vertexElements);
            break;

        case CHUNK_SUBMESH_OPERATION:
            readSubMeshOperation(smInfo);
            break;

        case CHUNK_SUBMESH_BONE_ASSIGNMENT:
            readSubMeshBoneAssignment(smInfo, boneIdxVE, boneWeightVE);
            break;

        case CHUNK_SUBMESH_TEXTURE_ALIAS:
            readSubMeshTextureAlias();
            break;

        default:
            OSG_OGRE_LOG(("OgreMeshReader::readSubMesh: Unknown chunkId '0x%x'\n",
                          _header.chunkId));
            stop = true;
            break;
        };

        if(stop == true)
        {
            skip(_is, -_chunkHeaderSize);
            break;
        }
    }

    if(boneIdxVE >= 0 || boneWeightVE >= 0)
    {
        verifyBoneAssignment(smInfo.vertexElements, boneIdxVE, boneWeightVE);
    }
}
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
OgreMeshReader::constructSubMesh(SubMeshInfo        &smInfo,
                                 VertexElementStore &vertexElements)
{
    OSG_OGRE_LOG(("OgreMeshReader::constructSubMesh: meshName '%s'"
                  "matName '%s'\n",
                  smInfo.name.c_str(), smInfo.matName.c_str()));

    if(smInfo.skelAnim == true)
    {
        smInfo.mesh = SkinnedGeometry::create();
    }
    else
    {
        smInfo.mesh = Geometry::create();
    }

    smInfo.meshN = makeNodeFor(smInfo.mesh);
    smInfo.meshN->editSFVolume()->setValue(_rootN->getVolume());

    setName(smInfo.meshN, smInfo.name);

    UInt16 nextIdx = Geometry::TexCoordsIndex;

    for(UInt32 i = 0; i < vertexElements.size(); ++i)
    {
        Int32 usage   = -1;
        Int16 propSlot = -1;

        switch(vertexElements[i].semantic)
        {
        case VES_POSITION:
            usage    = GeoProperty::UsageObjectSpace;
            propSlot = Geometry::PositionsIndex;
            break;

        case VES_BLEND_WEIGHTS:
        case VES_BLEND_INDICES:
        case VES_TEXTURE_COORDINATES:
            usage    = GeoProperty::UsageParameterSpace;
            propSlot = nextIdx++;
            break;

        case VES_BINORMAL:
        case VES_TANGENT:
            usage    = GeoProperty::UsageTangentSpace;
            propSlot = nextIdx++;
            break;

        case VES_NORMAL:
            usage    = GeoProperty::UsageTangentSpace;
            propSlot = Geometry::NormalsIndex;
            break;

        case VES_DIFFUSE:
            usage    = GeoProperty::UsageColorSpace;
            propSlot = Geometry::ColorsIndex;
            break;

        case VES_SPECULAR:
            usage    = GeoProperty::UsageColorSpace;
            propSlot = Geometry::SecondaryColorsIndex;
            break;
        }

        if(usage >= 0)
        {
            vertexElements[i].prop->setUsage(usage);
        }

        if(propSlot >= 0)
        {
            OSG_OGRE_LOG(("OgreMeshReader::constructSubMesh: vertex elem semantic '%s'"
                          " using property '%u'\n",
                          getVertexElementSemanticString(vertexElements[i].semantic).c_str(),
                          propSlot));

            smInfo.mesh->setProperty(vertexElements[i].prop, propSlot);
            smInfo.mesh->setIndex   (smInfo.propIdx,         propSlot);
        }
        else
        {
            SWARNING << "OgreMeshReader::constructSubMesh: no property slot found for "
                     << "vertex elem semantic '"
                     << getVertexElementSemanticString(vertexElements[i].semantic)
                     << "'. Skipping." << std::endl;
        }

        if(vertexElements[i].semantic == VES_BLEND_INDICES)
        {
            SkinnedGeometry* skin =
                dynamic_pointer_cast<SkinnedGeometry>(smInfo.mesh);

            skin->setJointIndexProperty(propSlot);
        }

        if(vertexElements[i].semantic == VES_BLEND_WEIGHTS)
        {
            SkinnedGeometry* skin =
                dynamic_pointer_cast<SkinnedGeometry>(smInfo.mesh);

            skin->setJointWeightProperty(propSlot);
        }
    }

    GeoUInt8PropertyUnrecPtr types = GeoUInt8Property::create();
    switch(smInfo.meshOp)
    {
    case SMO_POINT_LIST:
        types->addValue(GL_POINTS);
        break;

    case SMO_LINE_LIST:
        types->addValue(GL_LINES);
        break;

    case SMO_LINE_STRIP:
        types->addValue(GL_LINE_STRIP);
        break;

    case SMO_TRIANGLE_LIST:
        types->addValue(GL_TRIANGLES);
        break;

    case SMO_TRIANGLE_STRIP:
        types->addValue(GL_TRIANGLE_STRIP);
        break;

    case SMO_TRIANGLE_FAN:
        types->addValue(GL_TRIANGLE_FAN);
        break;
    }

    GeoUInt32PropertyUnrecPtr lengths = GeoUInt32Property::create();
    lengths->addValue(smInfo.propIdx->size());

    smInfo.mesh->setTypes  (types);
    smInfo.mesh->setLengths(lengths);

    constructMaterial(smInfo);

    if(smInfo.skelAnim == true && _skel != NULL)
    {
        SkinnedGeometry* skin = dynamic_pointer_cast<SkinnedGeometry>(smInfo.mesh);

        if(skin != NULL)
        {
            skin->setSkeleton  (_skel);
            skin->setRenderMode(SkinnedGeometry::RMSkeleton);
        }
    }

    _rootN->addChild(smInfo.meshN);
}
//----------------------------------------------------------------------
// Fills a geometry with a new text
// Author: afischle, pdaehne
//----------------------------------------------------------------------
void TextVectorFace::fillGeo(Geometry *geoPtr, const TextLayoutResult &layoutResult,
                             Real32 scale, Real32 depth, UInt32 level,
                             Real32 creaseAngle)
{
    // cast the field containers down to the needed type and create them
    // when they have the wrong type
    GeoPnt3fPropertyUnrecPtr posPtr = 
        dynamic_cast<GeoPnt3fProperty *>(geoPtr->getPositions());

    if (posPtr == NULL)
    {
        posPtr = GeoPnt3fProperty::create();
        geoPtr->setPositions(posPtr);
    }
    else
        posPtr->clear();
    GeoVec3fPropertyUnrecPtr normalsPtr = 
        dynamic_cast<GeoVec3fProperty *>(geoPtr->getNormals());

    if (normalsPtr == NULL)
    {
        normalsPtr = GeoVec3fProperty::create();
        geoPtr->setNormals(normalsPtr);
    }
    else
        normalsPtr->clear();

    GeoVec2fPropertyUnrecPtr texPtr = 
        dynamic_cast<GeoVec2fProperty *>(geoPtr->getTexCoords());

    if (texPtr == NULL)
    {
        texPtr = GeoVec2fProperty::create();
        geoPtr->setTexCoords(texPtr);
    }
    else
        texPtr->clear();

    GeoUInt32PropertyUnrecPtr lensPtr = 
        dynamic_cast<GeoUInt32Property *>(geoPtr->getLengths());

    if (lensPtr == NULL)
    {
        lensPtr = GeoUInt32Property::create();
        geoPtr->setLengths(lensPtr);
    }
    else
        lensPtr->clear();

    GeoUInt32PropertyUnrecPtr posIndicesPtr = 
        dynamic_cast<GeoUInt32Property *>(
            geoPtr->getIndex(Geometry::PositionsIndex));

    if (posIndicesPtr == NULL)
    {
        posIndicesPtr = GeoUInt32Property::create();
        geoPtr->setIndex(posIndicesPtr, Geometry::PositionsIndex);
    }
    else
        posIndicesPtr->clear();

    GeoUInt32PropertyUnrecPtr normalIndicesPtr = 
        dynamic_cast<GeoUInt32Property *>(
            geoPtr->getIndex(Geometry::NormalsIndex));

    if (normalIndicesPtr == NULL)
    {
        normalIndicesPtr = GeoUInt32Property::create();
        geoPtr->setIndex(normalIndicesPtr, Geometry::NormalsIndex);
    }
    else
        normalIndicesPtr->clear();

    GeoUInt32PropertyUnrecPtr texCoordIndicesPtr = 
        dynamic_cast<GeoUInt32Property *>(
            geoPtr->getIndex(Geometry::TexCoordsIndex));

    if (texCoordIndicesPtr == NULL)
    {
        texCoordIndicesPtr = GeoUInt32Property::create();
        geoPtr->setIndex(texCoordIndicesPtr, Geometry::TexCoordsIndex);
    }
    else
        texCoordIndicesPtr->clear();

    GeoUInt8PropertyUnrecPtr typesPtr = 
        dynamic_cast<GeoUInt8Property *>(geoPtr->getTypes());

    if (typesPtr == NULL)
    {
        typesPtr = GeoUInt8Property::create();
        geoPtr->setTypes(typesPtr);
    }
    else
        typesPtr->clear();

    geoPtr->setColors(NULL);
    geoPtr->setSecondaryColors(NULL);
    geoPtr->setTexCoords1(NULL);
    geoPtr->setTexCoords2(NULL);
    geoPtr->setTexCoords3(NULL);

    UInt32 numGlyphs = layoutResult.getNumGlyphs();
    if (numGlyphs == 0)
    {
        return;
    }

    // the interleaved multi-index blocks have the layout
    // Position | Normal | TexCoord
/*
    geoPtr->getIndexMapping().push_back(Geometry::MapPosition);
    geoPtr->getIndexMapping().push_back(Geometry::MapNormal);
    geoPtr->getIndexMapping().push_back(Geometry::MapTexCoords);
 */

    // store the normal for the front face
    normalsPtr->push_back(Vec3f(0.f, 0.f, 1.f));
    if (depth > 0.f)
        // store the normal for the back face
        normalsPtr->push_back(Vec3f(0.f, 0.f, -1.f));

    UInt32 i;
    for (i = 0; i < numGlyphs; ++i)
    {
        const TextVectorGlyph &glyph = getVectorGlyph(layoutResult.indices[i]);
        const TextVectorGlyph::PolygonOutline &outline = glyph.getLines(level);
        const Vec2f &pos = layoutResult.positions[i];

        // add the front face to the geometry

        // store positions and texture coordinates
        UInt32 coordOffset = posPtr->size();
        UInt32 texCoordOffset = texPtr->size();
        Real32 coordZ = 0.5f * depth;
        vector<Vec2f>::const_iterator cIt;
        for (cIt = outline.coords.begin(); cIt != outline.coords.end(); ++cIt)
        {
            Vec2f coord = *cIt + pos;
            Vec2f texCoord = coord;
            coord *= scale;
            posPtr->push_back(Vec3f(coord.x(), coord.y(), coordZ));
            texCoord -= layoutResult.positions.front();
            texPtr->push_back(texCoord);
        }

        // Store types, lengths and indices
        vector<TextVectorGlyph::PolygonOutline::TypeIndex>::const_iterator tIt;
        UInt32 indexBegin = 0, indexEnd;
        for (tIt = outline.types.begin(); tIt != outline.types.end(); ++tIt)
        {
            typesPtr->push_back(tIt->first);
            indexEnd = tIt->second;
            OSG_ASSERT(indexEnd >= indexBegin);
            lensPtr->push_back(indexEnd - indexBegin);
            UInt32 i;
            for (i = indexBegin; i < indexEnd; ++i)
            {
                // the interleaved multi-index blocks have the layout
                // Position | Normal | TexCoord
                OSG_ASSERT(i < outline.indices.size());
                UInt32 index = outline.indices[i];
                OSG_ASSERT(coordOffset + index < posPtr->size());
                posIndicesPtr->push_back(coordOffset + index);
                normalIndicesPtr->push_back(0);
                OSG_ASSERT(texCoordOffset + index < texPtr->size());
                texCoordIndicesPtr->push_back(texCoordOffset + index);
            }
            indexBegin = indexEnd;
        }

        // add the back and side faces only if depth > 0
        if (depth > 0.f)
        {
            // add the back face to the geometry

            // store positions
            // No need to store texture coordinates - we reuse the
            // texture coordinates from the front side
            UInt32 backCoordOffset = posPtr->size();
            coordZ = -0.5f * depth;
            for (cIt = outline.coords.begin(); cIt != outline.coords.end(); ++cIt)
            {
                Vec2f coord = *cIt + pos;
                coord *= scale;
                posPtr->push_back(Vec3f(coord.x(), coord.y(), coordZ));
            }

            // Store types, lengths and indices
            // We have to flip all triangles to enable correct backface culling.
            // For GL_TRIANGLES, we simply flip the vertices.
            // For GL_TRIANGLE_FANs, we leave the first vertex at its place and flip the
            // remaining vertices.
            // For GL_TRIANGLE_STRIPs, things are more complicated. When the number of
            // vertices is uneven, we simply flip the vertices. When the number of
            // vertices is even, we have to add an additional vertex before we flip the
            // vertices.
            vector<TextVectorGlyph::PolygonOutline::TypeIndex>::const_iterator tIt;
            UInt32 indexBegin = 0, indexEnd;
            for (tIt = outline.types.begin(); tIt != outline.types.end(); ++tIt)
            {
                typesPtr->push_back(tIt->first);
                indexEnd = tIt->second;
                OSG_ASSERT(indexEnd >= indexBegin);
                UInt32 len = indexEnd - indexBegin;
                UInt32 i = indexEnd;
                if (tIt->first == GL_TRIANGLE_FAN)
                {
                    i = indexBegin;
                    ++indexBegin;
                }
                if ((tIt->first == GL_TRIANGLE_STRIP) && ((len & 1) == 0))
                {
                    OSG_ASSERT((indexEnd >= 2) && (indexEnd - 2 >= indexBegin));
                    i = indexEnd - 2;
                    ++len;
                }
                if (i != indexEnd)
                {
                    // the interleaved multi-index blocks have the layout
                    // Position | Normal | TexCoord
                    OSG_ASSERT(i < outline.indices.size());
                    UInt32 index = outline.indices[i];
                    OSG_ASSERT(backCoordOffset + index < posPtr->size());
                    posIndicesPtr->push_back(backCoordOffset + index);
                    normalIndicesPtr->push_back(1);
                    OSG_ASSERT(texCoordOffset + index < texPtr->size());
                    texCoordIndicesPtr->push_back(texCoordOffset + index);
                    i = indexEnd;
                }
                lensPtr->push_back(len);
                while (true)
                {
                    if (i <= indexBegin)
                        break;
                    --i;

                    // the interleaved multi-index blocks have the layout
                    // Position | Normal | TexCoord
                    OSG_ASSERT(i < outline.indices.size());
                    UInt32 index = outline.indices[i];
                    OSG_ASSERT(backCoordOffset + index < posPtr->size());
                    posIndicesPtr->push_back(backCoordOffset + index);
                    normalIndicesPtr->push_back(1);
                    OSG_ASSERT(texCoordOffset + index < texPtr->size());
                    texCoordIndicesPtr->push_back(texCoordOffset + index);
                }
                indexBegin = indexEnd;
            }

            // Add the side faces to the geometry
            const TextVectorGlyph::Normals &normals = glyph.getNormals(level);

            // construct the multi index
            UInt32 start = 0, end, index = 0;
            vector<UInt32>::const_iterator iIt;
            vector<TextVectorGlyph::Orientation>::const_iterator oriIt = glyph.getContourOrientations().begin();
            for (iIt = outline.contours.begin(); iIt != outline.contours.end(); ++iIt, ++oriIt)
            {
                OSG_ASSERT(oriIt != glyph.getContourOrientations().end());
                UInt32 contourCoordOffset, contourBackCoordOffset;
                if (*oriIt == TextVectorGlyph::CCW)
                {
                    contourCoordOffset = coordOffset;
                    contourBackCoordOffset = backCoordOffset;
                }
                else
                {
                    contourCoordOffset = backCoordOffset;
                    contourBackCoordOffset = coordOffset;
                }

                end = *iIt;

                // the side faces are stored as quads
                GLenum mode = GL_QUAD_STRIP;
                UInt32 len = 0;

                UInt32 coordIndex, backCoordIndex;
                UInt32 normalOffset, startNormalOffset = normalsPtr->size();
                for (index = start; index < end; ++index)
                {
                    normalOffset = normalsPtr->size() - 1;
                    OSG_ASSERT(index < normals.size());
                    if (normals[index].edgeAngle > creaseAngle)
                    {
                        // We have an edge with two normals, so we need to
                        // add the vertices twice, but with different normals
                        // - but only when this is not the start index
                        if (index > start)
                        {
                            if ((mode == GL_QUAD_STRIP) && (len > 2))
                            {
                                typesPtr->push_back(GL_QUAD_STRIP);
                                OSG_ASSERT(((len + 2) & 1) == 0);
                                lensPtr->push_back(len + 2);
                                len = 0;
                                coordIndex = contourCoordOffset + index;
                                backCoordIndex = contourBackCoordOffset + index;
                            }
                            else
                            {
                                mode = GL_QUADS;
                                len += 2;
                                coordIndex = contourBackCoordOffset + index;
                                backCoordIndex = contourCoordOffset + index;
                            }

                            // back
                            OSG_ASSERT(backCoordIndex < posPtr->size());
                            posIndicesPtr->push_back(backCoordIndex);
                            OSG_ASSERT(normalOffset < normalsPtr->size());
                            normalIndicesPtr->push_back(normalOffset);
                            OSG_ASSERT(texCoordOffset + index < texPtr->size());
                            texCoordIndicesPtr->push_back(texCoordOffset + index);
                            // front
                            OSG_ASSERT(coordIndex < posPtr->size());
                            posIndicesPtr->push_back(coordIndex);
                            OSG_ASSERT(normalOffset < normalsPtr->size());
                            normalIndicesPtr->push_back(normalOffset);
                            OSG_ASSERT(texCoordOffset + index < texPtr->size());
                            texCoordIndicesPtr->push_back(texCoordOffset + index);
                        }

                        const Vec2f &normal = normals[index].nextEdgeNormal;
                        normalsPtr->push_back(Vec3f(normal.x(), normal.y(), 0.f));
                    }
                    else
                    {
                        if (mode == GL_QUADS)
                        {
                            typesPtr->push_back(GL_QUADS);
                            mode = GL_QUAD_STRIP;
                            OSG_ASSERT(len >= 6);
                            OSG_ASSERT(((len - 2) & 3) == 0);
                            lensPtr->push_back(len - 2);
                            len = 2;
                        }

                        const Vec2f &normal = normals[index].meanEdgeNormal;
                        normalsPtr->push_back(Vec3f(normal.x(), normal.y(), 0.f));
                    }
                    ++normalOffset;

                    // back
                    OSG_ASSERT(contourBackCoordOffset + index < posPtr->size());
                    posIndicesPtr->push_back(contourBackCoordOffset + index);
                    OSG_ASSERT(normalOffset < normalsPtr->size());
                    normalIndicesPtr->push_back(normalOffset);
                    OSG_ASSERT(texCoordOffset + index < texPtr->size());
                    texCoordIndicesPtr->push_back(texCoordOffset + index);
                    // front
                    OSG_ASSERT(contourCoordOffset + index < posPtr->size());
                    posIndicesPtr->push_back(contourCoordOffset + index);
                    OSG_ASSERT(normalOffset < normalsPtr->size());
                    normalIndicesPtr->push_back(normalOffset);
                    OSG_ASSERT(texCoordOffset + index < texPtr->size());
                    texCoordIndicesPtr->push_back(texCoordOffset + index);

                    len += 2;
                }

                // We have to close the strip, so add the start vertices again
                if (normals[start].edgeAngle <= creaseAngle)
                    normalOffset = startNormalOffset;
                if (mode == GL_QUAD_STRIP)
                {
                    coordIndex = contourCoordOffset + start;
                    backCoordIndex = contourBackCoordOffset + start;
                }
                else
                {
                    coordIndex = contourBackCoordOffset + start;
                    backCoordIndex = contourCoordOffset + start;
                }

                // back
                OSG_ASSERT(backCoordIndex < posPtr->size());
                posIndicesPtr->push_back(backCoordIndex);
                OSG_ASSERT(normalOffset < normalsPtr->size());
                normalIndicesPtr->push_back(normalOffset);
                OSG_ASSERT(texCoordOffset + start < texPtr->size());
                texCoordIndicesPtr->push_back(texCoordOffset + start);
                // front
                OSG_ASSERT(coordIndex < posPtr->size());
                posIndicesPtr->push_back(coordIndex);
                OSG_ASSERT(normalOffset < normalsPtr->size());
                normalIndicesPtr->push_back(normalOffset);
                OSG_ASSERT(texCoordOffset + start < texPtr->size());
                texCoordIndicesPtr->push_back(texCoordOffset + start);

                len += 2;

                // store the number of multi index blocks
                typesPtr->push_back(mode);
                OSG_ASSERT((mode != GL_QUADS) || ((len & 3) == 0));
                OSG_ASSERT((mode != GL_QUAD_STRIP) || ((len & 1) == 0));
                lensPtr->push_back(len);

                start = end;
            }
        }
    }
}