/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2013 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "PlayPenTests.h"
#include "OgreResourceGroupManager.h"
#include "OgreCodec.h"
#include "OgreFileSystemLayer.h"

using namespace Ogre;

PlayPen_ManualLOD::PlayPen_ManualLOD()
{
    mInfo["Title"] = "PlayPen_ManualLOD";
    mInfo["Description"] = "Testing meshes with manual LODs assigned";
    addScreenshotFrame(75);
}
//---------------------------------------------------------------------------

void PlayPen_ManualLOD::setupContent()
{
    String meshName = getLODMesh();

    Entity *ent;
    for (int i = 0; i < 5; ++i)
    {
        ent = mSceneMgr->createEntity("robot" + StringConverter::toString(i), meshName);
        // Add entity to the scene node
        mSceneMgr->getRootSceneNode()->createChildSceneNode(
            Vector3(0,0,(i*50)-(5*50/2)))->attachObject(ent);
    }

    mAnimation = ent->getAnimationState("Walk");
    mAnimation->setEnabled(true);

    // Give it a little ambience with lights
    Light* l;
    l = mSceneMgr->createLight("BlueLight");
    l->setPosition(-200,-80,-100);
    l->setDiffuseColour(0.5, 0.5, 1.0);

    l = mSceneMgr->createLight("GreenLight");
    l->setPosition(0,0,-100);
    l->setDiffuseColour(0.5, 1.0, 0.5);

    // Position the camera
    mCamera->setPosition(100,50,100);
    mCamera->lookAt(-50,50,0);

    mSceneMgr->setAmbientLight(ColourValue::White);
}
//---------------------------------------------------------------------------

bool PlayPen_ManualLOD::frameStarted(const FrameEvent& evt)
{
    mAnimation->addTime(evt.timeSinceLastFrame);
    return true;
}
//-----------------------------------------------------------------------

String PlayPen_ManualLOD::getLODMesh()
{
    MeshPtr msh1 = (MeshPtr)MeshManager::getSingleton().load("robot.mesh", 
        TRANSIENT_RESOURCE_GROUP);

    msh1->createManualLodLevel(200, "razor.mesh");
    msh1->createManualLodLevel(500, "sphere.mesh");

    return msh1->getName();
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

PlayPen_ManualLODFromFile::PlayPen_ManualLODFromFile()
{
    mInfo["Title"] = "PlayPen_ManualLOD_File";
    mInfo["Description"] = "Testing meshes with manual LODs assigned, loaded from a file";
    addScreenshotFrame(75);
}
//---------------------------------------------------------------------

String PlayPen_ManualLODFromFile::getLODMesh()
{
    MeshPtr msh1 = (MeshPtr)MeshManager::getSingleton().load("robot.mesh", 
        TRANSIENT_RESOURCE_GROUP);

    msh1->createManualLodLevel(200, "razor.mesh");
    msh1->createManualLodLevel(500, "sphere.mesh");

    // this time, we save this data to a file and re-load it

    MeshSerializer ser;
    const ResourceGroupManager::LocationList& ll = 
        ResourceGroupManager::getSingleton().getResourceLocationList(
        TRANSIENT_RESOURCE_GROUP);
    String prefix;
    for (ResourceGroupManager::LocationList::const_iterator i = ll.begin(); i != ll.end(); ++i)
    {
        if (StringUtil::endsWith((*i)->archive->getName(), "media"))
        {
            prefix = (*i)->archive->getName();
        }
    }
    ser.exportMesh(msh1.get(), prefix + "/testlod.mesh");

    MeshManager::getSingleton().removeAll();

    return "testlod.mesh";
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

PlayPen_ManualBlend::PlayPen_ManualBlend()
{
    mInfo["Title"] = "PlayPen_ManualBlending";
    mInfo["Description"] = "Manual blending";
    addScreenshotFrame(10);
}
//---------------------------------------------------------------------------

void PlayPen_ManualBlend::setupContent()
{
    // create material
    MaterialPtr mat = MaterialManager::getSingleton().create("TestMat", 
        TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass * p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->createTextureUnitState("Dirt.jpg");
    TextureUnitState* t = p->createTextureUnitState("ogrelogo.png");
    t->setColourOperationEx(LBX_BLEND_MANUAL, LBS_TEXTURE, LBS_CURRENT, 
        ColourValue::White, ColourValue::White, 0.75);

    Entity *planeEnt = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(planeEnt);
    planeEnt->setMaterialName("TestMat");

    mCamera->setPosition(0,0,600);
    mCamera->lookAt(Vector3::ZERO);
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------

PlayPen_ProjectSphere::PlayPen_ProjectSphere()
{
    mInfo["Title"] = "PlayPen_ProjectSphere";
    mInfo["Description"] = "Projecting a sphere's bounds onto the camera";
    addScreenshotFrame(10);
}
//---------------------------------------------------------------------------

void PlayPen_ProjectSphere::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue::White);

    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 0;
    MeshManager::getSingleton().createPlane("Myplane",
        TRANSIENT_RESOURCE_GROUP, plane,
        4500,4500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("Examples/GrassFloor");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);

    mProjectionSphere = new Sphere(Vector3(0, 2000, 0), 1500.0);

    ManualObject* debugSphere = mSceneMgr->createManualObject("debugSphere");
    debugSphere->begin("BaseWhiteNoLighting", RenderOperation::OT_LINE_STRIP);

    for (int i = 0; i <= 20; ++i)
    {
        Vector3 basePos(mProjectionSphere->getRadius(), 0, 0);
        Quaternion quat;
        quat.FromAngleAxis(Radian(((float)i/(float)20)*Math::TWO_PI), Vector3::UNIT_Y);
        basePos = quat * basePos;
        debugSphere->position(basePos);
    }
    for (int i = 0; i <= 20; ++i)
    {
        Vector3 basePos(mProjectionSphere->getRadius(), 0, 0);
        Quaternion quat;
        quat.FromAngleAxis(Radian(((float)i/(float)20)*Math::TWO_PI), Vector3::UNIT_Z);
        basePos = quat * basePos;
        debugSphere->position(basePos);
    }

    debugSphere->end();

    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0,2000,0))->attachObject(debugSphere);

    MaterialPtr mat = MaterialManager::getSingleton().create("scissormat", 
        TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setDepthWriteEnabled(false);
    p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    TextureUnitState* t = p->createTextureUnitState();
    t->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 
        ColourValue::Red);
    t->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f);


    mScissorRect = mSceneMgr->createManualObject("mScissorRect");
    mScissorRect->setUseIdentityProjection(true);
    mScissorRect->setUseIdentityView(true);
    AxisAlignedBox aabb;
    aabb.setInfinite();
    mScissorRect->setBoundingBox(aabb);
    mScissorRect->begin(mat->getName());
    mScissorRect->position(Vector3::ZERO);
    mScissorRect->position(Vector3::ZERO);
    mScissorRect->position(Vector3::ZERO);
    mScissorRect->quad(0, 1, 2, 3);
    mScissorRect->end();
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(mScissorRect);

    mCamera->setPosition(0,3000,5000);
    mCamera->lookAt(mProjectionSphere->getCenter());


}
//---------------------------------------------------------------------------

bool PlayPen_ProjectSphere::frameStarted(const FrameEvent& evt)
{
    Real left, top, right, bottom;
    mCamera->projectSphere(*mProjectionSphere, &left, &top, &right, &bottom);

    mScissorRect->beginUpdate(0);
    mScissorRect->position(left, top, 0);
    mScissorRect->position(left, bottom, 0);
    mScissorRect->position(right, bottom, 0);
    mScissorRect->position(right, top, 0);
    mScissorRect->quad(0,1,2,3);
    mScissorRect->end();
    return true;
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------

PlayPen_CameraSetDirection::PlayPen_CameraSetDirection()
: mUseParentNode(false)
, mUseFixedYaw(true)
, mFocus(100,200,-300)
{
    mInfo["Title"] = "PlayPen_CameraSetDirection";
    mInfo["Description"] = "Testing various settings for Camera::setDirection";
    addScreenshotFrame(10);
}
//---------------------------------------------------------------------

void PlayPen_CameraSetDirection::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue::White);

    Entity* e = mSceneMgr->createEntity("1", "knot.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode(mFocus)->attachObject(e);


    mCamera->setPosition(200,1000,1000);
    mCamera->lookAt(mFocus);

    //mTrayMgr->createButton(OgreBites::TL_BOTTOM, "Look At", "Look At");
    //mTrayMgr->createCheckBox(OgreBites::TL_BOTTOM, "tglParent", "Use Parent Node");
    //OgreBites::CheckBox* chk = mTrayMgr->createCheckBox(OgreBites::TL_BOTTOM, "tglFixedYaw", "Use Fixed Yaw");
    //chk->setChecked(true, false);
    //mTrayMgr->showCursor();
    //setDragLook(true);

    mParentNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(1000, 2000, -1000));

}
//---------------------------------------------------------------------

void PlayPen_CameraSetDirection::buttonHit(OgreBites::Button* button)
{
    mCamera->lookAt(mFocus);
}
//---------------------------------------------------------------------

void PlayPen_CameraSetDirection::checkBoxToggled(OgreBites::CheckBox* box)
{
    if (box->getName() == "tglParent")
    {
        mUseParentNode = !mUseParentNode;

        if (mUseParentNode)
            mParentNode->attachObject(mCamera);
        else
            mParentNode->detachAllObjects();
    }
    else if (box->getName() == "tglFixedYaw")
    {
        mUseFixedYaw = !mUseFixedYaw;
        if (mUseFixedYaw)
            mCamera->setFixedYawAxis(true);
        else
            mCamera->setFixedYawAxis(false);

    }
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------

PlayPen_MorphAnimationWithNormals::PlayPen_MorphAnimationWithNormals()
{
    mInfo["Title"] = "PlayPen_MorphAnimNormals";
    mInfo["Description"] = "Testing morph animation with normals";
    addScreenshotFrame(200);
}
//---------------------------------------------------------------------

void PlayPen_MorphAnimationWithNormals::setupContent()
{
    // explicitly disable stencil volume prep
    MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes(false);

    // Cannot change this to true, not possible to use software morph animation + normals with stencil shadows
    // because the former requires pos & normals to be in the same buffer, and the
    // latter requires positions to be on their own.
    //bool testStencil = false;

    //if (testStencil)
      //  mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);

    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    Light* l = mSceneMgr->createLight("light1");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(dir);

    
    MeshPtr mesh = MeshManager::getSingleton().load("sphere.mesh", 
        TRANSIENT_RESOURCE_GROUP);
    
    String morphName = "testmorphwithnormals.mesh";
    mesh = mesh->clone(morphName);

    SubMesh* sm = mesh->getSubMesh(0);
    // Re-organise geometry since this mesh has no animation and all 
    // vertex elements are packed into one buffer
    VertexDeclaration* newDecl = 
        sm->vertexData->vertexDeclaration->getAutoOrganisedDeclaration(false, true, true);
    sm->vertexData->reorganiseBuffers(newDecl);
    //if (testStencil)
      //  sm->vertexData->prepareForShadowVolume(); // need to re-prep since reorganised
    // get the position buffer (which should now be separate);
    const VertexElement* posElem = 
        sm->vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
    HardwareVertexBufferSharedPtr origbuf = 
        sm->vertexData->vertexBufferBinding->getBuffer(
            posElem->getSource());

    // Create a new position & normal buffer with updated values
    HardwareVertexBufferSharedPtr newbuf = 
        HardwareBufferManager::getSingleton().createVertexBuffer(
            VertexElement::getTypeSize(VET_FLOAT3) * 2,
            sm->vertexData->vertexCount, 
            HardwareBuffer::HBU_STATIC, true);
    float* pSrc = static_cast<float*>(origbuf->lock(HardwareBuffer::HBL_READ_ONLY));
    float* pDst = static_cast<float*>(newbuf->lock(HardwareBuffer::HBL_DISCARD));

    // Make the sphere turn into a cube
    // Do this just by clamping each of the directions (we shrink it)
    float cubeDimension = 0.3f * mesh->getBoundingSphereRadius();
    size_t srcSkip = origbuf->getVertexSize() / sizeof(float) - 3;
    for (size_t v = 0; v < sm->vertexData->vertexCount; ++v)
    {
        // x/y/z position
        Vector3 pos;
        for (int d = 0; d < 3; ++d)
        {
            if (*pSrc >= 0)
            {
                pos.ptr()[d] = std::min(cubeDimension, *pSrc++);
            }
            else 
            {
                pos.ptr()[d] = std::max(-cubeDimension, *pSrc++);            
            }
            *pDst++ = pos.ptr()[d];
        }
        
        // normal
        // this should point along the major axis
        // unfortunately since vertices are not duplicated at edges there will be
        // some inaccuracy here but the most important thing is to add sharp edges
        Vector3 norm = pos.normalisedCopy();
        norm = norm.primaryAxis();
        *pDst++ = norm.x;
        *pDst++ = norm.y;
        *pDst++ = norm.z;

        pSrc += srcSkip;

    }

    origbuf->unlock();
    newbuf->unlock();
    
    // create a morph animation
    Animation* anim = mesh->createAnimation("testAnim", 10.0f);
    VertexAnimationTrack* vt = anim->createVertexTrack(1, sm->vertexData, VAT_MORPH);
    // re-use start positions for frame 0
    VertexMorphKeyFrame* kf = vt->createVertexMorphKeyFrame(0);
    kf->setVertexBuffer(origbuf);

    // Use translated buffer for mid frame
    kf = vt->createVertexMorphKeyFrame(4.0f);
    kf->setVertexBuffer(newbuf);

    // Pause there
    kf = vt->createVertexMorphKeyFrame(6.0f);
    kf->setVertexBuffer(newbuf);
    
    // re-use start positions for final frame
    kf = vt->createVertexMorphKeyFrame(10.0f);
    kf->setVertexBuffer(origbuf);

    // Export the mesh
    String outPath, baseName;
    String exportName = mFSLayer->getWritablePath(morphName);
    StringUtil::splitFilename(exportName, baseName, outPath);
    Ogre::ResourceGroupManager& resMgr = Ogre::ResourceGroupManager::getSingleton();
    resMgr.addResourceLocation(outPath, "FileSystem", TRANSIENT_RESOURCE_GROUP);

    DataStreamPtr stream = Root::getSingleton().createFileStream(exportName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
    MeshSerializer ser;
    ser.exportMesh(mesh.get(), stream);
    stream->close();
    
    // Unload old mesh to force reload
    MeshManager::getSingleton().remove(mesh->getHandle());
    mesh->unload();
    mesh.setNull();

    Entity* e = mSceneMgr->createEntity("test", morphName);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    AnimationState* animState = e->getAnimationState("testAnim");
    animState->setEnabled(true);
    animState->setWeight(1.0f);
    mAnimations[0] = animState;

    e = mSceneMgr->createEntity("test2", morphName);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(200,0,0))->attachObject(e);
    // test hardware morph
    e->setMaterialName("Examples/HardwareMorphAnimationWithNormals");
    animState = e->getAnimationState("testAnim");
    animState->setEnabled(true);
    animState->setWeight(1.0f);
    mAnimations[1] = animState;

    mCamera->setNearClipDistance(0.5);
    mCamera->setPosition(0,100,-400);
    mCamera->lookAt(Vector3::ZERO);
    //mSceneMgr->setShowDebugShadows(true);

    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 200;
    MeshManager::getSingleton().createPlane("Myplane",
        TRANSIENT_RESOURCE_GROUP, plane,
        1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
}

bool PlayPen_MorphAnimationWithNormals::frameStarted(const FrameEvent& evt)
{
    mAnimations[0]->addTime(evt.timeSinceLastFrame);
    mAnimations[1]->addTime(evt.timeSinceLastFrame);
    return true;
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------

PlayPen_MorphAnimationWithoutNormals::PlayPen_MorphAnimationWithoutNormals()
{
    mInfo["Title"] = "PlayPen_MorphAnimNoNormals";
    mInfo["Description"] = "Testing morph animation without normals";
    addScreenshotFrame(200);
}
//---------------------------------------------------------------------

void PlayPen_MorphAnimationWithoutNormals::setupContent()
{
    //bool testStencil = false;

    //if (testStencil)
      //  mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);

    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    Light* l = mSceneMgr->createLight("light1");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(dir);


    MeshPtr mesh = MeshManager::getSingleton().load("sphere.mesh", 
        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

    String morphName = "testmorphnonormals.mesh";
    mesh = mesh->clone(morphName);

    SubMesh* sm = mesh->getSubMesh(0);
    // Re-organise geometry since this mesh has no animation and all 
    // vertex elements are packed into one buffer
    VertexDeclaration* newDecl = 
        sm->vertexData->vertexDeclaration->getAutoOrganisedDeclaration(false, true, false);
    sm->vertexData->reorganiseBuffers(newDecl);
    //if (testStencil)
      //  sm->vertexData->prepareForShadowVolume(); // need to re-prep since reorganised
    // get the position buffer (which should now be separate);
    const VertexElement* posElem = 
        sm->vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
    HardwareVertexBufferSharedPtr origbuf = 
        sm->vertexData->vertexBufferBinding->getBuffer(
        posElem->getSource());

    // Create a new position & normal buffer with updated values
    HardwareVertexBufferSharedPtr newbuf = 
        HardwareBufferManager::getSingleton().createVertexBuffer(
        VertexElement::getTypeSize(VET_FLOAT3),
        sm->vertexData->vertexCount, 
        HardwareBuffer::HBU_STATIC, true);
    float* pSrc = static_cast<float*>(origbuf->lock(HardwareBuffer::HBL_READ_ONLY));
    float* pDst = static_cast<float*>(newbuf->lock(HardwareBuffer::HBL_DISCARD));

    // Make the sphere turn into a cube
    // Do this just by clamping each of the directions (we shrink it)
    float cubeDimension = 0.3f * mesh->getBoundingSphereRadius();
    for (size_t v = 0; v < sm->vertexData->vertexCount; ++v)
    {
        // x/y/z position
        Vector3 pos;
        for (int d = 0; d < 3; ++d)
        {
            if (*pSrc >= 0)
            {
                pos.ptr()[d] = std::min(cubeDimension, *pSrc++);
            }
            else 
            {
                pos.ptr()[d] = std::max(-cubeDimension, *pSrc++);            
            }
            *pDst++ = pos.ptr()[d];
        }

    }

    origbuf->unlock();
    newbuf->unlock();

    // create a morph animation
    Animation* anim = mesh->createAnimation("testAnim", 10.0f);
    VertexAnimationTrack* vt = anim->createVertexTrack(1, sm->vertexData, VAT_MORPH);
    // re-use start positions for frame 0
    VertexMorphKeyFrame* kf = vt->createVertexMorphKeyFrame(0);
    kf->setVertexBuffer(origbuf);

    // Use translated buffer for mid frame
    kf = vt->createVertexMorphKeyFrame(4.0f);
    kf->setVertexBuffer(newbuf);

    // Pause there
    kf = vt->createVertexMorphKeyFrame(6.0f);
    kf->setVertexBuffer(newbuf);

    // re-use start positions for final frame
    kf = vt->createVertexMorphKeyFrame(10.0f);
    kf->setVertexBuffer(origbuf);

    // Export the mesh 
    String exportName = mFSLayer->getWritablePath(morphName);
    DataStreamPtr stream = Root::getSingleton().createFileStream(exportName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
    MeshSerializer ser;
    ser.exportMesh(mesh.get(), stream);
    stream->close();

    // Add resource location for exported mesh
    String path;
    StringUtil::splitFilename(exportName, morphName, path);
    ResourceGroupManager::getSingleton().addResourceLocation(path, "FileSystem");
    // Unload old mesh to force reload
    MeshManager::getSingleton().remove(mesh->getHandle());
    mesh->unload();
    mesh.setNull();

    Entity* e = mSceneMgr->createEntity("test", morphName);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    AnimationState* animState = e->getAnimationState("testAnim");
    animState->setEnabled(true);
    animState->setWeight(1.0f);
    mAnimations[0] = animState;

    e = mSceneMgr->createEntity("test2", morphName);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(200,0,0))->attachObject(e);
    // test hardware morph
    e->setMaterialName("Examples/HardwareMorphAnimation");
    animState = e->getAnimationState("testAnim");
    animState->setEnabled(true);
    animState->setWeight(1.0f);
    mAnimations[1] = animState;

    mCamera->setNearClipDistance(0.5);
    mCamera->setPosition(0,100,-400);
    mCamera->lookAt(Vector3::ZERO);
    //mSceneMgr->setShowDebugShadows(true);

    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 200;
    MeshManager::getSingleton().createPlane("Myplane",
        TRANSIENT_RESOURCE_GROUP, plane,
        1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);

}

bool PlayPen_MorphAnimationWithoutNormals::frameStarted(const FrameEvent& evt)
{
    mAnimations[0]->addTime(evt.timeSinceLastFrame);
    mAnimations[1]->addTime(evt.timeSinceLastFrame);
    return true;
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------

PlayPen_PoseAnimationWithNormals::PlayPen_PoseAnimationWithNormals()
{
    mInfo["Title"] = "PlayPen_PoseAnimNormals";
    mInfo["Description"] = "Testing pose animation with normals";
    addScreenshotFrame(200);
}
//---------------------------------------------------------------------

void PlayPen_PoseAnimationWithNormals::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    Light* l = mSceneMgr->createLight("light1");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(dir);

    MeshPtr mesh = MeshManager::getSingleton().load("cube.mesh", 
        TRANSIENT_RESOURCE_GROUP);
        
    String newName = "testposewithnormals.mesh";
    mesh = mesh->clone(newName);


    SubMesh* sm = mesh->getSubMesh(0);
    // Re-organise geometry since this mesh has no animation and all 
    // vertex elements are packed into one buffer
    VertexDeclaration* newDecl = 
        sm->vertexData->vertexDeclaration->getAutoOrganisedDeclaration(false, true, true);
    sm->vertexData->reorganiseBuffers(newDecl);

    // create 2 poses
    Pose* pose = mesh->createPose(1, "pose1");
    // Pose1 moves vertices 0, 1, 2 and 3 upward and pushes normals left
    Vector3 offset1(0, 50, 0);
    pose->addVertex(0, offset1, Vector3::NEGATIVE_UNIT_X);
    pose->addVertex(1, offset1, Vector3::NEGATIVE_UNIT_X);
    pose->addVertex(2, offset1, Vector3::NEGATIVE_UNIT_X);
    pose->addVertex(3, offset1, Vector3::NEGATIVE_UNIT_X);

    pose = mesh->createPose(1, "pose2");
    // Pose2 moves vertices 3, 4, and 5 to the right and pushes normals right
    // Note 3 gets affected by both
    Vector3 offset2(100, 0, 0);
    pose->addVertex(3, offset2, Vector3::UNIT_X);
    pose->addVertex(4, offset2, Vector3::UNIT_X);
    pose->addVertex(5, offset2, Vector3::UNIT_X);


    Animation* anim = mesh->createAnimation("poseanim", 20.0f);
    VertexAnimationTrack* vt = anim->createVertexTrack(1, sm->vertexData, VAT_POSE);
    
    // Frame 0 - no effect 
    vt->createVertexPoseKeyFrame(0);

    // Frame 1 - bring in pose 1 (index 0)
    VertexPoseKeyFrame* kf = vt->createVertexPoseKeyFrame(3);
    kf->addPoseReference(0, 1.0f);

    // Frame 2 - remove all 
    vt->createVertexPoseKeyFrame(6);

    // Frame 3 - bring in pose 2 (index 1)
    kf = vt->createVertexPoseKeyFrame(9);
    kf->addPoseReference(1, 1.0f);

    // Frame 4 - remove all
    vt->createVertexPoseKeyFrame(12);


    // Frame 5 - bring in pose 1 at 50%, pose 2 at 100% 
    kf = vt->createVertexPoseKeyFrame(15);
    kf->addPoseReference(0, 0.5f);
    kf->addPoseReference(1, 1.0f);

    // Frame 6 - bring in pose 1 at 100%, pose 2 at 50% 
    kf = vt->createVertexPoseKeyFrame(18);
    kf->addPoseReference(0, 1.0f);
    kf->addPoseReference(1, 0.5f);

    // Frame 7 - reset
    vt->createVertexPoseKeyFrame(20);


    // Export the mesh
    String exportName = mFSLayer->getWritablePath(newName);
    String outPath, baseName;
    StringUtil::splitFilename(exportName, baseName, outPath);
    Ogre::ResourceGroupManager& resMgr = Ogre::ResourceGroupManager::getSingleton();
    resMgr.addResourceLocation(outPath, "FileSystem", TRANSIENT_RESOURCE_GROUP);
    DataStreamPtr stream = Root::getSingleton().createFileStream(exportName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
    MeshSerializer ser;
    ser.exportMesh(mesh.get(), stream);
    stream->close();

    // Unload old mesh to force reload
    MeshManager::getSingleton().remove(mesh->getHandle());
    mesh->unload();
    mesh.setNull();

    Entity*  e;
    AnimationState* animState;
    // software pose
    e = mSceneMgr->createEntity("test2", newName);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(150,0,0))->attachObject(e);
    animState = e->getAnimationState("poseanim");
    animState->setEnabled(true);
    animState->setWeight(1.0f);
    mAnimations[0] = animState;
    
    // test hardware pose
    e = mSceneMgr->createEntity("test", newName);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    e->setMaterialName("Examples/HardwarePoseAnimationWithNormals");
    animState = e->getAnimationState("poseanim");
    animState->setEnabled(true);
    animState->setWeight(1.0f);
    mAnimations[1] = animState;

    mCamera->setNearClipDistance(0.5);
    mSceneMgr->setShowDebugShadows(true);

    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 200;
    MeshManager::getSingleton().createPlane("Myplane",
        TRANSIENT_RESOURCE_GROUP, plane,
        1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);

    mCamera->setPosition(0,-200,-300);
    mCamera->lookAt(0,0,0);

}
//---------------------------------------------------------------------

bool PlayPen_PoseAnimationWithNormals::frameStarted(const FrameEvent& evt)
{
    mAnimations[0]->addTime(evt.timeSinceLastFrame);
    mAnimations[1]->addTime(evt.timeSinceLastFrame);
    return true;
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------

PlayPen_PoseAnimationWithoutNormals::PlayPen_PoseAnimationWithoutNormals()
{
    mInfo["Title"] = "PlayPen_PoseAnimNoNormals";
    mInfo["Description"] = "Testing pose animation without normals";
    addScreenshotFrame(200);
}
//---------------------------------------------------------------------

void PlayPen_PoseAnimationWithoutNormals::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    Light* l = mSceneMgr->createLight("light1");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(dir);

    MeshPtr mesh = MeshManager::getSingleton().load("cube.mesh", 
        TRANSIENT_RESOURCE_GROUP);
        
    String newName = "testposenonormals.mesh";
    mesh = mesh->clone(newName);


    SubMesh* sm = mesh->getSubMesh(0);
    // Re-organise geometry since this mesh has no animation and all 
    // vertex elements are packed into one buffer
    VertexDeclaration* newDecl = 
        sm->vertexData->vertexDeclaration->getAutoOrganisedDeclaration(false, true, false);
    sm->vertexData->reorganiseBuffers(newDecl);

    // create 2 poses
    Pose* pose = mesh->createPose(1, "pose1");
    // Pose1 moves vertices 0, 1, 2 and 3 upward 
    Vector3 offset1(0, 50, 0);
    pose->addVertex(0, offset1);
    pose->addVertex(1, offset1);
    pose->addVertex(2, offset1);
    pose->addVertex(3, offset1);

    pose = mesh->createPose(1, "pose2");
    // Pose2 moves vertices 3, 4, and 5 to the right
    // Note 3 gets affected by both
    Vector3 offset2(100, 0, 0);
    pose->addVertex(3, offset2);
    pose->addVertex(4, offset2);
    pose->addVertex(5, offset2);


    Animation* anim = mesh->createAnimation("poseanim", 20.0f);
    VertexAnimationTrack* vt = anim->createVertexTrack(1, sm->vertexData, VAT_POSE);
    
    // Frame 0 - no effect 
    vt->createVertexPoseKeyFrame(0);

    // Frame 1 - bring in pose 1 (index 0)
    VertexPoseKeyFrame* kf = vt->createVertexPoseKeyFrame(3);
    kf->addPoseReference(0, 1.0f);

    // Frame 2 - remove all 
    vt->createVertexPoseKeyFrame(6);

    // Frame 3 - bring in pose 2 (index 1)
    kf = vt->createVertexPoseKeyFrame(9);
    kf->addPoseReference(1, 1.0f);

    // Frame 4 - remove all
    vt->createVertexPoseKeyFrame(12);


    // Frame 5 - bring in pose 1 at 50%, pose 2 at 100% 
    kf = vt->createVertexPoseKeyFrame(15);
    kf->addPoseReference(0, 0.5f);
    kf->addPoseReference(1, 1.0f);

    // Frame 6 - bring in pose 1 at 100%, pose 2 at 50% 
    kf = vt->createVertexPoseKeyFrame(18);
    kf->addPoseReference(0, 1.0f);
    kf->addPoseReference(1, 0.5f);

    // Frame 7 - reset
    vt->createVertexPoseKeyFrame(20);

    // Export the mesh
    String outPath, baseName;
    String exportName = mFSLayer->getWritablePath(newName);
    StringUtil::splitFilename(exportName, baseName, outPath);
    Ogre::ResourceGroupManager& resMgr = Ogre::ResourceGroupManager::getSingleton();
    resMgr.addResourceLocation(outPath, "FileSystem", TRANSIENT_RESOURCE_GROUP);

    DataStreamPtr stream = Root::getSingleton().createFileStream(exportName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
    MeshSerializer ser;
    ser.exportMesh(mesh.get(), stream);
    stream->close();

    // Unload old mesh to force reload
    MeshManager::getSingleton().remove(mesh->getHandle());
    mesh->unload();
    mesh.setNull();

    Entity*  e;
    AnimationState* animState;
    // software pose
    e = mSceneMgr->createEntity("test2", newName);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(150,0,0))->attachObject(e);
    animState = e->getAnimationState("poseanim");
    animState->setEnabled(true);
    animState->setWeight(1.0f);
    mAnimations[0] = animState;
    
    // test hardware pose
    e = mSceneMgr->createEntity("test", newName);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    e->setMaterialName("Examples/HardwarePoseAnimation");
    animState = e->getAnimationState("poseanim");
    animState->setEnabled(true);
    animState->setWeight(1.0f);
    mAnimations[1] = animState;
    

    mCamera->setNearClipDistance(0.5);

    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 200;
    MeshManager::getSingleton().createPlane("Myplane",
        TRANSIENT_RESOURCE_GROUP, plane,
        1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);

    mCamera->setPosition(0,-200,-300);
    mCamera->lookAt(0,0,0);
}
//---------------------------------------------------------------------------

bool PlayPen_PoseAnimationWithoutNormals::frameStarted(const FrameEvent& evt)
{
    mAnimations[0]->addTime(evt.timeSinceLastFrame);
    mAnimations[1]->addTime(evt.timeSinceLastFrame);
    return true;
}
//---------------------------------------------------------------------------

PlayPen_SceneNodeTracking::PlayPen_SceneNodeTracking()
{
    mInfo["Title"] = "PlayPen_SceneNodeTracking";
    mInfo["Description"] = "Testing scenenode tracking.";
    addScreenshotFrame(200);
}
//-----------------------------------------------------------------------

bool PlayPen_SceneNodeTracking::frameStarted(const FrameEvent& evt)
{
    mAnimState->addTime(evt.timeSinceLastFrame);
    return true;
}
//-----------------------------------------------------------------------

void PlayPen_SceneNodeTracking::setupContent()
{
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));

    // Create a skydome
    mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);

    // Create a light
    Light* l = mSceneMgr->createLight("MainLight");
    // Accept default settings: point light, white diffuse, just set position
    // NB I could attach the light to a SceneNode if I wanted it to move automatically with
    //  other objects, but I don't
    l->setPosition(20,80,50);

    Entity *ent;

    // Define a floor plane mesh
    Plane p;
    p.normal = Vector3::UNIT_Y;
    p.d = 200;
    MeshManager::getSingleton().createPlane("FloorPlane",
        TRANSIENT_RESOURCE_GROUP,
        p,200000,200000,20,20,true,1,50,50,Vector3::UNIT_Z);

    // Create an entity (the floor)
    ent = mSceneMgr->createEntity("floor", "FloorPlane");
    ent->setMaterialName("Examples/RustySteel");
    // Attach to child of root node, better for culling (otherwise bounds are the combination of the 2)
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);

    // Add a head, give it it's own node
    SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    ent = mSceneMgr->createEntity("head", "ogrehead.mesh");
    headNode->attachObject(ent);

    // Add another head, give it it's own node
    SceneNode* headNode2 = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    ent = mSceneMgr->createEntity("head2", "ogrehead.mesh");
    headNode2->attachObject(ent);

    // Make sure the head node tracks the root
    headNode->setAutoTracking(true, headNode2, Vector3::UNIT_Z);
    //headNode->setFixedYawAxis(true);

    // Create the camera node & attach camera
    //SceneNode* camNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    //camNode->attachObject(mCamera);

    // set up spline animation of node
    Animation* anim = mSceneMgr->createAnimation("CameraTrack", 10);
    // Spline it for nice curves
    anim->setInterpolationMode(Animation::IM_SPLINE);
    // Create a track to animate the head's node
    NodeAnimationTrack* track = anim->createNodeTrack(0, headNode);
    // Setup keyframes
    track->createNodeKeyFrame(0); // startposition
    TransformKeyFrame* key = track->createNodeKeyFrame(2.5);
    key->setTranslate(Vector3(500,500,-1000));
    key = track->createNodeKeyFrame(5);
    key->setTranslate(Vector3(-1500,1000,-600));
    key = track->createNodeKeyFrame(7.5);
    key->setTranslate(Vector3(0,-100,0));
    key = track->createNodeKeyFrame(10);
    key->setTranslate(Vector3(0,0,0));
    // Create a track to animate the second head's node
    track = anim->createNodeTrack(1, headNode2);
    // Setup keyframes
    track->createNodeKeyFrame(0); // startposition
    key = track->createNodeKeyFrame(2.5);
    key->setTranslate(Vector3(-500,600,-100));
    key = track->createNodeKeyFrame(5);
    key->setTranslate(Vector3(800,200,-600));
    key = track->createNodeKeyFrame(7.5);
    key->setTranslate(Vector3(200,-1000,0));
    key = track->createNodeKeyFrame(10);
    key->setTranslate(Vector3(30,70,110));
    // Create a new animation state to track this
    mAnimState = mSceneMgr->createAnimationState("CameraTrack");
    mAnimState->setEnabled(true);

    // Put in a bit of fog for the hell of it
    //mSceneMgr->setFog(FOG_EXP, ColourValue::White, 0.0002);

    mCamera->setPosition(-300,600,2000);
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
PlayPen_NonUniqueResourceNames::PlayPen_NonUniqueResourceNames()
{
    mInfo["Title"] = "PlayPen_NonUniqueResourceNames";
    mInfo["Description"] = "Testing resources without unique names (in different resource groups).";
    addScreenshotFrame(50);
}
//-----------------------------------------------------------------------

void PlayPen_NonUniqueResourceNames::setupContent()
{
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));

    // Define the required skyplane
    Plane plane;
    // 5000 world units from the camera
    plane.d = 5000;
    // Above the camera, facing down
    plane.normal = -Vector3::UNIT_Y;
    // Create the plane 10000 units wide, tile the texture 3 times
    mSceneMgr->setSkyPlane(true, plane, "Examples/SpaceSkyPlane",10000,3);

    // Create a light
    Light* l = mSceneMgr->createLight("MainLight");
    // Accept default settings: point light, white diffuse, just set position
    // NB I could attach the light to a SceneNode if I wanted it to move automatically with
    //  other objects, but I don't
    l->setPosition(20,80,50);

    createMeshEntity("Model1", Vector3(10, 10, 10));
    createMeshEntity("Model2", Vector3(-10, -10, -10));

    mCamera->setPosition(100,0,-100);
    mCamera->lookAt(0,0,0);
}
//-----------------------------------------------------------------------

void PlayPen_NonUniqueResourceNames::createMeshEntity(String group, Vector3 pos)
{
    // get path to test resources (ugly, but the only way I can think of to consistently get the
    // right path (since it's determined by cmake build location) without explicitly defining the 
    // groups in resources.cfg)
    const Ogre::ResourceGroupManager::LocationList& ll = Ogre::ResourceGroupManager::getSingleton().getResourceLocationList("Tests");
    const Ogre::ResourceGroupManager::ResourceLocation* loc = ll.front();
    Ogre::String testResourcePath = loc->archive->getName();

    Ogre::String meshFilePath = testResourcePath + "/" + group;

    Ogre::ResourceGroupManager& resMgr = Ogre::ResourceGroupManager::getSingleton();
    String newGroup = meshFilePath;
    resMgr.createResourceGroup(group, false);
    resMgr.addResourceLocation(meshFilePath, "FileSystem", group);
    resMgr.initialiseResourceGroup(group);

    Ogre::MeshPtr newMesh = Ogre::MeshManager::getSingleton().load("UniqueModel.MESH", group);
    Entity *newEnt = mSceneMgr->createEntity(group, "UniqueModel.MESH", group);

    SceneNode* newNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    newNode->attachObject(newEnt);
    newNode->setPosition(pos);

    // I was getting an assertion on some part of the skeleton loading
    //AnimationState* aniState =newEnt->getAnimationState(newEnt->getMesh()->getSkeleton()->getAnimation(0)->getName());
    //mAnimStateList.push_back(aniState);
    //aniState->setEnabled(true);
    //aniState->setLoop(true);
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

PlayPen_16Textures::PlayPen_16Textures()
{
    mInfo["Title"] = "PlayPen_16Textures";
    mInfo["Description"] = "Tests applying 16 textures in a single material.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_16Textures::setupContent()
{
    
    HighLevelGpuProgramPtr frag;
    if (StringUtil::match(Root::getSingleton().getRenderSystem()->getName(), "*GL 3+*"))
    {
        frag = HighLevelGpuProgramManager::getSingleton().createProgram("frag16", TRANSIENT_RESOURCE_GROUP,
        "glsl", GPT_FRAGMENT_PROGRAM);
        String source = " \
        #version " + StringConverter::toString(Root::getSingleton().getRenderSystem()->getNativeShadingLanguageVersion()) + "\n \
        uniform sampler2D tex0; \
        uniform sampler2D tex1; \
        uniform sampler2D tex2; \
        uniform sampler2D tex3; \
        uniform sampler2D tex4; \
        uniform sampler2D tex5; \
        uniform sampler2D tex6; \
        uniform sampler2D tex7; \
        uniform sampler2D tex8; \
        uniform sampler2D tex9; \
        uniform sampler2D tex10; \
        uniform sampler2D tex11; \
        uniform sampler2D tex12; \
        uniform sampler2D tex13; \
        uniform sampler2D tex14; \
        uniform sampler2D tex15; \
        in vec4 ambientUV; \
        out vec4 fragColour; \
        void main() \
        { \
        fragColour = texture(tex15, ambientUV.xy); \
        } \
        ";
        frag->setSource(source);
    }
    else if (StringUtil::match(Root::getSingleton().getRenderSystem()->getName(), "*GL ES 2*"))
    {
        frag = HighLevelGpuProgramManager::getSingleton().createProgram("frag16", TRANSIENT_RESOURCE_GROUP,
                                                                        "glsles", GPT_FRAGMENT_PROGRAM);
        frag->setSource(" \
                        #version " + StringConverter::toString(Root::getSingleton().getRenderSystem()->getNativeShadingLanguageVersion()) + "\n \
                        precision highp float; \
                        precision highp int; \
                        uniform sampler2D tex0; \
                        uniform sampler2D tex1; \
                        uniform sampler2D tex2; \
                        uniform sampler2D tex3; \
                        uniform sampler2D tex4; \
                        uniform sampler2D tex5; \
                        uniform sampler2D tex6; \
                        uniform sampler2D tex7; \
                        uniform sampler2D tex8; \
                        uniform sampler2D tex9; \
                        uniform sampler2D tex10; \
                        uniform sampler2D tex11; \
                        uniform sampler2D tex12; \
                        uniform sampler2D tex13; \
                        uniform sampler2D tex14; \
                        uniform sampler2D tex15; \
                        varying vec4 ambientUV; \
                        void main() \
                        { \
                        gl_FragColor = texture2D(tex15, ambientUV.xy); \
                        } \
                        ");
    }
    else if (StringUtil::match(Root::getSingleton().getRenderSystem()->getName(), "*GL*"))
    {
        frag = HighLevelGpuProgramManager::getSingleton().createProgram("frag16", TRANSIENT_RESOURCE_GROUP,
                                                                        "glsl", GPT_FRAGMENT_PROGRAM);
        frag->setSource(" \
                        uniform sampler2D tex0; \
                        uniform sampler2D tex1; \
                        uniform sampler2D tex2; \
                        uniform sampler2D tex3; \
                        uniform sampler2D tex4; \
                        uniform sampler2D tex5; \
                        uniform sampler2D tex6; \
                        uniform sampler2D tex7; \
                        uniform sampler2D tex8; \
                        uniform sampler2D tex9; \
                        uniform sampler2D tex10; \
                        uniform sampler2D tex11; \
                        uniform sampler2D tex12; \
                        uniform sampler2D tex13; \
                        uniform sampler2D tex14; \
                        uniform sampler2D tex15; \
                        void main() \
                        { \
                        gl_FragColor = texture2D(tex15, gl_TexCoord[0].xy); \
                        } \
                        ");
    }
    else
    {
        // DirectX
        frag = HighLevelGpuProgramManager::getSingleton().createProgram("frag16", TRANSIENT_RESOURCE_GROUP,
        "hlsl", GPT_FRAGMENT_PROGRAM);
        frag->setParameter("target", "ps_2_0");
        frag->setParameter("entry_point", "main");
        frag->setSource(" \
        float4 main( \
        float2 uv : TEXCOORD0, \
        uniform sampler2D tex0 : register(s0), \
        uniform sampler2D tex1 : register(s1), \
        uniform sampler2D tex2 : register(s2), \
        uniform sampler2D tex3 : register(s3), \
        uniform sampler2D tex4 : register(s4), \
        uniform sampler2D tex5 : register(s5), \
        uniform sampler2D tex6 : register(s6), \
        uniform sampler2D tex7 : register(s7), \
        uniform sampler2D tex8 : register(s8), \
        uniform sampler2D tex9 : register(s9), \
        uniform sampler2D tex10 : register(s10), \
        uniform sampler2D tex11 : register(s11), \
        uniform sampler2D tex12 : register(s12), \
        uniform sampler2D tex13 : register(s13), \
        uniform sampler2D tex14 : register(s14), \
        uniform sampler2D tex15 : register(s15) \
        ) : COLOR \
        { \
            return tex2D(tex15, uv); \
        } \
        ");
    }
    frag->load();
    
    MaterialPtr mat = MaterialManager::getSingleton().create("test16", TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setVertexProgram("Ogre/BasicVertexPrograms/AmbientOneTextureWithUV");
    p->setFragmentProgram(frag->getName());
    // create 15 textures the same
    for (int i = 0; i < 15; ++i)
    {
        p->createTextureUnitState("Dirt.jpg");
    }
    // create 16th texture differently
    p->createTextureUnitState("ogrelogo.png");
    if (StringUtil::match(Root::getSingleton().getRenderSystem()->getName(), "*GL*"))
    {
        // map samplers
        GpuProgramParametersSharedPtr params = p->getFragmentProgramParameters();
        for (int i = 0; i < 16; ++i)
        {
            params->setNamedConstant(String("tex") + StringConverter::toString(i), i);
        }
        
    }
    
    mat->load();
    
    Entity* e = mSceneMgr->createEntity("1", "knot.mesh");
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    
    mCamera->setPosition(0,0,250);
    mCamera->lookAt(0,0,0);
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_2bppAlphaPVR::PlayPen_2bppAlphaPVR()
{
    mInfo["Title"] = "PlayPen_2bppAlphaPVR";
    mInfo["Description"] = "Tests 2bpp pvr w/ alpha.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_2bppAlphaPVR::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testpvr", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    p->createTextureUnitState("ogreborderUp_pvr2a.pvr");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
}
//----------------------------------------------------------------------------

void PlayPen_2bppAlphaPVR::testCapabilities(const Ogre::RenderSystemCapabilities* caps)
{
    Codec* codec = Codec::getCodec("pvr");
    if (!codec)
        throw Ogre::Exception(999, "No support for PVR textures.", "testCapabilities");
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_2bppPVR::PlayPen_2bppPVR()
{
    mInfo["Title"] = "PlayPen_2bppPVR";
    mInfo["Description"] = "Tests 2 bpp pvr.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_2bppPVR::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testpvr", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    p->createTextureUnitState("ogreborderUp_pvr2.pvr");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
}
//----------------------------------------------------------------------------

void PlayPen_2bppPVR::testCapabilities(const Ogre::RenderSystemCapabilities* caps)
{
    Codec* codec = Codec::getCodec("pvr");
    if (!codec)
        throw Ogre::Exception(999, "No support for PVR textures.", "testCapabilities");
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_2Spotlights::PlayPen_2Spotlights()
{
    mInfo["Title"] = "PlayPen_2Spotlights";
    mInfo["Description"] = "Tests 2 spotlights on one mesh.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_2Spotlights::setupContent()
{
    SceneNode* mTestNode[5];
    mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));
    
    Light* mLight = mSceneMgr->createLight("MainLight");
    // Spotlight test
    mLight->setType(Light::LT_SPOTLIGHT);
    mLight->setDiffuseColour(1.0, 0.0, 0.8);
    mLight->setSpotlightRange(Degree(30), Degree(40));
    mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    mTestNode[0]->setPosition(800,600,0);
    mTestNode[0]->lookAt(Vector3(800,0,0), Node::TS_WORLD, Vector3::UNIT_Z);
    mTestNode[0]->attachObject(mLight);
    
    mTestNode[1] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    mLight = mSceneMgr->createLight("AnotherLight");
    // Spotlight test
    mLight->setType(Light::LT_SPOTLIGHT);
    mLight->setDiffuseColour(0, 1.0, 0.8);
    mLight->setSpotlightRange(Degree(30), Degree(40));
    mTestNode[1] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    mTestNode[1]->setPosition(0,600,800);
    mTestNode[1]->lookAt(Vector3(0,0,800), Node::TS_WORLD, Vector3::UNIT_Z);
    mTestNode[1]->attachObject(mLight);
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    3500,3500,100,100,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);

    mCamera->setPosition(-600,300,-600);
    mCamera->lookAt(300,0,300);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_4bppAlphaPVR::PlayPen_4bppAlphaPVR()
{
    mInfo["Title"] = "PlayPen_4bppAlphaPVR";
    mInfo["Description"] = "Tests 4bpp pvr with alpha.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_4bppAlphaPVR::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testpvr", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    p->createTextureUnitState("ogreborderUp_pvr4a.pvr");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
}
//----------------------------------------------------------------------------

void PlayPen_4bppAlphaPVR::testCapabilities(const Ogre::RenderSystemCapabilities* caps)
{
    Codec* codec = Codec::getCodec("pvr");
    if (!codec)
        throw Ogre::Exception(999, "No support for PVR textures.", "testCapabilities");
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_4bppPVR::PlayPen_4bppPVR()
{
    mInfo["Title"] = "PlayPen_4bppPVR";
    mInfo["Description"] = "Tests 4bpp pvr.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_4bppPVR::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testpvr", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    p->createTextureUnitState("ogreborderUp_pvr4.pvr");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
}
//----------------------------------------------------------------------------

void PlayPen_4bppPVR::testCapabilities(const Ogre::RenderSystemCapabilities* caps)
{
    Codec* codec = Codec::getCodec("pvr");
    if (!codec)
        throw Ogre::Exception(999, "No support for PVR textures.", "testCapabilities");
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_AlphaToCoverage::PlayPen_AlphaToCoverage()
{
    mInfo["Title"] = "PlayPen_AlphaToCoverage";
    mInfo["Description"] = "Tests alpha to coverage support.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_AlphaToCoverage::setupContent()
{
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testa2c", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setAlphaRejectSettings(CMPF_GREATER, 96);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->setAlphaToCoverageEnabled(true);
    TextureUnitState* t = p->createTextureUnitState("leaf.png");
    t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
    Entity *e = mSceneMgr->createEntity("PlaneA2C", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100, 0, 0))->attachObject(e);
    
    
    mat = MaterialManager::getSingleton().create("testnoa2c", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    p = mat->getTechnique(0)->getPass(0);
    p->setAlphaRejectSettings(CMPF_GREATER, 96);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->setAlphaToCoverageEnabled(false);
    t = p->createTextureUnitState("leaf.png");
    t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
    e = mSceneMgr->createEntity("PlaneNoA2C", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-100, 0, 0))->attachObject(e);
    
    mat = MaterialManager::getSingleton().create("bg", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    t = p->createTextureUnitState();
    t->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue::White);
    e = mSceneMgr->createEntity("PlaneBg", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    e->setRenderQueueGroup(RENDER_QUEUE_BACKGROUND);
    SceneNode* s = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0, 0, -10));
    s->setScale(5,5,5);
    s->attachObject(e);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_AttachObjectsToBones::PlayPen_AttachObjectsToBones()
{
    mInfo["Title"] = "PlayPen_AttachObjectsToBones";
    mInfo["Description"] = "Tests attaching objectes to bones.";
    addScreenshotFrame(120);
}
//----------------------------------------------------------------------------

void PlayPen_AttachObjectsToBones::setupContent()
{
    Entity *ent;
    for (int i = 0; i < 12; ++i)
    {
        ent = mSceneMgr->createEntity("robot" + StringConverter::toString(i), "robot.mesh");
        if (i % 2)
        {
            Entity* ent2 = mSceneMgr->createEntity("plane" + StringConverter::toString(i), "razor.mesh");
            ent->attachObjectToBone("Joint8", ent2);
        }
        else
        {
            ParticleSystem* psys = mSceneMgr->createParticleSystem("psys" + StringConverter::toString(i), "Examples/PurpleFountain");
            psys->getEmitter(0)->setTimeToLive(0.2);
            ent->attachObjectToBone("Joint15", psys);
        }
        // Add entity to the scene node
        mSceneMgr->getRootSceneNode()->createChildSceneNode(
        Vector3(0,0,(i*200)-(12*200/2)))->attachObject(ent);
        
        ent->getParentNode()->yaw(Degree(i * 45));

        AnimationState* animState = ent->getAnimationState("Walk");
        animState->setEnabled(true);
        mAnimStateList.push_back(animState);
    }
    
    
    
    // Give it a little ambience with lights
    Light* l;
    l = mSceneMgr->createLight("BlueLight");
    l->setPosition(-200,-80,-100);
    l->setDiffuseColour(0.5, 0.5, 1.0);
    
    l = mSceneMgr->createLight("GreenLight");
    l->setPosition(0,0,-100);
    l->setDiffuseColour(0.5, 1.0, 0.5);
    
    // Position the camera
    mCamera->setPosition(400,120,500);
    mCamera->lookAt(-50,50,0);
    
    mSceneMgr->setAmbientLight(ColourValue(1,1,1,1));
    //mSceneMgr->showBoundingBoxes(true);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_BasicPlane::PlayPen_BasicPlane()
{
    mInfo["Title"] = "PlayPen_BasicPlane";
    mInfo["Description"] = "Tests basic planes.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_BasicPlane::setupContent()
{
    /*
    // Create a light
    Light* l = mSceneMgr->createLight("MainLight");
    // Accept default settings: point light, white diffuse, just set position
    // NB I could attach the light to a SceneNode if I wanted it to move automatically with
    //  other objects, but I don't
    l->setPosition(20,80,50);
    */
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(-Vector3::UNIT_Y);
    Entity *ent;
    
    // Define a floor plane mesh
    Plane p;
    p.normal = Vector3::UNIT_Y;
    p.d = 200;
    MeshManager::getSingleton().createPlane("FloorPlane",
    TRANSIENT_RESOURCE_GROUP,
    p,2000,2000,1,1,true,1,5,5,Vector3::UNIT_Z);
    
    // Create an entity (the floor)
    ent = mSceneMgr->createEntity("floor", "FloorPlane");
    ent->setMaterialName("Examples/RustySteel");
    
    mSceneMgr->getRootSceneNode()->attachObject(ent);
    
    Entity* sphereEnt = mSceneMgr->createEntity("ogre", "ogrehead.mesh");
    
    SceneNode* mRootNode = mSceneMgr->getRootSceneNode();
    SceneNode* node = mSceneMgr->createSceneNode();
    node->attachObject(sphereEnt);
    mRootNode->addChild(node);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_BillboardAccurateFacing::PlayPen_BillboardAccurateFacing()
{
    mInfo["Title"] = "PlayPen_BillboardAccurateFacing";
    mInfo["Description"] = "Tests billboard facing.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_BillboardAccurateFacing::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    Light* l = mSceneMgr->createLight("light1");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(dir);
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    BillboardSet* bbs = mSceneMgr->createBillboardSet("1");
    bbs->setDefaultDimensions(50,50);
    bbs->createBillboard(-100, 25, 0);
    bbs->setBillboardType(BBT_ORIENTED_COMMON);
    bbs->setCommonDirection(Vector3::UNIT_Y);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(bbs);
    
    bbs = mSceneMgr->createBillboardSet("2");
    bbs->setDefaultDimensions(50,50);
    bbs->createBillboard(100, 25, 0);
    bbs->setUseAccurateFacing(true);
    bbs->setBillboardType(BBT_ORIENTED_COMMON);
    bbs->setCommonDirection(Vector3::UNIT_Y);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(bbs);

    mCamera->setPosition(200,120,300);
    mCamera->lookAt(0,0,0);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_BillboardChain::PlayPen_BillboardChain()
{
    mInfo["Title"] = "PlayPen_BillboardChain";
    mInfo["Description"] = "Tests billboard chains.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_BillboardChain::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    Light* l = mSceneMgr->createLight("light1");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(dir);
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    BillboardChain* chain = static_cast<BillboardChain*>(
    mSceneMgr->createMovableObject("1", "BillboardChain"));
    chain->setUseTextureCoords(true);
    chain->setUseVertexColours(false);
    
    BillboardChain::Element elem;
    elem.width = 10;
    elem.texCoord = 0;
    elem.position = Vector3(0,20,0);
    chain->addChainElement(0, elem);
    elem.position = Vector3(20,0,0);
    elem.texCoord = 1.0;
    chain->addChainElement(0, elem);
    elem.position = Vector3(40,10,0);
    elem.texCoord = 2.0;
    chain->addChainElement(0, elem);
    elem.position = Vector3(60,20,0);
    elem.texCoord = 3.0;
    chain->addChainElement(0, elem);
    elem.position = Vector3(80,40,0);
    elem.texCoord = 4.0;
    chain->addChainElement(0, elem);
    elem.position = Vector3(100,70,0);
    elem.texCoord = 5.0;
    chain->addChainElement(0, elem);
    
    chain->setMaterialName("Examples/ShowNormals");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(chain);
    
    mSceneMgr->showBoundingBoxes(true);

    mCamera->setPosition(-20,60,200);
    mCamera->lookAt(60,40,0);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_BillboardOrigins::PlayPen_BillboardOrigins()
{
    mInfo["Title"] = "PlayPen_BillboardOrigins";
    mInfo["Description"] = "Tests setting billboard origins.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_BillboardOrigins::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    Light* l = mSceneMgr->createLight("light1");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(dir);
    
    /*Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 0;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);*/
    
    BillboardSet* bbs = mSceneMgr->createBillboardSet("1");
    bbs->setDefaultDimensions(50,50);
    bbs->createBillboard(0, 0, 0);
    bbs->setBillboardOrigin(BBO_TOP_LEFT);
    bbs->setMaterialName("2 - Default");
    //bbs->setBillboardType(BBT_ORIENTED_COMMON);
    bbs->setCommonDirection(Vector3::UNIT_Y);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(bbs);
    
    bbs = mSceneMgr->createBillboardSet("2");
    bbs->setDefaultDimensions(50,50);
    bbs->createBillboard(0, -10, 0);
    bbs->setBillboardOrigin(BBO_CENTER);
    bbs->setMaterialName("Examples/RustySteel");
    //bbs->setBillboardType(BBT_ORIENTED_COMMON);
    bbs->setCommonDirection(Vector3::UNIT_Y);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(bbs);

    bbs = mSceneMgr->createBillboardSet("3");
    bbs->setDefaultDimensions(50,50);
    bbs->createBillboard(0, -20, 0);
    bbs->setBillboardOrigin(BBO_BOTTOM_RIGHT);
    bbs->setMaterialName("Examples/OgreLogo");
    //bbs->setBillboardType(BBT_ORIENTED_COMMON);
    bbs->setCommonDirection(Vector3::UNIT_Y);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(bbs);

    mCamera->setPosition(0,160,1);
    mCamera->lookAt(0,0,0);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_BillboardTextureCoords::PlayPen_BillboardTextureCoords()
{
    mInfo["Title"] = "PlayPen_BillboardTextureCoords";
    mInfo["Description"] = "Tests setting billboard texture coordinates.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_BillboardTextureCoords::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue::White);
    
    BillboardSet* bbs = mSceneMgr->createBillboardSet("test");
    BillboardSet* bbs2 = mSceneMgr->createBillboardSet("test2");
    float xsegs = 3;
    float ysegs = 3;
    float width = 300;
    float height = 300;
    float gap = 20;
    
    // set up texture coords
    bbs->setTextureStacksAndSlices(ysegs, xsegs);
    bbs->setDefaultDimensions(width/xsegs, height/xsegs);
    bbs2->setDefaultDimensions(width/xsegs, height/xsegs);
    
    for (float y = 0; y < ysegs; ++y)
    {
        for (float x = 0; x < xsegs; ++x)
        {
            Vector3 midPoint;
            midPoint.x = (x * width / xsegs) + ((x-1) * gap);
            midPoint.y = (y * height / ysegs) + ((y-1) * gap);
            midPoint.z = 0;
            Billboard* bb = bbs->createBillboard(midPoint);
            bb->setTexcoordIndex((ysegs - y - 1)*xsegs + x);
            Billboard* bb2 = bbs2->createBillboard(midPoint);
            bb2->setTexcoordRect(
            FloatRect((x + 0) / xsegs, (ysegs - y - 1) / ysegs,
            (x + 1) / xsegs, (ysegs - y - 0) / ysegs));
        }
    }
    
    bbs->setMaterialName("Examples/OgreLogo");
    bbs2->setMaterialName("Examples/OgreLogo");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(bbs);
    mSceneMgr->getRootSceneNode()
    ->createChildSceneNode(Vector3(- (width + xsegs * gap), 0, 0))
    ->attachObject(bbs2);
    
    mCamera->setPosition(-100,150,900);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_BlendDiffuseColour::PlayPen_BlendDiffuseColour()
{
    mInfo["Title"] = "PlayPen_BlendDiffuseColour";
    mInfo["Description"] = "Tests diffuse blending.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_BlendDiffuseColour::setupContent()
{
    MaterialPtr mat = MaterialManager::getSingleton().create(
    "testBlendDiffuseColour", TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* pass = mat->getTechnique(0)->getPass(0);
    // no lighting, it will mess up vertex colours
    pass->setLightingEnabled(false);
    // Make sure we pull in vertex colour as diffuse
    pass->setVertexColourTracking(TVC_DIFFUSE);
    // Base layer
    TextureUnitState* t = pass->createTextureUnitState("BeachStones.jpg");
    // don't want to bring in vertex diffuse on base layer
    t->setColourOperation(LBO_REPLACE); 
    // Second layer (lerp based on colour)
    t = pass->createTextureUnitState("terr_dirt-grass.jpg");
    t->setColourOperationEx(LBX_BLEND_DIFFUSE_COLOUR);
    // third layer (lerp based on alpha)
    ManualObject* man = mSceneMgr->createManualObject("quad");
    man->begin("testBlendDiffuseColour");
    man->position(-100, 100, 0);
    man->textureCoord(0,0);
    man->colour(0, 0, 0);
    man->position(-100, -100, 0);
    man->textureCoord(0,1);
    man->colour(0.5, 0.5, 0.5);
    man->position(100, -100, 0);
    man->textureCoord(1,1);
    man->colour(1, 1, 1);
    man->position(100, 100, 0);
    man->textureCoord(1,0);
    man->colour(0.5, 0.5, 0.5);
    man->quad(0, 1, 2, 3);
    man->end();
    
    mSceneMgr->getRootSceneNode()->attachObject(man);

    mCamera->setPosition(0,0,250);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_BlitSubTextures::PlayPen_BlitSubTextures()
{
    mInfo["Title"] = "PlayPen_BlitSubTextures";
    mInfo["Description"] = "Tests blitting textures onto on another.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_BlitSubTextures::setupContent()
{
    Image img;
    img.load("ogrelogo.png", TRANSIENT_RESOURCE_GROUP);
    
    TexturePtr tex = TextureManager::getSingleton().createManual("testblitdst", 
    TRANSIENT_RESOURCE_GROUP, TEX_TYPE_2D, 1024, 1024, 1, 0, PF_R8G8B8A8);
    
    PixelBox srcBox;
    // this box should select from halfway through the head, to the 'OG' part of the logo
    srcBox.left = 376;
    srcBox.top = 379;
    srcBox.right = 376 + 224;
    srcBox.bottom = 379 + 278;
    srcBox.back = 1;
    srcBox.front = 0;
    srcBox.format = img.getFormat();
    srcBox.data = img.getData();
    srcBox.rowPitch = img.getWidth();
    srcBox.slicePitch = img.getWidth() * img.getHeight();
    
    Image::Box dstBox;
    dstBox.left = srcBox.left;
    dstBox.top = srcBox.top;
    dstBox.right = srcBox.right;
    dstBox.bottom = srcBox.bottom;
    dstBox.back = 1;
    dstBox.front = 0;

    // I was getting uninitialized memory written to the texture buffer, so clear it explicitly
    memset(tex->getBuffer()->lock(0, tex->getBuffer()->getSizeInBytes(), 
        HardwareBuffer::HBL_NORMAL), 0, tex->getBuffer()->getSizeInBytes());
    tex->getBuffer()->unlock();
    
    tex->getBuffer()->blitFromMemory(srcBox, dstBox);
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testblit", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->createTextureUnitState(tex->getName());
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Green);
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Bsp::PlayPen_Bsp()
{
    mInfo["Title"] = "PlayPen_Bsp";
    mInfo["Description"] = "Tests BSP plugin.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_Bsp::setupContent()
{
    // Load Quake3 locations from a file
    ConfigFile cf;
    
    cf.load(mFSLayer->getConfigFilePath("quakemap.cfg"));
    
    String quakePk3 = cf.getSetting("Archive");
    String quakeLevel = cf.getSetting("Map");
    
    //ResourceGroupManager::getSingleton().addResourceLocation(quakePk3, "Zip");

    ResourceGroupManager::getSingleton().addResourceLocation(
        quakePk3, "Zip",
        ResourceGroupManager::getSingleton().getWorldResourceGroupName(), true);
    
    // Load world geometry
    //mSceneMgr->setWorldGeometry(quakeLevel);

    ResourceGroupManager& rgm = ResourceGroupManager::getSingleton();
    rgm.linkWorldGeometryToResourceGroup(rgm.getWorldResourceGroupName(), quakeLevel, mSceneMgr);
    rgm.initialiseResourceGroup(rgm.getWorldResourceGroupName());
    rgm.loadResourceGroup(rgm.getWorldResourceGroupName(), false);
    
    // modify camera for close work
    mCamera->setNearClipDistance(4);
    mCamera->setFarClipDistance(4000);
    
    // Also change position, and set Quake-type orientation
    // Get random player start point
    ViewPoint vp = mSceneMgr->getSuggestedViewpoint(true);
    mCamera->setPosition(vp.position);
    mCamera->pitch(Degree(90)); // Quake uses X/Y horizon, Z up
    mCamera->rotate(vp.orientation);
    // Don't yaw along variable axis, causes leaning
    mCamera->setFixedYawAxis(true, Vector3::UNIT_Z);

    mCamera->yaw(Ogre::Degree(-90.f));
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_BuildTangentOnAnimatedMesh::PlayPen_BuildTangentOnAnimatedMesh()
{
    mInfo["Title"] = "PlayPen_BuildTangentOnAnimatedMesh";
    mInfo["Description"] = "Tests building tangents for an animated mesh.";
    addScreenshotFrame(50);
}
//----------------------------------------------------------------------------

void PlayPen_BuildTangentOnAnimatedMesh::setupContent()
{
    SceneNode* mTestNode[2];
    Light* mLight = 0;
    //mSceneMgr->setShadowTextureSize(512);
    //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
    //mSceneMgr->setShadowFarDistance(1500);
    //mSceneMgr->setShadowColour(ColourValue(0.35, 0.35, 0.35));
    //mSceneMgr->setShadowFarDistance(800);
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));
    
    mLight = mSceneMgr->createLight("MainLight");
    
    /*/
    // Directional test
    mLight->setType(Light::LT_DIRECTIONAL);
    Vector3 vec(-1,-1,0);
    vec.normalise();
    mLight->setDirection(vec);
    /*/
    // Point test
    mLight->setType(Light::LT_POINT);
    mLight->setPosition(0, 200, 0);
    //*/
    MeshPtr pMesh = MeshManager::getSingleton().load("ninja.mesh",
    TRANSIENT_RESOURCE_GROUP/*,    
    HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, 
    HardwareBuffer::HBU_STATIC_WRITE_ONLY, 
    true, true*/); //so we can still read it
    // Build tangent vectors, all our meshes use only 1 texture coordset 
    unsigned short src, dest;
    if (!pMesh->suggestTangentVectorBuildParams(VES_TANGENT, src, dest))
    {
        pMesh->buildTangentVectors(VES_TANGENT, src, dest);
    }
    
    Entity* pEnt = mSceneMgr->createEntity("Ninja", "ninja.mesh");
    
    /*/
    mAnimState = pEnt->getAnimationState("Walk");
    mAnimState->setEnabled(true);
    /*/
    pEnt->getAnimationState("Walk")->setEnabled(true);
    //*/
    mTestNode[1] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    mTestNode[1]->attachObject( pEnt );
    mTestNode[1]->translate(-100,-100,0);
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);

    mCamera->setPosition(0,0,400);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ClearScene::PlayPen_ClearScene()
    :mFramesElapsed(0)
{
    mInfo["Title"] = "PlayPen_ClearScene";
    mInfo["Description"] = "Tests clearing a running scene.";
    addScreenshotFrame(25);
}
//----------------------------------------------------------------------------

bool PlayPen_ClearScene::frameStarted(const Ogre::FrameEvent& evt)
{
    ++mFramesElapsed;
    if(mFramesElapsed == 20)
        mSceneMgr->clearScene();
    return true;
}
//----------------------------------------------------------------------------

void PlayPen_ClearScene::setupContent()
{
    // Define a floor plane mesh
    Plane p;
    p.normal = Vector3::UNIT_Y;
    p.d = 200;
    MeshManager::getSingleton().createPlane("FloorPlane",
    TRANSIENT_RESOURCE_GROUP,
    p,200000,200000,20,20,true,1,50,50,Vector3::UNIT_Z);

    Entity* planeEnt;
    planeEnt = mSceneMgr->createEntity( "plane", "FloorPlane" );
    planeEnt->setMaterialName("Examples/Rockwall");
    mSceneMgr->getRootSceneNode()->attachObject(planeEnt);

    mCamera->setPosition(0,500,100);
    mCamera->lookAt(0,0,0);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_CompositorTechniqueSwitch::PlayPen_CompositorTechniqueSwitch()
{
    mInfo["Title"] = "PlayPen_CompositorTechniqueSwitch";
    mInfo["Description"] = "Tests switching compositor techniques rapidly.";
    addScreenshotFrame(15);
}
//----------------------------------------------------------------------------

void PlayPen_CompositorTechniqueSwitch::cleanupContent()
{
    CompositorManager::getSingleton().removeCompositorChain(mViewport);
}
//----------------------------------------------------------------------------

bool PlayPen_CompositorTechniqueSwitch::frameStarted(const FrameEvent& evt)
{
    mTimeUntilNextToggle -= evt.timeSinceLastFrame;

    if(mTimeUntilNextToggle <= 0.f)
    {
        ++mCompositorIndex;
        mCompositorIndex = mCompositorIndex % mCompositorSchemeList.size();
        mCompositorToSwitch->setScheme(mCompositorSchemeList[mCompositorIndex]);
        mTimeUntilNextToggle = 0.1;        
    }

    return true;
}
//----------------------------------------------------------------------------

void PlayPen_CompositorTechniqueSwitch::setupContent()
{
    mTimeUntilNextToggle = 0.1f;// swap compositors every 10 frames
    CompositorManager& cmgr = CompositorManager::getSingleton();
    CompositorPtr compositor = cmgr.create("testtechswitch", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Compositor>();
    // technique 1 (Invert)
    CompositionTechnique* ctech1 = compositor->createTechnique();
    CompositionTechnique::TextureDefinition* tdef =    ctech1->createTextureDefinition("rt0");
    tdef->formatList.push_back(PF_A8B8G8R8);
    tdef->width = tdef->height = 0;
    tdef->pooled = true;
    
    CompositionTargetPass* tpass = ctech1->createTargetPass();
    tpass->setOutputName("rt0");
    tpass->setInputMode(CompositionTargetPass::IM_PREVIOUS);
    CompositionTargetPass* tout = ctech1->getOutputTargetPass();
    tout->setInputMode(CompositionTargetPass::IM_NONE);
    CompositionPass* pass = tout->createPass();
    pass->setType(CompositionPass::PT_RENDERQUAD);
    pass->setMaterialName("Ogre/Compositor/Invert");
    pass->setInput(0, "rt0");
    
    // technique 2 (Tiling)
    ctech1 = compositor->createTechnique();
    ctech1->setSchemeName("Tiling");
    tdef =    ctech1->createTextureDefinition("rt0");
    tdef->formatList.push_back(PF_A8B8G8R8);
    tdef->width = tdef->height = 0;
    tdef->pooled = true;
    
    tpass = ctech1->createTargetPass();
    tpass->setOutputName("rt0");
    tpass->setInputMode(CompositionTargetPass::IM_PREVIOUS);
    tout = ctech1->getOutputTargetPass();
    tout->setInputMode(CompositionTargetPass::IM_NONE);
    pass = tout->createPass();
    pass->setType(CompositionPass::PT_RENDERQUAD);
    pass->setMaterialName("Ogre/Compositor/Tiling");
    pass->setInput(0, "rt0");
    
    compositor->load();
    
    Entity* e = mSceneMgr->createEntity("1", "knot.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox", 1000);
    
    // enable compositor (should pick first technique)
    Viewport* vp = mWindow->getViewport(0);
    
    mCompositorToSwitch = cmgr.addCompositor(vp, compositor->getName());
    mCompositorSchemeList.push_back("");
    mCompositorSchemeList.push_back("Tiling");
    
    cmgr.setCompositorEnabled(vp, compositor->getName(), true);
    
    mCamera->setPosition(0, 0, -300);
    mCamera->lookAt(Vector3::ZERO);
    
    mCompositorIndex = 0;
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_CompositorTextureShadows::PlayPen_CompositorTextureShadows()
{
    mInfo["Title"] = "PlayPen_CompositorTextureShadows";
    mInfo["Description"] = "Tests applying a compositor to a texture shadow manager.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_CompositorTextureShadows::cleanupContent()
{
    TexturePtr shadowTex = mSceneMgr->getShadowTexture(0);
    RenderTarget* shadowRtt = shadowTex->getBuffer()->getRenderTarget();
    Viewport* vp = shadowRtt->getViewport(0);
    CompositorManager::getSingleton().removeCompositorChain(vp);
    clearDebugTextureOverlays();
}
//----------------------------------------------------------------------------

void PlayPen_CompositorTextureShadows::setupContent()
{
    SceneNode* mTestNode[10];

    mSceneMgr->setShadowTextureSize(512);
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
    mSceneMgr->setShadowFarDistance(1500);
    mSceneMgr->setShadowColour(ColourValue(0.35, 0.35, 0.35));
    //mSceneMgr->setShadowFarDistance(800);
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));
    
    Light* mLight = mSceneMgr->createLight("MainLight");
    
    /*
    // Directional test
    mLight->setType(Light::LT_DIRECTIONAL);
    Vector3 vec(-1,-1,0);
    vec.normalise();
    mLight->setDirection(vec);
    
    */
    // Spotlight test
    mLight->setType(Light::LT_SPOTLIGHT);
    mLight->setDiffuseColour(1.0, 1.0, 0.8);
    mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    mTestNode[0]->setPosition(800,600,0);
    mTestNode[0]->lookAt(Vector3(0,0,0), Node::TS_WORLD, Vector3::UNIT_Z);
    mTestNode[0]->attachObject(mLight);
    
    
    mTestNode[1] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    
    
    Entity* pEnt;
    pEnt = mSceneMgr->createEntity( "1", "robot.mesh" );
    //pEnt->setRenderingDistance(100);
    AnimationState* mAnimState = pEnt->getAnimationState("Walk");
    mAnimState->setEnabled(true);
    mAnimStateList.push_back(mAnimState);
    //pEnt->setMaterialName("2 - Default");
    mTestNode[1]->attachObject( pEnt );
    mTestNode[1]->translate(0,-100,0);
    
    pEnt = mSceneMgr->createEntity( "3", "knot.mesh" );
    mTestNode[2] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-200, 0, -200));
    mTestNode[2]->attachObject( pEnt );
    
    // Transparent object (can force cast shadows)
    pEnt = mSceneMgr->createEntity( "3.5", "knot.mesh" );
    MaterialPtr tmat = MaterialManager::getSingleton().create("TestAlphaTransparency", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    tmat->setTransparencyCastsShadows(true);
    Pass* tpass = tmat->getTechnique(0)->getPass(0);
    tpass->setAlphaRejectSettings(CMPF_GREATER, 150);
    tpass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    tpass->createTextureUnitState("gras_02.png");
    tpass->setCullingMode(CULL_NONE);
    
    pEnt->setMaterialName("TestAlphaTransparency");
    mTestNode[3] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(350, 0, -200));
    mTestNode[3]->attachObject( pEnt );
    
    MeshPtr msh = MeshManager::getSingleton().load("knot.mesh",
    TRANSIENT_RESOURCE_GROUP);
    msh->buildTangentVectors(VES_TANGENT, 0, 0);
    pEnt = mSceneMgr->createEntity( "4", "knot.mesh" );
    //pEnt->setMaterialName("Examples/BumpMapping/MultiLightSpecular");
    mTestNode[2] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100, 0, 200));
    mTestNode[2]->attachObject( pEnt );
    
    mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    // Set up a debug panel to display the shadow
    addTextureShadowDebugOverlay(1, mSceneMgr);
    
    
    
    ParticleSystem* pSys2 = mSceneMgr->createParticleSystem("smoke", 
    "Examples/Smoke");
    mTestNode[4] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-300, -100, 200));
    mTestNode[4]->attachObject(pSys2);

    TexturePtr shadowTex = mSceneMgr->getShadowTexture(0);
    RenderTarget* shadowRtt = shadowTex->getBuffer()->getRenderTarget();
    Viewport* vp = shadowRtt->getViewport(0);
    // This originally used gaussian blur, but since compositor logic stuff has changed since the test
    // was originally written and I'm not especially familiar with it, I just swapped to a random 
    // compositor (it still tests the required functionality)
    CompositorManager::getSingleton().addCompositor(vp, "Laplace");
    CompositorManager::getSingleton().setCompositorEnabled(
    vp, "Laplace", true);

    mCamera->setPosition(400, 250, 350);
    mCamera->lookAt(0,0,0);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_CubeDDS::PlayPen_CubeDDS()
{
    mInfo["Title"] = "PlayPen_CubeDDS";
    mInfo["Description"] = "Tests DDS cubemaps.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_CubeDDS::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testcube", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    TextureUnitState* t = p->createTextureUnitState();
    t->setTextureName("grace_cube.dds", TEX_TYPE_CUBE_MAP);
    t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
    t->setEnvironmentMap(true, TextureUnitState::ENV_REFLECTION);
    Entity* e = mSceneMgr->createEntity("1", "sphere.mesh");
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    
    mCamera->setPosition(300,0,0);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_CustomProjectionMatrix::PlayPen_CustomProjectionMatrix()
{
    mInfo["Title"] = "PlayPen_CustomProjectionMatrix";
    mInfo["Description"] = "Tests custom projection matrix.";
}
//----------------------------------------------------------------------------

void PlayPen_CustomProjectionMatrix::setupContent()
{
    PlayPen_LotsAndLotsOfEntities::setupContent();
    Matrix4 mat = mCamera->getProjectionMatrix();
    mCamera->setCustomProjectionMatrix(true, mat);
    mat = mCamera->getProjectionMatrix();
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_DepthBias::PlayPen_DepthBias()
{
    mInfo["Title"] = "PlayPen_DepthBias";
    mInfo["Description"] = "Tests depth biasing.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_DepthBias::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    mSceneMgr->setAmbientLight(ColourValue::White);
    
    MaterialPtr mat = MaterialManager::getSingleton().create("mat1", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->createTextureUnitState("BumpyMetal.jpg");
    
    const String meshName("cube.mesh"); 
    Entity* entity = mSceneMgr->createEntity("base", meshName);
    entity->setMaterialName("mat1");
    mSceneMgr->getRootSceneNode()->attachObject(entity);
    
    
    entity = mSceneMgr->createEntity("base2", meshName);
    entity->setMaterialName("Examples/SphereMappedRustySteel");
    SceneNode* n = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    n->setPosition(-30, 0, 0);
    n->yaw(Degree(45));
    n->attachObject(entity);
    
    for (size_t i = 0; i <= 6;++i)
    {
        String name("decal");
        name += StringConverter::toString(i);
        
        MaterialPtr pMat = MaterialManager::getSingleton().create(name, TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
        
        pMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
        pMat->getTechnique(0)->getPass(0)->setAlphaRejectSettings(CMPF_GREATER_EQUAL, 128);
        pMat->getTechnique(0)->getPass(0)->setDepthBias(i);
        pMat->getTechnique(0)->getPass(0)->createTextureUnitState(name + ".png");
        
        entity = mSceneMgr->createEntity(name, meshName);
        entity->setMaterialName(name);
        mSceneMgr->getRootSceneNode()->attachObject(entity);
    }
    
    
    
    mCamera->setPosition(0,0,200);
    mCamera->lookAt(Vector3::ZERO);
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_DepthShadowMap::PlayPen_DepthShadowMap()
{
    mInfo["Title"] = "PlayPen_DepthShadowMap";
    mInfo["Description"] = "Tests depth shadowmapping.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_DepthShadowMap::setupContent()
{
    mSceneMgr->setShadowTextureCount(1);
    mSceneMgr->setShadowTextureConfig(0, 1024, 1024, PF_FLOAT32_R);
    mSceneMgr->setShadowTextureSelfShadow(true);
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE);
    mSceneMgr->setShadowCasterRenderBackFaces(false);
    
    mSceneMgr->setShadowTextureCasterMaterial("Ogre/DepthShadowmap/Caster/Float");

    LiSPSMShadowCameraSetup *mLiSPSMSetup = new LiSPSMShadowCameraSetup();
    //mLiSPSMSetup->setUseAggressiveFocusRegion(false);
    ShadowCameraSetupPtr mCurrentShadowCameraSetup = ShadowCameraSetupPtr(mLiSPSMSetup);
    //ShadowCameraSetupPtr mCurrentShadowCameraSetup = ShadowCameraSetupPtr(new PlaneOptimalShadowCameraSetup(mPlane));                    
    mSceneMgr->setShadowCameraSetup(mCurrentShadowCameraSetup);
    
    // Single light
    Light* l = mSceneMgr->createLight("l1");
    l->setType(Light::LT_SPOTLIGHT);
    //l->setPosition(500, 500, -100);
    l->setPosition(0, 300, 0);
    Vector3 dir = -l->getPosition();
    dir.normalise();
    l->setDirection(dir);
    l->setSpotlightOuterAngle(Degree(40));
    l->setSpotlightInnerAngle(Degree(35));
    
    // ground plane
    MovablePlane movablePlane = MovablePlane(Vector3::UNIT_Y, 0.f);

    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, movablePlane,
    500,500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("Ogre/DepthShadowmap/Receiver/RockWall");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    // box
    ManualObject* man = mSceneMgr->createManualObject("box");
    Real boxsize = 50;
    Real boxsizehalf = boxsize / 2.0;
    man->begin("Ogre/DepthShadowmap/Receiver/Float");
    man->position(-boxsizehalf, 0, boxsizehalf);
    man->position(boxsizehalf, 0, boxsizehalf);
    man->position(boxsizehalf, 0, -boxsizehalf);
    man->position(-boxsizehalf, 0, -boxsizehalf);
    man->position(-boxsizehalf, boxsize, boxsizehalf);
    man->position(boxsizehalf, boxsize, boxsizehalf);
    man->position(boxsizehalf, boxsize, -boxsizehalf);
    man->position(-boxsizehalf, boxsize, -boxsizehalf);
    man->quad(3, 2, 1, 0);
    man->quad(4, 5, 6, 7);
    man->quad(0, 1, 5, 4);
    man->quad(1, 2, 6, 5);
    man->quad(2, 3, 7, 6);
    man->quad(3, 0, 4, 7);
    man->end();
    
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(man);
    
    mCamera->setPosition(150, 100, 150);
    mCamera->lookAt(Vector3::ZERO);
    
    // Create RTT
    //TexturePtr rtt = TextureManager::getSingleton().createManual("rtt1", TRANSIENT_RESOURCE_GROUP, 
    //    TEX_TYPE_2D, 1024, 1024, 1, 0, PF_FLOAT32_R);
    
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

Entity* pTexListenerPlaneEnt = 0;// yucky global...
Camera* theCam = 0;

class RefractionTextureListener : public RenderTargetListener
{
public:
    void preRenderTargetUpdate(const RenderTargetEvent& evt)
    {
        pTexListenerPlaneEnt->setVisible(false);

    }
    void postRenderTargetUpdate(const RenderTargetEvent& evt)
    {
        pTexListenerPlaneEnt->setVisible(true);
    }

};

class ReflectionTextureListener : public RenderTargetListener
{
public:
    void preRenderTargetUpdate(const RenderTargetEvent& evt)
    {
        static Plane reflectPlane(Vector3::UNIT_Y, -100);
        pTexListenerPlaneEnt->setVisible(false);
        theCam->enableReflection(reflectPlane);

    }
    void postRenderTargetUpdate(const RenderTargetEvent& evt)
    {
        pTexListenerPlaneEnt->setVisible(true);
        theCam->disableReflection();
    }

};

PlayPen_Distortion::PlayPen_Distortion()
{
    mInfo["Title"] = "PlayPen_Distortion";
    mInfo["Description"] = "Tests distortion.";
    addScreenshotFrame(15);

    mRefractionListener = new RefractionTextureListener();
    mReflectionListener = new ReflectionTextureListener();
}
//----------------------------------------------------------------------------

PlayPen_Distortion::~PlayPen_Distortion()
{
    delete mRefractionListener;
    delete mReflectionListener;
}
//----------------------------------------------------------------------------

void PlayPen_Distortion::cleanupContent()
{
    TexturePtr rttTex = TextureManager::getSingleton().getByName("Refraction").staticCast<Texture>();
    rttTex->getBuffer()->getRenderTarget()->removeAllListeners();
    TextureManager::getSingleton().unload(rttTex->getHandle());
    rttTex = TextureManager::getSingleton().getByName("Reflection").staticCast<Texture>();
    rttTex->getBuffer()->getRenderTarget()->removeAllListeners();
    TextureManager::getSingleton().unload(rttTex->getHandle());
}
//----------------------------------------------------------------------------

void PlayPen_Distortion::setupContent()
{
    SceneNode* mTestNode[5];
    theCam = mCamera;
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(-Vector3::UNIT_Y);
    
    Entity* pEnt;
    
    TexturePtr rttTex = TextureManager::getSingleton().createManual("Refraction", 
    TRANSIENT_RESOURCE_GROUP, TEX_TYPE_2D, 
    512, 512, 1, 0, PF_R8G8B8, TU_RENDERTARGET);
    {
        Viewport *v = rttTex->getBuffer()->getRenderTarget()->addViewport( mCamera );
        MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflectionRefraction").staticCast<Material>();
        mat->getTechnique(0)->getPass(0)->getTextureUnitState(2)->setTextureName("Refraction");
        v->setOverlaysEnabled(false);
        rttTex->getBuffer()->getRenderTarget()->addListener(mRefractionListener);
    }
    
    rttTex = TextureManager::getSingleton().createManual("Reflection", 
    TRANSIENT_RESOURCE_GROUP, TEX_TYPE_2D, 
    512, 512, 1, 0, PF_R8G8B8, TU_RENDERTARGET);
    {
        Viewport *v = rttTex->getBuffer()->getRenderTarget()->addViewport( mCamera );
        MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflectionRefraction").staticCast<Material>();
        mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("Reflection");
        v->setOverlaysEnabled(false);
        rttTex->getBuffer()->getRenderTarget()->addListener(mReflectionListener);
    }
    // Define a floor plane mesh
    Plane p;
    p.normal = Vector3::UNIT_Y;
    p.d = 100;
    MeshManager::getSingleton().createPlane("WallPlane",
    TRANSIENT_RESOURCE_GROUP,
    p,1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    pTexListenerPlaneEnt = mSceneMgr->createEntity( "5", "WallPlane" );
    pTexListenerPlaneEnt->setMaterialName("Examples/FresnelReflectionRefraction");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pTexListenerPlaneEnt);
    
    
    mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
    
    mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    int i;
    for (i = 0; i < 10; ++i)
    {
        pEnt = mSceneMgr->createEntity( "ogre" + StringConverter::toString(i), "ogrehead.mesh" );
        mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(i*100 - 500, -75, 0))->attachObject(pEnt);
        pEnt = mSceneMgr->createEntity( "knot" + StringConverter::toString(i), "knot.mesh" );
        mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(i*100 - 500, 140, 0))->attachObject(pEnt);
    }
    
    mCamera->setPosition(100,200,300);
    mCamera->lookAt(0,0,0);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Dxt1Alpha::PlayPen_Dxt1Alpha()
{
    mInfo["Title"] = "PlayPen_Dxt1Alpha";
    mInfo["Description"] = "Tests dxt1 loading with alpha.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_Dxt1Alpha::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testdxt", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    p->setAlphaRejectSettings(CMPF_GREATER, 128);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->createTextureUnitState("gras_02_dxt1.dds");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Dxt1::PlayPen_Dxt1()
{
    mInfo["Title"] = "PlayPen_Dxt1";
    mInfo["Description"] = "Tests dxt1 loading.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_Dxt1::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testdxt", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->createTextureUnitState("BumpyMetal_dxt1.dds");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    
    mCamera->setPosition(0,0,-300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Dxt1FromMemory::PlayPen_Dxt1FromMemory()
{
    mInfo["Title"] = "PlayPen_Dxt1FromMemory";
    mInfo["Description"] = "Tests dxt1 loading from memory.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_Dxt1FromMemory::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    DataStreamPtr stream = ResourceGroupManager::getSingleton().openResource("BumpyMetal_dxt1.dds");
    // manually load into image
    Image img;
    img.load(stream, "dds");
    TextureManager::getSingleton().loadImage("testdxtfrommem", TRANSIENT_RESOURCE_GROUP, img);
    
    
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testdxt", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->createTextureUnitState("testdxtfrommem");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    
    mCamera->setPosition(0,0,-300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Dxt3::PlayPen_Dxt3()
{
    mInfo["Title"] = "PlayPen_Dxt3";
    mInfo["Description"] = "Tests dxt3 loading.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_Dxt3::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testdxt", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    p->createTextureUnitState("ogreborderUp_dxt3.dds");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Dxt3FromMemory::PlayPen_Dxt3FromMemory()
{
    mInfo["Title"] = "PlayPen_Dxt3FromMemory";
    mInfo["Description"] = "Tests dxt3 loading from memory.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_Dxt3FromMemory::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    DataStreamPtr stream = ResourceGroupManager::getSingleton().openResource("ogreborderUp_dxt3.dds");
    // manually load into image
    Image img;
    img.load(stream, "dds");
    TextureManager::getSingleton().loadImage("testdxtfrommem", TRANSIENT_RESOURCE_GROUP, img);
    
    
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testdxt", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    p->setAlphaRejectSettings(CMPF_GREATER, 128);
    mat->setReceiveShadows(false);
    TextureUnitState* t = p->createTextureUnitState("testdxtfrommem");
    t->setTextureScale(0.5,0.5);
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    SceneNode* n = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    n->setPosition(-50, 0, 35);
    n->yaw(Degree(90));
    n->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Dxt5::PlayPen_Dxt5()
{
    mInfo["Title"] = "PlayPen_Dxt5";
    mInfo["Description"] = "Tests dxt5 loading.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_Dxt5::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testdxt", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    p->createTextureUnitState("ogreborderUp_dxt5.dds");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_FarFromOrigin::PlayPen_FarFromOrigin()
{
    mInfo["Title"] = "PlayPen_FarFromOrigin";
    mInfo["Description"] = "Tests rending far from the origin.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_FarFromOrigin::cleanupContent()
{
    //clearDebugTextureOverlays();
}

void PlayPen_FarFromOrigin::setupContent()
{
    SceneNode* mTestNode[5];
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
    mSceneMgr->setShadowTextureSettings(1024, 2);
    
    Vector3 offset(100000, 0, 100000);
    //Vector3 offset(0, 0, 0);
    
    mSceneMgr->setAmbientLight(ColourValue(0.1, 0.1, 0.1));
    
    // Directional test
    Light* mLight = mSceneMgr->createLight("MainLight");
    mLight->setType(Light::LT_DIRECTIONAL);
    Vector3 vec(-1,-1,0);
    vec.normalise();
    mLight->setDirection(vec);
    mLight->setDiffuseColour(ColourValue(0.5, 0.5, 1.0));
    
    // Spotlight test
    mLight = mSceneMgr->createLight("SpotLight");
    mLight->setType(Light::LT_SPOTLIGHT);
    mLight->setAttenuation(10000, 1, 0, 0);
    mLight->setDiffuseColour(1.0, 1.0, 0.5);
    
    mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    mTestNode[0]->setPosition(offset + Vector3(-400,300,1000));
    mTestNode[0]->lookAt(offset, Node::TS_WORLD, Vector3::UNIT_Z);
    mTestNode[0]->attachObject(mLight);
    
    
    mTestNode[1] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    mTestNode[1]->setPosition(offset);
    
    Entity* pEnt;
    pEnt = mSceneMgr->createEntity( "1", "knot.mesh" );
    mTestNode[1]->attachObject( pEnt );
    
    
    mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    2500,2500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(offset)->attachObject(pPlaneEnt);
    
    ParticleSystem* pSys2 = mSceneMgr->createParticleSystem("smoke", 
    "Examples/Smoke");
    mTestNode[4] = mSceneMgr->getRootSceneNode()->createChildSceneNode(offset + Vector3(-300, -100, 200));
    mTestNode[4]->attachObject(pSys2);
    
    mCamera->setPosition(offset + Vector3(0, 1000, 500));
    mCamera->lookAt(offset);
    mCamera->setFarClipDistance(10000);
    
    mSceneMgr->setCameraRelativeRendering(true);
    
    FocusedShadowCameraSetup* camSetup = new FocusedShadowCameraSetup();
    mSceneMgr->setShadowCameraSetup(ShadowCameraSetupPtr(camSetup));
    //addTextureShadowDebugOverlay(1, mSceneMgr);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Float128DDS::PlayPen_Float128DDS()
{
    mInfo["Title"] = "PlayPen_Float128DDS";
    mInfo["Description"] = "Tests 128bit floating point dds textures.";
    addScreenshotFrame(250);
}
//----------------------------------------------------------------------------

void PlayPen_Float128DDS::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testdds", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    p->createTextureUnitState("ogreborderUp_float128.dds");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Float16DDS::PlayPen_Float16DDS()
{
    mInfo["Title"] = "PlayPen_Float16DDS";
    mInfo["Description"] = "Tests 16bit floating point dds textures.";
    addScreenshotFrame(250);
}
//----------------------------------------------------------------------------

void PlayPen_Float16DDS::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testdds", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->createTextureUnitState("BumpyMetal_float16.dds");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Float32DDS::PlayPen_Float32DDS()
{
    mInfo["Title"] = "PlayPen_Float32DDS";
    mInfo["Description"] = "Tests 32bit floating point dds textures.";
    addScreenshotFrame(250);
}
//----------------------------------------------------------------------------

void PlayPen_Float32DDS::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testdds", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->createTextureUnitState("BumpyMetal_float32.dds");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
    // try saving
    TexturePtr tx = TextureManager::getSingleton().getByName("BumpyMetal_float32.dds").staticCast<Texture>();
    float* dataBuf = new float[tx->getWidth() * tx->getHeight() * 4];
    PixelBox pb(tx->getWidth(), tx->getHeight(), 1, PF_FLOAT32_RGB, dataBuf);
    
    tx->getBuffer()->blitToMemory(pb);
    
    Image img;
    img.loadDynamicImage((uchar*)dataBuf, tx->getWidth(), tx->getHeight(), 1, PF_FLOAT32_RGB);
    img.save("test.hdr");
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Float64DDS::PlayPen_Float64DDS()
{
    mInfo["Title"] = "PlayPen_Float64DDS";
    mInfo["Description"] = "Tests 64bit floating point dds textures.";
    addScreenshotFrame(250);
}
//----------------------------------------------------------------------------

void PlayPen_Float64DDS::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    MaterialPtr mat = MaterialManager::getSingleton().create("testdds", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    p->createTextureUnitState("ogreborderUp_float64.dds");
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_GeometryShaders::PlayPen_GeometryShaders()
{
    mInfo["Title"] = "PlayPen_GeometryShaders";
    mInfo["Description"] = "Tests geometry shaders.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_GeometryShaders::testCapabilities(const Ogre::RenderSystemCapabilities* caps)
{
    if(!caps->hasCapability(RSC_GEOMETRY_PROGRAM))
        throw Ogre::Exception(999, "Video card doesn't support geometry shaders.", "testCapabilities");
}
//----------------------------------------------------------------------------

void PlayPen_GeometryShaders::setupContent()
{
    const String GLSL_MATERIAL_NAME = "Ogre/GPTest/SwizzleGLSL";
    const String ASM_MATERIAL_NAME = "Ogre/GPTest/SwizzleASM";
    const String CG_MATERIAL_NAME = "Ogre/GPTest/SwizzleCG";
    
    // Check capabilities
    const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
    if (!caps->hasCapability(RSC_GEOMETRY_PROGRAM))
    {
        OGRE_EXCEPT(Ogre::Exception::ERR_NOT_IMPLEMENTED, "Your card does not support geometry programs, so cannot "
        "run this demo. Sorry!", 
        "GeometryShading::createScene");
    }
    
    int maxOutputVertices = caps->getGeometryProgramNumOutputVertices();
    Ogre::LogManager::getSingleton().getDefaultLog()->stream() << 
    "Num output vertices per geometry shader run : " << maxOutputVertices;
    
    Entity *ent = mSceneMgr->createEntity("head", "ogrehead.mesh");
    mCamera->setPosition(20, 0, 100);
    mCamera->lookAt(0,0,0);
    
    //String materialName = GLSL_MATERIAL_NAME;
    String materialName = ASM_MATERIAL_NAME;
    //String materialName = CG_MATERIAL_NAME;
    
    // Set all of the material's sub entities to use the new material
    for (unsigned int i=0; i<ent->getNumSubEntities(); i++)
    {
        ent->getSubEntity(i)->setMaterialName(materialName);
    }
    
    // Add entity to the root scene node
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Green);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ImageCombine::PlayPen_ImageCombine()
{
    mInfo["Title"] = "PlayPen_ImageCombine";
    mInfo["Description"] = "Tests image combining.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_ImageCombine::setupContent()
{
    Image combined;
    
    // pick 2 files that are the same size, alpha texture will be made greyscale
    combined.loadTwoImagesAsRGBA("rockwall.tga", "flare.png", 
    TRANSIENT_RESOURCE_GROUP, PF_BYTE_RGBA);
    
    TexturePtr tex = TextureManager::getSingleton().createManual("1", TRANSIENT_RESOURCE_GROUP, TEX_TYPE_2D, 256, 256, 1, 0, PF_BYTE_RGBA);
    tex->loadImage(combined);
    
    MaterialManager& mmgr = MaterialManager::getSingleton();
    MaterialPtr mat = mmgr.create("m1", TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* pass = mat->getTechnique(0)->getPass(0);
    pass->setLightingEnabled(false);
    pass->setCullingMode(CULL_NONE);
    pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    pass->setDepthWriteEnabled(false);
    pass->createTextureUnitState(tex->getName());
    
    Entity *e = mSceneMgr->createEntity("test", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    
    mCamera->setPosition(0, 0, 200);
    mCamera->lookAt(Vector3::ZERO);
    
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Blue);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_InfiniteAAB::PlayPen_InfiniteAAB()
{
    mInfo["Title"] = "PlayPen_InfiniteAAB";
    mInfo["Description"] = "Tests finite/infinite AABBs.";
    addScreenshotFrame(15);
}
//----------------------------------------------------------------------------

void PlayPen_InfiniteAAB::setupContent()
{
    // When using the BspSceneManager
    mSceneMgr->setWorldGeometry("ogretestmap.bsp");
    
    // When using the TerrainSceneManager
    //mSceneMgr->setWorldGeometry("terrain.cfg");
    
    AxisAlignedBox b1; // null
    assert( b1.isNull() );
    
    AxisAlignedBox b2(Vector3::ZERO, 5.0 * Vector3::UNIT_SCALE); // finite
    assert( b2.isFinite() );
    
    AxisAlignedBox b3;
    b3.setInfinite();
    assert( b3.isInfinite() );
    
    {
        // Create background material
        MaterialPtr material = MaterialManager::getSingleton().create("Background", "General").staticCast<Material>();
        material->getTechnique(0)->getPass(0)->createTextureUnitState("rockwall.tga");
        material->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
        material->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
        material->getTechnique(0)->getPass(0)->setLightingEnabled(false);
        
        // Create left background rectangle
        // NOTE: Uses finite aab
        Rectangle2D* rect1 = new Rectangle2D(true);
        rect1->setCorners(-0.5, 0.1, -0.1, -0.1);
        // Hacky, set small bounding box, to show problem
        rect1->setBoundingBox(AxisAlignedBox(-10.0*Vector3::UNIT_SCALE, 10.0*Vector3::UNIT_SCALE));
        rect1->setMaterial("Background");
        rect1->setRenderQueueGroup(RENDER_QUEUE_OVERLAY - 1);
        SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode("Background1");
        node->attachObject(rect1);
        
        // Create right background rectangle
        // NOTE: Uses infinite aab
        Rectangle2D* rect2 = new Rectangle2D(true);
        rect2->setCorners(0.1, 0.1, 0.5, -0.1);
        AxisAlignedBox aabInf; aabInf.setInfinite();
        rect2->setBoundingBox(aabInf);
        rect2->setMaterial("Background");
        rect2->setRenderQueueGroup(RENDER_QUEUE_OVERLAY - 1);
        node = mSceneMgr->getRootSceneNode()->createChildSceneNode("Background2");
        node->attachObject(rect2);
        
        // Create a manual object for 2D
        ManualObject* manual = mSceneMgr->createManualObject("manual");
        manual->setUseIdentityProjection(true);
        manual->setUseIdentityView(true);
        manual->begin("BaseWhiteNoLighting", RenderOperation::OT_LINE_STRIP);
        manual->position(-0.2, -0.2, 0.0);
        manual->position( 0.2, -0.2, 0.0);
        manual->position( 0.2,  0.2, 0.0);
        manual->position(-0.2,  0.2, 0.0);
        manual->index(0);
        manual->index(1);
        manual->index(2);
        manual->index(3);
        manual->index(0);
        manual->end();
        manual->setBoundingBox(aabInf); // Use infinite aab to always stay visible
        rect2->setRenderQueueGroup(RENDER_QUEUE_OVERLAY - 1);
        mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(manual);
    }
    
    mSceneMgr->showBoundingBoxes(true);
    
    Entity* ent = mSceneMgr->createEntity("test", "ogrehead.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    "test", 50.0 * Vector3::UNIT_X)->attachObject(ent);

    mCamera->setPosition(100,50,350);
    mCamera->lookAt(0,0,0);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_IntersectionSceneQuery::PlayPen_IntersectionSceneQuery()
{
    mInfo["Title"] = "PlayPen_IntersectionSceneQuery";
    mInfo["Description"] = "Tests intersection query.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

bool PlayPen_IntersectionSceneQuery::frameStarted(const FrameEvent& evt)
{
    IntersectionSceneQueryResult& results = intersectionQuery->execute();
    for (SceneQueryMovableIntersectionList::iterator mov = results.movables2movables.begin();
        mov != results.movables2movables.end(); ++mov)
    {
        SceneQueryMovableObjectPair& thepair = *mov;
        if (thepair.first->getMovableType() == "Entity")
        {
            Entity* ent = static_cast<Entity*>(thepair.first);
            ent->setMaterialName("Examples/RustySteel");

        }
        if (thepair.second->getMovableType() == "Entity")
        {
            Entity* ent = static_cast<Entity*>(thepair.second);
            ent->setMaterialName("Examples/RustySteel");

        }
    }
    return true;
}
//----------------------------------------------------------------------------

void PlayPen_IntersectionSceneQuery::setupContent()
{
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(-Vector3::UNIT_Y);
    
    // Create a set of random balls
    Entity* ent = mSceneMgr->createEntity("Ball", "sphere.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    createRandomEntityClones(ent, 500, Vector3(-2500,-2500,-2500), Vector3(2500,2500,2500), mSceneMgr);
    
    intersectionQuery = mSceneMgr->createIntersectionQuery();

    mCamera->setPosition(0,0,2600);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_LightClipPlanes::PlayPen_LightClipPlanes()
{
    mInfo["Title"] = "PlayPen_LightClipPlanes";
    mInfo["Description"] = "Tests light clipping planes.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_LightClipPlanes::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue::White);
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 0;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    4500,4500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("Examples/GrassFloor");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(150,0,100))->attachObject(pPlaneEnt);
    
    Real lightRange = 1000;
    Real spotWidth = 300;
    
    ManualObject* debugSphere = mSceneMgr->createManualObject("debugSphere");
    debugSphere->begin("BaseWhiteNoLighting", RenderOperation::OT_LINE_STRIP);
    for (int i = 0; i <= 20; ++i)
    {
        Vector3 basePos(spotWidth, 0, 0);
        Quaternion quat;
        quat.FromAngleAxis(Radian(((float)i/(float)20)*Math::TWO_PI), Vector3::UNIT_Y);
        basePos = quat * basePos;
        debugSphere->position(basePos);
    }
    debugSphere->end();
    
    Light* l = mSceneMgr->createLight("l1");
    l->setAttenuation(lightRange, 1, 0, 0);
    SceneNode* n = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100,0,0));
    n->attachObject(debugSphere);
    /* SPOT LIGHT
    */
    // match spot width to groud
    Real spotHeight = lightRange * 0.5;
    n = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100,spotHeight,0));
    l->setType(Light::LT_SPOTLIGHT);
    Radian spotAngle = Math::ATan(spotWidth / spotHeight) * 2;
    l->setSpotlightOuterAngle(spotAngle); 
    l->setSpotlightInnerAngle(spotAngle * 0.75);
    Vector3 dir(0, -1, 0);
    dir.normalise();
    l->setDirection(dir);
    
    /* END SPOT LIGHT */
    n->attachObject(l);
    
    // Modify the plane material so that it clips to the light
    // Normally you'd only clip a secondary pass but this is engineered so you
    // can actually see the scissoring effect
    MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/GrassFloor").staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightClipPlanesEnabled(true);
    //if (scissortoo)
    //p->setLightScissoringEnabled(true);
    
    mCamera->setPosition(0, 200, 300);
    mCamera->lookAt(Vector3::ZERO);
    
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_LightClipPlanesMoreLights::PlayPen_LightClipPlanesMoreLights()
{
    mInfo["Title"] = "PlayPen_LightClipPlanesMoreLights";
    mInfo["Description"] = "Tests light clip planes with more lights.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_LightClipPlanesMoreLights::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue(0.3, 0.25, 0.2, 0));
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE);
    mSceneMgr->setShadowTextureCount(3);
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 0;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    4500,4500,100,100,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("Examples/GrassFloor");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    Real lightRange = 1000;
    Real spotWidth = 300;
    
    int numLights = 8;
    Real xoff = -numLights * spotWidth * 0.5;
    
    
    for (int i = 0; i < numLights; ++i)
    {
        Light* l = mSceneMgr->createLight("l" + StringConverter::toString(i));
        l->setAttenuation(lightRange, 1, 0, 0);
        /* SPOT LIGHT
        */
        // match spot width to groud
        Real spotHeight = lightRange * 0.5;
        SceneNode* n = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3((spotWidth+50)*i + xoff,spotHeight,0));
        l->setType(Light::LT_SPOTLIGHT);
        Radian spotAngle = Math::ATan(spotWidth / spotHeight) * 2;
        l->setSpotlightOuterAngle(spotAngle); 
        l->setSpotlightInnerAngle(spotAngle * 0.75);
        Vector3 dir(0, -1, 0);
        dir.normalise();
        l->setDirection(dir);
        
        /* END SPOT LIGHT */
        n->attachObject(l);
        
        Entity* e = mSceneMgr->createEntity("e" + StringConverter::toString(i), "robot.mesh");
        SceneNode* en = n->createChildSceneNode(Vector3(0, -200, 0));
        en->attachObject(e);
        
        
    }
    
    // Modify the plane material so that it clips to the light on the second pass, post ambient
    
    MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/GrassFloor").staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    String texname = p->getTextureUnitState(0)->getTextureName();
    p->removeAllTextureUnitStates();
    p->setIlluminationStage(IS_AMBIENT);
    p->setDiffuse(ColourValue::Black);
    p = mat->getTechnique(0)->createPass();
    p->setIlluminationStage(IS_PER_LIGHT);
    p->setIteratePerLight(true, false);
    p->setAmbient(ColourValue::Black);
    p->setLightClipPlanesEnabled(true);
    p->setSceneBlending(SBT_ADD);
    //if (scissortoo)
    p->setLightScissoringEnabled(true);
    p = mat->getTechnique(0)->createPass();
    p->setIlluminationStage(IS_DECAL);
    p->createTextureUnitState(texname);
    p->setLightingEnabled(false);
    p->setSceneBlending(SBT_MODULATE);
    
    
    mCamera->setPosition(0, 200, 300);
    mCamera->lookAt(Vector3::ZERO);
    
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_LightScissoring::PlayPen_LightScissoring()
{
    mInfo["Title"] = "PlayPen_LightScissoring";
    mInfo["Description"] = "Tests light scissoring.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_LightScissoring::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue::White);
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 0;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    4500,4500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("Examples/GrassFloor");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    Real lightRange = 100;
    
    ManualObject* debugSphere = mSceneMgr->createManualObject("debugSphere");
    debugSphere->begin("BaseWhiteNoLighting", RenderOperation::OT_LINE_STRIP);
    for (int i = 0; i <= 20; ++i)
    {
        Vector3 basePos(lightRange, 0, 0);
        Quaternion quat;
        quat.FromAngleAxis(Radian(((float)i/(float)20)*Math::TWO_PI), Vector3::UNIT_Y);
        basePos = quat * basePos;
        debugSphere->position(basePos);
    }
    for (int i = 0; i <= 20; ++i)
    {
        Vector3 basePos(lightRange, 0, 0);
        Quaternion quat;
        quat.FromAngleAxis(Radian(((float)i/(float)20)*Math::TWO_PI), Vector3::UNIT_Z);
        basePos = quat * basePos;
        debugSphere->position(basePos);
    }
    debugSphere->end();
    
    ManualObject* debugSphere2 = mSceneMgr->createManualObject("debugSphere2");
    debugSphere2->begin("BaseWhiteNoLighting", RenderOperation::OT_LINE_STRIP);
    for (int i = 0; i <= 20; ++i)
    {
        Vector3 basePos(lightRange, 0, 0);
        Quaternion quat;
        quat.FromAngleAxis(Radian(((float)i/(float)20)*Math::TWO_PI), Vector3::UNIT_Y);
        basePos = quat * basePos;
        debugSphere2->position(basePos);
    }
    for (int i = 0; i <= 20; ++i)
    {
        Vector3 basePos(lightRange, 0, 0);
        Quaternion quat;
        quat.FromAngleAxis(Radian(((float)i/(float)20)*Math::TWO_PI), Vector3::UNIT_Z);
        basePos = quat * basePos;
        debugSphere2->position(basePos);
    }
    debugSphere2->end();
    
    Light* l = mSceneMgr->createLight("l1");
    l->setAttenuation(lightRange, 1, 0, 0);
    SceneNode* n = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0,95,0));
    n->attachObject(debugSphere);
    n->attachObject(l);
    
    Light* l2 = mSceneMgr->createLight("l2");
    l2->setAttenuation(lightRange, 1, 0, 0);
    SceneNode* n2 = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100,50,0));
    n2->attachObject(debugSphere2);
    n2->attachObject(l2);
    
    // Modify the plane material so that it clips to the light
    // Normally you'd only clip a secondary pass but this is engineered so you
    // can actually see the scissoring effect
    MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/GrassFloor").staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightScissoringEnabled(true);
    //if (cliptoo)
    p->setLightClipPlanesEnabled(true);
    
    
    mCamera->setPosition(0, 200, 300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_LiSPSM::PlayPen_LiSPSM()
{
    mInfo["Title"] = "PlayPen_LiSPSM";
    mInfo["Description"] = "Tests light-space shadow mapping camera setup.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_LiSPSM::cleanupContent()
{
    clearDebugTextureOverlays();
}
//----------------------------------------------------------------------------

void PlayPen_LiSPSM::setupContent()
{
    SceneNode* mTestNode[10];

    mSceneMgr->setShadowTextureSize(1024);
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
    
    //FocusedShadowCameraSetup* lispsmSetup = new FocusedShadowCameraSetup();
    LiSPSMShadowCameraSetup* lispsmSetup = new LiSPSMShadowCameraSetup();
    lispsmSetup->setOptimalAdjustFactor(2);
    mSceneMgr->setShadowCameraSetup(ShadowCameraSetupPtr(lispsmSetup));
    
    mSceneMgr->setShadowFarDistance(3000);
    mSceneMgr->setShadowColour(ColourValue(0.35, 0.35, 0.35));
    mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));
    
    Light* mLight = mSceneMgr->createLight("MainLight");
    mLight->setType(Light::LT_DIRECTIONAL);
    Vector3 vec(-1,-1,0);
    vec.normalise();
    mLight->setDirection(vec);
    
    mTestNode[1] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    
    
    Entity* pEnt;
    pEnt = mSceneMgr->createEntity( "1", "robot.mesh" );
    //pEnt->setRenderingDistance(100);
    AnimationState* mAnimState = pEnt->getAnimationState("Walk");
    mAnimState->setEnabled(true);
    mAnimStateList.push_back(mAnimState);
    //pEnt->setMaterialName("2 - Default");
    mTestNode[1]->attachObject( pEnt );
    mTestNode[1]->translate(0,-100,0);
    
    pEnt = mSceneMgr->createEntity( "3", "knot.mesh" );
    mTestNode[2] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-200, 0, -200));
    mTestNode[2]->attachObject( pEnt );
    
    createRandomEntityClones(pEnt, 20, Vector3(-1000,0,-1000), Vector3(1000,0,1000), mSceneMgr);
    
    // Transparent object (can force cast shadows)
    pEnt = mSceneMgr->createEntity( "3.5", "knot.mesh" );
    MaterialPtr tmat = MaterialManager::getSingleton().create("TestAlphaTransparency", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    tmat->setTransparencyCastsShadows(true);
    Pass* tpass = tmat->getTechnique(0)->getPass(0);
    tpass->setAlphaRejectSettings(CMPF_GREATER, 150);
    tpass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    tpass->createTextureUnitState("gras_02.png");
    tpass->setCullingMode(CULL_NONE);
    
    pEnt->setMaterialName("TestAlphaTransparency");
    mTestNode[3] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(350, 0, -200));
    mTestNode[3]->attachObject( pEnt );
    
    MeshPtr msh = MeshManager::getSingleton().load("knot.mesh",
    TRANSIENT_RESOURCE_GROUP);
    msh->buildTangentVectors(VES_TANGENT, 0, 0);
    pEnt = mSceneMgr->createEntity( "4", "knot.mesh" );
    //pEnt->setMaterialName("Examples/BumpMapping/MultiLightSpecular");
    mTestNode[2] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100, 0, 200));
    mTestNode[2]->attachObject( pEnt );
    
    mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
    
    MovablePlane movablePlane = MovablePlane(Vector3::UNIT_Y, 100);
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, movablePlane,
    2500,2500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    addTextureShadowDebugOverlay(1, mSceneMgr);
    
    
    mCamera->setPosition(0, 1000, 500);
    mCamera->lookAt(0,0,0);
    mCamera->setFarClipDistance(10000);
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------


void createRandomEntityClones(Entity* ent, size_t cloneCount, 
    const Vector3& min, const Vector3& max, SceneManager* mgr)
{
    Entity *cloneEnt;
    for (size_t n = 0; n < cloneCount; ++n)
    {
        // Create a new node under the root
        SceneNode* node = mgr->createSceneNode();
        // Random translate
        Vector3 nodePos;
        nodePos.x = Math::RangeRandom(min.x, max.x);
        nodePos.y = Math::RangeRandom(min.y, max.y);
        nodePos.z = Math::RangeRandom(min.z, max.z);
        node->setPosition(nodePos);
        mgr->getRootSceneNode()->addChild(node);
        cloneEnt = ent->clone(ent->getName() + "_clone" + StringConverter::toString(n));
        // Attach to new node
        node->attachObject(cloneEnt);

    }
}

PlayPen_LotsAndLotsOfEntities::PlayPen_LotsAndLotsOfEntities()
{
    mInfo["Title"] = "PlayPen_LotsAndLotsOfEntities";
    mInfo["Description"] = "Tests setting up and rendering a lot of entities.";
    addScreenshotFrame(3);// only go a couple frames, this one is slow (and static)
}
//----------------------------------------------------------------------------

void PlayPen_LotsAndLotsOfEntities::setupContent()
{
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(-Vector3::UNIT_Y);
    
    // Create a set of random balls
    Entity* ent = mSceneMgr->createEntity("Ball", "cube.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    createRandomEntityClones(ent, 3000, Vector3(-1000,-1000,-1000), Vector3(1000,1000,1000), mSceneMgr);
    
    //bool val = true;
    //mSceneMgr->setOption("ShowOctree", &val);
    
    mCamera->setPosition(0,0, -4000);
    mCamera->lookAt(Vector3::ZERO);
    
    // enable the profiler
    Profiler* prof = Profiler::getSingletonPtr();
    if (prof)
        prof->setEnabled(true);
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ManualBoneMovement::PlayPen_ManualBoneMovement()
{
    mInfo["Title"] = "PlayPen_ManualBoneMovement";
    mInfo["Description"] = "Tests manually controlling a skeletal animation bone.";
    addScreenshotFrame(50);
}
//----------------------------------------------------------------------------

bool PlayPen_ManualBoneMovement::frameStarted(const FrameEvent& evt)
{
    mBone->yaw(Degree(evt.timeSinceLastFrame*100)); 
    return true;
}
//----------------------------------------------------------------------------

void PlayPen_ManualBoneMovement::setupContent()
{
    Entity *ent = mSceneMgr->createEntity("robot", "robot.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    mSceneMgr->setAmbientLight(ColourValue(0.8, 0.8, 0.8));
    
    //ent->setMaterialName("Examples/Rocky");
    
    SkeletonInstance* skel = ent->getSkeleton();
    Animation* anim = skel->getAnimation("Walk");       
    mBone = skel->getBone("Joint10");
    mBone->setManuallyControlled(true);
    anim->destroyNodeTrack(mBone->getHandle());
    
    //AnimationState* animState = ent->getAnimationState("Walk");
    //animState->setEnabled(true);
    
    mCamera->setPosition(100,50,200);
    mCamera->lookAt(0,25,0);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ManualIlluminationStage::PlayPen_ManualIlluminationStage()
{
    mInfo["Title"] = "PlayPen_ManualIlluminationStage";
    mInfo["Description"] = "Tests manual illumination stages.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_ManualIlluminationStage::setupContent()
{
    mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
    mSceneMgr->setShadowDirectionalLightExtrusionDistance(1000);
    MaterialManager::getSingleton().setDefaultTextureFiltering(TFO_ANISOTROPIC);
    MaterialManager::getSingleton().setDefaultAnisotropy(5);
    
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.0, 0.0, 0.0));
    
    Light* mLight = mSceneMgr->createLight("MainLight");
    mLight->setPosition(-400,400,-300);
    mLight->setDiffuseColour(0.9, 0.9, 1);
    mLight->setSpecularColour(0.9, 0.9, 1);
    mLight->setAttenuation(6000,1,0.001,0);
    
    
    mLight = mSceneMgr->createLight("Light2");
    mLight->setPosition(300,200,100);
    mLight->setDiffuseColour(1, 0.6, 0.5);
    mLight->setSpecularColour(0.9, 0.9, 1);
    mLight->setAttenuation(6000,1,0.001,0);
    
    
    
    MeshPtr msh = MeshManager::getSingleton().load("knot.mesh", TRANSIENT_RESOURCE_GROUP);
    msh->buildTangentVectors();
    Entity* pEnt = mSceneMgr->createEntity( "3.5", "knot.mesh" );
    pEnt->setMaterialName("Examples/OffsetMapping/Specular");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject( pEnt );
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshPtr planeMesh = MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,100,100,true,1,15,15,Vector3::UNIT_Z);
    planeMesh->buildTangentVectors();
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("Examples/OffsetMapping/Specular");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    mCamera->setPosition(180, 34, 223);
    mCamera->lookAt(0,50,0);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ManualObject2D::PlayPen_ManualObject2D()
{
    mInfo["Title"] = "PlayPen_ManualObject2D";
    mInfo["Description"] = "Tests 2d manual objects.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_ManualObject2D::setupContent()
{
    ManualObject* man = mSceneMgr->createManualObject("1");
    man->begin("Examples/OgreLogo");
    man->position( 0.0, 0.0, 0.0);  man->textureCoord( 0, 1 );
    man->position( 0.1, 0.0, 0.0);  man->textureCoord( 1, 1 );
    man->position( 0.1, 0.1, 0.0);  man->textureCoord( 1, 0 );
    man->position( 0.0, 0.1, 0.0);  man->textureCoord( 0, 0 );
    
    man->triangle( 0, 1, 2 );
    man->triangle( 0, 2, 3 );
    
    man->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY -1); 
    man->end();
    man->setUseIdentityProjection(true);
    man->setUseIdentityView(true);
    AxisAlignedBox aabb;
    aabb.setInfinite();
    man->setBoundingBox(aabb);
    
    SceneNode* sn = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    sn->setScale(5,5,1);
    sn->attachObject(man);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ManualObjectIndexed::PlayPen_ManualObjectIndexed()
{
    mInfo["Title"] = "PlayPen_ManualObjectIndexed";
    mInfo["Description"] = "Tests indexed manual objects.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_ManualObjectIndexed::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    Light* l = mSceneMgr->createLight("light1");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(dir);
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    ManualObject* man = static_cast<ManualObject*>(
    mSceneMgr->createMovableObject("test", ManualObjectFactory::FACTORY_TYPE_NAME));
    
    man->begin("Examples/OgreLogo");
    // Define a 40x40 plane, indexed
    man->position(-20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 0);
    
    man->position(-20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 1);
    
    man->position(20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 1);
    
    man->position(20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 0);
    
    man->quad(0, 1, 2, 3);
    
    man->end();
    
    man->begin("Examples/BumpyMetal");
    
    // Define a 40x40 plane, indexed
    man->position(-20, 20, 20);
    man->normal(0, 1, 0);
    man->textureCoord(0, 0);
    
    man->position(20, 20, 20);
    man->normal(0, 1, 0);
    man->textureCoord(0, 1);
    
    man->position(20, 20, -20);
    man->normal(0, 1, 0);
    man->textureCoord(1, 1);
    
    man->position(-20, 20, -20);
    man->normal(0, 1, 0);
    man->textureCoord(1, 0);
    
    man->quad(0, 1, 2, 3);
    
    man->end();
    
    
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(man);
    
    mCamera->setPosition(100,100,100);
    mCamera->lookAt(0,0,0);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ManualObjectIndexedUpdateLarger::PlayPen_ManualObjectIndexedUpdateLarger()
{
    mInfo["Title"] = "PlayPen_ManualObjectIndexedUpdateLarger";
    mInfo["Description"] = "Tests updating indexed manual objects.";
}
//----------------------------------------------------------------------------

void PlayPen_ManualObjectIndexedUpdateLarger::setupContent()
{
    PlayPen_ManualObjectIndexed::setupContent();
    ManualObject* man = static_cast<ManualObject*>(
    mSceneMgr->getMovableObject("test", ManualObjectFactory::FACTORY_TYPE_NAME));
    
    
    man->beginUpdate(0);
    // 1 quad larger
    man->position(-20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 0);
    
    man->position(-20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 1);
    
    man->position(20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 1);
    
    man->position(20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 0);
    
    
    man->position(-20, 40, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 0);
    
    man->position(-20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 1);
    
    man->position(20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 1);
    
    man->position(20, 40, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 0);
    
    man->quad(0, 1, 2, 3);
    man->quad(4, 5, 6, 7);
    
    man->end();
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ManualObjectIndexedUpdateSmaller::PlayPen_ManualObjectIndexedUpdateSmaller()
{
    mInfo["Title"] = "PlayPen_ManualObjectIndexedUpdateSmaller";
    mInfo["Description"] = "Tests updating indexed manual objects.";
}
//----------------------------------------------------------------------------

void PlayPen_ManualObjectIndexedUpdateSmaller::setupContent()
{
    PlayPen_ManualObjectIndexed::setupContent();
    ManualObject* man = static_cast<ManualObject*>(
    mSceneMgr->getMovableObject("test", ManualObjectFactory::FACTORY_TYPE_NAME));
    
    
    man->beginUpdate(0);
    // 1 tri smaller
    man->position(-20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 0);
    
    man->position(-20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 1);
    
    man->position(20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 1);
    
    man->triangle(0, 1, 2);
    
    man->end();
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ManualObjectNonIndexed::PlayPen_ManualObjectNonIndexed()
{
    mInfo["Title"] = "PlayPen_ManualObjectNonIndexed";
    mInfo["Description"] = "Tests non-indexed manual objects.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_ManualObjectNonIndexed::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    Light* l = mSceneMgr->createLight("light1");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(dir);
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    ManualObject* man = static_cast<ManualObject*>(
    mSceneMgr->createMovableObject("test", ManualObjectFactory::FACTORY_TYPE_NAME));
    
    man->begin("Examples/OgreLogo");
    // Define a 40x40 plane, non-indexed
    man->position(-20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 0);
    
    man->position(-20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 1);
    
    man->position(20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 0);
    
    man->position(-20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 1);
    
    man->position(20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 1);
    
    man->position(20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 0);
    
    man->end();
    
    man->begin("Examples/BumpyMetal");
    
    // Define a 40x40 plane, non-indexed
    man->position(-20, 20, 20);
    man->normal(0, 1, 0);
    man->textureCoord(0, 0);
    
    man->position(20, 20, 20);
    man->normal(0, 1, 0);
    man->textureCoord(0, 1);
    
    man->position(20, 20, -20);
    man->normal(0, 1, 0);
    man->textureCoord(1, 1);
    
    man->position(20, 20, -20);
    man->normal(0, 1, 0);
    man->textureCoord(1, 1);
    
    man->position(-20, 20, -20);
    man->normal(0, 1, 0);
    man->textureCoord(1, 0);
    
    man->position(-20, 20, 20);
    man->normal(0, 1, 0);
    man->textureCoord(0, 0);
    
    man->end();
    
    
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(man);
    mCamera->setPosition(100,100,100);
    mCamera->lookAt(0,0,0);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ManualObjectNonIndexedUpdateLarger::PlayPen_ManualObjectNonIndexedUpdateLarger()
{
    mInfo["Title"] = "PlayPen_ManualObjectNonIndexedUpdateLarger";
    mInfo["Description"] = "Tests updating non-indexed manual objects.";
}
//----------------------------------------------------------------------------

void PlayPen_ManualObjectNonIndexedUpdateLarger::setupContent()
{
    PlayPen_ManualObjectNonIndexed::setupContent();
    ManualObject* man = static_cast<ManualObject*>(
    mSceneMgr->getMovableObject("test", ManualObjectFactory::FACTORY_TYPE_NAME));
    
    // Redefine but make larger (2 more tri)
    man->beginUpdate(0);
    
    man->position(-20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 0);
    
    man->position(-20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 1);
    
    man->position(20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 0);
    
    man->position(-20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 1);
    
    man->position(20, -20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 1);
    
    man->position(20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 0);
    
    
    man->position(-20, 40, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 0);
    
    man->position(-20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 1);
    
    man->position(20, 40, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 0);
    
    man->position(-20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(0, 1);
    
    man->position(20, 20, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 1);
    
    man->position(20, 40, 20);
    man->normal(0, 0, 1);
    man->textureCoord(1, 0);
    
    
    man->end();
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ManualObjectNonIndexedUpdateSmaller::PlayPen_ManualObjectNonIndexedUpdateSmaller()
{
    mInfo["Title"] = "PlayPen_ManualObjectNonIndexedUpdateSmaller";
    mInfo["Description"] = "Tests updating non-indexed manual objects.";
}
//----------------------------------------------------------------------------

void PlayPen_ManualObjectNonIndexedUpdateSmaller::setupContent()
{
    PlayPen_ManualObjectNonIndexed::setupContent();
    ManualObject* man = static_cast<ManualObject*>(
    mSceneMgr->getMovableObject("test", ManualObjectFactory::FACTORY_TYPE_NAME));
    
    // Redefine but make smaller (one tri less)
    man->beginUpdate(0);
    man->position(-30, 30, 30);
    man->normal(0, 0, 1);
    man->textureCoord(0, 0);
    
    man->position(-30, -30, 30);
    man->normal(0, 0, 1);
    man->textureCoord(0, 1);
    
    man->position(90, 30, 30);
    man->normal(0, 0, 1);
    man->textureCoord(1, 0);
    
    
    man->end();
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_MaterialSchemes::PlayPen_MaterialSchemes()
{
    mInfo["Title"] = "PlayPen_MaterialSchemes";
    mInfo["Description"] = "Tests material scehemes in viewports.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_MaterialSchemes::setupContent()
{
    
    Entity *ent = mSceneMgr->createEntity("robot", "robot.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    mSceneMgr->setAmbientLight(ColourValue(0.8, 0.8, 0.8));
    
    MaterialPtr mat = MaterialManager::getSingleton().create("schemetest", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    // default scheme
    mat->getTechnique(0)->getPass(0)->createTextureUnitState("GreenSkin.jpg");
    
    Technique* t = mat->createTechnique();
    t->setSchemeName("newscheme");
    t->createPass()->createTextureUnitState("rockwall.tga");
    ent->setMaterialName("schemetest");
    
    // create a second viewport using alternate scheme
    Viewport* vp = mWindow->addViewport(mCamera, 1, 0.75, 0, 0.25, 0.25);
    vp->setMaterialScheme("newscheme");
    vp->setOverlaysEnabled(false);

    mCamera->setPosition(0,75,200);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_MaterialSchemesListener::PlayPen_MaterialSchemesListener()
{
    mInfo["Title"] = "PlayPen_MaterialSchemesListener";
    mInfo["Description"] = "Tests material scheme listener.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

class TestMatMgrListener : public MaterialManager::Listener
{
public:
    TestMatMgrListener() : mTech(0) {}
    Technique* mTech;
    

    Technique* handleSchemeNotFound(unsigned short schemeIndex, 
        const String& schemeName, Material* originalMaterial, unsigned short lodIndex, 
        const Renderable* rend)
    {
        return mTech;
    }
};
TestMatMgrListener schemeListener;

void PlayPen_MaterialSchemesListener::setupContent()
{
    Entity *ent = mSceneMgr->createEntity("robot", "robot.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    mSceneMgr->setAmbientLight(ColourValue(0.8, 0.8, 0.8));
    
    // create a second viewport using alternate scheme
    // notice it's not defined in a technique
    Viewport* vp = mWindow->addViewport(mCamera, 1, 0.75, 0, 0.25, 0.25);
    vp->setMaterialScheme("newscheme");
    vp->setOverlaysEnabled(false);
    
    MaterialPtr mat = MaterialManager::getSingleton().create("schemetest", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    // default scheme
    mat->getTechnique(0)->getPass(0)->createTextureUnitState("GreenSkin.jpg");
    
    schemeListener.mTech = mat->getTechnique(0);
    
    MaterialManager::getSingleton().addListener(&schemeListener);

    mCamera->setPosition(0,75,200);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_MaterialSchemesWithLOD::PlayPen_MaterialSchemesWithLOD()
{
    mInfo["Title"] = "PlayPen_MaterialSchemesWithLOD";
    mInfo["Description"] = "Tests material schemes with LODs.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_MaterialSchemesWithLOD::setupContent()
{
    
    Entity *ent = mSceneMgr->createEntity("robot", "robot.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    mSceneMgr->setAmbientLight(ColourValue(0.8, 0.8, 0.8));
    
    MaterialPtr mat = MaterialManager::getSingleton().create("schemetest", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    // default scheme
    mat->getTechnique(0)->getPass(0)->createTextureUnitState("GreenSkin.jpg");
    
    // LOD 0, newscheme 
    Technique* t = mat->createTechnique();
    t->setSchemeName("newscheme");
    t->createPass()->createTextureUnitState("rockwall.tga");
    ent->setMaterialName("schemetest");
    
    // LOD 1, default
    t = mat->createTechnique();
    t->setLodIndex(1);
    t->createPass()->createTextureUnitState("Water02.jpg");
    
    // LOD 1, newscheme
    t = mat->createTechnique();
    t->setLodIndex(1);
    t->createPass()->createTextureUnitState("r2skin.jpg");
    t->setSchemeName("newscheme");
    
    Material::LodValueList ldl;
    //ldl.push_back(Math::Sqr(500.0f));
    ldl.push_back(150.0f);
    mat->setLodLevels(ldl);
    
    
    ent->setMaterialName("schemetest");
    
    // create a second viewport using alternate scheme
    Viewport* vp = mWindow->addViewport(mCamera, 1, 0.75, 0, 0.25, 0.25);
    vp->setMaterialScheme("newscheme");
    vp->setOverlaysEnabled(false);

    mCamera->setPosition(0,90,250);
    //mCamera->lookAt(Vector3(0,0,0));
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_MaterialSchemesWithMismatchedLOD::PlayPen_MaterialSchemesWithMismatchedLOD()
{
    mInfo["Title"] = "PlayPen_MaterialSchemesWithMismatchedLOD";
    mInfo["Description"] = "Tests material scehemes in viewports with mismatched LODs.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_MaterialSchemesWithMismatchedLOD::setupContent()
{
    
    Entity *ent = mSceneMgr->createEntity("robot", "robot.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    mSceneMgr->setAmbientLight(ColourValue(0.8, 0.8, 0.8));
    
    MaterialPtr mat = MaterialManager::getSingleton().create("schemetest", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    // default scheme
    mat->getTechnique(0)->getPass(0)->createTextureUnitState("GreenSkin.jpg");
    
    // LOD 0, newscheme 
    Technique* t = mat->createTechnique();
    t->setSchemeName("newscheme");
    t->createPass()->createTextureUnitState("rockwall.tga");
    ent->setMaterialName("schemetest");
    
    // LOD 1, default
    t = mat->createTechnique();
    t->setLodIndex(1);
    t->createPass()->createTextureUnitState("Water02.jpg");
    
    // LOD 2, default
    t = mat->createTechnique();
    t->setLodIndex(2);
    t->createPass()->createTextureUnitState("clouds.jpg");
    
    // LOD 1, newscheme
    t = mat->createTechnique();
    t->setLodIndex(1);
    t->createPass()->createTextureUnitState("r2skin.jpg");
    t->setSchemeName("newscheme");
    
    // No LOD 2 for newscheme! Should fallback on LOD 1
    
    Material::LodValueList ldl;
    //ldl.push_back(Math::Sqr(250.0f));
    //ldl.push_back(Math::Sqr(500.0f));
    ldl.push_back(150.0f);
    ldl.push_back(300.0f);
    mat->setLodLevels(ldl);
    
    
    ent->setMaterialName("schemetest");
    
    // create a second viewport using alternate scheme
    Viewport* vp = mWindow->addViewport(mCamera, 1, 0.75, 0, 0.25, 0.25);
    vp->setMaterialScheme("newscheme");
    vp->setOverlaysEnabled(false);

    mCamera->setPosition(0,90,350);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

/*PlayPen_MRTCompositorScript::PlayPen_MRTCompositorScript()
{
    mInfo["Title"] = "PlayPen_MRTCompositorScript";
    mInfo["Description"] = "Tests MRT compositor.";
    addScreenshotFrame(250);
}
//----------------------------------------------------------------------------

void PlayPen_MRTCompositorScript::setupContent()
{
    
    Entity* e = mSceneMgr->createEntity("e1", "knot.mesh");
    e->setMaterialName("Ogre/MRTtest/scene");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mCamera->setPosition(0, 0, -100);
    mCamera->lookAt(Vector3::ZERO);
    
    CompositorInstance* compInst = 
    CompositorManager::getSingleton().addCompositor(mWindow->getViewport(0), "TestMRT");
    CompositorManager::getSingleton().setCompositorEnabled(mWindow->getViewport(0), "TestMRT", true);
    
    // Set up debug panels for each of the MRT outputs
    String texName = compInst->getTextureInstanceName("mrt0", 0);
    addTextureDebugOverlay(TextureManager::getSingleton().getByName(texName), 0);
    texName = compInst->getTextureInstanceName("mrt0", 1);
    addTextureDebugOverlay(TextureManager::getSingleton().getByName(texName), 1);
    texName = compInst->getTextureInstanceName("mrt0", 2);
    addTextureDebugOverlay(TextureManager::getSingleton().getByName(texName), 2);
    texName = compInst->getTextureInstanceName("mrt0", 3);
    addTextureDebugOverlay(TextureManager::getSingleton().getByName(texName), 3);
}*/
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

/*PlayPen_MRT::PlayPen_MRT()
{
    mInfo["Title"] = "PlayPen_MRT";
    mInfo["Description"] = "Tests MRT.";
    addScreenshotFrame(250);
}
//----------------------------------------------------------------------------

void PlayPen_MRT::setupContent()
{
    TexturePtr Tex[2];
    MultiRenderTarget* mrtTex;
    
    Viewport* viewport = mWindow->getViewport(0);
    int width = viewport->getActualWidth();
    int height = viewport->getActualHeight();
    
    Tex[0] = TextureManager::getSingleton().createManual("diffusemap", TRANSIENT_RESOURCE_GROUP, TEX_TYPE_2D,
    width,height,0,PF_R8G8B8A8,TU_RENDERTARGET);
    Tex[1] = TextureManager::getSingleton().createManual("normalmap",TRANSIENT_RESOURCE_GROUP, TEX_TYPE_2D,
    width,height,0,PF_R8G8B8A8,TU_RENDERTARGET);
    
    //    assert(Tex[0]->getFormat() == PF_FLOAT16_RGBA);
    
    mrtTex = Ogre::Root::getSingleton().getRenderSystem()->createMultiRenderTarget("MRT");
    RenderTexture* rTex[2];
    rTex[0] = Tex[0]->getBuffer()->getRenderTarget();
    rTex[1] = Tex[1]->getBuffer()->getRenderTarget();
    
    rTex[0]->setAutoUpdated(false);
    rTex[1]->setAutoUpdated(false);
    mrtTex->bindSurface(0, rTex[0]);
    mrtTex->bindSurface(1, rTex[1]);
    mrtTex->setAutoUpdated(true);
    
    Viewport *v = mrtTex->addViewport(mCamera);
    v->setMaterialScheme("MRT");
    v->setClearEveryFrame(true);
    v->setOverlaysEnabled(false);
    v->setSkiesEnabled(false);
    v->setBackgroundColour(ColourValue(0,0,0,0));
    
    // Create texture overlay here
    Overlay *debugOverlay = OverlayManager::getSingleton().create("Core/DebugOverlay");
    MaterialPtr debugMat = MaterialManager::getSingleton().create("DebugRTTMat1", TRANSIENT_RESOURCE_GROUP);
    debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
    TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState("normalmap");
    t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
    OverlayContainer *debugPanel = (OverlayContainer *) (OverlayManager::getSingleton().createOverlayElement("Panel","DebugRTTPanel1"));
    debugPanel->_setPosition(0.8,0);
    debugPanel->_setDimensions(0.2,0.3);
    debugPanel->setMaterialName(debugMat->getName());
    debugOverlay->add2D(debugPanel);
    
    debugMat = MaterialManager::getSingleton().create("DebugRTTMat2", TRANSIENT_RESOURCE_GROUP);
    debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
    t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState("diffusemap");
    t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
    debugPanel = (OverlayContainer *) (OverlayManager::getSingleton().createOverlayElement("Panel","DebugRTTPanel2"));
    debugPanel->_setPosition(0.8,0.3);
    debugPanel->_setDimensions(0.2,0.3);
    debugPanel->setMaterialName(debugMat->getName());
    debugOverlay->add2D(debugPanel);
    // Create scene items
    
    // Create a material to render differently to MRT compared to main viewport
    MaterialPtr mat = MaterialManager::getSingleton().create("MRTTest", 
    TRANSIENT_RESOURCE_GROUP);
    // normal technique (0), leave as default
    Technique* mrtTech = mat->createTechnique();
    mrtTech->setSchemeName("MRT");
    Pass* mrtPass = mrtTech->createPass();
    mrtPass->setVertexProgram("DeferredShading/material/hlsl/vs");
    mrtPass->setFragmentProgram("DeferredShading/material/hlsl/ps");
    mrtPass->createTextureUnitState("rockwall.tga");
    mat->load();
    
    Entity* ent = mSceneMgr->createEntity("knot", "knot.mesh");
    ent->setMaterialName("MRTTest");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    
    mCamera->setPosition(0, 0, 200);
    mCamera->lookAt(Vector3::ZERO);
    
    
    
}*/
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_MultiSceneManagersSimple::PlayPen_MultiSceneManagersSimple()
{
    mInfo["Title"] = "PlayPen_MultiSceneManagersSimple";
    mInfo["Description"] = "Tests multiple scene managers.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_MultiSceneManagersSimple::setupContent()
{
    // Create a secondary scene manager with it's own camera
    SceneManager* sm2 = Root::getSingleton().createSceneManager(ST_GENERIC);
    Camera* camera2 = sm2->createCamera("cam2");
    camera2->setPosition(0,0,-500);
    camera2->lookAt(Vector3::ZERO);
    Entity* ent = sm2->createEntity("knot2", "knot.mesh");
    sm2->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    Light* l = sm2->createLight("l2");
    l->setPosition(100,50,-100);
    l->setDiffuseColour(ColourValue::Green);
    sm2->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
    
    Viewport* vp = mWindow->addViewport(camera2, 1, 0.67, 0, 0.33, 0.25);
    vp->setOverlaysEnabled(false);
    vp->setBackgroundColour(ColourValue(1,0,0));
    
    // Use original SM for normal scene
    ent = mSceneMgr->createEntity("head", "ogrehead.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    l = mSceneMgr->createLight("l2"); // note same name, will work since different SM
    l->setPosition(100,50,-100);
    l->setDiffuseColour(ColourValue::Red);
    mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
    mCamera->setPosition(0,0,500);
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_MultiViewports::PlayPen_MultiViewports()
{
    mInfo["Title"] = "PlayPen_MultiViewports";
    mInfo["Description"] = "Tests multiple viewports.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_MultiViewports::setupContent()
{
    SceneNode* mTestNode[3];
    
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(-Vector3::UNIT_Y);
    
    Entity* pEnt = mSceneMgr->createEntity( "1", "knot.mesh" );
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-30,0,-50))->attachObject(pEnt);
    
    mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    
    pEnt = mSceneMgr->createEntity( "2", "ogrehead.mesh" );
    mTestNode[0]->attachObject( pEnt );
    mTestNode[0]->translate(0, 0, 200);
    
    Ogre::Frustum* frustum = new Frustum();
    //frustum->setVisible(true);
    frustum->setFarClipDistance(5000);
    frustum->setNearClipDistance(100);
    mTestNode[0]->attachObject(frustum);
    
    Viewport* vp = mWindow->addViewport(mCamera, 1, 0.5, 0.5, 0.5, 0.5);
    vp->setOverlaysEnabled(false);
    vp->setBackgroundColour(ColourValue(1,0,0));

    mCamera->setPosition(0,0,500);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_NegativeScale::PlayPen_NegativeScale()
{
    mInfo["Title"] = "PlayPen_NegativeScale";
    mInfo["Description"] = "Tests negative scaling.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_NegativeScale::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
    Light* l = mSceneMgr->createLight("l1");
    l->setPosition(500, 500, 200);
    l->setDiffuseColour(ColourValue::White);
    
    //mSceneMgr->setFlipCullingOnNegativeScale(false);
    
    Entity *e = mSceneMgr->createEntity("1", "knot.mesh");
    
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    
    // one reflection
    e = mSceneMgr->createEntity("2", "knot.mesh");
    SceneNode* n = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    n->translate(-200, 0, 0);
    n->scale(-1, 1, 1);
    n->attachObject(e);
    
    // three reflections - will need flipping
    e = mSceneMgr->createEntity("3", "knot.mesh");
    n = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    n->translate(200, 0, 0);
    n->scale(-1, -1, -1);
    n->attachObject(e);
    
    // two reflections - won't need flipping
    e = mSceneMgr->createEntity("4", "knot.mesh");
    n = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    n->translate(400, 0, 0);
    n->scale(-1, 1, -1);
    n->attachObject(e);
    
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_NormalMapMirroredUVs::PlayPen_NormalMapMirroredUVs()
{
    mInfo["Title"] = "PlayPen_NormalMapMirroredUVs";
    mInfo["Description"] = "Tests mirrored UVs with normal mapping shader.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_NormalMapMirroredUVs::setupContent()
{
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    // this mesh has been generated with 4-component tangents, including a parity in w
    Entity* e = mSceneMgr->createEntity("2", "testmirroreduvmesh.mesh");
    e->setMaterialName("Examples/BumpMapping/MultiLightTangentParity");
    // here's what it looks like without the parity
    //e->setMaterialName("Examples/BumpMapping/MultiLight");
    
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    
    Light* l = mSceneMgr->createLight("3");
    l->setPosition(1000,500,1000);
    
    mCamera->setPosition(0,200,50);
    mCamera->lookAt(Vector3::ZERO);
    
    mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Ortho::PlayPen_Ortho()
{
    mInfo["Title"] = "PlayPen_Ortho";
    mInfo["Description"] = "Tests orthographic rendering.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_Ortho::setupContent()
{
    SceneNode* mTestNode[3];
    
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.0, 0.0, 0.0));
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setPosition(800,600,0);
    
    mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    mSceneMgr->getRootSceneNode()->createChildSceneNode();
    
    Entity* pEnt = mSceneMgr->createEntity( "3", "knot.mesh" );
    mTestNode[1] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-200, 0, -200));
    mTestNode[1]->attachObject( pEnt );
    
    pEnt = mSceneMgr->createEntity( "4", "knot.mesh" );
    mTestNode[2] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100, 0, 200));
    mTestNode[2]->attachObject( pEnt );
    
    
    mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    mCamera->setFixedYawAxis(false);
    mCamera->setProjectionType(PT_ORTHOGRAPHIC);
    mCamera->setPosition(0,10000,0);
    mCamera->lookAt(0,0,0);
    mCamera->setNearClipDistance(1000);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_PointSprites::PlayPen_PointSprites()
{
    mInfo["Title"] = "PlayPen_PointSprites";
    mInfo["Description"] = "Tests point sprites.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_PointSprites::setupContent()
{
    MaterialPtr mat = MaterialManager::getSingleton().create("spriteTest1", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setPointSpritesEnabled(true);
    p->createTextureUnitState("flare.png");
    p->setLightingEnabled(false);
    p->setDepthWriteEnabled(false);
    p->setSceneBlending(SBT_ADD);
    p->setPointAttenuation(true);
    p->setPointSize(1);
    
    ManualObject* man = mSceneMgr->createManualObject("man");
    man->begin("spriteTest1", RenderOperation::OT_POINT_LIST);
    
    for (size_t i = 0; i < 1000; ++i)
    {
        man->position(Math::SymmetricRandom() * 500, 
        Math::SymmetricRandom() * 500, 
        Math::SymmetricRandom() * 500);
        man->colour(Math::RangeRandom(0.5f, 1.0f), 
        Math::RangeRandom(0.5f, 1.0f), Math::RangeRandom(0.5f, 1.0f));
    }
    
    /*for (size_t i = 0; i < 20; ++i)
    {
        for (size_t j = 0; j < 20; ++j)
        {
            for (size_t k = 0; k < 20; ++k)
            {
                if(rand()%10 == 0)
                    man->position(i * 30, j * 30, k * 30);
            }
        }
    }*/
    
    man->end();
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(man);

    mCamera->setPosition(0,0,1000);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_Projection::PlayPen_Projection()
{
    mInfo["Title"] = "PlayPen_Projection";
    mInfo["Description"] = "Tests projection.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_Projection::setupContent()
{
    SceneNode* mTestNode[3];
    
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(-Vector3::UNIT_Y);
    
    Entity* pEnt;
    //pEnt = mSceneMgr->createEntity( "1", "knot.mesh" );
    //mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-30,0,-50))->attachObject(pEnt);
    //pEnt->setMaterialName("Examples/OgreLogo");
    
    // Define a floor plane mesh
    Plane p;
    p.normal = Vector3::UNIT_Z;
    p.d = 200;
    MeshManager::getSingleton().createPlane("WallPlane",
    TRANSIENT_RESOURCE_GROUP,
    p,1500,1500,1,1,true,1,5,5,Vector3::UNIT_Y);
    pEnt = mSceneMgr->createEntity( "5", "WallPlane" );
    pEnt->setMaterialName("Examples/OgreLogo");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pEnt);
    
    
    mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    
    //pEnt = mSceneMgr->createEntity( "2", "ogrehead.mesh" );
    //mTestNode[0]->attachObject( pEnt );
    mTestNode[0]->translate(0, 0, 750);
    
    Ogre::Frustum* frustum = new Frustum();
    frustum->setVisible(true);
    frustum->setFarClipDistance(5000);
    frustum->setNearClipDistance(200);
    frustum->setAspectRatio(1);
    frustum->setProjectionType(PT_ORTHOGRAPHIC);
    mTestNode[0]->attachObject(frustum);
    
    // Hook the frustum up to the material
    MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/OgreLogo").staticCast<Material>();
    TextureUnitState *t = mat->getTechnique(0)->getPass(0)->getTextureUnitState(0);
    t->setProjectiveTexturing(true, frustum);
    //t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_RaySceneQuery::PlayPen_RaySceneQuery()
{
    mInfo["Title"] = "PlayPen_RaySceneQuery";
    mInfo["Description"] = "Tests ray scene query.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

bool PlayPen_RaySceneQuery::frameStarted(const FrameEvent& evt)
{
    rayQuery->setRay(mCamera->getCameraToViewportRay(0.5, 0.5));
    RaySceneQueryResult& results = rayQuery->execute();
    for (RaySceneQueryResult::iterator mov = results.begin();
            mov != results.end(); ++mov)
    {
        if (mov->movable)
        {
            if (mov->movable->getMovableType() == "Entity")
            {
                Entity* ent = static_cast<Entity*>(mov->movable);
                ent->setMaterialName("Examples/RustySteel");
            }
        }
    }
    return true;
}
//----------------------------------------------------------------------------

void PlayPen_RaySceneQuery::setupContent()
{
    mCamera->setPosition(0,0,500);
    mCamera->lookAt(0,0,0);

    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(-Vector3::UNIT_Y);
    
    // Create a set of random balls
    Entity* ent = mSceneMgr->createEntity("Ball", "sphere.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    createRandomEntityClones(ent, 100, Vector3(-1000,-1000,-1000), Vector3(1000,1000,1000), mSceneMgr);

    // stick one at the origin so one will always be hit
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(
        mSceneMgr->createEntity("Ball_origin", "sphere.mesh"));
    
    rayQuery = mSceneMgr->createRayQuery(
    mCamera->getCameraToViewportRay(0.5, 0.5));
    rayQuery->setSortByDistance(true, 1);
    
    bool val = true;
    mSceneMgr->setOption("ShowOctree", &val);

    //mCamera->setFarClipDistance(0);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ReflectedBillboards::PlayPen_ReflectedBillboards()
{
    mInfo["Title"] = "PlayPen_ReflectedBillboards";
    mInfo["Description"] = "Tests reflected billboards.";
    addScreenshotFrame(175); // needs to run for a bit so there are particles to be reflected...
}
//----------------------------------------------------------------------------

void PlayPen_ReflectedBillboards::setupContent()
{
    Camera* reflectCam = 0;
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
    
    // Create a light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setType(Light::LT_DIRECTIONAL);
    Vector3 dir(0.5, -1, 0);
    dir.normalise();
    l->setDirection(dir);
    l->setDiffuseColour(1.0f, 1.0f, 0.8f);
    l->setSpecularColour(1.0f, 1.0f, 1.0f);
    
    
    // Create a prefab plane
    Plane plane;
    plane.d = 0;
    plane.normal = Vector3::UNIT_Y;
    MeshManager::getSingleton().createPlane("ReflectionPlane", 
    TRANSIENT_RESOURCE_GROUP, 
    plane, 2000, 2000, 
    1, 1, true, 1, 1, 1, Vector3::UNIT_Z);
    Entity* planeEnt = mSceneMgr->createEntity( "Plane", "ReflectionPlane" );
    
    // Attach the rtt entity to the root of the scene
    SceneNode* rootNode = mSceneMgr->getRootSceneNode();
    SceneNode* planeNode = rootNode->createChildSceneNode();
    
    // Attach both the plane entity, and the plane definition
    planeNode->attachObject(planeEnt);

    mCamera->setPosition(-50, 100, 500);
    mCamera->lookAt(0,0,0);
    
    TexturePtr rttTex = TextureManager::getSingleton().createManual("RttTex", 
    TRANSIENT_RESOURCE_GROUP, TEX_TYPE_2D, 
    512, 512, 1, 0, PF_R8G8B8, TU_RENDERTARGET);
    {
        reflectCam = mSceneMgr->createCamera("ReflectCam");
        reflectCam->setNearClipDistance(mCamera->getNearClipDistance());
        reflectCam->setFarClipDistance(mCamera->getFarClipDistance());
        reflectCam->setAspectRatio(
        (Real)mWindow->getViewport(0)->getActualWidth() / 
        (Real)mWindow->getViewport(0)->getActualHeight());

        reflectCam->setPosition(mCamera->getPosition());
        reflectCam->setOrientation(mCamera->getOrientation());
        
        Viewport *v = rttTex->getBuffer()->getRenderTarget()->addViewport( reflectCam );
        v->setClearEveryFrame( true );
        v->setBackgroundColour( ColourValue::Black );
        
        MaterialPtr mat = MaterialManager::getSingleton().create("RttMat",
        TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
        mat->getTechnique(0)->getPass(0)->createTextureUnitState("RustedMetal.jpg");
        TextureUnitState* t = mat->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex");
        // Blend with base texture
        t->setColourOperationEx(LBX_BLEND_MANUAL, LBS_TEXTURE, LBS_CURRENT, ColourValue::White, 
        ColourValue::White, 0.25);
        t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
        t->setProjectiveTexturing(true, reflectCam);
        
        // set up linked reflection
        reflectCam->enableReflection(plane);
        // Also clip
        reflectCam->enableCustomNearClipPlane(plane);
    }
    
    // Give the plane a texture
    planeEnt->setMaterialName("RttMat");
    
    
    // point billboards
    ParticleSystem* pSys2 = mSceneMgr->createParticleSystem("fountain1", 
    "Examples/Smoke");
    // Point the fountain at an angle
    SceneNode* fNode = static_cast<SceneNode*>(rootNode->createChild());
    fNode->attachObject(pSys2);
    
    // oriented_self billboards
    ParticleSystem* pSys3 = mSceneMgr->createParticleSystem("fountain2", 
    "Examples/PurpleFountain");
    // Point the fountain at an angle
    fNode = rootNode->createChildSceneNode();
    fNode->translate(-200,-100,0);
    fNode->rotate(Vector3::UNIT_Z, Degree(-20));
    fNode->attachObject(pSys3);
    
    
    
    // oriented_common billboards
    ParticleSystem* pSys4 = mSceneMgr->createParticleSystem("rain", 
    "Examples/Rain");
    SceneNode* rNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    rNode->translate(0,1000,0);
    rNode->attachObject(pSys4);
    // Fast-forward the rain so it looks more natural
    pSys4->fastForward(5);
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ReinitialiseEntityAlteredMesh::PlayPen_ReinitialiseEntityAlteredMesh()
{
    mInfo["Title"] = "PlayPen_ReinitialiseEntityAlteredMesh";
    mInfo["Description"] = "Tests updating an entity while rendering.";
    addScreenshotFrame(100);
    mTimer = 0.5f;
}
//----------------------------------------------------------------------------

bool PlayPen_ReinitialiseEntityAlteredMesh::frameStarted(const FrameEvent& evt)
{
    if(mTimer > 0.f)
    {
        mTimer -= evt.timeSinceLastFrame;

        if(mTimer <= 0.f)
        {
            // change the mesh, add a new submesh

            // Load another mesh
            MeshPtr msh = MeshManager::getSingleton().load("ogrehead.mesh", 
                ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

            for (unsigned short e = 0; e < msh->getNumSubMeshes(); ++e)
            {
                SubMesh* sm = msh->getSubMesh(e);

                sm->clone("", mUpdate);
            }

            mTimer = -5.f;
        }
    }

    return true;
}
//----------------------------------------------------------------------------

void PlayPen_ReinitialiseEntityAlteredMesh::setupContent()
{
    // test whether an Entity picks up that Mesh has changed
    // and therefore rebuild SubEntities
    
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    
    Light* l = mSceneMgr->createLight("l1");
    l->setPosition(200, 300, 0);

    Ogre::MeshManager::getSingleton().load("knot.mesh", 
        ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME)->clone("knot_REINIT.mesh");
    
    Entity* pEnt = mSceneMgr->createEntity("testEnt", "knot_REINIT.mesh");
    mUpdate = pEnt->getMesh().get();
    
    mSceneMgr->getRootSceneNode()->attachObject(pEnt);
    
    mCamera->setPosition(0,0,200);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ReloadResources::PlayPen_ReloadResources()
{
    mInfo["Title"] = "PlayPen_ReloadResources";
    mInfo["Description"] = "Tests unloading and reloading resources.";
    addScreenshotFrame(100);
    mReloadTimer = 0.5f;
}
//----------------------------------------------------------------------------

bool PlayPen_ReloadResources::frameStarted(const FrameEvent& evt)
{
    if(mReloadTimer > 0.f)
    {
        mReloadTimer -= evt.timeSinceLastFrame;

        if(mReloadTimer <= 0.f)
        {
            // unload
            Entity* e = mSceneMgr->getEntity("1");
            e->getParentSceneNode()->detachObject("1");
            mSceneMgr->destroyAllEntities();
            ResourceGroupManager::getSingleton().unloadResourceGroup("TestReload");

            // reload
            e = mSceneMgr->createEntity("1", "UniqueModel.MESH");
            mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);

            mReloadTimer = -5.f;
        }
    }
    return true;
}
//----------------------------------------------------------------------------

void PlayPen_ReloadResources::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue::White);

    // get path to test resources
    const Ogre::ResourceGroupManager::LocationList& ll = Ogre::ResourceGroupManager::getSingleton().getResourceLocationList("Tests");
    const Ogre::ResourceGroupManager::ResourceLocation* loc = ll.front();
    Ogre::String testResourcePath = loc->archive->getName();

    // add a new group
    Ogre::String meshFilePath = testResourcePath + "/TestReload";
    Ogre::ResourceGroupManager& resMgr = Ogre::ResourceGroupManager::getSingleton();
    String newGroup = meshFilePath;
    resMgr.createResourceGroup("TestReload", false);
    resMgr.addResourceLocation(meshFilePath, "FileSystem", "TestReload");
    resMgr.initialiseResourceGroup("TestReload");

    MeshManager& mmgr = MeshManager::getSingleton();
    mmgr.load("UniqueModel.MESH", "TestReload");
    
    Entity* e = mSceneMgr->createEntity("1", "UniqueModel.MESH");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);

    mCamera->setPosition(0,0,200);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_RibbonTrail::PlayPen_RibbonTrail()
{
    mInfo["Title"] = "PlayPen_RibbonTrail";
    mInfo["Description"] = "Tests ribbon trail effect.";
    addScreenshotFrame(150);
}
//----------------------------------------------------------------------------

void PlayPen_RibbonTrail::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    Light* l = mSceneMgr->createLight("light1");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(dir);
    
    NameValuePairList pairList;
    pairList["numberOfChains"] = "2";
    pairList["maxElements"] = "80";
    RibbonTrail* trail = static_cast<RibbonTrail*>(
    mSceneMgr->createMovableObject("1", "RibbonTrail", &pairList));
    trail->setMaterialName("Examples/LightRibbonTrail");
    trail->setTrailLength(400);
    //mRibbonTrail = trail;
    
    
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(trail);
    
    // Create 3 nodes for trail to follow
    SceneNode* animNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    animNode->setPosition(0,20,0);
    Animation* anim = mSceneMgr->createAnimation("an1", 10);
    anim->setInterpolationMode(Animation::IM_SPLINE);
    NodeAnimationTrack* track = anim->createNodeTrack(1, animNode);
    TransformKeyFrame* kf = track->createNodeKeyFrame(0);
    kf->setTranslate(Vector3::ZERO);
    kf = track->createNodeKeyFrame(2);
    kf->setTranslate(Vector3(100, 0, 0));
    kf = track->createNodeKeyFrame(4);
    kf->setTranslate(Vector3(200, 0, 300));
    kf = track->createNodeKeyFrame(6);
    kf->setTranslate(Vector3(0, 20, 500));
    kf = track->createNodeKeyFrame(8);
    kf->setTranslate(Vector3(-100, 10, 100));
    kf = track->createNodeKeyFrame(10);
    kf->setTranslate(Vector3::ZERO);
    
    //testremoveNode = animNode;
    
    AnimationState* animState = mSceneMgr->createAnimationState("an1");
    animState->setEnabled(true);
    mAnimStateList.push_back(animState);
    
    trail->addNode(animNode);
    trail->setInitialColour(0, 1.0, 0.8, 0);
    trail->setColourChange(0, 0.5, 0.5, 0.5, 0.5);
    trail->setInitialWidth(0, 5);
    
    // Add light
    Light* l2 = mSceneMgr->createLight("l2");
    l2->setDiffuseColour(trail->getInitialColour(0));
    animNode->attachObject(l2);
    
    // Add billboard
    BillboardSet* bbs = mSceneMgr->createBillboardSet("bb", 1);
    bbs->createBillboard(Vector3::ZERO, trail->getInitialColour(0));
    bbs->setMaterialName("Examples/Flare");
    animNode->attachObject(bbs);
    
    animNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    animNode->setPosition(-50,10,0);
    anim = mSceneMgr->createAnimation("an2", 10);
    anim->setInterpolationMode(Animation::IM_SPLINE);
    track = anim->createNodeTrack(1, animNode);
    kf = track->createNodeKeyFrame(0);
    kf->setTranslate(Vector3::ZERO);
    kf = track->createNodeKeyFrame(2);
    kf->setTranslate(Vector3(-100, 150, -30));
    kf = track->createNodeKeyFrame(4);
    kf->setTranslate(Vector3(-200, 0, 40));
    kf = track->createNodeKeyFrame(6);
    kf->setTranslate(Vector3(0, -150, 70));
    kf = track->createNodeKeyFrame(8);
    kf->setTranslate(Vector3(50, 0, 30));
    kf = track->createNodeKeyFrame(10);
    kf->setTranslate(Vector3::ZERO);
    
    animState = mSceneMgr->createAnimationState("an2");
    animState->setEnabled(true);
    mAnimStateList.push_back(animState);
    
    trail->addNode(animNode);
    trail->setInitialColour(1, 0.0, 1.0, 0.4);
    trail->setColourChange(1, 0.5, 0.5, 0.5, 0.5);
    trail->setInitialWidth(1, 5);
    
    
    // Add light
    l2 = mSceneMgr->createLight("l3");
    l2->setDiffuseColour(trail->getInitialColour(1));
    animNode->attachObject(l2);
    
    // Add billboard
    bbs = mSceneMgr->createBillboardSet("bb2", 1);
    bbs->createBillboard(Vector3::ZERO, trail->getInitialColour(1));
    bbs->setMaterialName("Examples/Flare");
    animNode->attachObject(bbs);
    
    
    mCamera->setPosition(0,0,500);
    //mSceneMgr->showBoundingBoxes(true);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_SerialisedColour::PlayPen_SerialisedColour()
{
    mInfo["Title"] = "PlayPen_SerialisedColour";
    mInfo["Description"] = "Tests serializing mesh color.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_SerialisedColour::setupContent()
{
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    Light* l = mSceneMgr->createLight("light1");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(dir);
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    
    ManualObject* man = static_cast<ManualObject*>(
    mSceneMgr->createMovableObject("test", ManualObjectFactory::FACTORY_TYPE_NAME));
    
    man->begin("BaseWhiteNoLighting");
    // Define a 40x40 plane, non-indexed
    // Define a 40x40 plane, indexed
    man->position(-20, 20, 20);
    man->colour(1, 0, 0);
    
    man->position(-20, -20, 20);
    man->colour(1, 0, 0);
    
    man->position(20, -20, 20);
    man->colour(1, 0, 0);
    
    man->position(20, 20, 20);
    man->colour(1, 0, 0);
    
    man->quad(0, 1, 2, 3);
    man->end();
    
    MeshPtr mesh = man->convertToMesh("colourtest.mesh");
    MeshSerializer ms;
    ms.exportMesh(mesh.getPointer(), "colourtest.mesh");
    
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(man);
    
    Entity* c = mSceneMgr->createEntity("1", "colourtest.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(c);
    
    mCamera->setPosition(0,0,120);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ShadowLod::PlayPen_ShadowLod()
{
    mInfo["Title"] = "PlayPen_ShadowLod";
    mInfo["Description"] = "Tests whether LOD is based on shadow cam or main cam.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_ShadowLod::cleanupContent()
{
    clearDebugTextureOverlays();
}
//----------------------------------------------------------------------------

void PlayPen_ShadowLod::setupContent()
{
    SceneNode* mTestNode[10];

    // Test that LOD is based on main camera, not shadow camera
    
    mSceneMgr->setShadowTextureSize(1024);
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
    
    //FocusedShadowCameraSetup* lispsmSetup = new FocusedShadowCameraSetup();
    //LiSPSMShadowCameraSetup* lispsmSetup = new LiSPSMShadowCameraSetup();
    //lispsmSetup->setOptimalAdjustFactor(1.5);
    //mSceneMgr->setShadowCameraSetup(ShadowCameraSetupPtr(lispsmSetup));
    
    mSceneMgr->setShadowColour(ColourValue(0.35, 0.35, 0.35));
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));
    
    Light* mLight = mSceneMgr->createLight("MainLight");
    
    // Directional test
    if (false)
    {
        mLight->setType(Light::LT_DIRECTIONAL);
        Vector3 vec(-1,-1,0);
        vec.normalise();
        mLight->setDirection(vec);
    }
    // Spotlight test
    else
    {
        mLight->setType(Light::LT_SPOTLIGHT);
        mLight->setAttenuation(10000, 1, 0, 0);
        mLight->setDiffuseColour(1.0, 1.0, 0.8);
        mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
        mTestNode[0]->setPosition(400,300,0);
        mTestNode[0]->lookAt(Vector3(0,0,0), Node::TS_WORLD, Vector3::UNIT_Z);
        mTestNode[0]->attachObject(mLight);
    }
    
    mTestNode[1] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    
    
    Entity* pEnt;
    pEnt = mSceneMgr->createEntity( "1", "knot.mesh" );
    // rendering distance should also be based on main cam
    //pEnt->setRenderingDistance(100);
    //pEnt->setMaterialName("2 - Default");
    mTestNode[1]->attachObject( pEnt );
    //mTestNode[1]->translate(0,-100,0);
    /*
    pEnt = mSceneMgr->createEntity( "3", "knot.mesh" );
    mTestNode[2] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-200, 0, -200));
    mTestNode[2]->attachObject( pEnt );
    
    
    createRandomEntityClones(pEnt, 20, Vector3(-1000,0,-1000), Vector3(1000,0,1000));
    
    
    // Transparent object (can force cast shadows)
    pEnt = mSceneMgr->createEntity( "3.5", "knot.mesh" );
    MaterialPtr tmat = MaterialManager::getSingleton().create("TestAlphaTransparency", 
    TRANSIENT_RESOURCE_GROUP);
    tmat->setTransparencyCastsShadows(true);
    Pass* tpass = tmat->getTechnique(0)->getPass(0);
    tpass->setAlphaRejectSettings(CMPF_GREATER, 150);
    tpass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    tpass->createTextureUnitState("gras_02.png");
    tpass->setCullingMode(CULL_NONE);
    
    pEnt->setMaterialName("TestAlphaTransparency");
    mTestNode[3] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(350, 0, -200));
    mTestNode[3]->attachObject( pEnt );
    
    MeshPtr msh = MeshManager::getSingleton().load("knot.mesh",
    TRANSIENT_RESOURCE_GROUP);
    msh->buildTangentVectors(VES_TANGENT, 0, 0);
    pEnt = mSceneMgr->createEntity( "4", "knot.mesh" );
    //pEnt->setMaterialName("Examples/BumpMapping/MultiLightSpecular");
    mTestNode[2] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100, 0, 200));
    mTestNode[2]->attachObject( pEnt );
    
    mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
    */
    
    
    MovablePlane movablePlane(Vector3::UNIT_Y, 100);
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, movablePlane,
    2500,2500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    if (SHADOWTYPE_TEXTURE_MODULATIVE & SHADOWDETAILTYPE_INTEGRATED)
    {
        pPlaneEnt->setMaterialName("Examples/Plane/IntegratedShadows");
    }
    else
    {
        pPlaneEnt->setMaterialName("2 - Default");
    }
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    addTextureShadowDebugOverlay(1, mSceneMgr);
    
    
    /*
    ParticleSystem* pSys2 = mSceneMgr->createParticleSystem("smoke", 
    "Examples/Smoke");
    mTestNode[4] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-300, -100, 200));
    mTestNode[4]->attachObject(pSys2);
    */
    
    mCamera->setPosition(0, 1000, 500);
    mCamera->lookAt(0,0,0);
    mCamera->setFarClipDistance(10000);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_SkeletalAnimation::PlayPen_SkeletalAnimation()
{
    mInfo["Title"] = "PlayPen_SkeletalAnimation";
    mInfo["Description"] = "Tests skeletal animation.";
    addScreenshotFrame(100);
}
//----------------------------------------------------------------------------

void PlayPen_SkeletalAnimation::setupContent()
{
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    //mWindow->getViewport(0)->setBackgroundColour(ColourValue::White);
    
    
    
    Entity *ent = mSceneMgr->createEntity("robot", "robot.mesh");
    //ent->setDisplaySkeleton(true);
    // Uncomment the below to test software skinning
    ent->setMaterialName("Examples/Rocky");
    // Add entity to the scene node
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    Ogre::AnimationState* mAnimState = ent->getAnimationState("Walk");
    mAnimState->setEnabled(true);
    
    // Give it a little ambience with lights
    Light* l;
    l = mSceneMgr->createLight("BlueLight");
    l->setPosition(-200,-80,-100);
    l->setDiffuseColour(0.5, 0.5, 1.0);
    
    l = mSceneMgr->createLight("GreenLight");
    l->setPosition(0,0,-100);
    l->setDiffuseColour(0.5, 1.0, 0.5);
    
    // Position the camera
    mCamera->setPosition(200,50,0);
    mCamera->lookAt(0,50,0);
    
    // Report whether hardware skinning is enabled or not
    /*Technique* t = ent->getSubEntity(0)->getTechnique();
    Pass* p = t->getPass(0);
    OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText");
    if (p->hasVertexProgram() && 
    p->getVertexProgram()->isSkeletalAnimationIncluded())
    {
        guiDbg->setCaption("Hardware skinning is enabled");
    }
    else
    {
        guiDbg->setCaption("Software skinning is enabled");
    }*/
    
    mAnimStateList.push_back(mAnimState);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_SkeletonAnimationOptimise::PlayPen_SkeletonAnimationOptimise()
{
    mInfo["Title"] = "PlayPen_SkeletonAnimationOptimise";
    mInfo["Description"] = "Tests skeletal animation with hardware and software.";
    addScreenshotFrame(100);
}
//----------------------------------------------------------------------------

void PlayPen_SkeletonAnimationOptimise::setupContent()
{
    SceneNode* mTestNode[5];
    mSceneMgr->setShadowTextureSize(512);
    mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
    mSceneMgr->setShadowFarDistance(1500);
    mSceneMgr->setShadowColour(ColourValue(0.35, 0.35, 0.35));
    //mSceneMgr->setShadowFarDistance(800);
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));
    
    Light* mLight = mSceneMgr->createLight("MainLight");
    
    /*/
    // Directional test
    mLight->setType(Light::LT_DIRECTIONAL);
    Vector3 vec(-1,-1,0);
    vec.normalise();
    mLight->setDirection(vec);
    /*/
    // Point test
    mLight->setType(Light::LT_POINT);
    mLight->setPosition(0, 200, 0);
    //*/
    
    Entity* pEnt;
    
    // Hardware animation
    pEnt = mSceneMgr->createEntity( "1", "robot.mesh" );
    AnimationState* a = pEnt->getAnimationState("Walk");
    a->setEnabled(true);
    mAnimStateList.push_back(a);
    mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    mTestNode[0]->attachObject( pEnt );
    mTestNode[0]->translate(+100,-100,0);
    
    // Software animation
    pEnt = mSceneMgr->createEntity( "2", "robot.mesh" );
    pEnt->setMaterialName("BaseWhite");
    a = pEnt->getAnimationState("Walk");
    a->setEnabled(true);
    mAnimStateList.push_back(a);
    
    mTestNode[1] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    mTestNode[1]->attachObject( pEnt );
    mTestNode[1]->translate(-100,-100,0);
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);

    mCamera->setPosition(0,0,300);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_SpotlightViewProj::PlayPen_SpotlightViewProj()
{
    mInfo["Title"] = "PlayPen_SpotlightViewProj";
    mInfo["Description"] = "Tests spotlight camera projection.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_SpotlightViewProj::setupContent()
{
    SceneNode* mTestNode[10];
    bool worldViewProj = true;
    // Define programs that use spotlight projection
    
    String vpStr;
    vpStr = 
    "void vp(float4 position : POSITION,\n"
    "out float4 oPosition : POSITION,\n"
    "out float4 oUV : TEXCOORD0,\n";
    if (!worldViewProj)
    {
        vpStr += "uniform float4x4 world,\n"
        "uniform float4x4 spotlightViewProj,\n";
    }
    else
    {
        vpStr += "uniform float4x4 spotlightWorldViewProj,\n";
    }
    vpStr += "uniform float4x4 worldViewProj)\n"
    "{\n"
    "    oPosition = mul(worldViewProj, position);\n";
    if (worldViewProj)
    {
        vpStr += "    oUV = mul(spotlightWorldViewProj, position);\n";
    }
    else
    {
        vpStr += "    float4 worldPos = mul(world, position);\n"
        "    oUV = mul(spotlightViewProj, worldPos);\n";
    }
    vpStr += "}\n";
    
    String fpStr = 
    "void fp(\n"
    "float4 uv : TEXCOORD0,\n"
    "uniform sampler2D tex : register(s0),\n"
    "out float4 oColor : COLOR)\n"
    "{\n"
    "   uv = uv / uv.w;\n"
    "    oColor = tex2D(tex, uv.xy);\n"
    "}\n";
    
    HighLevelGpuProgramPtr vp = HighLevelGpuProgramManager::getSingleton()
    .createProgram("testvp", 
    TRANSIENT_RESOURCE_GROUP, 
    "cg", GPT_VERTEX_PROGRAM);
    vp->setSource(vpStr);
    vp->setParameter("profiles", "vs_1_1 arbvp1");
    vp->setParameter("entry_point", "vp");
    vp->load();
    
    HighLevelGpuProgramPtr fp = HighLevelGpuProgramManager::getSingleton()
    .createProgram("testfp", 
    TRANSIENT_RESOURCE_GROUP, 
    "cg", GPT_FRAGMENT_PROGRAM);
    fp->setSource(fpStr);
    fp->setParameter("profiles", "ps_2_0 arbfp1");
    fp->setParameter("entry_point", "fp");
    fp->load();
    
    MaterialPtr mat = MaterialManager::getSingleton().create("TestSpotlightProj", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setVertexProgram("testvp");
    p->getVertexProgramParameters()->setNamedAutoConstant(
    "worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
    
    if (worldViewProj)
    {
        p->getVertexProgramParameters()->setNamedAutoConstant(
        "spotlightWorldViewProj", GpuProgramParameters::ACT_SPOTLIGHT_WORLDVIEWPROJ_MATRIX);
    }
    else
    {
        p->getVertexProgramParameters()->setNamedAutoConstant(
        "world", GpuProgramParameters::ACT_WORLD_MATRIX);
        p->getVertexProgramParameters()->setNamedAutoConstant(
        "spotlightViewProj", GpuProgramParameters::ACT_SPOTLIGHT_VIEWPROJ_MATRIX);
    }
    p->setFragmentProgram("testfp");
    p->createTextureUnitState("ogrelogo.png");
    
    Entity* pEnt;
    
    // Define a plane mesh, use the above material
    Plane plane;
    plane.normal = Vector3::UNIT_Z;
    plane.d = 200;
    MeshManager::getSingleton().createPlane("WallPlane",
    TRANSIENT_RESOURCE_GROUP,
    plane,1500,1500,100,100,true,1,5,5,Vector3::UNIT_Y);
    pEnt = mSceneMgr->createEntity( "5", "WallPlane" );
    pEnt->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pEnt);
    
    
    mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    
    mTestNode[0]->translate(0, 0, 750);
    
    Light* spot = mSceneMgr->createLight("l1");
    spot->setType(Light::LT_SPOTLIGHT);
    spot->setDirection(Vector3::NEGATIVE_UNIT_Z);
    
    mTestNode[0]->attachObject(spot);
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_SRGBtexture::PlayPen_SRGBtexture()
{
    mInfo["Title"] = "PlayPen_SRGBtexture";
    mInfo["Description"] = "Tests sRGB textures.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_SRGBtexture::setupContent()
{
    // NOTE: enable flag only turns on SRGB for texture sampling, you may
    // need to configure the window for the reverse conversion for consistency!
    MaterialPtr mat = MaterialManager::getSingleton().create("testsrgb", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setLightingEnabled(false);
    p->setCullingMode(CULL_NONE);
    TextureUnitState* t = p->createTextureUnitState("ogrelogo.png");
    t->setHardwareGammaEnabled(true);
    Entity *e = mSceneMgr->createEntity("Plane", SceneManager::PT_PLANE);
    e->setMaterialName(mat->getName());
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    mWindow->getViewport(0)->setBackgroundColour(ColourValue::Red);
    
    mCamera->setPosition(0,0,300);
    mCamera->lookAt(Vector3::ZERO);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_StaticGeometry::PlayPen_StaticGeometry()
{
    mInfo["Title"] = "PlayPen_StaticGeometry";
    mInfo["Description"] = "Tests static geometry.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_StaticGeometry::setupContent()
{
    
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0, 0, 0));
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setDiffuseColour(0.4, 0.4, 0.4);
    l->setSpecularColour(ColourValue::White);
    
    SceneNode* animNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    Animation* anim = mSceneMgr->createAnimation("an1", 20);
    anim->setInterpolationMode(Animation::IM_SPLINE);
    NodeAnimationTrack* track = anim->createNodeTrack(1, animNode);
    TransformKeyFrame* kf = track->createNodeKeyFrame(0);
    kf->setTranslate(Vector3(2300, 600, 2300));
    kf = track->createNodeKeyFrame(5);
    kf->setTranslate(Vector3(-2300, 600, 2300));
    kf = track->createNodeKeyFrame(10);
    kf->setTranslate(Vector3(-2300, 600, -2300));
    kf = track->createNodeKeyFrame(15);
    kf->setTranslate(Vector3(2300, 600, -2300));
    kf = track->createNodeKeyFrame(20);
    kf->setTranslate(Vector3(2300, 600, 2300));
    
    //animNode->attachObject(l);
    l->setPosition(0, 600, 0);
    l->setAttenuation(10000, 1, 0, 0);
    
    AnimationState* animState = mSceneMgr->createAnimationState("an1");
    animState->setEnabled(true);
    mAnimStateList.push_back(animState);
    
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 0;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    4500,4500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("Examples/GrassFloor");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    Vector3 min(-2000,30,-2000);
    Vector3 max(2000,30,2000);
    
    
    MeshPtr msh = MeshManager::getSingleton().load("ogrehead.mesh", TRANSIENT_RESOURCE_GROUP);
    msh->buildTangentVectors();
    
    Entity* e = mSceneMgr->createEntity("1", "ogrehead.mesh");
    e->setMaterialName("Examples/BumpMapping/MultiLightSpecular");
    
    StaticGeometry* s = mSceneMgr->createStaticGeometry("bing");
    s->setCastShadows(true);
    s->setRegionDimensions(Vector3(500,500,500));
    for (int i = 0; i < 10; ++i)
    {
        Vector3 pos;
        pos.x = Math::RangeRandom(min.x, max.x);
        pos.y = Math::RangeRandom(min.y, max.y);
        pos.z = Math::RangeRandom(min.z, max.z);
        
        s->addEntity(e, pos);
        Entity* e2 = e->clone("clone" + StringConverter::toString(i));
        mSceneMgr->getRootSceneNode()->createChildSceneNode(pos+Vector3(0,60,0))->attachObject(e2);
        
    }
    
    s->build();
    mCamera->setLodBias(0.5);
    mCamera->setPosition(0,400,1200);
    mCamera->setDirection(0,-0.3f,-1.2f);
    
    //mTestNode[0] = s->getRegionIterator().getNext()->getParentSceneNode();
    
    
    
    
    
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_StaticGeometryWithLOD::PlayPen_StaticGeometryWithLOD()
{
    mInfo["Title"] = "PlayPen_StaticGeometryWithLOD";
    mInfo["Description"] = "Tests static geometry with LODs.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_StaticGeometryWithLOD::setupContent()
{
    //if (stencilShadows)
    //{
    //    mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);
    //}
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0, 0, 0));
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setDiffuseColour(0.4, 0.4, 0.4);
    l->setSpecularColour(ColourValue::White);
    
    SceneNode* animNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    Animation* anim = mSceneMgr->createAnimation("an1", 20);
    anim->setInterpolationMode(Animation::IM_SPLINE);
    NodeAnimationTrack* track = anim->createNodeTrack(1, animNode);
    TransformKeyFrame* kf = track->createNodeKeyFrame(0);
    kf->setTranslate(Vector3(2300, 600, 2300));
    kf = track->createNodeKeyFrame(5);
    kf->setTranslate(Vector3(-2300, 600, 2300));
    kf = track->createNodeKeyFrame(10);
    kf->setTranslate(Vector3(-2300, 600, -2300));
    kf = track->createNodeKeyFrame(15);
    kf->setTranslate(Vector3(2300, 600, -2300));
    kf = track->createNodeKeyFrame(20);
    kf->setTranslate(Vector3(2300, 600, 2300));
    
    //animNode->attachObject(l);
    l->setPosition(0, 600, 0);
    l->setAttenuation(10000, 1, 0, 0);
    
    AnimationState* animState = mSceneMgr->createAnimationState("an1");
    animState->setEnabled(true);
    mAnimStateList.push_back(animState);
    
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 0;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    4500,4500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("Examples/GrassFloor");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    Vector3 min(-2000,30,-2000);
    Vector3 max(2000,30,2000);
    
    
    MeshPtr msh = MeshManager::getSingleton().load("knot.mesh", TRANSIENT_RESOURCE_GROUP);
    
    Entity* e = mSceneMgr->createEntity("1", msh->getName());
    
    StaticGeometry* s = mSceneMgr->createStaticGeometry("bing");
    s->setCastShadows(true);
    s->setRegionDimensions(Vector3(500,500,500));
    for (int i = 0; i < 10; ++i)
    {
        Vector3 pos;
        pos.x = Math::RangeRandom(min.x, max.x);
        pos.y = Math::RangeRandom(min.y, max.y);
        pos.z = Math::RangeRandom(min.z, max.z);
        
        s->addEntity(e, pos);
        
    }
    
    s->build();
    mCamera->setLodBias(0.5);
    mCamera->setPosition(0,400,1200);
    mCamera->setDirection(0,-0.3f,-1.2f);
    
    //mTestNode[0] = s->getRegionIterator().getNext()->getParentSceneNode();
    
    
    
    
    
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

// render queues
#define RENDER_QUEUE_OUTLINE_GLOW_OBJECTS    RENDER_QUEUE_MAIN + 1
#define RENDER_QUEUE_OUTLINE_GLOW_GLOWS        RENDER_QUEUE_MAIN + 2
#define RENDER_QUEUE_FULL_GLOW_ALPHA_GLOW    RENDER_QUEUE_MAIN + 3
#define RENDER_QUEUE_FULL_GLOW_GLOW            RENDER_QUEUE_MAIN + 4
#define LAST_STENCIL_OP_RENDER_QUEUE        RENDER_QUEUE_FULL_GLOW_GLOW

// stencil values
#define STENCIL_VALUE_FOR_OUTLINE_GLOW 1
#define STENCIL_VALUE_FOR_FULL_GLOW 2
#define STENCIL_FULL_MASK 0xFFFFFFFF

// a Render queue listener to change the stencil mode
class StencilOpQueueListener : public Ogre::RenderQueueListener 
{ 
public: 
    virtual void renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& skipThisInvocation) 
    { 
        if (queueGroupId == RENDER_QUEUE_OUTLINE_GLOW_OBJECTS) // outline glow object 
        { 
            Ogre::RenderSystem * rendersys = Ogre::Root::getSingleton().getRenderSystem(); 

            rendersys->clearFrameBuffer(Ogre::FBT_STENCIL); 
            rendersys->setStencilCheckEnabled(true); 
            rendersys->setStencilBufferParams(Ogre::CMPF_ALWAYS_PASS,
                STENCIL_VALUE_FOR_OUTLINE_GLOW, STENCIL_FULL_MASK, STENCIL_FULL_MASK,
                Ogre::SOP_KEEP,Ogre::SOP_KEEP,Ogre::SOP_REPLACE,false);       
        } 
        if (queueGroupId == RENDER_QUEUE_OUTLINE_GLOW_GLOWS)  // outline glow
        { 
            Ogre::RenderSystem * rendersys = Ogre::Root::getSingleton().getRenderSystem(); 
            rendersys->setStencilCheckEnabled(true); 
            rendersys->setStencilBufferParams(Ogre::CMPF_NOT_EQUAL,
                STENCIL_VALUE_FOR_OUTLINE_GLOW, STENCIL_FULL_MASK, STENCIL_FULL_MASK,
                Ogre::SOP_KEEP,Ogre::SOP_KEEP,Ogre::SOP_REPLACE,false);       
        } 
        if (queueGroupId == RENDER_QUEUE_FULL_GLOW_ALPHA_GLOW)  // full glow - alpha glow
        { 
            Ogre::RenderSystem * rendersys = Ogre::Root::getSingleton().getRenderSystem(); 
            rendersys->setStencilCheckEnabled(true); 
            rendersys->setStencilBufferParams(Ogre::CMPF_ALWAYS_PASS,
                STENCIL_VALUE_FOR_FULL_GLOW,STENCIL_FULL_MASK, STENCIL_FULL_MASK,
                Ogre::SOP_KEEP,Ogre::SOP_KEEP,Ogre::SOP_REPLACE,false);       
        } 

        if (queueGroupId == RENDER_QUEUE_FULL_GLOW_GLOW)  // full glow - glow
        { 
            Ogre::RenderSystem * rendersys = Ogre::Root::getSingleton().getRenderSystem(); 
            rendersys->setStencilCheckEnabled(true); 
            rendersys->setStencilBufferParams(Ogre::CMPF_EQUAL,
                STENCIL_VALUE_FOR_FULL_GLOW,STENCIL_FULL_MASK, STENCIL_FULL_MASK,
                Ogre::SOP_KEEP,Ogre::SOP_KEEP,Ogre::SOP_ZERO,false);       
        } 

    } 

    virtual void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation) 
    { 
        if ( queueGroupId == LAST_STENCIL_OP_RENDER_QUEUE )
        {
            Ogre::RenderSystem * rendersys = Ogre::Root::getSingleton().getRenderSystem(); 
            rendersys->setStencilCheckEnabled(false); 
            rendersys->setStencilBufferParams(); 
        } 
    } 

}; 
//---------------------------------------------------------------------------

PlayPen_StencilGlow::PlayPen_StencilGlow()
    :mStencilListener(0)
{
    mInfo["Title"] = "PlayPen_StencilGlow";
    mInfo["Description"] = "Tests stencil glow effect.";
    addScreenshotFrame(50);
}
//---------------------------------------------------------------------------

PlayPen_StencilGlow::~PlayPen_StencilGlow()
{
    if(mStencilListener)
        delete mStencilListener;
}
//---------------------------------------------------------------------------

void PlayPen_StencilGlow::setupContent(void)
{
    // test media
    Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Tests");
    
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));

    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    // Accept default settings: point light, white diffuse, just set position
    // NB I could attach the light to a SceneNode if I wanted it to move automatically with
    //  other objects, but I don't
    l->setPosition(20,80,50);


    // outline glow entity
    Entity *outlineGlowEntity = mSceneMgr->createEntity("outlineGlow", "ogrehead.mesh");
    outlineGlowEntity->setRenderQueueGroup(RENDER_QUEUE_OUTLINE_GLOW_OBJECTS);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(outlineGlowEntity);


    // outline glow entity actual glow
    Ogre::Entity* actualOutlineGlowEntity = outlineGlowEntity->clone(outlineGlowEntity->getName() + "_glow"); 
    actualOutlineGlowEntity->setRenderQueueGroup(RENDER_QUEUE_OUTLINE_GLOW_GLOWS); 
    actualOutlineGlowEntity->setMaterialName("glow"); 
    Ogre::SceneNode* actualOutlineGlowNode = outlineGlowEntity->getParentSceneNode()->createChildSceneNode("outlineGlowNode"); 
    actualOutlineGlowNode->attachObject(actualOutlineGlowEntity); 


    // normal entity
    Entity *normalOgreEntity = mSceneMgr->createEntity("normalOgreEntity", "ogrehead.mesh");
    Ogre::SceneNode* normalOgreNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    normalOgreNode->attachObject(normalOgreEntity);
    normalOgreNode->setPosition(80, 0, 0);
     


    // full glow entity
    Entity *fullGlowEntity = mSceneMgr->createEntity("fullGlowEntity", "ogrehead.mesh");
    Ogre::SceneNode* fullGlowNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    fullGlowNode->attachObject(fullGlowEntity);
    fullGlowNode->setPosition(-80, 0, 0);

    // full glow alpha glow
    Ogre::Entity* alphaFullGlowEntity = fullGlowEntity->clone(fullGlowEntity->getName() + "_alphaGlow"); 
    alphaFullGlowEntity->setRenderQueueGroup(RENDER_QUEUE_FULL_GLOW_ALPHA_GLOW); 
    alphaFullGlowEntity->setMaterialName("alpha_glow"); 
    Ogre::SceneNode* alphaFullGlowNode = fullGlowEntity->getParentSceneNode()->createChildSceneNode("fullGlowAlphaNode"); 
    alphaFullGlowNode->attachObject(alphaFullGlowEntity); 

    // full glow alpha glow
    Ogre::Entity* glowFullGlowEntity = fullGlowEntity->clone(fullGlowEntity->getName() + "_glow"); 
    glowFullGlowEntity->setRenderQueueGroup(RENDER_QUEUE_FULL_GLOW_GLOW); 
    glowFullGlowEntity->setMaterialName("no_depth_check_glow"); 
    Ogre::SceneNode* glowFullGlowNode = fullGlowEntity->getParentSceneNode()->createChildSceneNode("fullGlowGlowNode"); 
    glowFullGlowNode->attachObject(glowFullGlowEntity); 

    mCamera->setPosition(0,0,200);
    mCamera->setDirection(0,0,-1);

    mStencilListener = new StencilOpQueueListener();
    mSceneMgr->addRenderQueueListener(mStencilListener);

}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_StencilShadows::PlayPen_StencilShadows()
{
    mInfo["Title"] = "PlayPen_StencilShadows";
    mInfo["Description"] = "Tests stencil shadows.";
    addScreenshotFrame(20);
}
//----------------------------------------------------------------------------

void PlayPen_StencilShadows::setupContent()
{
    SceneNode* mTestNode[10];
    Light* mLight = 0;

    mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
    //mSceneMgr->setShowDebugShadows(true);
    mSceneMgr->setShadowDirectionalLightExtrusionDistance(1000);
    //mSceneMgr->setShadowColour(ColourValue(0.4, 0.25, 0.25));
    
    //mSceneMgr->setShadowFarDistance(800);
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.0, 0.0, 0.0));
    
    // Point light
    //if(pointLight)
    //{
        mLight = mSceneMgr->createLight("MainLight");
        mLight->setPosition(-400,400,-300);
        mLight->setDiffuseColour(0.9, 0.9, 1);
        mLight->setSpecularColour(0.9, 0.9, 1);
        mLight->setAttenuation(6000,1,0.001,0);
    //}
    // Directional light
    //if (directionalLight)
    //{
        mLight = mSceneMgr->createLight("Light2");
        Vector3 dir(-1,-1,0);
        dir.normalise();
        mLight->setType(Light::LT_DIRECTIONAL);
        mLight->setDirection(dir);
        mLight->setDiffuseColour(1, 1, 0.8);
        mLight->setSpecularColour(1, 1, 1);
    //}
    
    mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    
    // Hardware skin
    Entity* pEnt;
    pEnt = mSceneMgr->createEntity( "1", "robot.mesh" );
    AnimationState* anim = pEnt->getAnimationState("Walk");
    anim->setEnabled(true);
    mAnimStateList.push_back(anim);
    mTestNode[0]->attachObject( pEnt );
    
    // Software skin
    pEnt = mSceneMgr->createEntity( "12", "robot.mesh" );
    anim = pEnt->getAnimationState("Walk");
    anim->setEnabled(true);
    mAnimStateList.push_back(anim);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100, 0, 0))->attachObject(pEnt);
    pEnt->setMaterialName("Examples/Rocky");
    
    // test object
    //pEnt = mSceneMgr->createEntity("tst", "building.mesh");
    //mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(300, 0, 0))->attachObject(pEnt);
    
    
    // Does not receive shadows
    pEnt = mSceneMgr->createEntity( "3", "knot.mesh" );
    pEnt->setMaterialName("Examples/EnvMappedRustySteel");
    MaterialPtr mat2 = MaterialManager::getSingleton().getByName("Examples/SphereMappedRustySteel").staticCast<Material>();
    mat2->setReceiveShadows(false);
    mTestNode[2] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-200, 0, -200));
    mTestNode[2]->attachObject( pEnt );
    
    // Transparent object 
    pEnt = mSceneMgr->createEntity( "3.5", "knot.mesh" );
    pEnt->setMaterialName("Examples/TransparentTest");
    MaterialPtr mat3 = MaterialManager::getSingleton().getByName("Examples/TransparentTest").staticCast<Material>();
    pEnt->setCastShadows(false);
    mTestNode[3] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(350, 0, -200));
    mTestNode[3]->attachObject( pEnt );
    
    // User test
    /*
    pEnt = mSceneMgr->createEntity( "3.6", "ogre_male_endCaps.mesh" );
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0, 0, 100))->attachObject( pEnt );
    */
    
    MeshPtr msh = MeshManager::getSingleton().load("knot.mesh", 
    TRANSIENT_RESOURCE_GROUP);
    unsigned short src, dest;
    if (!msh->suggestTangentVectorBuildParams(VES_TANGENT, src, dest))
    {
        msh->buildTangentVectors(VES_TANGENT, src, dest);
    }
    pEnt = mSceneMgr->createEntity( "4", "knot.mesh" );
    pEnt->setMaterialName("Examples/BumpMapping/MultiLightSpecular");
    mTestNode[2] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100, 0, 200));
    mTestNode[2]->attachObject( pEnt );
    
    // controller based material
    pEnt = mSceneMgr->createEntity( "432", "knot.mesh" );
    pEnt->setMaterialName("Examples/TextureEffect2");
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100, 200, 200))->attachObject( pEnt );
    
    ParticleSystem* pSys2 = mSceneMgr->createParticleSystem("smoke", 
    "Examples/Smoke");
    mTestNode[4] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-300, -100, 200));
    mTestNode[4]->attachObject(pSys2);
    
    
    mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    //mCamera->setPosition(180, 34, 223);
    //mCamera->setOrientation(Quaternion(0.7265, -0.2064, 0.6304, 0.1791));
    
    mCamera->setPosition(0,0,400);
    mCamera->setDirection(0,0,-1);

    // Create a render texture
/*    TexturePtr rtt = TextureManager::getSingleton().createManual("rtt0", 
    TRANSIENT_RESOURCE_GROUP, 
    TEX_TYPE_2D, 512, 512, 0, PF_R8G8B8, TU_RENDERTARGET);
    rtt->getBuffer()->getRenderTarget()->addViewport(mCamera);
    // Create an overlay showing the rtt
    MaterialPtr debugMat = MaterialManager::getSingleton().create(
    "DebugRTT", TRANSIENT_RESOURCE_GROUP);
    debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
    TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState("rtt0");
    t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
    OverlayContainer* debugPanel = (OverlayContainer*)
    (OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugShadowPanel"));
    debugPanel->_setPosition(0.6, 0);
    debugPanel->_setDimensions(0.4, 0.6);
    debugPanel->setMaterialName("DebugRTT");
    Overlay* debugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
    debugOverlay->add2D(debugPanel);*/
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_StencilShadowsMixedOpSubMeshes::PlayPen_StencilShadowsMixedOpSubMeshes()
{
    mInfo["Title"] = "PlayPen_StencilShadowsMixedOpSubMeshes";
    mInfo["Description"] = "Tests mixed operation submeshes.";
    addScreenshotFrame(20);
}
//----------------------------------------------------------------------------

void PlayPen_StencilShadowsMixedOpSubMeshes::setupContent()
{
    //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);
    mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE);
    //mSceneMgr->setShowDebugShadows(true);
    mSceneMgr->setShadowDirectionalLightExtrusionDistance(1000);
    
    //mSceneMgr->setShadowFarDistance(800);
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.0, 0.0, 0.0));
    
    Light* mLight;

    // Point light
    //if(pointLight)
    //{
        mLight = mSceneMgr->createLight("MainLight");
        mLight->setPosition(-400,400,-300);
        mLight->setDiffuseColour(0.9, 0.9, 1);
        mLight->setSpecularColour(0.9, 0.9, 1);
        mLight->setAttenuation(6000,1,0.001,0);
    //}
    // Directional light
    //if (directionalLight)
    //{
        /*mLight = mSceneMgr->createLight("Light2");
        Vector3 dir(-1,-1,0);
        dir.normalise();
        mLight->setType(Light::LT_DIRECTIONAL);
        mLight->setDirection(dir);
        mLight->setDiffuseColour(1, 1, 0.8);
        mLight->setSpecularColour(1, 1, 1);*/
    //}
    
    mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
    
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("2 - Default");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    //mCamera->setPosition(180, 34, 223);
    //mCamera->setOrientation(Quaternion(0.7265, -0.2064, 0.6304, 0.1791));
    
    
    ManualObject* man = mSceneMgr->createManualObject("testMO_");
    man->begin("2 - Default");
    man->position(0, 200, 0);
    man->position(0, 50, 100);
    man->position(100, 50, -100);
    man->position(-100, 50, -100);
    man->triangle(0, 1, 2);
    man->triangle(0, 2, 3);
    man->triangle(0, 3, 1);
    man->end();
    man->begin("2 - Default", RenderOperation::OT_LINE_STRIP);
    man->position(0, 200, 0);
    man->position(50, 250, 0);
    man->position(200, 300, 0);
    man->index(0);
    man->index(1);
    man->index(2);
    man->end();
    MeshPtr msh = man->convertToMesh("testMO.mesh_2");
    
    Entity* e = mSceneMgr->createEntity("34", "testMO.mesh_2");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(e);
    
    mCamera->setPosition(100,320,600);
    mCamera->lookAt(0,120,0);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_SubEntityVisibility::PlayPen_SubEntityVisibility()
{
    mInfo["Title"] = "PlayPen_SubEntityVisibility";
    mInfo["Description"] = "Tests sub entity visibility settings.";
    addScreenshotFrame(250);
}
//----------------------------------------------------------------------------

void PlayPen_SubEntityVisibility::setupContent()
{
    SceneNode* mTestNode[5];
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(-Vector3::UNIT_Y);
    
    mTestNode[0] = (SceneNode*)mSceneMgr->getRootSceneNode()->createChild();
    
    Entity* pEnt = mSceneMgr->createEntity( "1", "ogrehead.mesh" );
    mTestNode[0]->attachObject( pEnt );
    
    pEnt->getSubEntity(1)->setVisible(false);
    
    mCamera->setPosition(0,0,125);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_SuppressedShadows::PlayPen_SuppressedShadows()
{
    mInfo["Title"] = "PlayPen_SuppressedShadows";
    mInfo["Description"] = "Tests suppressing shadows for a viewport.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_SuppressedShadows::setupContent()
{
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE);
    
    // Setup lighting
    mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
    Light* light = mSceneMgr->createLight("MainLight");
    light->setType(Light::LT_DIRECTIONAL);
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    light->setDirection(dir);
    
    // Create a skydome
    //mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);
    
    // Create a floor plane mesh
    Plane plane(Vector3::UNIT_Y, 0.0);
    MeshManager::getSingleton().createPlane(
    "FloorPlane", TRANSIENT_RESOURCE_GROUP,
    plane, 200000, 200000, 20, 20, true, 1, 500, 500, Vector3::UNIT_Z);
    
    
    // Add a floor to the scene
    Entity* entity = mSceneMgr->createEntity("floor", "FloorPlane");
    entity->setMaterialName("Examples/RustySteel");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(entity);
    entity->setCastShadows(false);
    
    // Add the mandatory ogre head
    entity = mSceneMgr->createEntity("head", "ogrehead.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0.0, 10.0, 0.0))->attachObject(entity);
    
    // Position and orient the camera
    mCamera->setPosition(-100.0, 50.0, 90.0);
    mCamera->lookAt(0.0, 10.0, -35.0);
    
    // Add an additional viewport on top of the other one
    Viewport* pip = mWindow->addViewport(mCamera, 1, 0.7, 0.0, 0.3, 0.3);
    
    // Create a render queue invocation sequence for the pip viewport
    RenderQueueInvocationSequence* invocationSequence =
    mRoot->createRenderQueueInvocationSequence("pip");
    
    // Add an invocation to the sequence
    RenderQueueInvocation* invocation =
    invocationSequence->add(RENDER_QUEUE_MAIN, "main");
    
    // Disable render state changes and shadows for that invocation
    //invocation->setSuppressRenderStateChanges(true);
    invocation->setSuppressShadows(true);
    
    // Set the render queue invocation sequence for the pip viewport
    pip->setRenderQueueInvocationSequenceName("pip");
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------


PlayPen_TextureShadows::PlayPen_TextureShadows()
{
    mInfo["Title"] = "PlayPen_TextureShadows";
    mInfo["Description"] = "Tests texture shadows.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_TextureShadows::cleanupContent()
{
    clearDebugTextureOverlays();
}
//----------------------------------------------------------------------------

void PlayPen_TextureShadows::setupContent()
{
    SceneNode* mTestNode[10];

    mSceneMgr->setShadowTextureSize(1024);
    mSceneMgr->setShadowTextureCount(1);
    //mSceneMgr->setShadowTechnique(tech);
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE);
    
    //FocusedShadowCameraSetup* lispsmSetup = new FocusedShadowCameraSetup();
    //LiSPSMShadowCameraSetup* lispsmSetup = new LiSPSMShadowCameraSetup();
    //lispsmSetup->setOptimalAdjustFactor(1.5);
    //mSceneMgr->setShadowCameraSetup(ShadowCameraSetupPtr(lispsmSetup));
    
    mSceneMgr->setShadowFarDistance(1000);
    mSceneMgr->setShadowColour(ColourValue(0.35, 0.35, 0.35));
    //mSceneMgr->setShadowFarDistance(800);
    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));
    
    Light* mLight = mSceneMgr->createLight("MainLight");
    
    
    // Directional test
    //if (directional)
    //{
        mLight->setType(Light::LT_DIRECTIONAL);
        Vector3 vec(-1,-1,0);
        vec.normalise();
        mLight->setDirection(vec);
    //}
    // Spotlight test
    /*else
    {
        mLight->setType(Light::LT_SPOTLIGHT);
        mLight->setAttenuation(1500, 1, 0, 0);
        mLight->setDiffuseColour(1.0, 1.0, 0.8);
        mTestNode[0] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
        mTestNode[0]->setPosition(800,600,0);
        mTestNode[0]->lookAt(Vector3(0,0,0), Node::TS_WORLD, Vector3::UNIT_Z);
        mTestNode[0]->attachObject(mLight);
    }*/
    
    mTestNode[1] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    
    
    Entity* pEnt;
    pEnt = mSceneMgr->createEntity( "1", "robot.mesh" );
    //pEnt->setRenderingDistance(100);
    AnimationState* mAnimState = pEnt->getAnimationState("Walk");
    mAnimState->setEnabled(true);
    mAnimStateList.push_back(mAnimState);
    //pEnt->setMaterialName("2 - Default");
    mTestNode[1]->attachObject( pEnt );
    mTestNode[1]->translate(0,-100,0);
    
    Quaternion quat2;
    quat2.FromAngleAxis(Degree(360), Vector3::UNIT_Y);
    
    pEnt = mSceneMgr->createEntity( "3", "knot.mesh" );
    mTestNode[2] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-200, 0, -200));
    mTestNode[2]->attachObject( pEnt );
    
    createRandomEntityClones(pEnt, 20, Vector3(-1000,0,-1000), Vector3(1000,0,1000), mSceneMgr);
    
    
    // Transparent object (can force cast shadows)
    pEnt = mSceneMgr->createEntity( "3.5", "knot.mesh" );
    MaterialPtr tmat = MaterialManager::getSingleton().create("TestAlphaTransparency", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    tmat->setTransparencyCastsShadows(true);
    Pass* tpass = tmat->getTechnique(0)->getPass(0);
    tpass->setAlphaRejectSettings(CMPF_GREATER, 150);
    tpass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    tpass->createTextureUnitState("gras_02.png");
    tpass->setCullingMode(CULL_NONE);
    
    pEnt->setMaterialName("TestAlphaTransparency");
    mTestNode[3] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(350, 0, -200));
    mTestNode[3]->attachObject( pEnt );
    
    MeshPtr msh = MeshManager::getSingleton().load("knot.mesh",
    TRANSIENT_RESOURCE_GROUP);
    msh->buildTangentVectors(VES_TANGENT, 0, 0);
    pEnt = mSceneMgr->createEntity( "4", "knot.mesh" );
    //pEnt->setMaterialName("Examples/BumpMapping/MultiLightSpecular");
    mTestNode[2] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100, 0, 200));
    mTestNode[2]->attachObject( pEnt );
    
    mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
    
    
    MovablePlane movablePlane(Vector3::UNIT_Y, 100);
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, movablePlane,
    2500,2500,10,10,true,1,5,5,Vector3::UNIT_Z);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    if (SHADOWTYPE_TEXTURE_ADDITIVE & SHADOWDETAILTYPE_INTEGRATED)
    {
      pPlaneEnt->setMaterialName("Examples/Plane/IntegratedShadows");
    }
    else
    {
        pPlaneEnt->setMaterialName("2 - Default");
    }
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    addTextureShadowDebugOverlay(1,mSceneMgr);
    
    
    /*
    ParticleSystem* pSys2 = mSceneMgr->createParticleSystem("smoke", 
    "Examples/Smoke");
    mTestNode[4] = mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-300, -100, 200));
    mTestNode[4]->attachObject(pSys2);
    */
    
    mCamera->setPosition(0, 1000, 500);
    mCamera->lookAt(0,0,0);
    mCamera->setFarClipDistance(10000);
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_TextureShadowsCustomCasterMat::PlayPen_TextureShadowsCustomCasterMat()
{
    mInfo["Title"] = "PlayPen_TextureShadowsCustomCasterMat";
    mInfo["Description"] = "Tests texture shadows with a custom caster material.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_TextureShadowsCustomCasterMat::setupContent()
{
    PlayPen_TextureShadows::setupContent();
    
    String customCasterMatVp = 
    "void customCasterVp(float4 position : POSITION,\n"
    "out float4 oPosition : POSITION,\n"
    "uniform float4x4 worldViewProj)\n"
    "{\n"
    "    oPosition = mul(worldViewProj, position);\n"
    "}\n";
    String customCasterMatFp = 
    "void customCasterFp(\n"
    "out float4 oColor : COLOR)\n"
    "{\n"
    "    oColor = float4(1,1,0,1); // just a test\n"
    "}\n";
    
    HighLevelGpuProgramPtr vp = HighLevelGpuProgramManager::getSingleton()
    .createProgram("CustomShadowCasterVp", 
    TRANSIENT_RESOURCE_GROUP, 
    "cg", GPT_VERTEX_PROGRAM);
    vp->setSource(customCasterMatVp);
    vp->setParameter("profiles", "vs_1_1 arbvp1");
    vp->setParameter("entry_point", "customCasterVp");
    vp->load();
    
    HighLevelGpuProgramPtr fp = HighLevelGpuProgramManager::getSingleton()
    .createProgram("CustomShadowCasterFp", 
    TRANSIENT_RESOURCE_GROUP, 
    "cg", GPT_FRAGMENT_PROGRAM);
    fp->setSource(customCasterMatFp);
    fp->setParameter("profiles", "ps_1_1 arbfp1");
    fp->setParameter("entry_point", "customCasterFp");
    fp->load();
    
    MaterialPtr mat = MaterialManager::getSingleton().create("CustomShadowCaster", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setVertexProgram("CustomShadowCasterVp");
    p->getVertexProgramParameters()->setNamedAutoConstant(
    "worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
    p->setFragmentProgram("CustomShadowCasterFp");
    
    mSceneMgr->setShadowTextureCasterMaterial("CustomShadowCaster");
    
    
    
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_TextureShadowsCustomReceiverMat::PlayPen_TextureShadowsCustomReceiverMat()
{
    mInfo["Title"] = "PlayPen_TextureShadowsCustomReceiverMat";
    mInfo["Description"] = "Tests texture shadows with a custom receiver material.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_TextureShadowsCustomReceiverMat::setupContent()
{
    PlayPen_TextureShadows::setupContent();
    
    String customReceiverMatVp = 
    "void customReceiverVp(float4 position : POSITION,\n"
    "out float4 oPosition : POSITION,\n"
    "out float2 oUV : TEXCOORD0,\n"
    "uniform float4x4 texViewProj,\n"
    "uniform float4x4 worldViewProj)\n"
    "{\n"
    "    oPosition = mul(worldViewProj, position);\n"
    "    float4 suv = mul(texViewProj, position);\n"
    "    oUV = suv.xy / suv.w;\n"
    "}\n";
    String customReceiverMatFp = 
    "void customReceiverFp(\n"
    "float2 uv : TEXCOORD0,\n"
    "uniform sampler2D shadowTex : register(s0),\n"
    "out float4 oColor : COLOR)\n"
    "{\n"
    "    float4 shadow = tex2D(shadowTex, uv);\n"
    "    oColor = shadow * float4(1,0,1,1); // just a test\n"
    "}\n";
    
    HighLevelGpuProgramPtr vp = HighLevelGpuProgramManager::getSingleton()
    .createProgram("CustomShadowReceiverVp", 
    TRANSIENT_RESOURCE_GROUP, 
    "cg", GPT_VERTEX_PROGRAM);
    vp->setSource(customReceiverMatVp);
    vp->setParameter("profiles", "vs_1_1 arbvp1");
    vp->setParameter("entry_point", "customReceiverVp");
    vp->load();
    
    HighLevelGpuProgramPtr fp = HighLevelGpuProgramManager::getSingleton()
    .createProgram("CustomShadowReceiverFp", 
    TRANSIENT_RESOURCE_GROUP, 
    "cg", GPT_FRAGMENT_PROGRAM);
    fp->setSource(customReceiverMatFp);
    fp->setParameter("profiles", "ps_1_1 arbfp1");
    fp->setParameter("entry_point", "customReceiverFp");
    fp->load();
    
    MaterialPtr mat = MaterialManager::getSingleton().create("CustomShadowReceiver", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* p = mat->getTechnique(0)->getPass(0);
    p->setVertexProgram("CustomShadowReceiverVp");
    p->getVertexProgramParameters()->setNamedAutoConstant(
    "worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
    p->getVertexProgramParameters()->setNamedAutoConstant(
    "texViewProj", GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX);
    p->setFragmentProgram("CustomShadowReceiverFp");
    p->createTextureUnitState(); // shadow texture will populate
    
    mSceneMgr->setShadowTextureReceiverMaterial("CustomShadowReceiver");
    
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_TextureShadowsIntegrated::PlayPen_TextureShadowsIntegrated()
{
    mInfo["Title"] = "PlayPen_TextureShadowsIntegrated";
    mInfo["Description"] = "Tests integrated texture shadows.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_TextureShadowsIntegrated::cleanupContent()
{
    clearDebugTextureOverlays();
}
//----------------------------------------------------------------------------

void PlayPen_TextureShadowsIntegrated::setupContent()
{
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
    //mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
    MaterialManager::getSingleton().setDefaultTextureFiltering(TFO_ANISOTROPIC);
    MaterialManager::getSingleton().setDefaultAnisotropy(5);
    
    mSceneMgr->setShadowTextureSettings(1024, 2);
    
    mSceneMgr->setAmbientLight(ColourValue::Black);
    Light* l = mSceneMgr->createLight("Spot1");
    l->setType(Light::LT_SPOTLIGHT);
    l->setAttenuation(5000,1,0,0);
    l->setSpotlightRange(Degree(30),Degree(45),1.0f);
    SceneNode* lightNode1 = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    lightNode1->attachObject(l);
    lightNode1->setPosition(400, 250, 500);
    lightNode1->lookAt(Vector3(0,-200,0), Node::TS_WORLD);
    l->setDirection(Vector3::NEGATIVE_UNIT_Z);
    l->setDiffuseColour(0.7, 0.7, 0.5);
    
    l = mSceneMgr->createLight("Spot2");
    l->setAttenuation(5000,1,0,0);
    /* // spotlight */
    l->setType(Light::LT_SPOTLIGHT);
    l->setSpotlightRange(Degree(30),Degree(45),1.0f);
    /**/
    // point
    SceneNode* lightNode2 = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    lightNode2->attachObject(l);
    lightNode2->setPosition(-500, 200, 500);
    lightNode2->lookAt(Vector3(0,-200,0), Node::TS_WORLD);
    l->setDirection(Vector3::NEGATIVE_UNIT_Z);
    /* // directional
    l->setType(Light::LT_DIRECTIONAL);
    Vector3 dir(0.5, -1, 0.5);
    dir.normalise();
    l->setDirection(dir);
    */
    l->setDiffuseColour(1, 0.2, 0.2);
    
    /*
    // Test spot 3
    l = mSceneMgr->createLight("Spot3");
    l->setType(Light::LT_SPOTLIGHT);
    l->setAttenuation(5000,1,0,0);
    l->setSpotlightRange(Degree(30),Degree(45),1.0f);
    SceneNode* lightNode3 = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    lightNode3->attachObject(l);
    lightNode3->setPosition(700, 250, 500);
    lightNode3->lookAt(Vector3(0,-200,0), Node::TS_WORLD);
    l->setDirection(Vector3::NEGATIVE_UNIT_Z);
    l->setDiffuseColour(0.0, 0.7, 1.0);
    */
    
    // Create a basic plane to have something in the scene to look at
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshPtr msh = MeshManager::getSingleton().createPlane("Myplane_IS",
    TRANSIENT_RESOURCE_GROUP, plane,
    4500,4500,100,100,true,1,40,40,Vector3::UNIT_Z);
    msh->buildTangentVectors(VES_TANGENT);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane_IS" );
    //pPlaneEnt->setMaterialName("Examples/OffsetMapping/Specular");
    pPlaneEnt->setMaterialName("Examples/OffsetMapping/IntegratedShadows");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    pPlaneEnt = mSceneMgr->createEntity( "plane2", "Myplane_IS" );
    //pPlaneEnt->setMaterialName("Examples/OffsetMapping/Specular");
    pPlaneEnt->setMaterialName("Examples/OffsetMapping/IntegratedShadows");
    pPlaneEnt->setCastShadows(false);
    SceneNode* n = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    n->roll(Degree(90));
    n->translate(100,0,0);
    //n->attachObject(pPlaneEnt);
    
    pPlaneEnt = mSceneMgr->createEntity( "plane3", "Myplane_IS" );
    //pPlaneEnt->setMaterialName("Examples/OffsetMapping/Specular");
    pPlaneEnt->setMaterialName("Examples/OffsetMapping/IntegratedShadows");
    pPlaneEnt->setCastShadows(false);
    n = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    n->pitch(Degree(90));
    n->yaw(Degree(-90));
    n->translate(0,0,-100);
    n->attachObject(pPlaneEnt);
    
    mCamera->setPosition(-50, 500, 1000);
    mCamera->lookAt(Vector3(-50,-100,0));
    
    Entity* ent = mSceneMgr->createEntity("athene", "athene.mesh");
    ent->setMaterialName("Examples/Athene/NormalMapped");
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0,-20,0))->attachObject(ent);
    
    addTextureShadowDebugOverlay(2, mSceneMgr);
    
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_TextureShadowsIntegratedPSSM::PlayPen_TextureShadowsIntegratedPSSM()
{
    mInfo["Title"] = "PlayPen_TextureShadowsIntegratedPSSM";
    mInfo["Description"] = "Tests integrated parallel split shadow mapping.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_TextureShadowsIntegratedPSSM::cleanupContent()
{
    clearDebugTextureOverlays();
}
//----------------------------------------------------------------------------

void PlayPen_TextureShadowsIntegratedPSSM::setupContent()
{
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
    
    // 3 textures per directional light
    mSceneMgr->setShadowTextureCountPerLightType(Ogre::Light::LT_DIRECTIONAL, 3);
    mSceneMgr->setShadowTextureSettings(512, 3, PF_FLOAT32_R);
    mSceneMgr->setShadowTextureSelfShadow(true);
    // Set up caster material - this is just a standard depth/shadow map caster
    mSceneMgr->setShadowTextureCasterMaterial("PSSM/shadow_caster");
    
    // shadow camera setup
    PSSMShadowCameraSetup* pssmSetup = new PSSMShadowCameraSetup();
    pssmSetup->calculateSplitPoints(3, mCamera->getNearClipDistance(), mCamera->getFarClipDistance());
    pssmSetup->setSplitPadding(10);
    pssmSetup->setOptimalAdjustFactor(0, 2);
    pssmSetup->setOptimalAdjustFactor(1, 1);
    pssmSetup->setOptimalAdjustFactor(2, 0.5);
    
    mSceneMgr->setShadowCameraSetup(ShadowCameraSetupPtr(pssmSetup));
    
    
    mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));
    Light* l = mSceneMgr->createLight("Dir");
    l->setType(Light::LT_DIRECTIONAL);
    Vector3 dir(0.3, -1, 0.2);
    dir.normalise();
    l->setDirection(dir);
    
    
    // Create a basic plane to have something in the scene to look at
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshPtr msh = MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    4500,4500,100,100,true,1,40,40,Vector3::UNIT_Z);
    msh->buildTangentVectors(VES_TANGENT);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("PSSM/Plane");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    mCamera->setPosition(-50, 500, 1000);
    mCamera->lookAt(Vector3(-50,-100,0));
    
    Entity* ent = mSceneMgr->createEntity("knot", "knot.mesh");
    ent->setMaterialName("PSSM/Knot");
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0,0,0))->attachObject(ent);
    createRandomEntityClones(ent, 20, Vector3(-1000,0,-1000), Vector3(1000,0,1000), mSceneMgr);
    
    
    Vector4 splitPoints;
    const PSSMShadowCameraSetup::SplitPointList& splitPointList = pssmSetup->getSplitPoints();
    for (int i = 0; i < 3; ++i)
    {
        splitPoints[i] = splitPointList[i];
    }
    MaterialPtr mat = MaterialManager::getSingleton().getByName("PSSM/Plane").staticCast<Material>();
    mat->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("pssmSplitPoints", splitPoints);
    mat = MaterialManager::getSingleton().getByName("PSSM/Knot").staticCast<Material>();
    mat->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("pssmSplitPoints", splitPoints);
    
    addTextureShadowDebugOverlay(3, mSceneMgr);
    
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_TextureShadowsTransparentCaster::PlayPen_TextureShadowsTransparentCaster()
{
    mInfo["Title"] = "PlayPen_TextureShadowsTransparentCaster";
    mInfo["Description"] = "Tests transparent shadow casters.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_TextureShadowsTransparentCaster::setupContent()
{
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE);
    
    
    LiSPSMShadowCameraSetup *mLiSPSMSetup = new LiSPSMShadowCameraSetup();
    //mLiSPSMSetup->setUseAggressiveFocusRegion(false);
    ShadowCameraSetupPtr mCurrentShadowCameraSetup = ShadowCameraSetupPtr(mLiSPSMSetup);
    //ShadowCameraSetupPtr mCurrentShadowCameraSetup = ShadowCameraSetupPtr(new PlaneOptimalShadowCameraSetup(mPlane));                    
    mSceneMgr->setShadowCameraSetup(mCurrentShadowCameraSetup);
    
    PixelFormat pxFmt = PF_L8;
    if (Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_TEXTURE_FLOAT))
    {
        if (Root::getSingleton().getRenderSystem()->getName().find("GL") != String::npos)
        {
            // GL performs much better if you pick half-float format
            pxFmt = PF_FLOAT16_R;
        }
        else
        {
            // D3D is the opposite - if you ask for PF_FLOAT16_R you
            // get an integer format instead! You can ask for PF_FLOAT16_GR
            // but the precision doesn't work well
            pxFmt = PF_FLOAT32_R;
        }
    }
    mSceneMgr->setShadowTextureSettings(1024, 1, pxFmt);
    
    // New depth shadow mapping
    String CUSTOM_ROCKWALL_MATERIAL("Ogre/DepthShadowmap/Receiver/RockWall");
    String CUSTOM_CASTER_MATERIAL("Ogre/DepthShadowmap/Caster/Float");
    String CUSTOM_RECEIVER_MATERIAL("Ogre/DepthShadowmap/Receiver/Float");
    
    mSceneMgr->setShadowTextureCasterMaterial(CUSTOM_CASTER_MATERIAL);
    mSceneMgr->setShadowTextureReceiverMaterial(CUSTOM_RECEIVER_MATERIAL);
    mSceneMgr->setShadowTextureSelfShadow(true);
    
    mSceneMgr->setShadowTextureFadeStart(1.0);
    mSceneMgr->setShadowTextureFadeEnd(1.0);
    
    mSceneMgr->setShadowTextureSelfShadow(true);
    
    MaterialManager::getSingleton().setDefaultTextureFiltering(TFO_ANISOTROPIC);
    MaterialManager::getSingleton().setDefaultAnisotropy(5);
    
    mSceneMgr->setShadowDirLightTextureOffset(0.2);
    mSceneMgr->setShadowFarDistance(150);
    //mSceneMgr->setShadowCasterRenderBackFaces(false);
    
    // Create a basic plane to have something in the scene to look at
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    MeshPtr msh = MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    4500,4500,100,100,true,1,40,40,Vector3::UNIT_Z);
    msh->buildTangentVectors(VES_TANGENT);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    
    pPlaneEnt->setMaterialName(CUSTOM_ROCKWALL_MATERIAL);
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    
    
    // Reorient the plane and create a plane mesh for the test planes
    plane.normal = Vector3::UNIT_Z;
    MeshManager::getSingleton().createPlane(
    "Test_Plane", TRANSIENT_RESOURCE_GROUP, 
    plane, 50.0, 50.0, 1, 1, true);
    
    
    const String GRASSMAT("Examples/GrassBladesAdditiveFloatTransparent");
    //const String GRASSMAT("Examples/DepthShadowmap/CasterReceiver/GrassBlades");
    //const String GRASSMAT("tree4324");//"tree1.tga");
    
    
    // Add test plane entities to the scene
    Entity* entity = mSceneMgr->createEntity("GrassBlades0", "Test_Plane");
    entity->setMaterialName(GRASSMAT);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(0.0, -100.0+25.0, 0.0))->attachObject(entity);
    
    
    entity = mSceneMgr->createEntity("GrassBlades1", "Test_Plane");
    entity->setMaterialName(GRASSMAT);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(0.0, -100.0+25.0, -20.0))->attachObject(entity);
    
    entity = mSceneMgr->createEntity("GrassBlades2", "Test_Plane");
    entity->setMaterialName(GRASSMAT);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(0.0, -100.0+25.0, -40.0))->attachObject(entity);
    
    // Add test plane entities to the scene, shadowed partially by athene mesh
    entity = mSceneMgr->createEntity("GrassBlades3", "Test_Plane");
    entity->setMaterialName(GRASSMAT);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(-80.0, -100.0+25.0, 0.0))->attachObject(entity);
    
    entity = mSceneMgr->createEntity("GrassBlades4", "Test_Plane");
    entity->setMaterialName(GRASSMAT);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(-130.0, -100.0+25.0, -20.0))->attachObject(entity);
    
    entity = mSceneMgr->createEntity("GrassBlades5", "Test_Plane");
    entity->setMaterialName(GRASSMAT);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(-180.0, -100.0+25.0, -40.0))->attachObject(entity);
    
    
    
    Entity* ent = mSceneMgr->createEntity("athene", "athene.mesh");
    ent->setMaterialName(CUSTOM_ROCKWALL_MATERIAL);
    //ent->setMaterialName(GRASSMAT);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0,-20,-20))->attachObject(ent);
    
    // Add test plane entities to the scene, one after another
    entity = mSceneMgr->createEntity("GrassBlades6", "Test_Plane");
    entity->setMaterialName(GRASSMAT);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(-260.0, -100.0+25.0, 0.0))->attachObject(entity);
    
    entity = mSceneMgr->createEntity("GrassBlades7", "Test_Plane");
    entity->setMaterialName(GRASSMAT);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(-260.0, -100.0+25.0, -10.0))->attachObject(entity);
    
    entity = mSceneMgr->createEntity("GrassBlades8", "Test_Plane");
    entity->setMaterialName(GRASSMAT);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(-260.0, -100.0+25.0, -20.0))->attachObject(entity);
    
    // Add test plane entities to the scene, alone with other material
    
    const String GRASSMAT_CUSTOM_DEFAULT_CUSTOM("Examples/GrassBladesAdditiveFloat");
    const String GRASSMAT_CUSTOM_NOSPECIAL_CUSTOM("Examples/GrassBladesAdditive");        
    const String GRASSMAT_ORIG("Examples/GrassBlades");
    
    entity = mSceneMgr->createEntity("GrassBlades9", "Test_Plane");
    entity->setMaterialName(GRASSMAT_CUSTOM_DEFAULT_CUSTOM);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(-80.0, -100.0+25.0, -80.0))->attachObject(entity);
    
    entity = mSceneMgr->createEntity("GrassBlades10", "Test_Plane");
    entity->setMaterialName(GRASSMAT_CUSTOM_NOSPECIAL_CUSTOM);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(-130.0, -100.0+25.0, -90.0))->attachObject(entity);
    
    entity = mSceneMgr->createEntity("GrassBlades11", "Test_Plane");
    entity->setMaterialName(GRASSMAT_ORIG);
    mSceneMgr->getRootSceneNode()->createChildSceneNode(
    Vector3(-180.0, -100.0+25.0, -90.0))->attachObject(entity);
    
    // Position and orient the camera
    //mCamera->setPosition(-55.0, 40.0, 100.0);
    //mCamera->lookAt(-10.0, 20.0, -35.0);
    //mCamera->setPosition(-75.0, 30.0, 150.0);
    //mCamera->lookAt(0.0, 20.0, -35.0);
    mCamera->setPosition(100,50,150);
    mCamera->lookAt(0,0,0);
    
    //mSceneMgr->setAmbientLight(ColourValue::Black);
    Light* l;
    
    l = mSceneMgr->createLight("Dir1");
    l->setType(Light::LT_DIRECTIONAL);
    //l->setAttenuation(5000,1,0,0);
    Vector3 dir1(0.0, -0.7, -0.5);
    dir1.normalise();
    l->setDirection(dir1);
    l->setCastShadows(true);
    
    l->setDiffuseColour(ColourValue(1.0, 1.0, 1.0));
    
    
    mSceneMgr->setAmbientLight(ColourValue(0.0, 0.0, 0.2));
    
    //         l = mSceneMgr->createLight("Spot2");
    //         l->setAttenuation(5000,1,0,0);
    //         /* // spotlight */
    //         l->setType(Light::LT_SPOTLIGHT);
    //         l->setSpotlightRange(Degree(30),Degree(45),1.0f);
    //         
    //         
    //         SceneNode* lightNode2 = mSceneMgr->getRootSceneNode()->createChildSceneNode();
    //         lightNode2->attachObject(l);
    //         lightNode2->setPosition(-500, 200, 500);
    //         lightNode2->lookAt(Vector3(0,-200,0), Node::TS_WORLD);
    //         l->setDirection(Vector3::NEGATIVE_UNIT_Z);
    //lightNode2->setPosition(-75.0, 30.0, 150.0);
    //lightNode2->lookAt(Vector3(.0, 20.0, -35.0), Node::TS_WORLD);
    
    
    //addTextureShadowDebugOverlay(1, mSceneMgr);
    
    // not completely necessary, and can't guarantee determinism easily
    //Root::getSingleton().addFrameListener(new GrassListener(mSceneMgr));
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_TransparencyMipMaps::PlayPen_TransparencyMipMaps()
{
    mInfo["Title"] = "PlayPen_TransparencyMipMaps";
    mInfo["Description"] = "Tests transparent materials with mipmaps.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_TransparencyMipMaps::setupContent()
{
    MaterialPtr mat = MaterialManager::getSingleton().create("test", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    // known png with alpha
    Pass* pass = mat->getTechnique(0)->getPass(0);
    pass->createTextureUnitState("sdk_logo.png");
    pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
    // alpha blend
    pass->setDepthWriteEnabled(false);
    
    // alpha reject
    //pass->setDepthWriteEnabled(true);
    //pass->setAlphaRejectSettings(CMPF_LESS, 128);
    
    // Define a floor plane mesh
    Plane p;
    p.normal = Vector3::UNIT_Y;
    p.d = 200;
    MeshManager::getSingleton().createPlane("FloorPlane",
    TRANSIENT_RESOURCE_GROUP,
    p,2000,2000,1,1,true,1,5,5,Vector3::UNIT_Z);
    
    // Create an entity (the floor)
    Entity* ent = mSceneMgr->createEntity("floor", "FloorPlane");
    ent->setMaterialName("test");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
    
    mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);
    mSceneMgr->setAmbientLight(ColourValue::White);
    
    
    {
        
        Real alphaLevel = 0.5f;
        MaterialPtr alphamat = MaterialManager::getSingleton().create("testy", 
        TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
        Pass* alphaPass = alphamat->getTechnique(0)->getPass(0);
        alphaPass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
        alphaPass->setDepthWriteEnabled(false);
        TextureUnitState* t = pass->createTextureUnitState();
        t->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, alphaLevel);
        
        ent = mSceneMgr->createEntity("asd", "ogrehead.mesh");
        ent->setMaterialName("testy");
        mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
        
    }

    mCamera->setPosition(0,0,1000);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_VertexTexture::PlayPen_VertexTexture()
{
    mInfo["Title"] = "PlayPen_VertexTexture";
    mInfo["Description"] = "Tests vertex texture rendering (DX only).";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_VertexTexture::setupContent()
{
    
    // NOTE: DirectX only right now
    
    Light* l = mSceneMgr->createLight("MainLight");
    l->setType(Light::LT_POINT);
    l->setPosition(0, 200, 0);
    
    
    // Create single-channel floating point texture, no mips
    TexturePtr tex = TextureManager::getSingleton().createManual(
    "vertexTexture", TRANSIENT_RESOURCE_GROUP, TEX_TYPE_2D, 
    128, 128, 0, PF_FLOAT32_R);
    float* pData = static_cast<float*>(
    tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD));
    // write concentric circles into the texture
    for (int y  = -64; y < 64; ++y)
    {
        for (int x = -64; x < 64; ++x)
        {
            
            float val = Math::Sqrt(x*x + y*y);
            // repeat every 20 pixels
            val = val * Math::TWO_PI / 20.0f;
            *pData++ = Math::Sin(val);
        }
    }
    tex->getBuffer()->unlock();
    
    String progSource = 
    "void main(\n"
    "float4 pos : POSITION,\n"
    "float2 uv1 : TEXCOORD0,\n"
    "uniform float4x4 world, \n"
    "uniform float4x4 viewProj,\n"
    "uniform float heightscale,\n"
    "uniform sampler2D heightmap,\n"
    "out float4 oPos : POSITION,\n"
    "out float2 oUv1 : TEXCOORD1,\n"
    "out float4 col : COLOR)\n"
    "{\n"
    "oPos = mul(world, pos);\n"
    "// tex2Dlod since no mip\n"
    "float4 t = float4(0,0,0,0);\n"
    "t.xy = uv1.xy;\n"
    "float height = tex2Dlod(heightmap, t);\n"
    "oPos.y = oPos.y + (height * heightscale);\n"
    "oPos = mul(viewProj, oPos);\n"
    "oUv1 = uv1;\n"
    "col = float4(1,1,1,1);\n"
    "}\n";
    HighLevelGpuProgramPtr prog = HighLevelGpuProgramManager::getSingleton().createProgram(
    "TestVertexTextureFetch", TRANSIENT_RESOURCE_GROUP, 
    "hlsl", GPT_VERTEX_PROGRAM);
    prog->setSource(progSource);
    prog->setParameter("target", "vs_3_0");
    prog->setVertexTextureFetchRequired(true);
    prog->setParameter("entry_point", "main");
    prog->load();
    
    
    MaterialPtr mat = MaterialManager::getSingleton().create("TestVertexTexture", 
    TRANSIENT_RESOURCE_GROUP).staticCast<Material>();
    Pass* pass = mat->getTechnique(0)->getPass(0);
    pass->setLightingEnabled(false);
    pass->setVertexProgram("TestVertexTextureFetch");
    GpuProgramParametersSharedPtr vp = pass->getVertexProgramParameters();
    vp->setNamedAutoConstant("world", GpuProgramParameters::ACT_WORLD_MATRIX);
    vp->setNamedAutoConstant("viewProj", GpuProgramParameters::ACT_VIEWPROJ_MATRIX);
    vp->setNamedConstant("heightscale", 30.0f);
    // vertex texture
    TextureUnitState* t = pass->createTextureUnitState("vertexTexture");
    t->setBindingType(TextureUnitState::BT_VERTEX);
    // regular texture
    pass->createTextureUnitState("BumpyMetal.jpg");
    
    Plane plane;
    plane.normal = Vector3::UNIT_Y;
    plane.d = 100;
    // 128 x 128 segment plane
    MeshManager::getSingleton().createPlane("Myplane",
    TRANSIENT_RESOURCE_GROUP, plane,
    1500,1500,128,128,true,1,1,1,Vector3::UNIT_Z);
    Entity* pPlaneEnt;
    pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
    pPlaneEnt->setMaterialName("TestVertexTexture");
    pPlaneEnt->setCastShadows(false);
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
    
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_ViewportNoShadows::PlayPen_ViewportNoShadows()
{
    mInfo["Title"] = "PlayPen_ViewportNoShadows";
    mInfo["Description"] = "Tests disabling shadows for a viewport.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_ViewportNoShadows::setupContent()
{
    mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE);
    
    // Setup lighting
    mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
    Light* light = mSceneMgr->createLight("MainLight");
    light->setType(Light::LT_DIRECTIONAL);
    Vector3 dir(-1, -1, 0.5);
    dir.normalise();
    light->setDirection(dir);
    
    // Create a skydome
    //mSceneMgr->setSkyDome(true, "Examples/CloudySky", 5, 8);
    
    // Create a floor plane mesh
    Plane plane(Vector3::UNIT_Y, 0.0);
    MeshManager::getSingleton().createPlane(
    "FloorPlane", TRANSIENT_RESOURCE_GROUP,
    plane, 200000, 200000, 20, 20, true, 1, 500, 500, Vector3::UNIT_Z);
    
    
    // Add a floor to the scene
    Entity* entity = mSceneMgr->createEntity("floor", "FloorPlane");
    entity->setMaterialName("Examples/RustySteel");
    mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(entity);
    entity->setCastShadows(false);
    
    // Add the mandatory ogre head
    entity = mSceneMgr->createEntity("head", "ogrehead.mesh");
    mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0.0, 10.0, 0.0))->attachObject(entity);
    
    // Position and orient the camera
    mCamera->setPosition(-100.0, 50.0, 90.0);
    mCamera->lookAt(0.0, 10.0, -35.0);
    
    // Add an additional viewport on top of the other one
    Viewport* pip = mWindow->addViewport(mCamera, 1, 0.7, 0.0, 0.3, 0.3);
    pip->setShadowsEnabled(false);
    
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------

PlayPen_WindowedViewportMode::PlayPen_WindowedViewportMode()
{
    mInfo["Title"] = "PlayPen_WindowedViewportMode";
    mInfo["Description"] = "Tests windowed viewport.";
    addScreenshotFrame(10);
}
//----------------------------------------------------------------------------

void PlayPen_WindowedViewportMode::setupContent()
{
    Ogre::SceneNode* mTestNode[5];

    // Set ambient light
    mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
    
    // Create a point light
    Light* l = mSceneMgr->createLight("MainLight");
    l->setType(Light::LT_DIRECTIONAL);
    l->setDirection(-Vector3::UNIT_Y);
    
    mTestNode[0] = (SceneNode*)mSceneMgr->getRootSceneNode()->createChild();
    
    Entity* pEnt = mSceneMgr->createEntity( "1", "ogrehead.mesh" );
    mTestNode[0]->attachObject( pEnt );
    
    mCamera->setWindow(0,0,0.5,0.5);
    

    mCamera->setPosition(0,0,125);
}

//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

void addTextureDebugOverlay(const Ogre::String& texname, size_t i)
{
    Ogre::Overlay* debugOverlay = Ogre::OverlayManager::getSingleton().getByName("Core/DebugOverlay");

    if(!debugOverlay)
        debugOverlay = Ogre::OverlayManager::getSingleton().create("Core/DebugOverlay");

    debugOverlay->show();

    // Set up a debug panel to display the shadow
    Ogre::MaterialPtr debugMat = Ogre::MaterialManager::getSingleton().create(
        "Ogre/DebugTexture" + Ogre::StringConverter::toString(i), 
        "VisualTestTransient").staticCast<Material>();
    debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
    Ogre::TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(texname);
    t->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP);
    //t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState("spot_shadow_fade.png");
    //t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
    //t->setColourOperation(LBO_ADD);
    

    Ogre::OverlayContainer* debugPanel = (Ogre::OverlayContainer*)
        (Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + Ogre::StringConverter::toString(i)));
    debugPanel->_setPosition(0.8, i*0.25);
    debugPanel->_setDimensions(0.2, 0.24);
    debugPanel->setMaterialName(debugMat->getName());
    debugOverlay->add2D(debugPanel);

}
//-----------------------------------------------------------------------

void clearDebugTextureOverlays()
{
    Ogre::Overlay* debugOverlay = Ogre::OverlayManager::getSingleton().getByName("Core/DebugOverlay");

    if(debugOverlay)
        Ogre::OverlayManager::getSingleton().destroy("Core/DebugOverlay");
        //debugOverlay->hide();

    for(int i = 0; i < 10; ++i)
    {
        if(Ogre::OverlayManager::getSingleton().hasOverlayElement( 
        "Ogre/DebugTexPanel" + Ogre::StringConverter::toString(i)))
        {
            OverlayManager::getSingleton().destroyOverlayElement(
                "Ogre/DebugTexPanel" + Ogre::StringConverter::toString(i));
            Ogre::MaterialManager::getSingleton().remove("Ogre/DebugTexture" + Ogre::StringConverter::toString(i));
        }
    }
}
//-----------------------------------------------------------------------

void addTextureDebugOverlay(Ogre::TexturePtr tex, size_t i)
{
    addTextureDebugOverlay(tex->getName(), i);
}
//-----------------------------------------------------------------------

void addTextureShadowDebugOverlay(size_t num, Ogre::SceneManager* mgr)
{
    for (size_t i = 0; i < num; ++i)
    {
        Ogre::TexturePtr shadowTex = mgr->getShadowTexture(i);
        addTextureDebugOverlay(shadowTex, i);
    }
}
//-----------------------------------------------------------------------
