Technique Switcher         Switch render modes between textured, solid, wireframe and hidden lines.

Introduction

This small snippets shows how to use the class ViewOgreTechniqueSwitcher from the wxOgreMVC ogreaddons project to switch between textured, solid, wireframe and hidden lines render modes.

help This snippet has a forum support topic here.

Rendering the Ogre head in Hidden Lines mode
Rendering the Ogre head in Hidden Lines mode
Rendering the Ogre head in Solid mode
Rendering the Ogre head in Solid mode

Prerequisites

Because wxOgreMVC is licensed under the MIT license, and thus cannot be hosted here, you need to grab the ViewOgreTechniqueSwitcher class from the repository:
https://ogreaddons.svn.sourceforge.net/svnroot/ogreaddons/trunk/wxOgreMVC/src/OgreMVCViewOgreWindow.cpp
https://ogreaddons.svn.sourceforge.net/svnroot/ogreaddons/trunk/wxOgreMVC/include/OgreMVCGeneral.h

Implementation

When you've grabbed the two files above, you need to modify your code to make use of it.

  1. Put this forward declaration in your header:
    class ViewOgreTechniqueSwitcher;
  2. This enum goes into your class:
    enum ViewDetail
    {
        WIREFRAME = 0,
        HIDDEN_LINE = 1,
        SHADED = 2,
        TEXTURED = 3
    };
  3. Add the following three class member declarations somewhere in your class:
    ViewDetail mViewDetail;
    ViewOgreTechniqueSwitcher* mTechSwitcher;
    Ogre::ColourValue mBackgroundColour;
  4. Add a declaration for a setViewDetail member function to your class:
    void setViewDetail(ViewDetail v);

Source

In your implementation file (cpp) do the following:

  1. Copy the struct RenderableContext from 'OgreMVCGeneral.h' into the implementation file.
    It's an internally used struct, so let's just put it in the implementation as a static local struct.
  2. Copy the ViewOgreTechniqueSwitcher class from 'OgreMVCViewOgreWindow.cpp' into your implementation file.
  3. Add the following two lines to ViewOgreTechniqueSwitcher::renderableQueued, just before the '// Always render normally' comment.
    if((groupID <= Ogre::RENDER_QUEUE_2) || (groupID >= Ogre::RENDER_QUEUE_8))
        return true;

    The idea is to skip render queues lower than 3 and higher than 7, which means that skyboxes and overlays is going to be unaffected by the view details techniques.
  4. Add these three initializations to your class constructors initializer list:
    mViewDetail(TEXTURED),
    mTechSwitcher(0),
    mBackgroundColour(0.4, 0.4, 0.4)
  5. This goes in the destructor of your class:
    delete mTechSwitcher;
  6. Now, just before starting rendering, add these three lines of code:
    mTechSwitcher = new ViewOgreTechniqueSwitcher(mBackgroundColour);
    
    mCamera->getSceneManager()->getRenderQueue()->setRenderableListener(mTechSwitcher);
    
    setViewDetail(TEXTURED);
  7. The setViewDetail function definition:
    void HiddenLines::setViewDetail(ViewDetail v)
    {
        mViewDetail = v;
        mTechSwitcher->detail = v;
    }
  8. Put this in your keyPressed function:
    else if (arg.key == OIS::KC_R)   // cycle view detail mode
        {
            Ogre::String newVal;
            ViewDetail newMode;
    
            switch (mViewDetail)
            {
            case HIDDEN_LINE:
                newVal = "Wireframe";
                newMode = WIREFRAME;
                break;
            case WIREFRAME:
                newVal = "Flat Shaded";
                newMode = SHADED;
                break;
            case SHADED:
                newVal = "Textured";
                newMode = TEXTURED;
                break;
            case TEXTURED:
                newVal = "Hidden Line";
                newMode = HIDDEN_LINE;
                break;
            }
    
            setViewDetail(newMode);
            mDetailsPanel->setParamValue(10, newVal);
        }


And that's it. :-)

One More Trick

Well, there's one more neat trick to play..
Remember the RenderableContext struct you copied into your implementation file?
Let's make use of it in our createScene function (or similar):

void createScene()

    // Create the scene
    Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");

    Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    headNode->attachObject(ogreHead);

    // Set ambient light
    mSceneMgr->setAmbientLight(Ogre::ColourValue(0.0, 0.0, 0.0));

    // Create a light
    Ogre::Light* l = mSceneMgr->createLight("MainLight");
    l->setPosition(20,80,50);

    // create a floor mesh resource
    Ogre::MeshManager::getSingleton().createPlane("floor", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
        Ogre::Plane(Ogre::Vector3::UNIT_Y, -30), 1000, 1000, 10, 10, true, 1, 8, 8, Ogre::Vector3::UNIT_Z);
    // create a floor entity, give it a material, and place it at the origin
    Ogre::Entity* floor = mSceneMgr->createEntity("Floor", "floor");
    floor->setMaterialName("Examples/BumpyMetal");
    Ogre::SceneNode* planeNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    planeNode->attachObject(floor);

    RenderableContext ctx;
    ctx.ignoreViewDetail = true;
    floor->getSubEntity(0)->setUserAny(Ogre::Any(ctx));

    mSceneMgr->setSkyDome(true, "Examples/CloudySky");
}

Notice the last bit of code which create a RenderableContext and sets it's 'ignoreViewDetail' member to true, before giving it to 'floor' as a UserAny.
Now the 'floor' is not going to be affected by the render view effect.
Adding a skydome to demonstrate that sky geometry is not affected by the render effect either.