void SkinnedGeometryBase::onCreate(const SkinnedGeometry *source)
{
    Inherited::onCreate(source);

    if(source != NULL)
    {
        SkinnedGeometry *pThis = static_cast<SkinnedGeometry *>(this);

        pThis->setSkeleton(source->getSkeleton());

        pThis->setSkinningAlgorithm(source->getSkinningAlgorithm());
    }
}
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);
}