void RenderAction::dropFunctor(DrawEnv::DrawFunctor &func,
                               Material             *pMat,
                               bool                  bIgnoreOverrides)
{
    if(pMat == NULL)
        return;

    PrimeMaterial *pPrimeMat = pMat->finalize(_oCurrentRenderProp, _pWindow);

    if(pPrimeMat == NULL)
        return;

    UInt32 uiNPasses = pPrimeMat->getNPasses();
    
    for(UInt32 uiPass = 0; uiPass < uiNPasses; ++uiPass)
    {
        State *st = pPrimeMat->getState(uiPass);
        
        if(st != NULL)
        {
            this->dropFunctor(func, 
                              st, 
                              pPrimeMat->getSortKey() + uiPass,
                              bIgnoreOverrides                );
        }
        else
        {
#ifndef WIN32
            FINFO(("%s: hit material with NULL state!\n", __func__));
#else
            FINFO(("Hit material with NULL state!\n"));
#endif
        }
    }
}
Action::ResultE MaterialDrawable::renderActionEnterHandler(Action *action)
{
    RenderAction  *a = dynamic_cast<RenderAction *>(action);

    Material      *m         = a->getMaterial();
    PrimeMaterial *pPrimeMat = NULL;

    if(m == NULL)
    {
        if(this->getMaterial() != NULL)
        {
            pPrimeMat =
                this->getMaterial()->finalize(a->getRenderProperties(),
                                              a->getWindow()          );
        }
    }
    else
    {
        pPrimeMat = m->finalize(a->getRenderProperties(),
                                a->getWindow          ());
    }

    if(pPrimeMat == NULL)
    {
        pPrimeMat = getDefaultMaterial();

        FNOTICE(("MaterialDrawable::render: no Material!?!\n"));
    }

    UInt32 uiNPasses = pPrimeMat->getNPasses();

    for(UInt32 uiPass = 0; uiPass < uiNPasses; ++uiPass)
    {
        State *st = pPrimeMat->getState(uiPass);

        if(st != NULL)
        {
            a->dropFunctor(_drawFunc,
                           st,
                           pPrimeMat->getSortKey() + uiPass);
        }
        else
        {
            FINFO(("%s: Material %p has NULL state for pass %d\n",
                   OSG_FUNCNAME_MACRO, pPrimeMat, uiPass));
        }
    }

    if(a->pushVisibility())
    {
        if(a->selectVisibles() == 0)
        {
            a->popVisibility();
            return Action::Skip;
        }
    }

    return Action::Continue;
}
void CPUSkinningAlgorithm::renderGeometry(
    RenderAction              *ract,
    SkinnedGeometry           *skinGeo,
    CPUSkinningDataAttachment *data   )
{
    Material      *pMat      = ract->getMaterial();
    PrimeMaterial *pPrimeMat = NULL;

    if(pMat == NULL)
    {
        if(skinGeo->getMaterial() != NULL)
        {
            pPrimeMat = skinGeo->getMaterial()->finalize(
                ract->getRenderProperties(), 
                ract->getCurrentOverrides(),
                ract->getWindow());
        }
    }
    else
    {
        pPrimeMat = pMat->finalize(
            ract->getRenderProperties(), 
            ract->getCurrentOverrides(),
            ract->getWindow());
    }

    if(pPrimeMat == NULL)
    {
        SNOTICE << "CPUSkinningAlgorithm::preDrawPrimitives: No Material "
                << "for SkinnedGeometry " << skinGeo
                << std::endl;

        pPrimeMat = getDefaultMaterial();
    }

    DrawEnv::DrawFunctor drawFunc  = boost::bind(
        &CPUSkinningAlgorithm::drawPrimitives, this, skinGeo, data, _1);
    UInt32               uiNPasses = pPrimeMat->getNPasses();
    
    for(UInt32 uiPass = 0; uiPass < uiNPasses; ++uiPass)
    {
        State *st = pPrimeMat->getState(uiPass);
        
        if(st != NULL)
        {
            ract->dropFunctor(drawFunc,
                              st, 
                              pPrimeMat->getSortKey() + uiPass);
        }
        else
        {
            FINFO(("%s: Material %p has NULL state for pass %d\n",
                   OSG_FUNCNAME_MACRO, pPrimeMat, uiPass));
        }
    }
}
void PrimeMaterialBase::execSyncV(      FieldContainer    &oFrom,
                                        ConstFieldMaskArg  whichField,
                                        AspectOffsetStore &oOffsets,
                                        ConstFieldMaskArg  syncMode,
                                  const UInt32             uiSyncInfo)
{
    PrimeMaterial *pThis = static_cast<PrimeMaterial *>(this);

    pThis->execSync(static_cast<PrimeMaterial *>(&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;
}