Index: GTP/trunk/App/Demos/Geom/Demo_LodStrips.sln
===================================================================
--- GTP/trunk/App/Demos/Geom/Demo_LodStrips.sln	(revision 1029)
+++ GTP/trunk/App/Demos/Geom/Demo_LodStrips.sln	(revision 1029)
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Demo_LodStrips", "Demo_LodStrips.vcproj", "{756E8FBA-EA25-400C-9CA9-CB5AE5D7621E}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		Debug = Debug
+		Release = Release
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{756E8FBA-EA25-400C-9CA9-CB5AE5D7621E}.Debug.ActiveCfg = Debug|Win32
+		{756E8FBA-EA25-400C-9CA9-CB5AE5D7621E}.Debug.Build.0 = Debug|Win32
+		{756E8FBA-EA25-400C-9CA9-CB5AE5D7621E}.Release.ActiveCfg = Release|Win32
+		{756E8FBA-EA25-400C-9CA9-CB5AE5D7621E}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
Index: GTP/trunk/App/Demos/Geom/main.cpp
===================================================================
--- GTP/trunk/App/Demos/Geom/main.cpp	(revision 1029)
+++ GTP/trunk/App/Demos/Geom/main.cpp	(revision 1029)
@@ -0,0 +1,482 @@
+/*	==========================================================================
+ *	(C) 2006 Universitat Jaume I
+ *	==========================================================================
+ *	PROYECT:	GAME TOOLS
+ *	==========================================================================*/
+/**	CONTENT:	
+	*
+	*
+	*	@file	main.cpp
+/** COMMENTS:
+	* Model must be in "media/models" folder.
+	* Lod file must be in "media/GT" folder.
+/*===========================================================================*/
+#include "ExampleApplication.h"
+#include "OgreLodStripsLibrary.h"
+
+
+// Distance values
+#define dist_min 300
+#define dist_max 700
+
+// Model name
+#define model_name "dwarf2"
+
+
+//Global variables
+Entity* entity;
+LodStripsLibrary* myStrips;
+SceneNode* node;
+
+MaterialPtr *mat;
+
+ColourValue color=ColourValue::Red;
+
+Camera* theCam;
+Entity* pPlaneEnt;
+std::vector<Entity*> belowWaterEnts;
+std::vector<Entity*> aboveWaterEnts;
+
+Plane reflectionPlane;
+
+OverlayElement* mInfo;
+OverlayElement* mInfo2;
+
+class RefractionTextureListener : public RenderTargetListener
+{
+public:
+    void preRenderTargetUpdate(const RenderTargetEvent& evt)
+    {
+        // Hide plane and objects above the water
+        pPlaneEnt->setVisible(false);
+        std::vector<Entity*>::iterator i, iend;
+        iend = aboveWaterEnts.end();
+        for (i = aboveWaterEnts.begin(); i != iend; ++i)
+        {
+            (*i)->setVisible(false);
+        }
+
+    }
+    void postRenderTargetUpdate(const RenderTargetEvent& evt)
+    {
+        // Show plane and objects above the water
+        pPlaneEnt->setVisible(true);
+        std::vector<Entity*>::iterator i, iend;
+        iend = aboveWaterEnts.end();
+        for (i = aboveWaterEnts.begin(); i != iend; ++i)
+        {
+            (*i)->setVisible(true);
+        }
+    }
+
+};
+class ReflectionTextureListener : public RenderTargetListener
+{
+public:
+    void preRenderTargetUpdate(const RenderTargetEvent& evt)
+    {
+        // Hide plane and objects below the water
+        pPlaneEnt->setVisible(false);
+        std::vector<Entity*>::iterator i, iend;
+        iend = belowWaterEnts.end();
+        for (i = belowWaterEnts.begin(); i != iend; ++i)
+        {
+            (*i)->setVisible(false);
+        }
+        theCam->enableReflection(reflectionPlane);
+
+    }
+    void postRenderTargetUpdate(const RenderTargetEvent& evt)
+    {
+        // Show plane and objects below the water
+        pPlaneEnt->setVisible(true);
+        std::vector<Entity*>::iterator i, iend;
+        iend = belowWaterEnts.end();
+        for (i = belowWaterEnts.begin(); i != iend; ++i)
+        {
+            (*i)->setVisible(true);
+        }
+        theCam->disableReflection();
+    }
+
+};
+
+class FresnelFrameListener : public ExampleFrameListener
+{
+	int manage;
+
+public:
+
+    FresnelFrameListener(RenderWindow* win, Camera* cam)
+        : ExampleFrameListener(win, cam, false, false)
+    {
+		manage=1;
+	}
+
+	bool frameStarted(const FrameEvent& evt)
+    {
+		Vector3 dist; 
+		int distance=0,inc2=0,d;
+		unsigned int nlod,diflods;
+
+		// Move upto 80 units/second
+		Real MoveFactor = 180.0 * evt.timeSinceLastFrame;
+
+		// Copy the current state of the input devices
+		mInputDevice->capture();
+
+		// If this is the first frame, pick a speed
+		if (evt.timeSinceLastFrame == 0)
+		{
+			mMoveScale = 1;
+			mRotScale = 0.1;
+		}
+		// Otherwise scale movement units by time passed since last frame
+		else
+		{
+			// Move about 100 units per second,
+			mMoveScale = mMoveSpeed * evt.timeSinceLastFrame;
+			// Take about 10 seconds for full rotation
+			mRotScale = mRotateSpeed * evt.timeSinceLastFrame;
+		}
+
+		mRotX = 0;
+        mRotY = 0;
+	    mTranslateVector = Vector3::ZERO;
+
+		//LOD selection
+		int difdist = dist_max - dist_min;
+	
+		int i=0;
+
+		dist = node->getPosition() - mCamera->getPosition(); 
+		distance =dist.length();
+
+
+		if (( distance >= dist_min) && (distance <= dist_max))
+		{
+			diflods=myStrips->MaxLod()-myStrips->MinLod();
+			inc2=diflods/difdist;
+			inc2++;
+
+			d = distance - dist_min;
+
+			nlod = d*inc2+myStrips->MinLod();
+
+			if ((nlod!=myStrips->mCurrentLod)&&(nlod>=myStrips->MinLod())&&(nlod<=myStrips->MaxLod()))
+			{
+
+				myStrips->GoToLod(nlod);
+
+				nlod -= myStrips->MinLod();
+				if (nlod<diflods/3)
+				{
+					color.r=0.0;
+					color.g=nlod*1.0/(diflods/3);
+					color.b=1.0-(nlod*1.0/(diflods/3));
+				}
+				else
+				{
+					if (nlod<2*diflods/3)
+					{
+						color.r=(nlod-diflods/3)*1.0/(diflods/3);
+						color.g=1.0;
+						color.b=0.0;
+					}
+					else
+					{
+						color.r=1.0;
+						color.g=1.0-(nlod-(2*diflods/3))*1.0/(diflods/3);
+						color.b=0.0;
+					}
+				}
+				mat[0]->setDiffuse(color);
+			}
+		}
+		else
+		{
+			if ((myStrips->MaxLod()!=myStrips->mCurrentLod)&&(distance > dist_max))
+			{
+				myStrips->GoToLod(myStrips->MaxLod());
+
+				color.r=1.0;
+				color.g=0.0;
+				color.b=0.0;
+				mat[0]->setDiffuse(color);
+
+			}
+			else
+			{
+				if ((myStrips->MinLod()!=myStrips->mCurrentLod)&&(distance < dist_min))
+				{
+					myStrips->GoToLod(myStrips->MinLod());
+
+					color.r=0.0;
+					color.g=0.0;
+					color.b=1.0;
+					mat[0]->setDiffuse(color);
+				}
+			}
+		}
+
+
+
+		// Move the node
+		if(mInputDevice->isKeyDown(Ogre::KC_UP))
+		  mTranslateVector.z = -mMoveScale;
+
+
+		if(mInputDevice->isKeyDown(Ogre::KC_DOWN))
+		  mTranslateVector.z = mMoveScale;
+
+		// Instead of moving the ship left and right, rotate it using yaw()
+		if(mInputDevice->isKeyDown(Ogre::KC_LEFT))
+		  mCamera->yaw(mRotScale);
+
+		if(mInputDevice->isKeyDown(Ogre::KC_RIGHT))
+		  mCamera->yaw(-mRotScale);
+
+		// Move the node
+		if(mInputDevice->isKeyDown(Ogre::KC_W))
+		  node->translate(0,mMoveScale,0);
+
+		if(mInputDevice->isKeyDown(Ogre::KC_S))
+		  node->translate(0,-mMoveScale,0);
+
+		if(mInputDevice->isKeyDown(Ogre::KC_Z))
+		  node->scale(1.01,1.01,1.01);
+
+		if(mInputDevice->isKeyDown(Ogre::KC_X))
+		  node->scale(0.99,0.99,0.99);
+
+		// Rotate
+		if(mInputDevice->isKeyDown(Ogre::KC_A))
+		  node->yaw(mRotScale);
+
+		if(mInputDevice->isKeyDown(Ogre::KC_D))
+		  node->yaw(-mRotScale);
+
+		if(mInputDevice->isKeyDown(Ogre::KC_ESCAPE))
+		{
+			delete myStrips;
+
+			delete [] mat;
+
+		    return false;
+		}
+
+        if( mInputDevice->getMouseButton( 1 ) )
+        {
+            mTranslateVector.x += mInputDevice->getMouseRelativeX() * 0.13;
+            mTranslateVector.y -= mInputDevice->getMouseRelativeY() * 0.13;
+        }
+        else
+        {
+            mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13);
+            mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13);
+        }
+
+
+		char cadena[256];
+
+				
+		sprintf(cadena,"Distance: %d",distance);
+		
+		mInfo->setCaption(cadena);
+		
+		sprintf(cadena,"Lods: %d - Current lod: %d",myStrips->MaxLod(),myStrips->mCurrentLod);
+
+		mInfo2->setCaption(cadena);
+
+		mCamera->yaw(mRotX);
+        mCamera->pitch(mRotY);
+        mCamera->moveRelative(mTranslateVector);
+
+		return true;
+    }
+};
+
+class FresnelApplication : public ExampleApplication
+{
+protected:
+    RefractionTextureListener mRefractionListener;
+    ReflectionTextureListener mReflectionListener;
+public:
+    FresnelApplication() {
+    
+    
+    }
+
+    ~FresnelApplication() 
+    {
+    }
+protected:
+    
+
+
+    // Just override the mandatory create scene method
+    void createScene(void)
+    {
+		Entity* pEnt;
+
+		mat = new MaterialPtr[1];
+		
+	    // Check prerequisites first
+		const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities();
+        if (!caps->hasCapability(RSC_VERTEX_PROGRAM) || !(caps->hasCapability(RSC_FRAGMENT_PROGRAM)))
+        {
+            OGRE_EXCEPT(1, "Your card does not support vertex and fragment programs, so cannot "
+                "run this demo. Sorry!", 
+                "Fresnel::createScene");
+        }
+        else
+        {
+            if (!GpuProgramManager::getSingleton().isSyntaxSupported("arbfp1") &&
+                !GpuProgramManager::getSingleton().isSyntaxSupported("ps_2_0") &&
+				!GpuProgramManager::getSingleton().isSyntaxSupported("ps_1_4")
+				)
+            {
+                OGRE_EXCEPT(1, "Your card does not support advanced fragment programs, "
+                    "so cannot run this demo. Sorry!", 
+                "Fresnel::createScene");
+            }
+        }
+
+        theCam = mCamera;
+        theCam->setPosition(0,20,dist_max+50);
+        // Set ambient light
+        mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));
+
+        // Create a point light
+        Light* l = mSceneMgr->createLight("MainLight");
+        l->setType(Light::LT_DIRECTIONAL);
+        l->setDirection(0.0,0.0,-1.0);
+
+       
+        RenderTexture* rttTex = mRoot->getRenderSystem()->createRenderTexture( "Refraction", 512, 512 );
+		
+        {
+            Viewport *v = rttTex->addViewport( mCamera );
+            MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflectionRefraction");
+            mat->getTechnique(0)->getPass(0)->getTextureUnitState(2)->setTextureName("Refraction");
+            v->setOverlaysEnabled(false);
+            rttTex->addListener(&mRefractionListener);
+        }
+        
+		
+        rttTex = mRoot->getRenderSystem()->createRenderTexture( "Reflection", 512, 512 );
+        {
+            Viewport *v = rttTex->addViewport( mCamera );
+            MaterialPtr mat = MaterialManager::getSingleton().getByName("Examples/FresnelReflectionRefraction");
+            mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName("Reflection");
+            v->setOverlaysEnabled(false);
+            rttTex->addListener(&mReflectionListener);
+        }
+        
+        
+        // Define a floor plane mesh
+        reflectionPlane.normal = Vector3::UNIT_Y;
+        reflectionPlane.d = 0;
+        MeshManager::getSingleton().createPlane("ReflectPlane",
+            ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
+            reflectionPlane,
+            9000,9000,10,10,true,1,5,5,Vector3::UNIT_Z);
+        pPlaneEnt = mSceneMgr->createEntity( "plane", "ReflectPlane" );
+        pPlaneEnt->setMaterialName("Examples/FresnelReflectionRefraction");
+        mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
+
+        
+        mSceneMgr->setSkyBox(true, "Examples/CloudyNoonSkyBox");
+
+        // My node to which all objects will be attached
+        SceneNode* myRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
+
+
+        // Now the below water ents
+        pEnt = mSceneMgr->createEntity( "PoolFloor", "PoolFloor.mesh" );
+        myRootNode->attachObject(pEnt);
+        belowWaterEnts.push_back(pEnt);
+		myRootNode->scale(6.0,6.0,6.0);
+
+		std::string model_file=model_name;
+		model_file.append(".mesh");
+
+		//Models
+        entity = mSceneMgr->createEntity( model_name, model_file);
+
+        node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
+        node->attachObject( entity );
+
+		std::string lod_file="../../media/GT/";
+		lod_file.append(model_name);
+		lod_file.append(".lod");
+
+		myStrips = new LodStripsLibrary(lod_file,entity->getMesh().getPointer());
+
+		entity->setNormaliseNormals(true);
+
+		aboveWaterEnts.push_back(entity);
+
+		// Colour-coded material
+		mat[0] = MaterialManager::getSingleton().create("test_mat", 
+			ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
+		mat[0]->setCullingMode(CULL_NONE);
+		mat[0]->setAmbient(ColourValue::Black);
+		mat[0]->setDiffuse(color);
+		mat[0]->setLightingEnabled(true);
+		entity->setMaterialName("test_mat");
+
+        // show overlay
+        Overlay* pOver = OverlayManager::getSingleton().getByName("Demo_LodStrips/Overlay");    
+        mInfo = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Info_1");
+		mInfo2 = OverlayManager::getSingleton().getOverlayElement("Demo_LodStrips/Info_2");
+	    pOver->show();
+
+    }
+
+    void createFrameListener(void)
+    {
+        mFrameListener= new FresnelFrameListener(mWindow, mCamera);
+        mFrameListener->showDebugOverlay(true);
+        mRoot->addFrameListener(mFrameListener);
+    }
+
+};
+
+
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+#define WIN32_LEAN_AND_MEAN
+#include "windows.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
+#else
+int main(int argc, char **argv)
+#endif
+{
+    // Create application object
+    FresnelApplication app;
+
+    try {
+        app.go();
+    } catch( Exception& e ) {
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
+#else
+        std::cerr << "An exception has occured: " << e.getFullDescription();
+#endif
+    }
+
+
+    return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
Index: GTP/trunk/App/Demos/Geom/OgreLodStripsLibrary.cpp
===================================================================
--- GTP/trunk/App/Demos/Geom/OgreLodStripsLibrary.cpp	(revision 1029)
+++ GTP/trunk/App/Demos/Geom/OgreLodStripsLibrary.cpp	(revision 1029)
@@ -0,0 +1,672 @@
+/*	==========================================================================
+ *	(C) 2006 Universitat Jaume I
+ *	==========================================================================
+ *	PROYECT:	GAME TOOLS
+ *	==========================================================================*/
+/**	CONTENT:	
+	*
+	*
+	*	@file	OgreLodStripsLibrary.cpp
+/*===========================================================================*/
+
+#include "OgreLodStripsLibrary.h"
+
+//-----------------------------------------------------------------------------
+//	Constructors.
+//-----------------------------------------------------------------------------
+LodStripsLibrary::LodStripsLibrary(	std::string	name, Ogre::Mesh	*geomesh)
+{
+	const	char	*name_of_file;
+
+	mMaxLod=0;
+	mMinLod=0;
+
+	//	Sets the current lod.
+	mCurrentLod	=	0;
+
+	//	Converts a String to const char *.
+	name_of_file	=	name.data();
+
+	original_mesh=geomesh;
+
+	//	Loads the Level Of Detail file.
+	LodStripsLibrary::LoadStripMesh((char*)name_of_file,geomesh);
+}
+
+//-----------------------------------------------------------------------------
+//	Destroyer.
+//-----------------------------------------------------------------------------
+LodStripsLibrary::~LodStripsLibrary()
+{		
+		delete [] mPChanges;
+		
+		if (mMaxLod>0)
+			delete [] mStrips;
+
+		delete [] mVertex;
+		delete [] mStripsSubmesh;
+		delete [] mRegLODBegin;
+		delete [] mDataBegin;
+}
+
+//-----------------------------------------------------------------------------
+//	Public.
+//-----------------------------------------------------------------------------
+
+/*
+	Go to the level of detail.
+*/
+Ogre::uint32 LodStripsLibrary::GoToLod(Ogre::uint32 newLOD)
+{
+	register	int							j;
+	register	int							offset;
+	unsigned			int							i;
+	long			int							k;
+	long			int							l;
+	unsigned			int							lod;
+	long			int							t;
+	long			int							r;
+	long			int							sig;
+	long			int							el1;
+	long			int							el2;
+	long			int							total_changes;
+	long			int							totalR;
+	SmallIntVector						*strip;
+	SmallIntVector::iterator	start;
+	Ogre::uint32										return_value;
+
+	//	Initialize the return value to the current LOD.
+	return_value	=	mCurrentLod;
+
+	if (newLOD != mCurrentLod)
+	{
+		if (newLOD > mCurrentLod)
+		{
+			//HACIA ADELANTE
+			//CurrentRegLOD
+			//Incrementamos el LOD -> Calcular siguientes
+			for (lod = mCurrentLod; lod < newLOD; lod++)
+			{
+				sig				=	mVertex[lod];
+				total_changes	=	mPChanges[lod];
+
+				for (i = 0; i < total_changes; i++)
+				{
+					//	Strip q Cambia.
+					t			=	mCurrentRegLOD->strip; 
+					strip	=	&(mStrips[t]);
+					//start	=	strip->begin();	
+
+					start=(mStrips+t)->begin();
+				
+					//	Position.
+					totalR	=	mCurrentRegLOD->position;
+
+					for (j = totalR - 1; j >= 0; j--)
+					{
+						//start[*mCurrentData]	=	sig;
+						*(start+*mCurrentData)=sig;
+						
+						++mCurrentData;
+					}
+					
+					//	L1.
+					totalR	=	mCurrentRegLOD->vertexRepetition;
+					
+					for (j = totalR - 1; j >= 0; j--)
+					{
+						offset	=	*mCurrentData + 1;
+
+						strip->erase(	start + offset,
+													start
+													+
+													offset
+													+
+													(*(mCurrentData + 1)));
+
+						++mCurrentData;
+						++mCurrentData;
+					}
+					
+					//	L2
+					totalR	=	mCurrentRegLOD->edgeRepetition;
+					
+					for (j = totalR - 1; j >= 0; j--)
+					{
+						offset	=	*mCurrentData + 2;
+						strip->erase(	start	+	offset,
+													start
+													+
+													offset
+													+
+													2*(*(mCurrentData + 1)));
+
+						++mCurrentData;
+						++mCurrentData;
+					}
+
+					++mCurrentRegLOD;
+					
+					
+				
+				}
+				
+				mCurrentLod	=	lod + 1;
+			}
+
+		}
+		//	Si el nuevo LOD es menos que el actual.
+		else
+		{ 
+			--mCurrentRegLOD;
+			--mCurrentData;
+			
+			//	Decrementamos el LOD -> Calcular anteriores.
+			for (lod = mCurrentLod; lod > newLOD; lod--)
+			{
+				total_changes	=	mPChanges[lod - 1];
+				
+				for (i = 0; i < total_changes; i++)
+				{
+					t			=	mCurrentRegLOD->strip;
+					strip	=	&(mStrips[t]);
+					//start	=	mStrips[t].begin();
+
+					start=(mStrips+t)->begin();
+
+					//	L2.
+					totalR	=	mCurrentRegLOD->edgeRepetition;
+					
+					for (j = 0; j < totalR; j++)
+					{
+						el1	=	(*strip)[*(mCurrentData - 1)];
+						el2	=	(*strip)[*(mCurrentData - 1) + 1];
+						r		=	*(mCurrentData);
+						
+						for (k = 0; k < r; k++)
+						{
+							(*strip).insert(start+*(mCurrentData - 1),el2);
+							(*strip).insert(start+*(mCurrentData - 1),el1);
+						}
+						
+						--mCurrentData;
+						--mCurrentData;
+					}
+
+					//	Vertex Repetition.
+					totalR	=	mCurrentRegLOD->vertexRepetition;
+					
+					for (j = 0; j < totalR; j++)
+					{
+						el1	=	(*strip)[*(mCurrentData-1)];
+						r		=	*(mCurrentData);
+						
+						for (k = 0; k < r; k++)
+						{
+							(*strip).insert(start+*(mCurrentData-1),el1);
+						}
+
+						--mCurrentData;
+						--mCurrentData;
+					}
+					
+					//	POS.
+					totalR	=	mCurrentRegLOD->position;
+					
+					for (j = 0; j < totalR; j++)
+					{
+						(*strip)[*mCurrentData]	=	lod - 1;
+						--mCurrentData;
+					}
+					
+					--mCurrentRegLOD;
+					
+				}			
+				
+				//	Actualizar LOD.
+				mCurrentLod	=	lod - 1;
+			}
+			
+			++mCurrentData;
+			++mCurrentRegLOD;
+		} 
+
+	}	
+
+	// Copy to Ogre buffers including the degenerated triangles
+
+	for (i	=	0; i < GetStripCount(); i++)
+	{
+		start	=	mStrips[i].begin();
+		
+		mStrips[i].insert(start,mStrips[i][0]);
+		mStrips[i].push_back(mStrips[i][mStrips[i].size()-1]);
+	}
+
+
+	Ogre::HardwareIndexBufferSharedPtr	ibuf;
+	Ogre::IndexData	*indexes;
+	Ogre::RenderOperation mRenderOp;
+
+	j=0;
+
+	for (int submesh=0; submesh < original_mesh->getNumSubMeshes(); submesh++)
+	{
+		k=0;
+		for (i	=	0; i < mStripsSubmesh[submesh]; i++)
+			k+=mStrips[j+i].size();
+
+
+		original_mesh->getSubMesh(submesh)->_getRenderOperation(mRenderOp,0);
+
+		ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( 
+			Ogre::HardwareIndexBuffer::IT_32BIT, // type of index 
+			k, // number of indexes 
+			Ogre::HardwareBuffer::HBU_DISCARDABLE , // usage
+			false); // no shadow buffer 
+					
+		mRenderOp.indexData->indexBuffer = ibuf; 
+		mRenderOp.indexData->indexStart = 0; 
+		mRenderOp.indexData->indexCount = k;
+
+		k=0;
+		unsigned long* pIdx = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
+
+		for (i	=	0; i < mStripsSubmesh[submesh]; i++)
+		{
+			for (l=0;l<mStrips[j].size();l++)
+			{
+				pIdx[k++]=mStrips[j][l];
+			}
+
+			j++;
+		}
+
+		
+
+		ibuf->unlock();
+
+	}
+	
+
+	//Erase the degenerated triangles
+	for (i	=	0; i < GetStripCount(); i++)
+	{
+		start	=	mStrips[i].begin();
+
+		mStrips[i].erase(start);
+
+		mStrips[i].pop_back();
+	}
+	
+	return	return_value;
+}
+
+
+/*
+	Gets the maximum level of detail.
+*/
+Ogre::uint32 LodStripsLibrary::MaxLod()
+{
+	return	mMaxLod;
+}
+
+/*
+	Gets the minimum level of detail.
+*/
+Ogre::uint32 LodStripsLibrary::MinLod()
+{
+	return	mMinLod;
+}
+
+/// Returns the number of vertices of the highest LOD.
+Ogre::uint32	LodStripsLibrary::MaxVertices()
+{
+	Ogre::uint32	number_of_vertices;
+
+	number_of_vertices	=	mTotalVertices;
+
+	return	number_of_vertices;
+}
+
+/// Returns the number of vertices of the lowest LOD.
+Ogre::uint32	LodStripsLibrary::MinVertices()
+{
+	Ogre::uint32	number_of_vertices;
+
+	//	Total vertices less total lod.
+	number_of_vertices	=	mTotalVertices - (mMaxLod + 1);
+
+	return	number_of_vertices;
+}
+
+/// Returns the number of triangles of the highest LOD.
+Ogre::uint32	LodStripsLibrary::MaxFaces()
+{
+	Ogre::uint32	number_of_faces;
+
+	Ogre::uint32	current_lod;
+
+	current_lod	=	GoToLod(MaxLod());
+
+	//	Initialize number of faces count.
+	number_of_faces	=	0;
+
+	//	For each strip.
+	for (int strip	=	0; strip < mTotalStrips; strip++)
+	{
+		number_of_faces	+=	mStrips[strip].size() - 2;
+	}
+
+	GoToLod(current_lod);
+
+	return	number_of_faces;
+}
+
+/// Returns the number of triangles of the lowest LOD.
+Ogre::uint32	LodStripsLibrary::MinFaces()
+{
+	Ogre::uint32	current_lod;
+	Ogre::uint32	number_of_faces;
+
+	current_lod	=	GoToLod(MinLod());
+
+	//	Initialize number of faces count.
+	number_of_faces	=	0;
+
+	//	For each strip.
+	for (int strip	=	0; strip < mTotalStrips; strip++)
+	{
+		number_of_faces	+=	mStrips[strip].size() - 2;
+	}
+
+	GoToLod(current_lod);
+
+	return	number_of_faces;
+}
+
+/// Establishes the new LOD range.
+/// Only the LODs in that range are stored and used.
+void		LodStripsLibrary::TrimByLod(Ogre::uint32 minLod, Ogre::uint32 maxLod)
+{
+	mMinLod	=	minLod;
+	mMaxLod	=	maxLod;
+}
+
+Ogre::uint32	LodStripsLibrary::GetStripCount() const
+{
+	return	(Ogre::uint32)	mTotalStrips;
+}
+
+Ogre::uint32	LodStripsLibrary::GetIndexCountByStrip(Ogre::uint32 istrip) const
+{
+	return (Ogre::uint32)	mStrips[istrip].size();
+}
+
+//-----------------------------------------------------------------------------
+//	Private.
+//-----------------------------------------------------------------------------
+
+/*
+	Copy a STL vector to a C array.
+*/
+void LodStripsLibrary::CopyVectors2Arrays()
+{
+	unsigned int		i;
+	int					j;
+	SmallInt 			max;
+	SmallInt 			t;
+	SmallInt 			*data_array;
+	SmallIntVector 		tira;
+	LODRegisterType		*changes_array;
+	LODRegisterVector	list_changes;
+
+	mTotalStrips		=	mFileStrips.size();
+	mVertex				=	new SmallInt[mTotalVertices];
+	mStrips				=	new SmallIntVector[mTotalStrips];
+	data_array			=	new SmallInt[mData.size()];
+	
+	//Calcular el tamaño maximo de tira y el numero de caras total
+	max					=	0;
+	mTotalFaces	=	0;
+	
+	for (i = 0; i < mFileStrips.size(); i++)
+	{
+		t	=	mFileStrips[i].size();
+		
+		if (t>max)
+		{
+			max	=	t;
+		}
+
+		mTotalFaces	+=	t - 2;
+	}
+
+	//Nueva version de ALLOCATE.
+	changes_array	=	new LODRegisterType[mFileChangesLOD.size()];
+	
+	//Rellenar vChanges
+	for (i = 0; i < mFileChangesLOD.size(); ++i)
+	{
+		changes_array[i]	=	mFileChangesLOD[i];
+	}
+
+	mCurrentRegLOD	=	changes_array;
+	mRegLODBegin	=	changes_array;
+	
+	//COPY----------------------------------
+	//Copiar las tiras
+	for (i = 0; i < mFileStrips.size(); i++)
+	{
+		for (j = 0; j < mFileStrips[i].size(); j++)
+		{
+			//Rellenar el vVector
+			mStrips[i].push_back(mFileStrips[i][j]);
+		}
+					
+	}
+
+	for (i = 0; i < mData.size(); i++)
+	{
+		data_array[i]	=	mData[i];
+	}
+	
+	mCurrentData	=	data_array;
+	mDataBegin	=	data_array;
+
+	//Meter los vertices en mVertex 
+	for(i = 0; i < mFileVertices.size(); i++)
+	{
+		mVertex[i]	=	mFileVertices[i];
+	}
+
+	mFileVertices.clear();
+	mFileVertices.clear();
+	mFileChangesLOD.clear();
+	mFileStrips.clear();
+	mData.clear();
+
+	
+}
+
+//-----------------------------------------------------------------------------
+// LoadStripMesh
+//-----------------------------------------------------------------------------
+void LodStripsLibrary::LoadStripMesh(char *name, Ogre::Mesh *geomesh)
+{
+	FILE															*fp;
+	SmallIntVector										strip_aux;
+	LODRegisterType										lod_register;
+	std::vector			<LODRegisterType>	list_pos;
+	std::vector			<unsigned int>		p_changes;
+	int																value;
+	int																v		=	0;
+	int																t		=	0;
+	int																c		=	-1;
+	char															buff[80];
+	Ogre::SubMesh														*geoSubMesh;
+	int count=0;
+	int num_strips=0;
+
+	//	Open the LOD file.
+	if ((fp = fopen (name, "r")) == NULL)
+	{
+		//	Error in open.
+	}
+	else
+	{
+		mTotalChanges	=	0;
+		
+
+		while (!feof (fp))
+		{
+			fgets (buff, 80, fp);
+			
+			if (*buff == 'v')
+			{
+				//VERTICES
+				sscanf (buff+2,"%d",&value);
+				
+				mFileVertices.push_back(value);
+				v++;
+			}
+			else if ( (*buff == 'c') || (*buff == 'd'))
+			{
+				if (*buff == 'c')
+				{
+					// c indica que empieza un nuevo cambio
+					c++;
+				}
+				else
+				{
+					unsigned	int	a;
+					unsigned	int	b;
+					unsigned	int	c;
+					unsigned	int	d;
+					
+					sscanf (buff+2,"%u %u %u %u\n",&a,&b,&c,&d);
+					lod_register.strip						=	a;
+					lod_register.position					=	b;
+					lod_register.vertexRepetition	=	c;
+					lod_register.edgeRepetition		=	d;
+					
+					mFileChangesLOD.push_back(lod_register);
+				}
+			}
+			else if (*buff=='b')
+			{
+				sscanf(buff+2,"%u",&value);
+				mData.push_back(value);
+			}
+			else if (*buff=='p')
+			{
+				sscanf (buff+2,"%u",&value);
+				p_changes.push_back(value);
+			}//Fin ElseIf
+
+		} // End WhileEOF
+		
+		fclose(fp);
+
+		mStripsSubmesh= new int [geomesh->getNumSubMeshes()];
+
+		//	For each one of the submeshes.
+		for (int submesh	=	0; submesh < geomesh->getNumSubMeshes(); submesh++)
+		{
+			geoSubMesh	=	geomesh->getSubMesh(submesh);
+
+			count=0;
+			num_strips=0;
+
+			Ogre::HardwareIndexBufferSharedPtr ibuf	=	geoSubMesh->indexData->indexBuffer;
+
+			if (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT)
+			{
+				unsigned int* pIndexes = static_cast<unsigned int*> (ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY) );
+
+				//We must be carefull with the degenerated triangles
+				while (count<(geoSubMesh->indexData->indexCount-1))
+				{
+					// Insert an empty strip.
+					strip_aux.clear();
+					mFileStrips.push_back(strip_aux);
+
+					mFileStrips[t].push_back(pIndexes[count++]);
+
+					while ((count<(geoSubMesh->indexData->indexCount-1))&&(pIndexes[count]!=pIndexes[count+1]))
+					{
+						mFileStrips[t].push_back(pIndexes[count++]);
+					}
+
+					mFileStrips[t].push_back(pIndexes[count]);
+
+					//For the degenerated triangles
+					count+=3;
+
+					char linea[256];
+					sprintf(linea,"%d %d (%d) %d %d %d %d",pIndexes[count-2],pIndexes[count-1],pIndexes[count],pIndexes[count+1],pIndexes[count+2],pIndexes[count+3],pIndexes[count+4]);
+					
+					t++;
+					num_strips++;
+
+				}
+
+			}
+			else
+			{
+				unsigned short* pIndexes = static_cast<unsigned short*> (ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY) );
+
+				while (count<geoSubMesh->indexData->indexCount)
+				{
+					// Insert an empty strip.
+					strip_aux.clear();
+					mFileStrips.push_back(strip_aux);
+
+					mFileStrips[t].push_back(pIndexes[count++]);
+
+					while ((count<(geoSubMesh->indexData->indexCount-1))&&(pIndexes[count]!=pIndexes[count+1]))
+					{
+						mFileStrips[t].push_back(pIndexes[count++]);
+					}
+
+					mFileStrips[t].push_back(pIndexes[count]);
+
+					//For the degenerated triangles
+					count+=3;
+
+					char linea[256];
+					sprintf(linea,"%d %d (%d) %d %d %d %d",pIndexes[count-2],pIndexes[count-1],pIndexes[count],pIndexes[count+1],pIndexes[count+2],pIndexes[count+3],pIndexes[count+4]);
+					
+					t++;
+					num_strips++;
+
+				}
+			}
+
+			ibuf->unlock();
+
+			mStripsSubmesh[submesh]=num_strips;
+		}
+		
+		//	Max / Min values for LOD.
+		mLods											=	p_changes.size();
+		mMinLod										=	0;
+		mMaxLod										=	mLods;
+
+		//// CHAPUZA PROVISIONAL: EL ULTIMO ELEMENTO SE REPITE 2 VECES V.v
+		mPChanges			=	new SmallInt[mLods];
+		
+		for (unsigned int i = 0; i < mLods; i++)
+		{
+			mPChanges[i] = p_changes[i];
+		}
+
+		mTotalVertices			=	mFileVertices.size();
+		mTotalStrips				=	mFileStrips.size();
+		mTotalChanges				=	mFileChangesLOD.size();
+
+		//Copy the data to the structure we will use
+		CopyVectors2Arrays();
+	}
+}
+
Index: GTP/trunk/App/Demos/Geom/Demo_LodStrips.vcproj
===================================================================
--- GTP/trunk/App/Demos/Geom/Demo_LodStrips.vcproj	(revision 1029)
+++ GTP/trunk/App/Demos/Geom/Demo_LodStrips.vcproj	(revision 1029)
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="Demo_LodStrips"
+	ProjectGUID="{756E8FBA-EA25-400C-9CA9-CB5AE5D7621E}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="build\Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				ImproveFloatingPointConsistency="TRUE"
+				AdditionalIncludeDirectories="..\OgreStuff\include"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+				MinimalRebuild="TRUE"
+				ExceptionHandling="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="5"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="OgreMain_d.lib"
+				OutputFile="$(OutDir)/Demo_LodStrips.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="..\OgreStuff\lib"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/Demo_LodStrips.pdb"
+				SubSystem="2"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="xcopy /Y ..\OgreStuff\bin\Debug\*.dll build\Debug
+xcopy /Y ..\OgreStuff\bin\Debug\*.cfg build\Debug"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="build\Release"
+			IntermediateDirectory="build\Release"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="..\OgreStuff\include"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="OgreMain.lib"
+				OutputFile="$(OutDir)/Demo_LodStrips.exe"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="..\OgreStuff\lib"
+				GenerateDebugInformation="TRUE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="xcopy /Y ..\OgreStuff\bin\Release\*.dll build\Release
+xcopy /Y ..\OgreStuff\bin\Release\*.cfg build\Release"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+			<File
+				RelativePath=".\main.cpp">
+			</File>
+			<File
+				RelativePath=".\OgreLodStripsLibrary.cpp">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+			<File
+				RelativePath=".\OgreLodStripsLibrary.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: GTP/trunk/App/Demos/Geom/OgreLodStripsLibrary.h
===================================================================
--- GTP/trunk/App/Demos/Geom/OgreLodStripsLibrary.h	(revision 1029)
+++ GTP/trunk/App/Demos/Geom/OgreLodStripsLibrary.h	(revision 1029)
@@ -0,0 +1,160 @@
+/*	==========================================================================
+ *	(C) 2006 Universidad Jaime I
+ *	==========================================================================
+ *	PROYECT:	GAME TOOLS
+ *	==========================================================================*/
+/**	CONTENT:
+	*
+	*
+	*	@file	OgreLodStripsLibrary.h
+/*===========================================================================*/
+
+// For integrating the library in the Ogre engine,
+// we have modified the class constructor and also the GoToLod function
+
+#include	"Ogre.h"
+#include	<vector>
+
+
+typedef unsigned long	SmallInt;
+typedef unsigned long	ULong;
+typedef	long			Long;
+
+typedef struct
+{
+	SmallInt strip;
+	SmallInt position;
+	SmallInt rep; //For the vertex repetition
+} PositionType;
+
+typedef	struct
+{
+	unsigned	long	strip;
+	char						position;
+	char						vertexRepetition;
+	char						edgeRepetition;
+}	LODRegisterType;
+
+typedef struct
+{
+	float Vertex[3];
+	SmallInt Next;
+} VertexType;
+
+typedef std::vector	<SmallInt>				SmallIntVector;
+typedef	std::vector	<LODRegisterType>	LODRegisterVector;
+typedef	std::vector	<Long>						LongVector;
+
+/// LodStripsLibrary interface class.
+/** This module contains functions that handle the levels of detail of the input multiresolution objects made of polygonal meshes. For any given resolution and object, this module returns a set of triangle strips representing the object at that resolution, that is, at the level of detail requested. These models use triangle strips to reduce storage usage and to speed up realistic rendering.
+\n\n
+
+Inputs:\n
+- The module receives a file describing a multiresolution object.
+.
+
+Outputs:\n
+- The module returns a strip set that represents the level of detail requested.
+.
+
+*/
+class LodStripsLibrary
+{
+	private:
+
+		///Structures with the data read from the file
+		///We won't work with these structures
+		SmallIntVector						mFileVertices;
+		std::vector	<LODRegisterType>		mFileChangesLOD;
+		std::vector	<SmallIntVector>		mFileStrips;
+		LongVector							mData;
+
+		///Structures with the data to work with
+		SmallInt	mTotalStrips;		///Total strips of the multiresolution object.
+		SmallInt	mTotalVertices;	///Total vertices of the multiresolution object.
+		SmallInt	mTotalChanges;	///Total changes of the multiresolution object.
+		SmallInt	mLods;					///Available Lods.
+
+
+
+		//	For the efficient version.
+		SmallInt				mTotalFaces;
+		SmallInt				*mCurrentData;
+		SmallInt				*mDataBegin;
+		LODRegisterType			*mCurrentRegLOD;
+		LODRegisterType			*mRegLODBegin;
+		SmallInt				*mVertex;
+
+	
+		//	Changes of Strips in LOD file (p).
+		SmallInt	*mPChanges;
+
+		//	Strips vector.
+		SmallIntVector	*mStrips; 	
+
+		///Total of vertices shown at the moment.
+		long	int	mTotal;
+
+		/*
+			Copa STL vectors to C arrays.
+		*/
+		void	CopyVectors2Arrays();
+
+		/*
+			Loads Mesh
+		*/
+		void	LoadStripMesh(char *name, Ogre::Mesh *geomesh);	
+
+		Ogre::Mesh* original_mesh;
+
+		//Number of strips in each submesh
+		int* mStripsSubmesh;
+		
+	public:
+
+		SmallInt	mMaxLod;				///Max level of detail.
+		SmallInt	mMinLod;				///Min level of detail.
+
+		SmallInt	mCurrentLod;		///Current Lod.	
+
+		/// Constructor, receives as a parameter the name of the file including the multiresolution object.
+		LodStripsLibrary(std::string, Ogre::Mesh *geomesh);
+
+		/// Destructor.
+		~LodStripsLibrary(void);
+
+		/// Copy constructor
+		//LodStripsLibrary(const LodStripsLibrary&);
+
+		/// Assignment operator
+		//LodStripsLibrary& operator =(const LodStripsLibrary&);
+
+		/// Returns the highest LOD.
+		Ogre::uint32	MaxLod();
+
+		/// Returns the lowest LOD.
+		Ogre::uint32	MinLod();
+
+		/// Returns de current LOD and changes to the specified LOD.
+		Ogre::uint32	GoToLod(Ogre::uint32);
+
+		/// Establishes the new LOD range.
+		/// Only the LODs in that range are stored and used.
+		void		TrimByLod(Ogre::uint32, Ogre::uint32);
+
+		/// Returns the number of triangles of the highest LOD.
+		Ogre::uint32	MaxFaces();
+
+		/// Returns the number of triangles of the lowest LOD.
+		Ogre::uint32	MinFaces();
+
+		/// Returns the number of vertices of the highest LOD.
+		Ogre::uint32	MaxVertices();
+
+		/// Returns the number of vertices of the lowest LOD.
+		Ogre::uint32	MinVertices();
+
+		//	(New)	Get the number of strips.
+		Ogre::uint32	GetStripCount() const;
+		Ogre::uint32  GetIndexCountByStrip(Ogre::uint32) const;
+};
