text: /*
    -----------------------------------------------------------------------------
    This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
    For the latest info, see http://www.ogre3d.org/
  
  Copyright (c) 2000-2014 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"
  #include "OgreLodConfig.h"
  #include "OgreMovablePlane.h"
  #include "OgreRectangle2D.h"
  #include "OgreMovableObject.h"
  #include "OgreBillboard.h"
  #include "OgreParticleSystem.h"
  
  #ifdef OGRE_BUILD_COMPONENT_MESHLODGENERATOR
  #include "OgreMeshLodGenerator.h"
  #endif
  
  using namespace Ogre;
  
  static void createRandomEntityClones(Entity* ent, size_t cloneCount,
      const Vector3& min, const Vector3& max, SceneManager* mgr);
  
  #ifdef OGRE_BUILD_COMPONENT_MESHLODGENERATOR
  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
          SceneNode* n = mSceneMgr->getRootSceneNode()->createChildSceneNode(
              Vector3(0, 0, (i * 50) - (5 * 50 / 2)));
          n->setScale(0.2, 0.2, 0.2);
          n->attachObject(ent);
      }
  
      mAnimation = ent->getAnimationState("Walk");
      mAnimation->setEnabled(true);
  
      // Give it a little ambience with lights
      Light* l;
      l = mSceneMgr->createLight("BlueLight");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-200,-80,-100))->attachObject(l);
      l->setDiffuseColour(0.5, 0.5, 1.0);
  
      l = mSceneMgr->createLight("GreenLight");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0,0,-100))->attachObject(l);
      l->setDiffuseColour(0.5, 1.0, 0.5);
  
      // Position the camera
      mCameraNode->setPosition(100,25,100);
      mCameraNode->lookAt(Vector3(-50, 0, -25), Node::TS_PARENT);
  
      mSceneMgr->setAmbientLight(ColourValue::White);
  }
  //---------------------------------------------------------------------------
  
  bool PlayPen_ManualLOD::frameStarted(const FrameEvent& evt)
  {
      mAnimation->addTime(evt.timeSinceLastFrame);
      return true;
  }
  //-----------------------------------------------------------------------
  
  String PlayPen_ManualLOD::getLODMesh()
  {
      MeshPtr msh1 = MeshManager::getSingleton().load("robot.mesh", ASSETS_RESOURCE_GROUP);
  
      LodConfig lodConfig(msh1);
      lodConfig.createManualLodLevel(136, "razor.mesh");
      lodConfig.createManualLodLevel(211, "sphere.mesh");
      MeshLodGenerator().generateLodLevels(lodConfig);
  
      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 = MeshManager::getSingleton().load("robot.mesh", ASSETS_RESOURCE_GROUP);
  
      LodConfig lodConfig(msh1);
      lodConfig.createManualLodLevel(136, "razor.mesh");
      lodConfig.createManualLodLevel(211, "sphere.mesh");
      MeshLodGenerator().generateLodLevels(lodConfig);
  
      // this time, we save this data to a file and re-load it
  
      MeshSerializer ser;
      const ResourceGroupManager::LocationList& ll =
          ResourceGroupManager::getSingleton().getResourceLocationList("Tests");
      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";
  }
  #endif
  //---------------------------------------------------------------------------
  //---------------------------------------------------------------------------
  
  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);
      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");
  
      mCameraNode->setPosition(0,0,600);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  }
  //---------------------------------------------------------------------
  //---------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,3000,5000);
      mCameraNode->lookAt(mProjectionSphere->getCenter(), Node::TS_PARENT);
  
  }
  //---------------------------------------------------------------------------
  
  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);
  
  
      mCameraNode->setPosition(200,1000,1000);
      mCameraNode->lookAt(mFocus, Node::TS_PARENT);
  
      //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)
  {
      mCameraNode->lookAt(mFocus, Node::TS_PARENT);
  }
  //---------------------------------------------------------------------
  
  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)
              mCameraNode->setFixedYawAxis(true);
          else
              mCameraNode->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", ASSETS_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, false, false);
  
      DataStreamPtr stream = resMgr.createResource(morphName, TRANSIENT_RESOURCE_GROUP);
      MeshSerializer ser;
      ser.exportMesh(mesh.get(), stream);
      stream->close();
  
      // Unload old mesh to force reload
      MeshManager::getSingleton().remove(mesh->getHandle());
      mesh->unload();
      mesh.reset();
  
      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;
  
      resMgr.deleteResource(morphName, TRANSIENT_RESOURCE_GROUP);
  
      mCamera->setNearClipDistance(0.5);
      mCameraNode->setPosition(0,100,-400);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
      //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);
  
      // Add resource location for exported mesh
      String exportName = mFSLayer->getWritablePath(morphName);
      String path;
      StringUtil::splitFilename(exportName, morphName, path);
      ResourceGroupManager::getSingleton().addResourceLocation(path, "FileSystem", TRANSIENT_RESOURCE_GROUP, false, false);
  
      // Export the mesh
      DataStreamPtr stream = ResourceGroupManager::getSingleton().createResource(morphName, TRANSIENT_RESOURCE_GROUP);
      MeshSerializer ser;
      ser.exportMesh(mesh.get(), stream);
      stream->close();
  
  
      // Unload old mesh to force reload
      MeshManager::getSingleton().remove(mesh->getHandle());
      mesh->unload();
      mesh.reset();
  
      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;
  
      ResourceGroupManager::getSingleton().deleteResource(morphName, TRANSIENT_RESOURCE_GROUP);
  
      mCamera->setNearClipDistance(0.5);
      mCameraNode->setPosition(0,100,-400);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
      // 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", ASSETS_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, false, false);
      DataStreamPtr stream = resMgr.createResource(newName, TRANSIENT_RESOURCE_GROUP);
      MeshSerializer ser;
      ser.exportMesh(mesh.get(), stream);
      stream->close();
  
      // Unload old mesh to force reload
      MeshManager::getSingleton().remove(mesh->getHandle());
      mesh->unload();
      mesh.reset();
  
      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;
  
      resMgr.deleteResource(newName, TRANSIENT_RESOURCE_GROUP);
  
      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);
  
      mCameraNode->setPosition(0,-200,-300);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  
  }
  //---------------------------------------------------------------------
  
  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", ASSETS_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, false, false);
  
      DataStreamPtr stream = resMgr.createResource(newName, TRANSIENT_RESOURCE_GROUP);
      MeshSerializer ser;
      ser.exportMesh(mesh.get(), stream);
      stream->close();
  
      // Unload old mesh to force reload
      MeshManager::getSingleton().remove(mesh->getHandle());
      mesh->unload();
      mesh.reset();
  
      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;
  
      resMgr.deleteResource(newName, TRANSIENT_RESOURCE_GROUP);
  
      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);
  
      mCameraNode->setPosition(0,-200,-300);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  }
  //---------------------------------------------------------------------------
  
  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
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(20,80,50))->attachObject(l);
  
      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);
  
      mCameraNode->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
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(20,80,50))->attachObject(l);
  
      createMeshEntity("Model1", Vector3(10, 10, 10));
      createMeshEntity("Model2", Vector3(-10, -10, -10));
  
      mCameraNode->setPosition(100,0,-100);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  }
  //-----------------------------------------------------------------------
  
  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::testCapabilities(const Ogre::RenderSystemCapabilities* caps) {
      if(caps->getNumTextureUnits() < 16)
          throw Ogre::Exception(999, "Needs 16 Texture Units to run", "testCapabilities");
  }
  
  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 130\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 100\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);
      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);
  
      mCameraNode->setPosition(0,0,250);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  
  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);
      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);
      mTestNode[1]->attachObject(mLight);
  
      Plane plane( Vector3::UNIT_Y, -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);
  
      mCameraNode->setPosition(-600,300,-600);
      mCameraNode->lookAt(Vector3(300, 0, 300), Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  
  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);
      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);
      t->setColourOperation(LBO_ALPHA_BLEND);
      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);
      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);
      t->setColourOperation(LBO_ALPHA_BLEND);
      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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-200,-80,-100))->attachObject(l);
      l->setDiffuseColour(0.5, 0.5, 1.0);
  
      l = mSceneMgr->createLight("GreenLight");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0,0,-100))->attachObject(l);
      l->setDiffuseColour(0.5, 1.0, 0.5);
  
      // Position the camera
      mCameraNode->setPosition(400,120,500);
      mCameraNode->lookAt(Vector3(-50, 50, 0), Node::TS_PARENT);
  
      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 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(Vector3::UNIT_Y, -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");
      // ent->setMaterialName("BaseWhiteNoLighting");
      // ent->setMaterialName("BaseWhite");
  
      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);
  
      //mCameraNode->lookAt(Vector3(1, 1, 1), Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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));
      Light* l = mSceneMgr->createLight("light1");
      l->setType(Light::LT_DIRECTIONAL);
      l->setDirection(Vector3(-1, -1, 0.5).normalisedCopy());
  
      Plane plane(Vector3::UNIT_Y, -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);
  
      mCameraNode->setPosition(200,120,300);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
  
      // BillboardChain does not calculate normals, so result will be inconsistent.
      //chain->setMaterialName("Examples/ShowNormals");
      mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(chain);
  
      mSceneMgr->showBoundingBoxes(true);
  
      mCameraNode->setPosition(-20,60,200);
      mCameraNode->lookAt(Vector3(60, 40, 0), Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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));
      
      // Billboards currently have no normals.
      // Vector3 dir(-1, -1, 0.5);
      // dir.normalise();
      // Light* l = mSceneMgr->createLight("light1");
      // l->setType(Light::LT_DIRECTIONAL);
      // l->setDirection(dir);
  
      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);
  
      mCameraNode->setPosition(0,160,1);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
  
      mCameraNode->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);
      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);
  
      mCameraNode->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", ASSETS_RESOURCE_GROUP);
  
      TexturePtr tex = TextureManager::getSingleton().createManual(
          "testblitdst",
          TRANSIENT_RESOURCE_GROUP, TEX_TYPE_2D, 1024, 1024, 1, 0, img.getFormat());
  
      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();
  
      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);
  
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
      mWindow->getViewport(0)->setBackgroundColour(ColourValue::Green);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  PlayPen_HardwareScaleBlit::PlayPen_HardwareScaleBlit()
  {
      mInfo["Title"] = "PlayPen_HardwareScaleBlit";
      mInfo["Description"] = "Tests blitting texture with hardware scaling.";
      addScreenshotFrame(10);
  }
  //----------------------------------------------------------------------------
  
  void PlayPen_HardwareScaleBlit::setupContent()
  {
      Image img;
      img.load("ogrelogo.png", ASSETS_RESOURCE_GROUP);
  
      TexturePtr tex = TextureManager::getSingleton().createManual(
          "testblitdst",
          TRANSIENT_RESOURCE_GROUP, TEX_TYPE_2D, 64, 64, 1, 0, img.getFormat());
  
      Box dstBox(0, 0, 64, 64);
      tex->getBuffer()->blitFromMemory(img.getPixelBox(), dstBox);
  
      MaterialPtr mat = MaterialManager::getSingleton().create(
          "testblit",
          TRANSIENT_RESOURCE_GROUP);
  
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
      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);
      mCameraNode->setPosition(vp.position);
      mCameraNode->pitch(Degree(90)); // Quake uses X/Y horizon, Z up
      mCameraNode->rotate(vp.orientation);
      // Don't yaw along variable axis, causes leaning
      mCameraNode->setFixedYawAxis(true, Vector3::UNIT_Z);
  
      mCameraNode->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);
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0, 200, 0))->attachObject(mLight);
      //*/
      MeshPtr pMesh = MeshManager::getSingleton().load("ninja.mesh", ASSETS_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");
      pEnt->getAnimationState("Walk")->setEnabled(true);
      mTestNode[1] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
      mTestNode[1]->attachObject( pEnt );
      mTestNode[1]->translate(-100,-100,0);
  
  
      Plane plane(Vector3::UNIT_Y, -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);
  
      mCameraNode->setPosition(0,0,400);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  PlayPen_ClearScene::PlayPen_ClearScene()
  {
      mInfo["Title"] = "PlayPen_ClearScene";
      mInfo["Description"] = "Tests clearing a running scene.";
      addScreenshotFrame(25);
  }
  //----------------------------------------------------------------------------
  
  bool PlayPen_ClearScene::isScreenshotFrame(unsigned int frame)
  {
      if(frame == 20)
          mSceneMgr->clearScene();
      return VisualTest::isScreenshotFrame(frame);
  }
  //----------------------------------------------------------------------------
  
  void PlayPen_ClearScene::setupContent()
  {
      mSceneMgr->setAmbientLight(ColourValue::White);
  
      // Define a floor plane mesh
      Plane p(Vector3::UNIT_Y, -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);
  
      mCameraNode->setPosition(0,500,100);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      // 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);
  
      mCameraNode->setPosition(0, 0, -300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
      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);
      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);
      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", ASSETS_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);
  
      mCameraNode->setPosition(400, 250, 350);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(300,0,0);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      // mat->setSceneBlending(SBT_TRANSPARENT_ALPHA);
      Pass* p = mat->getTechnique(0)->getPass(0);
      p->setLightingEnabled(false);
      p->createTextureUnitState("BumpyMetal.jpg");
      // t->setColourOperation(LBO_ALPHA_BLEND);
  
      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)
      for (size_t i = 0; i <= 3; ++i)
      {
          String name("decal");
          name += StringConverter::toString(i);
  
          MaterialPtr pMat = MaterialManager::getSingleton().create(name, TRANSIENT_RESOURCE_GROUP);
  
          p = pMat->getTechnique(0)->getPass(0);
          p->setLightingEnabled(false);
          p->setAlphaRejectSettings(CMPF_GREATER_EQUAL, 128);
          p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
          p->setDepthBias(i);
          p->createTextureUnitState(name + ".png");
          // t->setColourOperation(LBO_ALPHA_BLEND);
  
          entity = mSceneMgr->createEntity(name, meshName);
          entity->setMaterialName(name);
          mSceneMgr->getRootSceneNode()->attachObject(entity);
      }
  
      mCameraNode->setPosition(0,0,200);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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(
          MaterialManager::getSingleton().getByName("Ogre/DepthShadowmap/Caster/Float", "General"));
  
      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);
      //mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(500, 500, -100))->attachObject(l);
      Vector3 pos(0, 300, 0);
      mSceneMgr->getRootSceneNode()->createChildSceneNode(pos)->attachObject(l);
      l->setDirection(-pos.normalisedCopy());
      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);
  
      mCameraNode->setPosition(150, 100, 150);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
      // 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", TRANSIENT_RESOURCE_GROUP);
      rttTex->getBuffer()->getRenderTarget()->removeAllListeners();
      rttTex->unload();
      rttTex = TextureManager::getSingleton().getByName("Reflection", TRANSIENT_RESOURCE_GROUP);
      rttTex->getBuffer()->getRenderTarget()->removeAllListeners();
      rttTex->unload();
  }
  //----------------------------------------------------------------------------
  
  void PlayPen_Distortion::setupContent()
  {
      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");
          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");
          mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("Reflection");
          v->setOverlaysEnabled(false);
          rttTex->getBuffer()->getRenderTarget()->addListener(mReflectionListener);
      }
      // Define a floor plane mesh
      Plane p(Vector3::UNIT_Y, -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");
  
      for (int 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);
      }
  
      mCameraNode->setPosition(100,200,300);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,0,-300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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", "Tests");
      // 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);
      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);
  
      mCameraNode->setPosition(0,0,-300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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", "Tests");
      // 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);
  
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(offset + Vector3(0, 1000, 500));
      mCameraNode->lookAt(offset, Node::TS_PARENT);
      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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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()
  {
      // 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");
      
      // 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("Ogre/GPTest/Swizzle");
      }
  
      // Add entity to the root scene node
      mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
  
      mWindow->getViewport(0)->setBackgroundColour(ColourValue::Green);
  
      mCameraNode->setPosition(20, 0, 100);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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", ASSETS_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);
      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);
  
      mCameraNode->setPosition(0, 0, 200);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
      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");
          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(material);
          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(material);
          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);
  
      mCameraNode->setPosition(100,50,350);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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");
      Pass* p = mat->getTechnique(0)->getPass(0);
      p->setLightClipPlanesEnabled(true);
      //if (scissortoo)
      //p->setLightScissoringEnabled(true);
  
      mCameraNode->setPosition(0, 200, 300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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");
      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, true);
      //TODO Shouldn't the case below also be tested?
      // 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);
  
      mCameraNode->setPosition(0, 200, 300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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");
      Pass* p = mat->getTechnique(0)->getPass(0);
      p->setLightScissoringEnabled(true);
      //if (cliptoo)
      p->setLightClipPlanesEnabled(true);
  
  
      mCameraNode->setPosition(0, 200, 300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      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", ASSETS_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);
  
  
      mCameraNode->setPosition(0, 1000, 500);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
      mCamera->setFarClipDistance(10000);
  
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  
  static 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 cubes.
      Entity* ent = mSceneMgr->createEntity("Cube", "cube.mesh");
      ent->setMaterial(MaterialManager::getSingleton().getDefaultMaterial());
      mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
      createRandomEntityClones(ent, 3000, Vector3(-1000,-1000,-1000), Vector3(1000,1000,1000), mSceneMgr);
  
      //bool val = true;
      //mSceneMgr->setOption("ShowOctree", &val);
  
      mCameraNode->setPosition(0,0, -4000);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
      // 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);
  
      mCameraNode->setPosition(100,50,200);
      mCameraNode->lookAt(Vector3(0, 25, 0), Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-400,400,-300))->attachObject(mLight);
      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");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(300,200,100))->attachObject(mLight);
      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", ASSETS_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);
  
      mCameraNode->setPosition(180, 34, 223);
      mCameraNode->lookAt(Vector3(0, 50, 0), Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
  
      // Define a 40x40 plane, indexed
      //! [manual_plane_begin]
      Ogre::ManualObject* man = mSceneMgr->createManualObject("test");
      man->begin("Examples/OgreLogo", Ogre::RenderOperation::OT_TRIANGLE_LIST);
      //! [manual_plane_begin]
  
      //! [manual_plane_vertices]
      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);
      //! [manual_plane_vertices]
  
      //! [manual_plane_faces]
      man->quad(0, 1, 2, 3);
      //! [manual_plane_faces]
  
      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);
  
      //! [manual_plane_end]
      man->end();
      mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(man);
      //! [manual_plane_end]
  
      mCameraNode->setPosition(100,100,100);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      mCameraNode->setPosition(100,100,100);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      // 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");
  
  #ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM
      // force create shaders for non default scheme
      t->setSchemeName("newscheme_tmp");
      RTShader::ShaderGenerator& rtShaderGen = RTShader::ShaderGenerator::getSingleton();
      rtShaderGen.createShaderBasedTechnique(*mat, "newscheme_tmp", "newscheme");
      rtShaderGen.validateMaterial("newscheme", mat->getName(), mat->getGroup());
  #endif
  
      // 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);
  
      mCameraNode->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()
  {
      mSceneMgr->setAmbientLight(ColourValue(0.8, 0.8, 0.8));
  
      Entity *ent = mSceneMgr->createEntity("robot", "robot.mesh");
      mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
      
      // 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);
      // default scheme
      mat->getTechnique(0)->getPass(0)->createTextureUnitState("GreenSkin.jpg");
  
      schemeListener.mTech = mat->getTechnique(0);
      MaterialManager::getSingleton().addListener(&schemeListener);
  
      mCameraNode->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);
      // 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);
  
      mCameraNode->setPosition(0,90,250);
      //mCameraNode->lookAt(Vector3(Vector3(0, 0, 0)), Node::TS_PARENT);
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      // 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);
  
      mCameraNode->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);
    mCameraNode->setPosition(0, 0, -100);
    mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
    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);
  
    mCameraNode->setPosition(0, 0, 200);
    mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  
  
    }*/
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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();
      Light* l = sm2->createLight("l2");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100, 50, -100))->attachObject(l);
      l->setDiffuseColour(ColourValue::Green);
      // l->setDiffuseColour(ColourValue::Red);
      sm2->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
      // sm2->setAmbientLight(ColourValue(1, 1, 1));
      Entity* ent = sm2->createEntity("knot2", "knot.mesh");
      // Entity* ent = sm2->createEntity("head", "ogrehead.mesh");
      sm2->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
      Camera* camera2 = sm2->createCamera("cam2");
      SceneNode* camNode2 = sm2->getRootSceneNode()->createChildSceneNode();
      camNode2->attachObject(camera2);
      camNode2->setPosition(0, 0, -500);
      camNode2->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
      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
      l = mSceneMgr->createLight("l"); // note same name, will work since different SM
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(100, 50, -100))->attachObject(l);
      l->setDiffuseColour(ColourValue::Red);
      mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
      ent = mSceneMgr->createEntity("head", "ogrehead.mesh");
      // ent = mSceneMgr->createEntity("knot", "knot.mesh");
      mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
      mCameraNode->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));
  
      mCameraNode->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");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(500, 500, 200))->attachObject(l);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(1000,500,1000))->attachObject(l);
  
      mCameraNode->setPosition(0,200,50);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
      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");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(800,600,0))->attachObject(l);
  
      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);
  
      mCameraNode->setFixedYawAxis(false);
      mCamera->setProjectionType(PT_ORTHOGRAPHIC);
      mCameraNode->setPosition(0,10000,0);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
      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);
      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(3);
      p->setVertexColourTracking(TVC_DIFFUSE);
  
      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);
  
      mCameraNode->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");
      TextureUnitState *t = mat->getTechnique(0)->getPass(0)->getTextureUnitState(0);
      t->setProjectiveTexturing(true, frustum);
      //t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
  
      mCameraNode->setPosition(-50, 100, 500);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  
      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());
  
          SceneNode* reflectCamNode = rootNode->createChildSceneNode();
          reflectCamNode->attachObject(reflectCam);
          reflectCamNode->setPosition(mCameraNode->getPosition());
          reflectCamNode->setOrientation(mCameraNode->getOrientation());
  
          Viewport *v = rttTex->getBuffer()->getRenderTarget()->addViewport( reflectCam );
          v->setClearEveryFrame( true );
          v->setBackgroundColour( ColourValue::Black );
  
          MaterialPtr mat = MaterialManager::getSingleton().create("RttMat",
                                                                   TRANSIENT_RESOURCE_GROUP);
          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");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(200, 300, 0))->attachObject(l);
  
      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);
  
      mCameraNode->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::String meshFilePath = testResourcePath + "/Model2";
      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);
  
      mCameraNode->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);
  
  
      mCameraNode->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));
  
      MaterialPtr mat = MaterialManager::getSingleton().create(
          "AmbientVertexColourTracking", TRANSIENT_RESOURCE_GROUP);
      Pass* p = mat->getTechnique(0)->getPass(0);
      p->setVertexColourTracking(TVC_AMBIENT);
      p->setLightingEnabled(false);
  
      man->begin("AmbientVertexColourTracking");
      //TODO 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();
  
      mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(man);
  
      MeshPtr mesh = man->convertToMesh("colourtest.mesh");
      MeshSerializer ms;
      ms.exportMesh(mesh.get(), "colourtest.mesh");
  
      Entity* c = mSceneMgr->createEntity("1", "colourtest.mesh");
      mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(c);
  
      mCameraNode->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);
          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);
      */
  
      mCameraNode->setPosition(0, 1000, 500);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
      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");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-200,-80,-100))->attachObject(l);
      l->setDiffuseColour(0.5, 0.5, 1.0);
  
      l = mSceneMgr->createLight("GreenLight");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0,0,-100))->attachObject(l);
      l->setDiffuseColour(0.5, 1.0, 0.5);
  
      // Position the camera
      mCameraNode->setPosition(200,50,0);
      mCameraNode->lookAt(Vector3(0, 50, 0), Node::TS_PARENT);
  
      // 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_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);
      /*/
      // Point test
      mLight->setType(Light::LT_POINT);
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0, 200, 0))->attachObject(mLight);
      //*/
  
      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(Vector3::UNIT_Y, -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);
  
      mCameraNode->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 glslv");
      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 glslf");
      fp->setParameter("entry_point", "fp");
      fp->load();
  
      MaterialPtr mat = MaterialManager::getSingleton().create("TestSpotlightProj",
                                                               TRANSIENT_RESOURCE_GROUP);
      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);
  
      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);
      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);
  
      mCameraNode->setPosition(0,0,300);
      mCameraNode->lookAt(Vector3::ZERO, Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0, 600, 0))->attachObject(l);
      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", ASSETS_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);
      mCameraNode->setPosition(0,400,1200);
      mCameraNode->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);
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0, 600, 0))->attachObject(l);
      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", ASSETS_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);
      mCameraNode->setPosition(0,400,1200);
      mCameraNode->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(100);
  }
  //---------------------------------------------------------------------------
  
  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
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(20,80,50))->attachObject(l);
  
  
      // 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);
  
      mCameraNode->setPosition(0,0,200);
      mCameraNode->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_MODULATIVE);
      //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");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-400,400,-300))->attachObject(mLight);
      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");
      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");
      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", ASSETS_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);
  
      //mCameraNode->setPosition(180, 34, 223);
      //mCamera->setOrientation(Quaternion(0.7265, -0.2064, 0.6304, 0.1791));
  
      mCameraNode->setPosition(0,0,400);
      mCameraNode->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");
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(-400,400,-300))->attachObject(mLight);
      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);
  
      //mCameraNode->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);
  
      mCameraNode->setPosition(100,320,600);
      mCameraNode->lookAt(Vector3(0, 120, 0), Node::TS_PARENT);
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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);
  
      mCameraNode->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_MODULATIVE);
  
      // 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
      mCameraNode->setPosition(-100.0, 50.0, 90.0);
      mCameraNode->lookAt(Vector3(0.0, 10.0, -35.0), Node::TS_PARENT);
  
      // 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_MODULATIVE);
  
      //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);
      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", ASSETS_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);
      */
  
      mCameraNode->setPosition(0, 1000, 500);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
      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 glslv");
      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 glslf");
      fp->setParameter("entry_point", "customCasterFp");
      fp->load();
  
      MaterialPtr mat = MaterialManager::getSingleton().create("CustomShadowCaster",
                                                               TRANSIENT_RESOURCE_GROUP);
      Pass* p = mat->getTechnique(0)->getPass(0);
      p->setVertexProgram("CustomShadowCasterVp");
      p->getVertexProgramParameters()->setNamedAutoConstant(
          "worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
      p->setFragmentProgram("CustomShadowCasterFp");
  
      mSceneMgr->setShadowTextureCasterMaterial(mat);
  
  
  
  
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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 glslv");
      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 glslf");
      fp->setParameter("entry_point", "customReceiverFp");
      fp->load();
  
      MaterialPtr mat = MaterialManager::getSingleton().create("CustomShadowReceiver",
                                                               TRANSIENT_RESOURCE_GROUP);
      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(mat);
  
  
  
  }
  //----------------------------------------------------------------------------
  //----------------------------------------------------------------------------
  
  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->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);
      /* // 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->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);
  
      mCameraNode->setPosition(-50, 500, 1000);
      mCameraNode->lookAt(Vector3(Vector3(-50, -100, 0)), Node::TS_PARENT);
  
      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_MODULATIVE_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(
          MaterialManager::getSingleton().getByName("PSSM/shadow_caster", "General"));
  
      // 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);
  
      mCameraNode->setPosition(-50, 500, 1000);
      mCameraNode->lookAt(Vector3(Vector3(-50, -100, 0)), Node::TS_PARENT);
  
      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");
      mat->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("pssmSplitPoints", splitPoints);
      mat = MaterialManager::getSingleton().getByName("PSSM/Knot");
      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");
      MaterialPtr CUSTOM_CASTER_MATERIAL = MaterialManager::getSingleton().getByName("Ogre/DepthShadowmap/Caster/Float", "General");
      MaterialPtr CUSTOM_RECEIVER_MATERIAL = MaterialManager::getSingleton().getByName("Ogre/DepthShadowmap/Receiver/Float", "General");
  
      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
      //mCameraNode->setPosition(-55.0, 40.0, 100.0);
      //mCameraNode->lookAt(-10.0, 20.0, -35.0, Node::TS_PARENT);
      //mCameraNode->setPosition(-75.0, 30.0, 150.0);
      //mCameraNode->lookAt(0.0, 20.0, -35.0, Node::TS_PARENT);
      mCameraNode->setPosition(100,50,150);
      mCameraNode->lookAt(Vector3(0, 0, 0), Node::TS_PARENT);
  
      //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);
      //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);
      // 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);
          Pass* alphaPass = alphamat->getTechnique(0)->getPass(0);
          alphaPass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
          alphaPass->setDepthWriteEnabled(false);
          TextureUnitState* t = alphaPass->createTextureUnitState();
          t->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, alphaLevel);
  
          ent = mSceneMgr->createEntity("asd", "ogrehead.mesh");
          ent->setMaterialName("testy");
          mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
  
      }
  
      mCameraNode->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()
  {
      //TODO DirectX only right now - add OpenGL.
  
      Light* l = mSceneMgr->createLight("MainLight");
      l->setType(Light::LT_POINT);
      mSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0, 200, 0))->attachObject(l);
  
  
      // 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);
      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_MODULATIVE);
  
      // 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
      mCameraNode->setPosition(-100.0, 50.0, 90.0);
      mCameraNode->lookAt(Vector3(0.0, 10.0, -35.0), Node::TS_WORLD);
  
      // 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);
  
      mCameraNode->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");
      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));
              MaterialManager::getSingleton().remove("Ogre/DebugTexture" + StringConverter::toString(i), "VisualTestTransient");
          }
      }
  }
  //-----------------------------------------------------------------------
  
  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);
      }
  }
  //-----------------------------------------------------------------------
  