Action::ResultE
CPUSkinningAlgorithm::intersectEnter(Action *action)
{
    Action::ResultE  res     = Action::Continue;
    SkinnedGeometry *skinGeo = getSkin    ();
    Skeleton        *skel    = getSkeleton();
    IntersectAction *iact    =
        boost::polymorphic_downcast<IntersectAction *>(action);

    CPUSkinningDataAttachmentUnrecPtr data = getCPUSkinningData(skinGeo);

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

    skel->intersectEnter(action, skinGeo);

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

        data->setDataValid(true);
    }

    intersectGeometry(iact, skinGeo, data);

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

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

    CPUSkinningDataAttachmentUnrecPtr data = getCPUSkinningData(skinGeo);

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

    skel->renderEnter(action, skinGeo);

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

        data->setDataValid(true);
    }

    renderGeometry(ract, skinGeo, data);

    return res;
}
ActionBase::ResultE
SkeletonSkinningAlgorithm::intersectEnter(Action *action)
{
    SkinnedGeometry *skinGeo = getSkin();

    return skinGeo->intersect(action);
}
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 SkinnedGeometryBase::execSyncV(      FieldContainer    &oFrom,
                                        ConstFieldMaskArg  whichField,
                                        AspectOffsetStore &oOffsets,
                                        ConstFieldMaskArg  syncMode,
                                  const UInt32             uiSyncInfo)
{
    SkinnedGeometry *pThis = static_cast<SkinnedGeometry *>(this);

    pThis->execSync(static_cast<SkinnedGeometry *>(&oFrom),
                    whichField,
                    oOffsets,
                    syncMode,
                    uiSyncInfo);
}
Action::ResultE
SkeletonSkinningAlgorithm::renderEnter(Action *action)
{
    Action::ResultE  res  = Action::Continue;
    RenderAction    *ract =
        boost::polymorphic_downcast<RenderAction *>(action);

    SkinnedGeometry *skinGeo = getSkin();
    Skeleton        *skel    = skinGeo->getSkeleton();

    skel->renderEnter(action, skinGeo);

    const Skeleton::MFJointsType        *joints       = skel->getMFJoints();
    const Skeleton::MFParentJointsType  *parentJoints =
        skel->getMFParentJoints();
    const Skeleton::MFJointMatricesType *jointMats    =
        skel->getMFJointMatrices();

    UInt32 numJoints = joints->size32();

#ifndef OSG_SKELETON_SKINNING_ALGO_DRAW_AXIS
    _mfDrawPositions.resize(numJoints);
    _mfDrawIndex    .clear (         );

    for(UInt32 i = 0; i < numJoints; ++i)
    {
        (*jointMats)[i].mult(Pnt3f(0.f, 0.f, 0.f),
                             _mfDrawPositions[i]  );

        if((*parentJoints)[i] != NULL)
        {
            _mfDrawIndex.push_back(i                               );
            _mfDrawIndex.push_back((*parentJoints)[i]->getJointId());
        }
    }

#else
    Real32 axisLen = 1.f;

    _mfDrawPositions.resize(4 * numJoints);
    _mfDrawIndex    .clear (             );

    for(UInt32 i = 0; i < numJoints; ++i)
    {
        (*jointMats)[i].mult(Pnt3f(0.f, 0.f, 0.f),
                             _mfDrawPositions[4 * i + 0]);

        if((*parentJoints)[i] != NULL)
        {
            _mfDrawIndex.push_back(4 * i                                + 0);
            _mfDrawIndex.push_back(4 * (*parentJoints)[i]->getJointId() + 0);

            Vec3f vec =
                _mfDrawPositions[4 * i                                + 0] -
                _mfDrawPositions[4 * (*parentJoints)[i]->getJointId() + 0];

            axisLen = 0.2f * vec.length();
            axisLen = 1.f;
        }
        else
        {
            axisLen = 1.f;
        }

        (*jointMats)[i].mult(
            Pnt3f(axisLen, 0.f,     0.f    ), _mfDrawPositions[4 * i + 1]);
        (*jointMats)[i].mult(
            Pnt3f(0.f,     axisLen, 0.f    ), _mfDrawPositions[4 * i + 2]);
        (*jointMats)[i].mult(
            Pnt3f(0.f,     0.f,     axisLen), _mfDrawPositions[4 * i + 3]);

        _mfDrawIndex.push_back(4 * i + 0);
        _mfDrawIndex.push_back(4 * i + 1);
        _mfDrawIndex.push_back(4 * i + 0);
        _mfDrawIndex.push_back(4 * i + 2);
        _mfDrawIndex.push_back(4 * i + 0);
        _mfDrawIndex.push_back(4 * i + 3);
    }
#endif // #ifndef OSG_SKELETON_SKINNING_ALGO_DRAW_AXIS

    DrawEnv::DrawFunctor   drawFuncSkinAlgo =
        boost::bind(&SkeletonSkinningAlgorithm::drawFunc, this, _1);
    PrimeMaterial         *skelMat          = getDefaultUnlitMaterial();
    State                 *state            = skelMat->getState      ();

    ract->dropFunctor(drawFuncSkinAlgo, state, skelMat->getSortKey());

    return res;
}
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);
}
Action::ResultE
GPUSkinningAlgorithm::renderEnter(Action *action)
{
    Action::ResultE  res     = Action::Continue;
    SkinnedGeometry *skinGeo = getSkin    ();
    Skeleton        *skel    = getSkeleton();
    RenderAction    *ract    =
        boost::polymorphic_downcast<RenderAction *>(action); 

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

    GPUSkinningDataAttachmentUnrecPtr data = getGPUSkinningData(skel);

    if(data == NULL)
    {
        data = GPUSkinningDataAttachment::create();
        skel->addAttachment(data);
    }

    skel->renderEnter(action, skinGeo);

    ShaderProgramChunkUnrecPtr shCode = data->getShaderCode();

    if(shCode == NULL)
    {
        shCode = ShaderProgramChunk::create();
        data->setShaderCode(shCode);

        ShaderProgramUnrecPtr vp = ShaderProgram::createVertexShader();
        vp->setProgram(_vpVertexSkinning);

        shCode->addShader(vp);

        vp->addUniformVariable(
            "matJoints",    (*skel->getMFJointMatrices()));
        vp->addUniformVariable(
            "matBindShape", skinGeo->getBindShapeMatrix());
    }
    else if(data->getDataValid() == false)
    {
        ShaderProgram *vp = shCode->getVertexShader(0);
        OSG_ASSERT(vp != NULL);

        vp->updateUniformVariable(
            "matJoints",    (*skel->getMFJointMatrices()));
        vp->updateUniformVariable(
            "matBindShape", skinGeo->getBindShapeMatrix());

        data->setDataValid(true);
    }

    ract->pushState();
    {
        ract->addOverride(ShaderProgramChunk::getStaticClassId(),
                          shCode                                 );

        res = skinGeo->SkinnedGeometry::Inherited::renderEnter(ract);
    }
    ract->popState ();

    return res;
}