Index: CaWE/MapBezierPatch.hpp
===================================================================
--- CaWE/MapBezierPatch.hpp	(revisiÃ³n: 97)
+++ CaWE/MapBezierPatch.hpp	(copia de trabajo)
@@ -180,8 +180,8 @@
     unsigned long       GetWidth()        const { return cv_Width; }
     unsigned long       GetHeight()       const { return cv_Height; }
     // Get the number of vertices in width or height of the rendermesh representation of the bezier patch.
-    unsigned long       GetRenderWidth()  const { UpdateRenderMesh(); return BPRenderMesh->Meshes.Size()+1; }
-    unsigned long       GetRenderHeight() const { UpdateRenderMesh(); assert(BPRenderMesh->Meshes.Size()>0); return BPRenderMesh->Meshes[0]->Vertices.Size()/2; }
+    unsigned long       GetRenderWidth()  const { UpdateRenderMesh(); return BPRenderMesh->MeshWidth; }
+    unsigned long       GetRenderHeight() const { UpdateRenderMesh(); return BPRenderMesh->MeshHeight; }
 
     // Get the origin of vertice x/y from the rendermesh
     Vector3fT           GetRenderVertexPos(unsigned long x, unsigned long y) const;
Index: CaWE/Renderer3D.cpp
===================================================================
--- CaWE/Renderer3D.cpp	(revisiÃ³n: 97)
+++ CaWE/Renderer3D.cpp	(copia de trabajo)
@@ -194,6 +194,7 @@
             Mesh.Vertices[2].SetOrigin(V3); Mesh.Vertices[2].SetColor(rSh, gSh, bSh);
             Mesh.Vertices[3].SetOrigin(V4); Mesh.Vertices[3].SetColor(rSh, gSh, bSh);
 
+            Mesh.Invalidate();
             MatSys::Renderer->SetCurrentMaterial(GetRMatFlatShaded());
             MatSys::Renderer->RenderMesh(Mesh);
         }
@@ -295,6 +296,7 @@
         // mesh, or else the depth offset won't work right (they are probably differently rasterized).
         MatSys::MeshT Mesh(Pass==1 ? MatSys::MeshT::Polygon : MatSys::MeshT::TriangleFan);
         Mesh.Vertices.PushBackEmpty(4);
+        Mesh.Invalidate();
 
         float color[3]={ 0.0f, 0.0f, 0.0f };
         color[Depth % 3]=(Pass==1) ? 1.0f : 0.4f;
@@ -338,6 +340,7 @@
     Mesh.Vertices[5].SetColor(0, 0, 1);
     Mesh.Vertices[5].SetOrigin(Pos + Vector3fT(Mat[0][2], Mat[1][2], Mat[2][2])*Length);
 
+    Mesh.Invalidate();
     MatSys::Renderer->SetCurrentMaterial(GetRMatWireframe());
     MatSys::Renderer->RenderMesh(Mesh);
 }
@@ -370,6 +373,7 @@
     Mesh.Vertices[10].SetOrigin(Center.x, Center.y-RADIUS-1, 0); Mesh.Vertices[10].SetColor(1, 1, 1);
     Mesh.Vertices[11].SetOrigin(Center.x, Center.y+RADIUS,   0); Mesh.Vertices[11].SetColor(1, 1, 1);
 
+    Mesh.Invalidate();
     MatSys::Renderer->SetCurrentMaterial(GetRMatWireframe());
     MatSys::Renderer->RenderMesh(Mesh);
 }
Index: CaWE/MapFace.cpp
===================================================================
--- CaWE/MapFace.cpp	(revisiÃ³n: 97)
+++ CaWE/MapFace.cpp	(copia de trabajo)
@@ -177,6 +177,7 @@
     Mesh.Type=(MatSys::Renderer->GetMaterialFromRM(RenderMat)->PolygonMode==MaterialT::Filled) ? MatSys::MeshT::TriangleFan : MatSys::MeshT::Polygon;
     Mesh.Vertices.Overwrite();
     Mesh.Vertices.PushBackEmpty(m_Vertices.Size());
+    Mesh.Invalidate();
 
     for (unsigned long VertexNr=0; VertexNr<m_Vertices.Size(); VertexNr++)
     {
Index: CaWE/MapBezierPatch.cpp
===================================================================
--- CaWE/MapBezierPatch.cpp	(revisiÃ³n: 97)
+++ CaWE/MapBezierPatch.cpp	(copia de trabajo)
@@ -1176,7 +1176,9 @@
 
 Vector3fT MapBezierPatchT::GetRenderVertexPos(unsigned long x, unsigned long y) const
 {
-    assert(BPRenderMesh->Meshes.Size()>0);
+    assert(false); // Unimplemented
+    return Vector3fT(0.0f, 0.0f, 0.0f);
+    /*assert(BPRenderMesh->Meshes.Size()>0);
     assert(x<=BPRenderMesh->Meshes.Size());
     assert(y<BPRenderMesh->Meshes[0]->Vertices.Size()/2);
 
@@ -1191,5 +1193,5 @@
     VertexPos.y=BPRenderMesh->Meshes[x-c]->Vertices[2*y+c].Origin[1];
     VertexPos.z=BPRenderMesh->Meshes[x-c]->Vertices[2*y+c].Origin[2];
 
-    return VertexPos;
+    return VertexPos;*/
 }
Index: CaWE/MapTerrain.cpp
===================================================================
--- CaWE/MapTerrain.cpp	(revisiÃ³n: 97)
+++ CaWE/MapTerrain.cpp	(copia de trabajo)
@@ -196,6 +196,7 @@
 
     // Finally, draw the terrain.
     m_TerrainMesh.Vertices.Overwrite();
+    m_TerrainMesh.Invalidate();
 
 #if 1
     const ArrayT<Vector3fT>& VectorStrip=GetTerrain().ComputeVectorStrip(VI);
@@ -636,6 +637,7 @@
 
 void MapTerrainT::TrafoMirror(unsigned int NormalAxis, float Dist)
 {
+
     Vector3fT Min=m_TerrainBounds.Min;
     Vector3fT Max=m_TerrainBounds.Max;
 
Index: SConscript
===================================================================
--- SConscript	(revisiÃ³n: 97)
+++ SConscript	(copia de trabajo)
@@ -53,7 +53,7 @@
     # envTools.Append(LINKFLAGS = ['-Wl,--export-dynamic'])     # Not needed any more, .so libs now link to the required .a libs directly, just as under Windows.
     # GLU is needed for the TerrainViewerOld *and* for e.g. gluBuild2DMipmaps() in the renderers...
     envTools.Append(CPPPATH=['/usr/include/freetype2'])         # As of 2009-09-10, this line is to become unnecessary in the future, see /usr/include/ftbuild.h for details.
-    envTools.Append(LIBS=Split("SceneGraph MatSys cfsLib cfsCoreLib cfsLib ClipSys cfs_png cfs_jpeg bulletcollision lua minizip lightwave z")
+    envTools.Append(LIBS=Split("SceneGraph MatSys cfsLib cfsCoreLib cfsLib MatSys ClipSys cfs_png cfs_jpeg bulletcollision lua minizip lightwave z")
                        + Split("GL GLU"))
 
 envTools.Program('CaSanity', ['CaTools/CaSanity.cpp'] + CommonWorldObject)
@@ -97,7 +97,7 @@
     # -Wl,-rpath,.           is so that also the . directory is searched for dynamic libraries when they're opened.
     # -Wl,--export-dynamic   is so that the exe exports its symbols so that the MatSys, SoundSys and game .so libs can in turn resolve theirs.
     envCafu.Append(LINKFLAGS = ['-Wl,-rpath,.', '-Wl,--export-dynamic'])
-    envCafu.Append(LIBS=Split("MatSys SoundSys SceneGraph cfsLib cfsCoreLib cfs_png cfs_jpeg bulletdynamics bulletcollision bulletmath openal alut mpg123 ogg vorbis vorbisfile minizip z lua lightwave ClipSys GuiSysNullEditor"))
+    envCafu.Append(LIBS=Split("SoundSys SceneGraph MatSys cfsLib cfsCoreLib cfs_png cfs_jpeg bulletdynamics bulletcollision bulletmath openal alut mpg123 ogg vorbis vorbisfile minizip z lua lightwave ClipSys GuiSysNullEditor"))
     # We need GLU for e.g. gluBuild2DMipmaps() in the renderers.
     # pthread is needed because some libraries that we load (possibly indirectly), e.g. the libCg.so and libopenal.so, use functions
     # from the pthread library, but have not been linked themselves against it. They rely on the executable to be linked appropriately
Index: Libs/SceneGraph/FaceBatchesNode.cpp
===================================================================
--- Libs/SceneGraph/FaceBatchesNode.cpp	(revisiÃ³n: 0)
+++ Libs/SceneGraph/FaceBatchesNode.cpp	(revisiÃ³n: 0)
@@ -0,0 +1,485 @@
+#include "FaceBatchesNode.hpp"
+#include "LightMapMan.hpp"
+#include "FaceNode.hpp"
+#include "ConsoleCommands/ConVar.hpp"
+#include "MaterialSystem/Material.hpp"
+#include "MaterialSystem/Renderer.hpp"
+
+#include <cassert>
+
+using namespace cf::SceneGraph;
+
+FaceBatchesNodeT::FaceBatchesNodeT(LightMapManT& LMM)
+    : LightMapMan(LMM), ShadowVolumeMesh(MatSys::MeshT::Triangles, MatSys::MeshT::CCW), IsStencilShadowsValid(false)
+{
+    ShadowVolumeMesh.VertexBuffer = NULL;
+}
+
+FaceBatchesNodeT::~FaceBatchesNodeT()
+{
+    // Delete the meshes
+    for(unsigned long Nr=0; Nr<OpaqueMeshes.Size(); Nr++)
+        delete OpaqueMeshes[Nr].Mesh;
+
+    for(unsigned long Nr=0; Nr<TranslucentMeshes.Size(); Nr++)
+        delete TranslucentMeshes[Nr].Mesh;
+
+    // Free the render materials
+    MaterialMapT::iterator it2 = MaterialMap.begin();
+    for(; it2 != MaterialMap.end(); it2++)
+    {
+        MatSys::RenderMaterialT *RenderMat = it2->second;
+        MatSys::Renderer->FreeMaterial(RenderMat);
+    }
+}
+
+void FaceBatchesNodeT::DrawAmbientContrib(const Vector3dT& ViewerPos) const
+{
+    assert(MatSys::Renderer!=NULL);
+    assert(MatSys::Renderer->GetCurrentRenderAction()==MatSys::RendererI::AMBIENT);
+
+    for(unsigned long Nr=0; Nr<OpaqueMeshes.Size(); Nr++)
+    {
+        const MeshDataT &Data = OpaqueMeshes[Nr];
+        const MeshKeyT &Key = Data.MeshKey;
+        const MatSys::MeshT *Mesh = Data.Mesh;
+
+        // Ignore empty meshes
+        if(Data.Empty || Mesh->VertexBuffer->GetSize() == 0)
+            continue;
+
+        if (Key.LightMapNr<LightMapMan.Textures.Size())
+        {
+            MatSys::Renderer->SetCurrentLightMap   (LightMapMan.Textures [Key.LightMapNr]);
+            MatSys::Renderer->SetCurrentLightDirMap(LightMapMan.Textures2[Key.LightMapNr]);
+        }
+
+        MatSys::Renderer->SetCurrentMaterial(Key.RenderMat);
+        MatSys::Renderer->RenderMesh(*Mesh);
+    }
+}
+
+void FaceBatchesNodeT::DrawStencilShadowVolumes(const Vector3dT& LightPos, const float LightRadius) const
+{
+    assert(MatSys::Renderer!=NULL);
+    assert(MatSys::Renderer->GetCurrentRenderAction()==MatSys::RendererI::STENCILSHADOW);
+
+    if(PrepareStencilShadows(LightPos, LightRadius))
+        MatSys::Renderer->RenderMesh(ShadowVolumeMesh);
+}
+
+void FaceBatchesNodeT::DrawLightSourceContrib(const Vector3dT& ViewerPos, const Vector3dT& LightPos) const
+{
+    assert(MatSys::Renderer!=NULL);
+    assert(MatSys::Renderer->GetCurrentRenderAction()==MatSys::RendererI::LIGHTING);
+
+    for(unsigned long Nr=0; Nr<OpaqueMeshes.Size(); Nr++)
+    {
+        const MeshDataT &Data = OpaqueMeshes[Nr];
+        const MeshKeyT &Key = Data.MeshKey;
+        const MatSys::MeshT *Mesh = Data.Mesh;
+
+        // Ignore empty meshes
+        if(Data.Empty || Mesh->VertexBuffer->GetSize() == 0 ||
+           LightMaterials.find(Key) == LightMaterials.end())
+            continue;
+
+        MatSys::Renderer->SetCurrentMaterial(Key.RenderMat);
+        MatSys::Renderer->RenderMesh(*Mesh);
+    }
+}
+
+void FaceBatchesNodeT::DrawTranslucentContrib(const Vector3dT& ViewerPos) const
+{
+    for(unsigned long Nr=0; Nr<TranslucentMeshes.Size(); Nr++)
+    {
+        const MeshDataT &Data = TranslucentMeshes[Nr];
+        const MeshKeyT &Key = Data.MeshKey;
+        const MatSys::MeshT *Mesh = Data.Mesh;
+
+        // Ignore empty meshes
+        if(Data.Empty || Mesh->VertexBuffer->GetSize() == 0)
+            continue;
+
+        if (Key.LightMapNr<LightMapMan.Textures.Size())
+        {
+            MatSys::Renderer->SetCurrentLightMap   (LightMapMan.Textures [Key.LightMapNr]);
+            MatSys::Renderer->SetCurrentLightDirMap(LightMapMan.Textures2[Key.LightMapNr]);
+        }
+
+        MatSys::Renderer->SetCurrentMaterial(Key.RenderMat);
+        MatSys::Renderer->RenderMesh(*Mesh);
+    }
+}
+
+void FaceBatchesNodeT::Reset()
+{
+    NewOpaqueFaces.Overwrite();
+    NewTranslucentFaces.Overwrite();
+}
+
+void FaceBatchesNodeT::AppendOpaqueFace(const FaceNodeT *Face)
+{
+    assert(Face);
+    NewOpaqueFaces.PushBack(Face);
+}
+
+void FaceBatchesNodeT::AppendTranslucentFace(const FaceNodeT *Face)
+{
+    assert(Face);
+    NewTranslucentFaces.PushBack(Face);
+}
+
+void FaceBatchesNodeT::InitLight()
+{
+    ShadowFaces.Overwrite();
+    LightMaterials.clear();
+    IsStencilShadowsValid = false;
+}
+
+void FaceBatchesNodeT::AppendFrontFace(const FaceNodeT *Face)
+{
+    assert(Face);
+    MatSys::RenderMaterialT *RenderMaterial = GetRenderMaterial(Face->Material);
+    unsigned short LightMapNr = Face->LightMapInfo.LightMapNr;
+    LightMaterials.insert(MeshKeyT(RenderMaterial, LightMapNr));
+}
+
+void FaceBatchesNodeT::AppendBackFace(const FaceNodeT *Face)
+{
+    assert(Face);
+    ShadowFaces.PushBack(Face);
+}
+
+bool FaceBatchesNodeT::PrepareStencilShadows(const Vector3dT& LightPos, const float LightRadius) const
+{
+    if(IsStencilShadowsValid)
+        return true;
+
+    unsigned long NrOfFaces = ShadowFaces.Size();
+    if(NrOfFaces == 0)
+        return false;
+
+    // Count the number of vertices and the faces with vertices
+    unsigned long NrOfVertices = 0;
+    unsigned long NrOfIndices = 0;
+    unsigned long NrOfUsableFaces = 0;
+    for(unsigned long Nr=0; Nr < NrOfFaces; Nr++)
+    {
+        const FaceNodeT *Face = ShadowFaces[Nr];
+        const MatSys::MeshT &FaceMesh = Face->GetFaceMesh();
+
+        unsigned long NrOfFaceVertices = FaceMesh.VertexBuffer->GetSize();
+        if(NrOfFaceVertices == 0)
+            continue;
+
+        NrOfVertices += NrOfFaceVertices;
+        //NrOfIndices += /*Caps*/6*(NrOfFaceVertices-2) + /*Silhouette*/NrOfFaceVertices*6;
+        NrOfIndices += 12*NrOfFaceVertices-12;
+        //NrOfIndices += NrOfFaceVertices*6;
+        NrOfUsableFaces++;
+    }
+
+    if(NrOfUsableFaces == 0)
+        return false;
+
+    // Allocate the space
+    if(!ShadowVolumeMesh.VertexBuffer)
+    {
+        ShadowVolumeMesh.VertexBuffer = MatSys::CreateVertexBuffer<StencilVertexT> (MatSys::VertexBufferI::Stream);
+        ShadowVolumeMesh.PrimitiveBuffer = MatSys::CreatePrimitiveBuffer(MatSys::PrimitiveBufferI::UnsignedShort, 
+                                                                         MatSys::PrimitiveBufferI::Stream);
+    }
+
+    ShadowVolumeMesh.VertexBuffer->SetSize(NrOfVertices*2);
+    ShadowVolumeMesh.PrimitiveBuffer->SetSize(NrOfIndices);
+    StencilVertexT *Vertices = (StencilVertexT*)ShadowVolumeMesh.VertexBuffer->LockWrite();
+    unsigned short *Indices = (unsigned short*)ShadowVolumeMesh.PrimitiveBuffer->LockWrite();
+
+    unsigned long VPos = 0;
+    unsigned long IPos = 0;
+    unsigned long FVPos;
+    for(unsigned long Nr=0; Nr < NrOfFaces; Nr++)
+    {
+        const FaceNodeT *Face = ShadowFaces[Nr];
+        const MatSys::MeshT &FaceMesh = Face->GetFaceMesh();
+
+        // Ignore empty faces
+        unsigned long NrOfFaceVertices = FaceMesh.VertexBuffer->GetSize();
+        if(NrOfFaceVertices == 0)
+            continue;
+
+        VertexT *FaceVertices =(VertexT*)FaceMesh.VertexBuffer->LockRead();
+
+        // Store the front and back caps
+        for (unsigned long VertexNr=0; VertexNr<NrOfFaceVertices; VertexNr++)
+        {
+            const VectorT  A=VectorT(FaceVertices[VertexNr].Origin[0], FaceVertices[VertexNr].Origin[1],
+                                     FaceVertices[VertexNr].Origin[2]);
+            const VectorT LA=A-LightPos;
+            Vertices[VPos + VertexNr*2+0].SetOrigin(LA.x, LA.y, LA.z, 0.0);
+            Vertices[VPos + VertexNr*2+1].SetOrigin(A.x, A.y, A.z, 1.0);
+        }
+
+        // Store the front cap indices. Reverse the order
+        for(FVPos = 0; FVPos < NrOfFaceVertices-2; FVPos++)
+        {
+            Indices[IPos + FVPos*3+2] = VPos + 1;
+            Indices[IPos + FVPos*3+1] = VPos + 2*FVPos+3;
+            Indices[IPos + FVPos*3+0] = VPos + 2*FVPos+5;
+        }
+
+        IPos += 3*(NrOfFaceVertices-2);
+
+        // Store the back cap indices
+        for(FVPos = 0; FVPos < NrOfFaceVertices-2; FVPos++)
+        {
+            Indices[IPos + FVPos*3+0] = VPos + 0;
+            Indices[IPos + FVPos*3+1] = VPos + 2*FVPos+2;
+            Indices[IPos + FVPos*3+2] = VPos + 2*FVPos+4;
+        }
+
+        IPos += 3*(NrOfFaceVertices-2);
+
+        // Store the silhoutte indices
+        for(FVPos = 0; FVPos < NrOfFaceVertices-1; FVPos++)
+        {
+            // First quad
+            Indices[IPos + FVPos*6+0] = VPos + 2*FVPos+0;
+            Indices[IPos + FVPos*6+1] = VPos + 2*FVPos+1;
+            Indices[IPos + FVPos*6+2] = VPos + 2*FVPos+2;
+            // Second quad
+            Indices[IPos + FVPos*6+3] = VPos + 2*FVPos+1;
+            Indices[IPos + FVPos*6+4] = VPos + 2*FVPos+3;
+            Indices[IPos + FVPos*6+5] = VPos + 2*FVPos+2;
+
+        }
+
+        // Close the silhoutte
+        // First quad
+        Indices[IPos + FVPos*6+0] = VPos + 2*FVPos+0;
+        Indices[IPos + FVPos*6+1] = VPos + 2*FVPos+1;
+        Indices[IPos + FVPos*6+2] = VPos + 0;
+        // Second quad
+        Indices[IPos + FVPos*6+3] = VPos + 2*FVPos+1;
+        Indices[IPos + FVPos*6+4] = VPos + 1;
+        Indices[IPos + FVPos*6+5] = VPos + 0;
+
+        IPos += NrOfFaceVertices*6;
+        VPos += NrOfFaceVertices*2;
+
+        FaceMesh.VertexBuffer->Unlock();
+    }
+    
+    //printf("NI %d IP %d\n", int(NrOfIndices), int(IPos));
+    // Unlock the buffers
+    ShadowVolumeMesh.VertexBuffer->Unlock();
+    ShadowVolumeMesh.PrimitiveBuffer->Unlock();
+
+    // Prepare the meshes
+    IsStencilShadowsValid = true;
+    return true;
+}
+
+inline bool IsLessFace(const FaceNodeT *F1, const FaceNodeT *F2)
+{
+    // Check if one of the faces is null
+    if(F1 == NULL || F2 == NULL)
+        return F1 < F2;
+
+    if(F1->Material == F2->Material)
+        return F1->LightMapInfo.LightMapNr < F2->LightMapInfo.LightMapNr;
+
+    return F1->Material < F2->Material;
+}
+
+void FaceBatchesNodeT::Finish()
+{
+    // Sort the new opaque faces by material.
+    NewOpaqueFaces.QuickSort(IsLessFace);
+
+    // Check if the opaque faces changed
+    if(OldOpaqueFaces != NewOpaqueFaces)
+    {
+        // Prepare the opaque faces
+        PrepareFaces(NewOpaqueFaces, OpaqueMeshes);
+
+        // Swap the arrays data
+        OldOpaqueFaces.Swap(NewOpaqueFaces);
+    }
+
+    // Check if the translucent face changed
+    if(OldTranslucentFaces != NewTranslucentFaces)
+    {
+        // Prepare the translucent faces
+        PrepareFaces(NewTranslucentFaces, TranslucentMeshes);
+
+        // Swap the arrays data
+        OldTranslucentFaces.Swap(NewTranslucentFaces);
+    }
+}
+
+void FaceBatchesNodeT::PrepareFaces(const FaceListT &Faces, MeshesDataT &Meshes)
+{
+    static MeshesDataT Temp;
+    Temp.Overwrite();
+
+    unsigned long MeshNr = 0;
+    MeshKeyT CurrentKey;
+    unsigned long FaceStart = 0;
+    unsigned long NrOfVertices = 0;
+    unsigned long NrOfIndices = 0;
+    unsigned long Nr;
+    for(Nr=0; Nr < Faces.Size(); Nr++)
+    {
+        const FaceNodeT *Face = Faces[Nr];
+        const MatSys::MeshT &FaceMesh = Face->GetFaceMesh();
+
+        // Ignore empty faces
+        unsigned long NrOfFaceVertices = FaceMesh.VertexBuffer->GetSize();
+        if(NrOfFaceVertices == 0)
+            continue;
+
+        // Extract face key
+        MatSys::RenderMaterialT *RenderMaterial = GetRenderMaterial(Face->Material);
+        unsigned short LightMapNr = Face->LightMapInfo.LightMapNr;
+        MeshKeyT Key(RenderMaterial, LightMapNr);
+
+        // Ignore meshes without material
+        if(!Face->Material)
+            continue;
+
+        // Change current mesh, only if it isn't the first.
+        if(Key != CurrentKey && Nr > 0)
+        {
+            CurrentKey = Key;
+            if(NrOfVertices > 0 && NrOfIndices > 0)
+                Temp.PushBack(PrepareFaceRange(Faces, Meshes, FaceStart, Nr, NrOfVertices, NrOfIndices, MeshNr));
+            FaceStart = Nr;
+            NrOfVertices = 0;
+            NrOfIndices = 0;
+        }
+        
+        // Increase the number of vertices
+        NrOfVertices += NrOfFaceVertices;
+        NrOfIndices += 3*(NrOfFaceVertices-2);
+    }
+
+    // Append the last mesh
+    if(NrOfVertices > 0 && NrOfIndices > 0)
+        Temp.PushBack(PrepareFaceRange(Faces, Meshes, FaceStart, Nr, NrOfVertices, NrOfIndices, MeshNr));
+
+    // Append the remaining meshes into the recycling list, avoids memory leaks
+    for(; MeshNr < Meshes.Size(); MeshNr++)
+    {
+        MeshDataT &MeshData = Meshes[MeshNr];
+        MeshData.Empty = true;
+        Temp.PushBack(MeshData);
+    }
+
+    // Swap the meshes
+    Meshes.Swap(Temp);
+}
+
+FaceBatchesNodeT::MeshDataT FaceBatchesNodeT::PrepareFaceRange(const FaceListT &Faces, MeshesDataT &Meshes,
+                    unsigned long Start, unsigned long End, unsigned long NrOfVertices, unsigned long NrOfIndices,
+                    unsigned long &MeshNr)
+{
+    // Extract face key
+    const FaceNodeT *Face = Faces[Start];
+    MatSys::RenderMaterialT *RenderMaterial = GetRenderMaterial(Face->Material);
+    unsigned short LightMapNr = Face->LightMapInfo.LightMapNr;
+    MeshKeyT Key(RenderMaterial, LightMapNr);
+
+    MeshDataT MeshData;
+    MeshData.MeshKey = Key;
+    MeshData.Empty = false;
+
+    MatSys::MeshT *Mesh;
+    MatSys::VertexBufferI *VertexBuffer;
+    MatSys::PrimitiveBufferI *PrimitiveBuffer;
+
+    // Recycle meshes
+    if(MeshNr < Meshes.Size())
+    {
+        // Prepare the mesh
+        Mesh = Meshes[MeshNr++].Mesh;
+        MeshData.Mesh = Mesh;
+        VertexBuffer = Mesh->VertexBuffer;
+        PrimitiveBuffer = Mesh->PrimitiveBuffer;
+    }
+    else
+    {
+        // Create a new mesh
+        Mesh = new MatSys::MeshT();
+        VertexBuffer = MatSys::CreateVertexBuffer<VertexT> (MatSys::VertexBufferI::Dynamic);
+        PrimitiveBuffer = MatSys::CreatePrimitiveBuffer(MatSys::PrimitiveBufferI::UnsignedShort,
+                                                        MatSys::PrimitiveBufferI::Dynamic);
+        Mesh->VertexBuffer = VertexBuffer;
+        Mesh->PrimitiveBuffer = PrimitiveBuffer;
+        Mesh->Type = MatSys::MeshT::Triangles;
+
+        // Store the mesh
+        MeshData.Mesh = Mesh;
+    }
+
+    // Lock the buffer
+    VertexBuffer->SetSize(NrOfVertices);
+    VertexT *Vertices = (VertexT*) VertexBuffer->LockWrite();
+
+    PrimitiveBuffer->SetSize(NrOfIndices);
+    unsigned short *Indices = (unsigned short*)PrimitiveBuffer->LockWrite();
+
+    unsigned long VPos = 0;
+    unsigned long IPos = 0;
+    for(unsigned long Nr = Start; Nr < End; Nr++)
+    {
+        // Retrieve the face
+        Face = Faces[Nr];
+        const MatSys::MeshT &FaceMesh = Face->GetFaceMesh();
+        const MatSys::VertexBufferI* FaceVertices = FaceMesh.VertexBuffer;
+
+        unsigned long NrOfFaceVertices = FaceVertices->GetSize();
+        if(NrOfFaceVertices == 0) // Ignore empty faces
+            continue;
+
+        // Copy the face vertices
+        VertexT *FVertices = (VertexT *)FaceVertices->LockRead();
+
+        for(unsigned long FVPos = 0; FVPos < NrOfFaceVertices; FVPos++)
+            Vertices[VPos+FVPos] = FVertices[FVPos];
+
+        FaceVertices->Unlock();
+
+        // Store the indices
+        for(unsigned long FVPos = 0; FVPos < NrOfFaceVertices-2; FVPos++)
+        {
+            Indices[IPos + FVPos*3+0] = VPos;
+            Indices[IPos + FVPos*3+1] = VPos + FVPos+1;
+            Indices[IPos + FVPos*3+2] = VPos + FVPos+2;
+        }
+
+        IPos += 3*(NrOfFaceVertices-2);
+        VPos += NrOfFaceVertices;
+    }
+
+    // Unlock the buffers
+    PrimitiveBuffer->Unlock();
+    VertexBuffer->Unlock();
+    return MeshData;
+}
+
+MatSys::RenderMaterialT* FaceBatchesNodeT::GetRenderMaterial(MaterialT* Material)
+{
+    // Retrieve the render material from the map
+    MaterialMapT::const_iterator it = MaterialMap.find(Material);
+    if(it != MaterialMap.end())
+        return it->second;
+
+    // Register the material and store the render material
+    MatSys::RenderMaterialT *RenderMaterial = MatSys::Renderer->RegisterMaterial(Material);
+    MaterialMap[Material] = RenderMaterial;
+    return RenderMaterial;
+}
+
+
Index: Libs/SceneGraph/FaceBatchesNode.hpp
===================================================================
--- Libs/SceneGraph/FaceBatchesNode.hpp	(revisiÃ³n: 0)
+++ Libs/SceneGraph/FaceBatchesNode.hpp	(revisiÃ³n: 0)
@@ -0,0 +1,150 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+#ifndef _CF_SCENEGRAPH_FACEBATCHESNODE_HPP_
+#define _CF_SCENEGRAPH_FACEBATCHESNODE_HPP_
+
+#include <map>
+#include <set>
+#include "Node.hpp"
+#include "MaterialSystem/Mesh.hpp"
+#include "MaterialSystem/VertexFormats.hpp"
+
+namespace MatSys
+{
+    class RenderMaterialT;
+}
+
+class  MaterialT;
+
+namespace cf
+{
+    namespace SceneGraph
+    {
+        class FaceNodeT;
+
+        class FaceBatchesNodeT: public GenericNodeT
+        {
+        public:
+            FaceBatchesNodeT(LightMapManT& LMM);
+            ~FaceBatchesNodeT();
+
+            virtual void DrawAmbientContrib(const Vector3dT& ViewerPos) const;
+            virtual void DrawStencilShadowVolumes(const Vector3dT& LightPos, const float LightRadius) const;
+            virtual void DrawLightSourceContrib(const Vector3dT& ViewerPos, const Vector3dT& LightPos) const;
+            virtual void DrawTranslucentContrib(const Vector3dT& ViewerPos) const;
+
+            // Reset the batch generation
+            void Reset();
+
+            void AppendOpaqueFace(const FaceNodeT *Face);
+            void AppendTranslucentFace(const FaceNodeT *Face);
+
+            // Finish the batch generation
+            void Finish();
+
+            // Lighting
+            void InitLight();
+            void AppendFrontFace(const FaceNodeT *Face);
+            void AppendBackFace(const FaceNodeT *Face);
+
+        private:
+            struct MeshKeyT
+            {
+                MeshKeyT(MatSys::RenderMaterialT *RM = NULL, unsigned short LM = 0)
+                 : RenderMat(RM), LightMapNr(LM) {}
+
+                bool operator<(const MeshKeyT &o) const
+                {
+                    if(RenderMat == o.RenderMat)
+                        return LightMapNr < o.LightMapNr;
+                    return RenderMat < o.RenderMat;
+                }
+
+                bool operator==(const MeshKeyT &o) const
+                {
+                    return RenderMat==o.RenderMat && LightMapNr==o.LightMapNr;
+                }
+
+                bool operator!=(const MeshKeyT &o) const
+                {
+                    return RenderMat!=o.RenderMat || LightMapNr!=o.LightMapNr;
+                }
+
+                MatSys::RenderMaterialT *RenderMat;
+                unsigned short LightMapNr;
+
+            };
+
+            struct MeshDataT
+            {
+                MeshDataT()
+                 : Mesh(NULL), Empty(true) {}
+
+                MatSys::MeshT *Mesh;
+                bool Empty;
+                MeshKeyT MeshKey;
+            };
+
+            typedef MatSys::StaticVertexT VertexT;
+            typedef MatSys::StencilShadowCpuT StencilVertexT;
+
+            typedef std::map<MaterialT*, MatSys::RenderMaterialT*> MaterialMapT;
+            typedef ArrayT<const FaceNodeT*> FaceListT;
+            typedef ArrayT<MeshDataT> MeshesDataT;
+            typedef std::set<MeshKeyT> FaceSetT;
+
+            MatSys::RenderMaterialT* GetRenderMaterial(MaterialT* Material);
+
+            void PrepareFaces(const FaceListT &Faces, MeshesDataT &Meshes);
+            MeshDataT PrepareFaceRange(const FaceListT &Faces, MeshesDataT &Meshes,
+                    unsigned long Start, unsigned long End, unsigned long NrOfVertices, unsigned long NrOfIndices,
+                    unsigned long &MeshNr);
+            bool PrepareStencilShadows(const Vector3dT& LightPos, const float LightRadius) const;
+
+            LightMapManT& LightMapMan;
+            MaterialMapT  MaterialMap;
+
+            // Opaque meshes
+            FaceListT     OldOpaqueFaces;
+            FaceListT     NewOpaqueFaces;
+            MeshesDataT   OpaqueMeshes;
+            
+            // Translucent meshes
+            FaceListT     OldTranslucentFaces;
+            FaceListT     NewTranslucentFaces;
+            MeshesDataT   TranslucentMeshes;
+
+            // Shadow volumes
+            FaceListT             ShadowFaces;
+            mutable MatSys::MeshT ShadowVolumeMesh;
+            mutable bool          IsStencilShadowsValid;
+
+            // Lighting. Recycle ambient faces
+            FaceSetT      LightMaterials;
+        };
+    }
+}
+
+#endif // _CF_SCENEGRAPH_FACEBATCHESNODE_HPP_H
+
Index: Libs/SceneGraph/FaceNode.cpp
===================================================================
--- Libs/SceneGraph/FaceNode.cpp	(revisiÃ³n: 97)
+++ Libs/SceneGraph/FaceNode.cpp	(copia de trabajo)
@@ -242,19 +242,15 @@
     // **********************
 
     Mesh.Type=MatSys::MeshT::TriangleFan;
-    Mesh.Vertices.PushBackEmpty(DrawIndices.Size());
+    Mesh.VertexBuffer = MatSys::CreateVertexBuffer<VertexT> (MatSys::VertexBufferI::Temporal);
+    Mesh.VertexBuffer->SetSize(DrawIndices.Size());
+    VertexT *Vertices = (VertexT*)Mesh.VertexBuffer->LockWrite();
 
     for (unsigned long VertexNr=0; VertexNr<DrawIndices.Size(); VertexNr++)
     {
-        Mesh.Vertices[VertexNr].Origin[0]=SharedVertices[DrawIndices[VertexNr]].x;
-        Mesh.Vertices[VertexNr].Origin[1]=SharedVertices[DrawIndices[VertexNr]].y;
-        Mesh.Vertices[VertexNr].Origin[2]=SharedVertices[DrawIndices[VertexNr]].z;
-        Mesh.Vertices[VertexNr].Origin[3]=1.0;
-
-        Mesh.Vertices[VertexNr].Color[0]=1.0;
-        Mesh.Vertices[VertexNr].Color[1]=1.0;
-        Mesh.Vertices[VertexNr].Color[2]=1.0;
-        Mesh.Vertices[VertexNr].Color[3]=1.0;
+        Vertices[VertexNr].Origin[0]=SharedVertices[DrawIndices[VertexNr]].x;
+        Vertices[VertexNr].Origin[1]=SharedVertices[DrawIndices[VertexNr]].y;
+        Vertices[VertexNr].Origin[2]=SharedVertices[DrawIndices[VertexNr]].z;
     }
 
 
@@ -299,8 +295,8 @@
         const double s=dot(SharedVertices[DrawIndices[VertexNr]], TI_U)/(LengthU*LengthU)+TI.OffsetU-SmallestS;
         const double t=dot(SharedVertices[DrawIndices[VertexNr]], TI_V)/(LengthV*LengthV)+TI.OffsetV-SmallestT;
 
-        Mesh.Vertices[VertexNr].TextureCoord[0]=float(s);
-        Mesh.Vertices[VertexNr].TextureCoord[1]=float(t);
+        Vertices[VertexNr].TextureCoord[0]=float(s);
+        Vertices[VertexNr].TextureCoord[1]=float(t);
     }
 
 
@@ -347,8 +343,8 @@
         const double s=((dot(SharedVertices[DrawIndices[VertexNr]], U)-SmallestU)/LightMapInfoT::PatchSize+1.0+PosS)/double(cf::SceneGraph::LightMapManT::SIZE_S);
         const double t=((dot(SharedVertices[DrawIndices[VertexNr]], V)-SmallestV)/LightMapInfoT::PatchSize+1.0+PosT)/double(cf::SceneGraph::LightMapManT::SIZE_T);
 
-        Mesh.Vertices[VertexNr].LightMapCoord[0]=float(s);
-        Mesh.Vertices[VertexNr].LightMapCoord[1]=float(t);
+        Vertices[VertexNr].LightMapCoord[0]=float(s);
+        Vertices[VertexNr].LightMapCoord[1]=float(t);
     }
 
 #if SHL_ENABLED
@@ -363,8 +359,8 @@
         const double s=(dot(SharedVertices[DrawIndices[VertexNr]], U)/SHLMapInfoT::PatchSize-floor(SmallestU/SHLMapInfoT::PatchSize)+1.0+PosS)/double(cf::SceneGraph::SHLMapManT::SIZE_S);
         const double t=(dot(SharedVertices[DrawIndices[VertexNr]], V)/SHLMapInfoT::PatchSize-floor(SmallestV/SHLMapInfoT::PatchSize)+1.0+PosT)/double(cf::SceneGraph::SHLMapManT::SIZE_T);
 
-        Mesh.Vertices[VertexNr].SHLMapCoord[0]=float(s);
-        Mesh.Vertices[VertexNr].SHLMapCoord[1]=float(t);
+        Vertices[VertexNr].SHLMapCoord[0]=float(s);
+        Vertices[VertexNr].SHLMapCoord[1]=float(t);
     }
 #endif
 
@@ -381,7 +377,7 @@
     const VectorT  TexU     =TI.U.AsVectorOfDouble();
     const VectorT  TexV     =TI.V.AsVectorOfDouble();
 
-    // Note that
+    // Note thatif(!Mesh.VertexBuffer)
     // a) our intention here is to compute the proper coordinate axes of the texture-space,
     // b) the above used 'U' and 'V' span vectors are absolutely useless for this purpose (they are entirely arbitrary and unrelated), and
     // c) the 'TexU' and 'TexV' vectors (together with 'TexNormal') are not correct either.
@@ -415,9 +411,9 @@
     // Fill-in the 'NormalXYZ', 'TangentXYZ', and 'BiNormalXYZ' components of the 'FaceVertexInfos', taking SmoothGroups into account.
     for (unsigned long VertexNr=0; VertexNr<DrawIndices.Size(); VertexNr++)
     {
-        Mesh.Vertices[VertexNr].SetNormal  (TexNormal   .AsVectorOfFloat());
-        Mesh.Vertices[VertexNr].SetTangent (FaceTangent .AsVectorOfFloat());
-        Mesh.Vertices[VertexNr].SetBiNormal(FaceBiNormal.AsVectorOfFloat());
+        Vertices[VertexNr].SetNormal  (TexNormal   .AsVectorOfFloat());
+        Vertices[VertexNr].SetTangent (FaceTangent .AsVectorOfFloat());
+        Vertices[VertexNr].SetBiNormal(FaceBiNormal.AsVectorOfFloat());
     }
 
 
@@ -426,6 +422,7 @@
     // ***********************
 
     RenderMat=MatSys::Renderer->RegisterMaterial(Material);
+    Mesh.VertexBuffer->Unlock();
 }
 
 
@@ -487,6 +484,11 @@
 }
 
 
+const MatSys::MeshT &FaceNodeT::GetFaceMesh() const
+{
+    return Mesh;
+}
+
 void FaceNodeT::WriteTo(std::ostream& OutFile, aux::PoolT& Pool) const
 {
     aux::Write(OutFile, "Face");
@@ -605,21 +607,28 @@
     assert(MatSys::Renderer!=NULL);
     assert(MatSys::Renderer->GetCurrentRenderAction()==MatSys::RendererI::STENCILSHADOW);
 
+    if(!Mesh.VertexBuffer)
+        return;
+
+    VertexT *Vertices = (VertexT*)Mesh.VertexBuffer->LockRead();
+    unsigned long NrOfVertices = Mesh.VertexBuffer->GetSize();
+
     // Render the silhouette quads.
     static MatSys::MeshT SilhouetteMesh(MatSys::MeshT::QuadStrip, MatSys::MeshT::CCW);
     SilhouetteMesh.Vertices.Overwrite();
-    SilhouetteMesh.Vertices.PushBackEmpty(2*Mesh.Vertices.Size()+2);
+    SilhouetteMesh.Vertices.PushBackEmpty(2*NrOfVertices+2);
+    SilhouetteMesh.Invalidate();
 
-    const VectorT  A0=VectorT(Mesh.Vertices[0].Origin[0], Mesh.Vertices[0].Origin[1], Mesh.Vertices[0].Origin[2]);
+    const VectorT  A0=VectorT(Vertices[0].Origin[0], Vertices[0].Origin[1], Vertices[0].Origin[2]);
     const VectorT LA0=A0-LightPos;
 
     // Note that the order is reversed because we're dealing with a back-facing polygon as occluder!
     SilhouetteMesh.Vertices[0].SetOrigin(LA0.x, LA0.y, LA0.z, 0.0);
     SilhouetteMesh.Vertices[1].SetOrigin( A0.x,  A0.y,  A0.z, 1.0);
 
-    for (unsigned long VertexNr=1; VertexNr<Mesh.Vertices.Size(); VertexNr++)
+    for (unsigned long VertexNr=1; VertexNr<NrOfVertices; VertexNr++)
     {
-        const VectorT  A=VectorT(Mesh.Vertices[VertexNr].Origin[0], Mesh.Vertices[VertexNr].Origin[1], Mesh.Vertices[VertexNr].Origin[2]);
+        const VectorT  A=VectorT(Vertices[VertexNr].Origin[0], Vertices[VertexNr].Origin[1], Vertices[VertexNr].Origin[2]);
         const VectorT LA=A-LightPos;
 
         // Note that the order is reversed because we're dealing with a back-facing polygon as occluder!
@@ -627,8 +636,8 @@
         SilhouetteMesh.Vertices[VertexNr*2+1].SetOrigin( A.x,  A.y,  A.z, 1.0);
     }
 
-    SilhouetteMesh.Vertices[Mesh.Vertices.Size()*2+0].SetOrigin(LA0.x, LA0.y, LA0.z, 0.0);  // Close the silhouette for this occluder.
-    SilhouetteMesh.Vertices[Mesh.Vertices.Size()*2+1].SetOrigin( A0.x,  A0.y,  A0.z, 1.0);
+    SilhouetteMesh.Vertices[NrOfVertices*2+0].SetOrigin(LA0.x, LA0.y, LA0.z, 0.0);  // Close the silhouette for this occluder.
+    SilhouetteMesh.Vertices[NrOfVertices*2+1].SetOrigin( A0.x,  A0.y,  A0.z, 1.0);
 
     MatSys::Renderer->RenderMesh(SilhouetteMesh);
 
@@ -639,12 +648,13 @@
     //  we have to reverse the order of its vertices in order to turn it into a CCW ordered, front-facing polygon.)
     static MatSys::MeshT M_front(MatSys::MeshT::TriangleFan, MatSys::MeshT::CCW);
     M_front.Vertices.Overwrite();
-    M_front.Vertices.PushBackEmpty(Mesh.Vertices.Size());
+    M_front.Vertices.PushBackEmpty(NrOfVertices);
+    M_front.Invalidate();
 
-    for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-        M_front.Vertices[M_front.Vertices.Size()-VertexNr-1].SetOrigin(Mesh.Vertices[VertexNr].Origin[0],
-                                                                       Mesh.Vertices[VertexNr].Origin[1],
-                                                                       Mesh.Vertices[VertexNr].Origin[2], 1.0);
+    for (unsigned long VertexNr=0; VertexNr<NrOfVertices; VertexNr++)
+        M_front.Vertices[M_front.Vertices.Size()-VertexNr-1].SetOrigin(Vertices[VertexNr].Origin[0],
+                                                                       Vertices[VertexNr].Origin[1],
+                                                                       Vertices[VertexNr].Origin[2], 1.0);
 
     // What a pity the order isn't the other way round. Could then simply write:  MatSys::Renderer->RenderMesh(Mesh);
     MatSys::Renderer->RenderMesh(M_front);
@@ -655,14 +665,16 @@
     // we just have to project them to infinity as seen from the light source.
     static MatSys::MeshT M_back(MatSys::MeshT::TriangleFan, MatSys::MeshT::CCW);
     M_back.Vertices.Overwrite();
-    M_back.Vertices.PushBackEmpty(Mesh.Vertices.Size());
+    M_back.Vertices.PushBackEmpty(NrOfVertices);
+    M_back.Invalidate();
 
-    for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-        M_back.Vertices[VertexNr].SetOrigin(Mesh.Vertices[VertexNr].Origin[0]-LightPos.x,
-                                            Mesh.Vertices[VertexNr].Origin[1]-LightPos.y,
-                                            Mesh.Vertices[VertexNr].Origin[2]-LightPos.z, 0.0);
+    for (unsigned long VertexNr=0; VertexNr<NrOfVertices; VertexNr++)
+        M_back.Vertices[VertexNr].SetOrigin(Vertices[VertexNr].Origin[0]-LightPos.x,
+                                            Vertices[VertexNr].Origin[1]-LightPos.y,
+                                            Vertices[VertexNr].Origin[2]-LightPos.z, 0.0);
 
     MatSys::Renderer->RenderMesh(M_back);
+    Mesh.VertexBuffer->Unlock();
 }
 
 
Index: Libs/SceneGraph/BezierPatchNode.cpp
===================================================================
--- Libs/SceneGraph/BezierPatchNode.cpp	(revisiÃ³n: 97)
+++ Libs/SceneGraph/BezierPatchNode.cpp	(copia de trabajo)
@@ -54,8 +54,12 @@
       Material(NULL),
       LightMapInfo(),
       LightMapMan(LMM),
-      RenderMaterial(NULL)
+      Mesh(MatSys::MeshT::TriangleStrip),
+      RenderMaterial(NULL),
+      MeshWidth(1),
+      MeshHeight(1)
 {
+    Mesh.VertexBuffer = NULL;
     Init();
 }
 
@@ -71,7 +75,10 @@
       Material(Material_),
       LightMapInfo(),
       LightMapMan(LMM),
-      RenderMaterial(NULL)
+      Mesh(MatSys::MeshT::TriangleStrip),
+      RenderMaterial(NULL),
+      MeshWidth(1),
+      MeshHeight(1)
 {
     for (unsigned long ComponentNr=0; ComponentNr<ControlPoints_.Size(); ComponentNr+=5)
     {
@@ -79,6 +86,7 @@
         ControlPointsUV .PushBack(Vector3fT(ControlPoints_[ComponentNr+3], ControlPoints_[ComponentNr+4], 0.0f));
     }
 
+    Mesh.VertexBuffer = NULL;
     Init();
 }
 
@@ -94,8 +102,12 @@
       Material(Material_),
       LightMapInfo(),
       LightMapMan(LMM),
-      RenderMaterial(NULL)
+      Mesh(MatSys::MeshT::TriangleStrip),
+      RenderMaterial(NULL),
+      MeshWidth(1),
+      MeshHeight(1)
 {
+    Mesh.VertexBuffer = NULL;
     Init();
 }
 
@@ -272,8 +284,7 @@
     // cLOD Überlegungen sind denkbar - siehe "r_lodCurveError" convar im Q3 Quellcode.
     // Siehe http://xreal.sourceforge.net/xrealwiki/XMapExplanations
     // Aber: Sind wg. Tangent-Space viel aufwendiger als bei Q3... Performance?
-    for (unsigned long MeshNr=0; MeshNr<Meshes.Size(); MeshNr++)
-        MatSys::Renderer->RenderMesh(*Meshes[MeshNr]);
+    MatSys::Renderer->RenderMesh(Mesh);
 
 #if 0
     // Render the tangent-space axes (for debugging).
@@ -322,9 +333,7 @@
     assert(MatSys::Renderer->GetCurrentRenderAction()==MatSys::RendererI::LIGHTING);
 
     MatSys::Renderer->SetCurrentMaterial(RenderMaterial);
-
-    for (unsigned long MeshNr=0; MeshNr<Meshes.Size(); MeshNr++)
-        MatSys::Renderer->RenderMesh(*Meshes[MeshNr]);
+    MatSys::Renderer->RenderMesh(Mesh);
 }
 
 
@@ -339,17 +348,19 @@
 
 void BezierPatchNodeT::UpdateMeshColor(const float red, const float green, const float blue, const float alpha)
 {
-    for (unsigned int i=0; i<Meshes.Size(); i++)
+    if(!Mesh.VertexBuffer)
+        return;
+
+    // WARNING: This is a potential performance bottleneck
+    VertexT *Vertices = (VertexT*)Mesh.VertexBuffer->LockReadWrite();
+    for(unsigned int j=0; j<Mesh.VertexBuffer->GetSize(); j++)
     {
-        MatSys::MeshT* currentMesh=Meshes[i];
-        for(unsigned int j=0; j<currentMesh->Vertices.Size(); j++)
-        {
-            currentMesh->Vertices[j].Color[0]=red;
-            currentMesh->Vertices[j].Color[1]=green;
-            currentMesh->Vertices[j].Color[2]=blue;
-            currentMesh->Vertices[j].Color[3]=alpha;
-        }
+        Vertices[j].Color[0]=red;
+        Vertices[j].Color[1]=green;
+        Vertices[j].Color[2]=blue;
+        Vertices[j].Color[3]=alpha;
     }
+    Mesh.VertexBuffer->Unlock();
 }
 
 
@@ -440,6 +451,10 @@
     PatchMesh.Height=PatchMesh.WrapsVert ? LightMapInfo.SizeT-1 : LightMapInfo.SizeT;
     PatchMesh.Patches.PushBackEmpty(PatchMesh.Width*PatchMesh.Height);
 
+
+
+
+
     PatchMesh.Node    =this;
     PatchMesh.Material=Material;
 
@@ -685,7 +700,7 @@
 }
 
 
-static void AssignMatSysFromBezierPatchVertex(MatSys::MeshT::VertexT& msV, const cf::math::BezierPatchT<float>::VertexT& bpV)
+static void AssignMatSysFromBezierPatchVertex(cf::SceneGraph::BezierPatchNodeT::VertexT& msV, const cf::math::BezierPatchT<float>::VertexT& bpV)
 {
     msV.SetOrigin       (bpV.Coord);
     msV.SetColor        (0.0, 1.0, 1.0);    // For debugging materials that use "useMeshColors".
@@ -733,16 +748,28 @@
     GenerateLightMapMesh(CurveMesh, true);
 #endif
 
-    // Copy the curve mesh into MatSys meshes.
+    // Allocate the vertex buffr
+    if(!Mesh.VertexBuffer)
+        Mesh.VertexBuffer = MatSys::CreateVertexBuffer<VertexT> (MatSys::VertexBufferI::Static);
+
+    // Store the mesh size
+    MeshWidth = CurveMesh.Width;
+    MeshHeight = CurveMesh.Height;
+
+    // Calculate mesh sizes
+    const unsigned long RangeCount = 2*CurveMesh.Height;
+    const unsigned long NrOfVertices =RangeCount*(CurveMesh.Width-1);
+    Mesh.VertexBuffer->SetSize(NrOfVertices);
+    VertexT *Vertices = (VertexT*)Mesh.VertexBuffer->LockWrite();
+
     for (unsigned long ColumnNr=0; ColumnNr+1<CurveMesh.Width; ColumnNr++)
     {
         // There is one triangle strip for each column of the curve mesh.
-        Meshes.PushBack(new MatSys::MeshT(MatSys::MeshT::TriangleStrip));
-        Meshes[ColumnNr]->Vertices.PushBackEmpty(2*CurveMesh.Height);
-
+        const unsigned long Pos = RangeCount*ColumnNr;
+        Mesh.SubRanges.PushBack(MatSys::MeshT::RangeT(Pos, RangeCount));
         for (unsigned long RowNr=0; RowNr<CurveMesh.Height; RowNr++)
         {
-            MatSys::MeshT::VertexT& Left =Meshes[ColumnNr]->Vertices[RowNr*2+0];
+            VertexT& Left =Vertices[Pos + RowNr*2+0];
 
             AssignMatSysFromBezierPatchVertex(Left, CurveMesh.GetVertex(ColumnNr, RowNr));
 
@@ -750,20 +777,25 @@
             const float LeftLmT=(float(LightMapInfo.PosT)+0.5f + (float(RowNr   )/(CurveMesh.Height-1))*(LightMapInfo.SizeT-1)) / cf::SceneGraph::LightMapManT::SIZE_T;
 
             Left.SetLightMapCoord(LeftLmS, LeftLmT);
+#if SHL_ENABLED
             Left.SetSHLMapCoord  (LeftLmS, LeftLmT);
+#endif
 
+            VertexT& Right=Vertices[Pos + RowNr*2+1];
 
-            MatSys::MeshT::VertexT& Right=Meshes[ColumnNr]->Vertices[RowNr*2+1];
-
             AssignMatSysFromBezierPatchVertex(Right, CurveMesh.GetVertex(ColumnNr+1, RowNr));
 
             const float RightLmS=(float(LightMapInfo.PosS)+0.5f + (float(ColumnNr+1)/(CurveMesh.Width -1))*(LightMapInfo.SizeS-1)) / cf::SceneGraph::LightMapManT::SIZE_S;
             const float RightLmT=LeftLmT;
 
             Right.SetLightMapCoord(RightLmS, RightLmT);
+#if SHL_ENABLED
             Right.SetSHLMapCoord  (RightLmS, RightLmT);
+#endif
         }
     }
+
+    Mesh.VertexBuffer->Unlock();
 #else
     /*** OLD METHOD ***/
 
@@ -886,6 +918,7 @@
                     }
 
                     if (AbsIndexX<TotalNrOfTriangleColumns)
+
                     {
                         MatSys::MeshT::VertexT& V=Meshes[AbsIndexX]->Vertices[AbsIndexY*2];
 
@@ -912,8 +945,12 @@
 
 void BezierPatchNodeT::Clean()
 {
-    for (unsigned long MeshNr=0; MeshNr<Meshes.Size(); MeshNr++) delete Meshes[MeshNr];
-    Meshes.Clear();
+    if(Mesh.VertexBuffer)
+    {
+        delete Mesh.VertexBuffer;
+        Mesh.VertexBuffer = NULL;
+        Mesh.SubRanges.Overwrite();
+    }
 
     if (RenderMaterial!=NULL)
     {
Index: Libs/SceneGraph/FaceNode.hpp
===================================================================
--- Libs/SceneGraph/FaceNode.hpp	(revisiÃ³n: 97)
+++ Libs/SceneGraph/FaceNode.hpp	(copia de trabajo)
@@ -44,6 +44,7 @@
         class FaceNodeT : public GenericNodeT
         {
             public:
+            typedef MatSys::StaticVertexT VertexT;
 
             struct TexInfoT
             {
@@ -123,6 +124,8 @@
             void CreatePatchMeshes(ArrayT<PatchMeshT>& PatchMeshes, ArrayT< ArrayT< ArrayT<Vector3dT> > >& SampleCoords) const;
             void BackToLightMap(const PatchMeshT& PatchMesh);
 
+            /// Returns the face mesh. For FaceBatchesNode
+            const MatSys::MeshT &GetFaceMesh() const;
 
             // TODO: The stuff below should actually be protected or private rather than public.
             // However, it used to be in the obsolete FaceT struct that I used earlier, and a lot of Code (CaBSP, CaLight etc.)
Index: Libs/SceneGraph/BspTreeNode.cpp
===================================================================
--- Libs/SceneGraph/BspTreeNode.cpp	(revisiÃ³n: 97)
+++ Libs/SceneGraph/BspTreeNode.cpp	(copia de trabajo)
@@ -24,6 +24,7 @@
 #include "BspTreeNode.hpp"
 #include "_aux.hpp"
 #include "FaceNode.hpp"
+#include "FaceBatchesNode.hpp"
 #include "ConsoleCommands/ConVar.hpp"
 #include "MaterialSystem/Material.hpp"
 #include "MaterialSystem/Renderer.hpp"
@@ -39,6 +40,7 @@
 BspTreeNodeT::BspTreeNodeT()
     : NextLightNeedsInit(true)
 {
+    FaceBatches = NULL;
 }
 
 
@@ -46,6 +48,7 @@
     LightMapManT& LMM, SHLMapManT& SMM, PlantDescrManT& PDM, const ArrayT<const TerrainT*>& ShTe)
 {
     BspTreeNodeT* BspTree=new BspTreeNodeT();
+    BspTree->FaceBatches = new FaceBatchesNodeT(LMM);
 
     // Read the FaceChildren.
     for (unsigned long Count=aux::ReadUInt32(InFile); Count>0; Count--)
@@ -154,6 +157,9 @@
 
     for (unsigned long ChildNr=0; ChildNr<OtherChildren.Size(); ChildNr++)
         delete OtherChildren[ChildNr];
+
+    if(FaceBatches)
+        delete FaceBatches;
 }
 
 
@@ -315,6 +321,8 @@
     // b) Eine Liste der relevanten, translucent Faces, die anschließend back-to-front gezeichnet werden (für korrektes Blending).
     BackToFrontListOpaque.Overwrite();
     BackToFrontListTranslucent.Overwrite();
+    if(FaceBatches)
+        FaceBatches->Reset();
 
     for (unsigned long OrderNr=0; OrderNr<OrderedLeaves.Size(); OrderNr++)
     {
@@ -336,8 +344,16 @@
 
             FaceChildIsInViewerPVS[ChildNr]=true;
 
-            if (FaceNode->IsOpaque()) BackToFrontListOpaque     .PushBack(FaceNode);
-                                 else BackToFrontListTranslucent.PushBack(FaceNode);
+            if(FaceBatches)
+            {
+                if (FaceNode->IsOpaque()) FaceBatches->AppendOpaqueFace(FaceNode);
+                else FaceBatches->AppendTranslucentFace(FaceNode);
+            }
+            else
+            {
+                if (FaceNode->IsOpaque()) BackToFrontListOpaque     .PushBack(FaceNode);
+                else BackToFrontListTranslucent.PushBack(FaceNode);
+            }
         }
 
         // Sort the "regular" children more in front than the faces - it likely gives a better overall back-to-front order.
@@ -362,6 +378,11 @@
         }
     }
 
+    if(FaceBatches)
+    {
+        FaceBatches->Finish();
+        FaceBatches->DrawAmbientContrib(ViewerPos);
+    }
 
     for (unsigned long Count=BackToFrontListOpaque.Size(); Count>0;)
     {
@@ -393,6 +414,9 @@
     FrontFacingList.Overwrite();
     BackFacingList.Overwrite();
 
+    if(FaceBatches)
+        FaceBatches->InitLight();
+
     for (unsigned long LeafNr=0; LeafNr<Leaves.Size(); LeafNr++)
     {
         const LeafT& L=Leaves[LeafNr];
@@ -429,14 +453,20 @@
              // if (FaceNode->TI.Alpha!=255) continue;                      // Only fully opaque surfaces receive light (even if FLAG_ISWATER is set).
              // if (FaceNode->Material->NoDynLight) continue;               // [This is not really needed here, just for symmetry. This is no meta keyword as NoShadows should be.]
 
-                FrontFacingList.PushBack(FaceNode);
+                if(FaceBatches)
+                    FaceBatches->AppendFrontFace(FaceNode);
+                else
+                    FrontFacingList.PushBack(FaceNode);
             }
             else
             {
                 // Back-facing face wrt. the light (SHADOW CASTER).
                 if (FaceNode->Material->NoShadows) continue;                // Faces with materials that have NoShadows set don't cast shadows.
 
-                BackFacingList.PushBack(FaceNode);
+                if(FaceBatches)
+                    FaceBatches->AppendBackFace(FaceNode);
+                else
+                    BackFacingList.PushBack(FaceNode);
             }
         }
 
@@ -475,6 +505,9 @@
 
     if (NextLightNeedsInit) InitForNextLight();
 
+    if(FaceBatches)
+       FaceBatches->DrawStencilShadowVolumes(LightPos, LightRadius);
+
     for (unsigned long Count=0; Count<BackFacingList.Size(); Count++)
         BackFacingList[Count]->DrawStencilShadowVolumes(LightPos, LightRadius);
 }
@@ -487,6 +520,9 @@
 
     if (NextLightNeedsInit) InitForNextLight();
 
+    if(FaceBatches)
+        FaceBatches->DrawLightSourceContrib(ViewerPos, LightPos);
+
     for (unsigned long Count=0; Count<FrontFacingList.Size(); Count++)
         FrontFacingList[Count]->DrawLightSourceContrib(ViewerPos, LightPos);
 
@@ -499,6 +535,9 @@
     assert(MatSys::Renderer!=NULL);
     assert(MatSys::Renderer->GetCurrentRenderAction()==MatSys::RendererI::AMBIENT);
 
+    if(FaceBatches)
+        FaceBatches->DrawTranslucentContrib(ViewerPos);
+
     // Render translucent nodes back-to-front.
     for (unsigned long Count=0; Count<BackToFrontListTranslucent.Size(); Count++)
         BackToFrontListTranslucent[Count]->DrawTranslucentContrib(ViewerPos);
@@ -589,6 +628,8 @@
         VB_Trace3T<double> OtherChildrenTrace(1.0);
 
         for (unsigned long SetNr=0; SetNr<Leaf.OtherChildrenSet.Size(); SetNr++)
+
+
         {
             const unsigned long ChildNr=Leaf.OtherChildrenSet[SetNr];
 
Index: Libs/SceneGraph/TerrainNode.cpp
===================================================================
--- Libs/SceneGraph/TerrainNode.cpp	(revisiÃ³n: 97)
+++ Libs/SceneGraph/TerrainNode.cpp	(copia de trabajo)
@@ -212,6 +212,7 @@
     static MatSys::MeshT TerrainMesh(MatSys::MeshT::TriangleStrip);
     TerrainMesh.Vertices.Overwrite();
     TerrainMesh.Vertices.PushBackEmpty(VectorStrip.Size());
+    TerrainMesh.Invalidate();
 
     for (unsigned long VNr=0; VNr<VectorStrip.Size(); VNr++)
         TerrainMesh.Vertices[VNr].SetOrigin(VectorStrip[VNr]);
Index: Libs/SceneGraph/BezierPatchNode.hpp
===================================================================
--- Libs/SceneGraph/BezierPatchNode.hpp	(revisiÃ³n: 97)
+++ Libs/SceneGraph/BezierPatchNode.hpp	(copia de trabajo)
@@ -25,13 +25,12 @@
 #define _CF_SCENEGRAPH_BEZIERPATCHNODE_HPP_
 
 #include "Node.hpp"
+#include "MaterialSystem/Mesh.hpp"
 
-
 class MapBezierPatchT;
 
 namespace MatSys
 {
-    class MeshT;
     class RenderMaterialT;
 }
 
@@ -52,6 +51,7 @@
 
 
             public:
+            typedef MatSys::StaticVertexColorT VertexT;
 
             /// The constructor for creating an "empty" bezier patch.
             /// Needed e.g. by the named constructor CreateFromFile_cw() below.
@@ -91,7 +91,6 @@
 
 
             private:
-
             struct LightMapInfoT
             {
                 unsigned short LightMapNr;  ///< In welcher LightMap liegt unsere Teil-LightMap?
@@ -136,8 +135,10 @@
             // Additional information for an entire patch (not only a 3x3 sub-patch).
             LightMapManT&            LightMapMan;
             BoundingBox3T<double>    BB;        ///< The BB of this bezier patch.
-            ArrayT<MatSys::MeshT*>   Meshes;
+            MatSys::MeshT            Mesh;
             MatSys::RenderMaterialT* RenderMaterial;
+            unsigned long            MeshWidth;
+            unsigned long            MeshHeight;
         };
     }
 }
Index: Libs/SceneGraph/BspTreeNode.hpp
===================================================================
--- Libs/SceneGraph/BspTreeNode.hpp	(revisiÃ³n: 97)
+++ Libs/SceneGraph/BspTreeNode.hpp	(copia de trabajo)
@@ -40,6 +40,7 @@
     namespace SceneGraph
     {
         class FaceNodeT;
+        class FaceBatchesNodeT;
 
 
         /// The class represents a BSP Tree node, implementing the Composite design pattern.
@@ -172,6 +173,7 @@
             mutable ArrayT<cf::SceneGraph::GenericNodeT*> FrontFacingList;
             mutable ArrayT<cf::SceneGraph::GenericNodeT*> BackFacingList;
             mutable bool                                  NextLightNeedsInit;
+            mutable FaceBatchesNodeT*                     FaceBatches;
         };
     }
 }
Index: Libs/GuiSys/GuiImpl.cpp
===================================================================
--- Libs/GuiSys/GuiImpl.cpp	(revisiÃ³n: 97)
+++ Libs/GuiSys/GuiImpl.cpp	(copia de trabajo)
@@ -337,6 +337,7 @@
         static MatSys::MeshT CrossMesh(MatSys::MeshT::Lines);
         CrossMesh.Vertices.Overwrite();
         CrossMesh.Vertices.PushBackEmpty(4);     // Just a single quad for the background rectangle.
+        CrossMesh.Invalidate();
 
         for (unsigned long VertexNr=0; VertexNr<CrossMesh.Vertices.Size(); VertexNr++)
         {
@@ -386,6 +387,7 @@
     // Note that the processing of the mouse event is orthogonal to (independent of) MouseIsShown.
     // That is, we may be active and interactive even if the mouse cursor is *not* shown,
     // as for example with the 3D window of the Cafu engine client, which must receive the
+
     // mouse events even if no mouse cursor is shown!
 
     bool MEWasProcessed=false;      // If the Lua script handler consumed the event.
Index: Libs/GuiSys/Window.cpp
===================================================================
--- Libs/GuiSys/Window.cpp	(revisiÃ³n: 97)
+++ Libs/GuiSys/Window.cpp	(copia de trabajo)
@@ -356,6 +356,7 @@
     static MatSys::MeshT BackMesh(MatSys::MeshT::Quads);
     BackMesh.Vertices.Overwrite();
     BackMesh.Vertices.PushBackEmpty(4);     // Just a single quad for the background rectangle.
+    BackMesh.Invalidate();
 
     for (unsigned long VertexNr=0; VertexNr<BackMesh.Vertices.Size(); VertexNr++)
     {
@@ -385,6 +386,7 @@
         static MatSys::MeshT BorderMesh(MatSys::MeshT::Quads);
         BorderMesh.Vertices.Overwrite();
         BorderMesh.Vertices.PushBackEmpty(4*4);     // One rectangle for each side of the background.
+        BorderMesh.Invalidate();
 
         for (unsigned long VertexNr=0; VertexNr<BorderMesh.Vertices.Size(); VertexNr++)
         {
Index: Libs/Models/Model_cmdl.cpp
===================================================================
--- Libs/Models/Model_cmdl.cpp	(revisiÃ³n: 97)
+++ Libs/Models/Model_cmdl.cpp	(copia de trabajo)
@@ -994,6 +994,7 @@
     for (unsigned long MeshNr=0; MeshNr<m_Meshes.Size(); MeshNr++)
     {
         const MeshT& Mesh=m_Meshes[MeshNr];
+        m_Draw_Meshes[MeshNr].Invalidate();
 
         for (unsigned long TriNr=0; TriNr<Mesh.Triangles.Size(); TriNr++)
         {
@@ -1181,6 +1182,7 @@
 
                 // Note that we have to cull the following polygons wrt. the *VIEWER* (not the light source)!
                 static MatSys::MeshT MeshSilhouette(MatSys::MeshT::Quads);  // The default winding order is "CW".
+                MeshSilhouette.Invalidate();
                 MeshSilhouette.Vertices.Overwrite();
 
                 for (unsigned long TriNr=0; TriNr<Mesh.Triangles.Size(); TriNr++)
@@ -1215,10 +1217,10 @@
                     }
                 }
 
-                MatSys::Renderer->RenderMesh(MeshSilhouette);
+                if(MeshSilhouette.Vertices.Size() > 0) MatSys::Renderer->RenderMesh(MeshSilhouette);
 
-
                 static MatSys::MeshT MeshCaps(MatSys::MeshT::Triangles);    // The default winding order is "CW".
+                MeshCaps.Invalidate();
                 MeshCaps.Vertices.Overwrite();
 
                 for (unsigned long TriNr=0; TriNr<Mesh.Triangles.Size(); TriNr++)
@@ -1251,7 +1253,7 @@
                     MeshCaps.Vertices[MeshSize-1].SetOrigin(LA, 0.0);
                 }
 
-                MatSys::Renderer->RenderMesh(MeshCaps);
+                if(MeshCaps.Vertices.Size() > 0) MatSys::Renderer->RenderMesh(MeshCaps);
             }
 
             break;
Index: Libs/Models/Model_mdl.hpp
===================================================================
--- Libs/Models/Model_mdl.hpp	(revisiÃ³n: 97)
+++ Libs/Models/Model_mdl.hpp	(copia de trabajo)
@@ -54,6 +54,8 @@
 
 
     private:
+    typedef MatSys::StaticVertexT SoftSkinVertexT;
+    typedef MatSys::StaticVertexT HardSkinVertexT;
 
     struct TriangleInfoT
     {
@@ -70,6 +72,7 @@
     ArrayT<MaterialT*>               Materials;                 ///< The MatSys materials (only needed for the ugly optimization below, in order to see whether the Normal-Map is empty or not).
     ArrayT<MatSys::RenderMaterialT*> RenderMaterials;           ///< The MatSys render materials.
     ArrayT< ArrayT<TriangleInfoT> >  TriangleInfos;             ///< For the first model of each body part, this contains information about each triangle across all meshes of that model.
+    ArrayT< ArrayT<MatSys::MeshT*> > RenderMeshes;              ///< Each boypart sub meshes
     ArrayT< ArrayT< ArrayT<int> > >  TrianglesReferingToNormal; ///< For each normal of the first model of each body part, this is a list of triangle indices into TriangleInfos of triangles that refer to this normal (with one vertex).
 
     // Convenient abbreviations into the above data arrays
Index: Libs/Models/Model_mdl.cpp
===================================================================
--- Libs/Models/Model_mdl.cpp	(revisiÃ³n: 97)
+++ Libs/Models/Model_mdl.cpp	(copia de trabajo)
@@ -302,11 +302,14 @@
         const int              SkinNr         =0;
         const short*           SkinRefs       =((short*)((char*)StudioTextureHeader+StudioTextureHeader->SkinIndex)) + (SkinNr<StudioTextureHeader->NumSkinFamilies ? SkinNr*StudioTextureHeader->NumSkinRef : 0);
 
+        RenderMeshes.PushBack(ArrayT<MatSys::MeshT*> ());
+
         for (int MeshNr=0; MeshNr<CurrentModel.NumMesh; MeshNr++)
         {
             const StudioMeshT&  CurrentMesh   =StudioMeshes[MeshNr];
             const signed short* TriangleStrips=(signed short*)(&ModelData[0]+CurrentMesh.TriIndex);
-
+            unsigned long NrOfMeshVertices = 0;
+            unsigned long NrOfIndices = 0;
             while (*TriangleStrips)
             {
                 // Anzahl und Art (FAN vs. STRIP) der Vertices im nächsten TriangleStrip.
@@ -359,7 +362,76 @@
                 }
 
                 TriangleStrips+=4*NrOfVertices;
+                NrOfMeshVertices += NrOfVertices;
+                NrOfIndices += 3*(NrOfVertices-2);
             }
+
+            // Compute triangle indices information.
+            // Create the render mesh.
+            MatSys::MeshT *RenderMesh = new MatSys::MeshT(MatSys::MeshT::Triangles);
+
+            // Create the vertex buffer.
+            RenderMesh->VertexBuffer = MatSys::CreateVertexBuffer<SoftSkinVertexT> (MatSys::VertexBufferI::Dynamic);
+            RenderMesh->VertexBuffer->SetSize(NrOfMeshVertices);
+
+            // Create the index buffer.
+            RenderMesh->PrimitiveBuffer = MatSys::CreatePrimitiveBuffer (MatSys::PrimitiveBufferI::UnsignedShort, MatSys::PrimitiveBufferI::Static);
+            RenderMesh->PrimitiveBuffer->SetSize(NrOfIndices);
+
+            // Fill the index buffer.
+            unsigned short *Indices = (unsigned short*)RenderMesh->PrimitiveBuffer->LockWrite();
+            TriangleStrips=(signed short*)(&ModelData[0]+CurrentMesh.TriIndex);
+            unsigned long VPos = 0;
+            unsigned long IPos = 0;
+            while (*TriangleStrips)
+            {
+                signed short NrOfVertices=*(TriangleStrips++);
+                bool         IsTriangleFan   =false;
+
+                if (NrOfVertices<0)
+                {
+                    // Triangle fan.
+                    NrOfVertices = -NrOfVertices; // Use a positive sign.
+                    IsTriangleFan = true;
+                }
+
+                // Triangle strip.
+                for(unsigned long StripPos = 0; StripPos < (unsigned long)NrOfVertices-2; StripPos++)
+                {
+                    if(IsTriangleFan)
+                    {
+                        Indices[IPos + StripPos*3+0] = VPos;
+                        Indices[IPos + StripPos*3+1] = VPos + StripPos+1;
+                        Indices[IPos + StripPos*3+2] = VPos + StripPos+2;
+                    }
+                    else
+                    {
+                        if(StripPos & 1)
+                        {
+                            // Odd position
+                            Indices[IPos + StripPos*3+0] = VPos + StripPos+1;
+                            Indices[IPos + StripPos*3+1] = VPos + StripPos;
+                            Indices[IPos + StripPos*3+2] = VPos + StripPos+2;
+                        }
+                        else
+                        {
+                            // Even Position
+                            Indices[IPos + StripPos*3+0] = VPos + StripPos;
+                            Indices[IPos + StripPos*3+1] = VPos + StripPos+1;
+                            Indices[IPos + StripPos*3+2] = VPos + StripPos+2;
+                        }
+                    }
+                }
+
+                // Increase the dest positions
+                VPos += NrOfVertices;
+                IPos += 3*(NrOfVertices-2);
+                TriangleStrips+=4*NrOfVertices;
+            }
+
+            // Unlock the index buffer and store th render mesh.
+            RenderMesh->PrimitiveBuffer->Unlock();
+            RenderMeshes[BodyPartNr].PushBack(RenderMesh);
         }
 
         // Compute additional triangle information (neighbours).
@@ -1070,6 +1142,8 @@
                 else
                 {
                     // Should never occur...
+
+
                     TriangleTangents[TriangleNr][0]=1.0;
                     TriangleTangents[TriangleNr][1]=0.0;
                     TriangleTangents[TriangleNr][2]=0.0;
@@ -1157,6 +1231,7 @@
             static MatSys::MeshT MeshSilhouette(MatSys::MeshT::Quads);
 
             MeshSilhouette.Vertices.Overwrite();
+            MeshSilhouette.Invalidate();
 
             for (unsigned long TriNr=0; TriNr<TriangleInfos[BodyPartNr].Size(); TriNr++)
             {
@@ -1196,6 +1271,7 @@
             static MatSys::MeshT MeshCaps(MatSys::MeshT::Triangles);
 
             MeshCaps.Vertices.Overwrite();
+            MeshCaps.Invalidate();
 
             for (unsigned long TriNr=0; TriNr<TriangleInfos[BodyPartNr].Size(); TriNr++)
             {
@@ -1238,39 +1314,41 @@
 
             MatSys::Renderer->SetCurrentMaterial(RenderMaterials[SkinRefs[CurrentMesh.SkinRef]]);
 
-            while (*TriangleStrips)
+            MatSys::MeshT *Mesh = RenderMeshes[BodyPartNr][MeshNr];
+#if ENABLE_OPT_CACHING
+            if(IsUpdateRequired_TransformedVertices)
+#endif
             {
-                // Anzahl und Art (FAN vs. STRIP) der Vertices im nächsten TriangleStrip.
-                signed short NrOfVertices=*(TriangleStrips++);
+                SoftSkinVertexT *Vertices = (SoftSkinVertexT*)Mesh->VertexBuffer->LockWrite();
+                unsigned long VPos = 0;
+                while (*TriangleStrips)
+                {
+                    // Anzahl und Art (FAN vs. STRIP) der Vertices im nächsten TriangleStrip.
+                    signed short NrOfVertices=*(TriangleStrips++);
+                    if (NrOfVertices<0) NrOfVertices=-NrOfVertices;
 
-                static MatSys::MeshT Mesh;
+                    for (unsigned long VertexNr=0; VertexNr<(unsigned long)NrOfVertices; VertexNr++, TriangleStrips+=4)
+                    {
+                        SoftSkinVertexT& V=Vertices[VertexNr + VPos];
 
-                Mesh.Type=NrOfVertices<0 ? MatSys::MeshT::TriangleFan : MatSys::MeshT::TriangleStrip;
+                        // TriangleStrips[0] -- Index ins (Transformed-)Vertices-Array
+                        // TriangleStrips[1] -- Index ins (Transformed-)Normals-Array
+                        // TriangleStrips[2] -- s-Texture-Coord (in Pixel)
+                        // TriangleStrips[3] -- t-Texture-Coord (in Pixel)
 
-                if (NrOfVertices<0) NrOfVertices=-NrOfVertices;
+                        V.SetOrigin      (TransformedVertices[TriangleStrips[0]][0], TransformedVertices[TriangleStrips[0]][1], TransformedVertices[TriangleStrips[0]][2]);
+                        V.SetTextureCoord(TriangleStrips[2]*s, TriangleStrips[3]*t);
 
-                Mesh.Vertices.Overwrite();
-                Mesh.Vertices.PushBackEmpty(NrOfVertices);
+                        if (IsNeeded_TransformedNormals ) V.SetNormal  (TransformedNormals  [TriangleStrips[1]][0], TransformedNormals  [TriangleStrips[1]][1], TransformedNormals  [TriangleStrips[1]][2]);
+                        if (IsNeeded_TransformedTangents) V.SetTangent (TransformedTangents [TriangleStrips[1]][0], TransformedTangents [TriangleStrips[1]][1], TransformedTangents [TriangleStrips[1]][2]);
+                        if (IsNeeded_TransformedTangents) V.SetBiNormal(TransformedBiNormals[TriangleStrips[1]][0], TransformedBiNormals[TriangleStrips[1]][1], TransformedBiNormals[TriangleStrips[1]][2]);
+                    }
 
-                for (unsigned long VertexNr=0; VertexNr<(unsigned long)NrOfVertices; VertexNr++, TriangleStrips+=4)
-                {
-                    MatSys::MeshT::VertexT& V=Mesh.Vertices[VertexNr];
-
-                    // TriangleStrips[0] -- Index ins (Transformed-)Vertices-Array
-                    // TriangleStrips[1] -- Index ins (Transformed-)Normals-Array
-                    // TriangleStrips[2] -- s-Texture-Coord (in Pixel)
-                    // TriangleStrips[3] -- t-Texture-Coord (in Pixel)
-
-                    V.SetOrigin      (TransformedVertices[TriangleStrips[0]][0], TransformedVertices[TriangleStrips[0]][1], TransformedVertices[TriangleStrips[0]][2]);
-                    V.SetTextureCoord(TriangleStrips[2]*s, TriangleStrips[3]*t);
-
-                    if (IsNeeded_TransformedNormals ) V.SetNormal  (TransformedNormals  [TriangleStrips[1]][0], TransformedNormals  [TriangleStrips[1]][1], TransformedNormals  [TriangleStrips[1]][2]);
-                    if (IsNeeded_TransformedTangents) V.SetTangent (TransformedTangents [TriangleStrips[1]][0], TransformedTangents [TriangleStrips[1]][1], TransformedTangents [TriangleStrips[1]][2]);
-                    if (IsNeeded_TransformedTangents) V.SetBiNormal(TransformedBiNormals[TriangleStrips[1]][0], TransformedBiNormals[TriangleStrips[1]][1], TransformedBiNormals[TriangleStrips[1]][2]);
+                    VPos += NrOfVertices;
                 }
-
-                MatSys::Renderer->RenderMesh(Mesh);
+                Mesh->VertexBuffer->Unlock();
             }
+            MatSys::Renderer->RenderMesh(*Mesh);
         }
     }
 
Index: Libs/Templates/Array.hpp
===================================================================
--- Libs/Templates/Array.hpp	(revisiÃ³n: 97)
+++ Libs/Templates/Array.hpp	(copia de trabajo)
@@ -63,7 +63,11 @@
     ArrayT(const ArrayT<T>& OldArray);                          ///< Copy  constructor
    ~ArrayT();                                                   ///< Destructor
     ArrayT<T>& operator = (const ArrayT<T>& OldArray);          ///< Assignment operator
+    void          Swap(ArrayT<T> &Other);                       ///< Swaps the arrays data
 
+    bool operator==(const ArrayT<T>& Other) const;              ///< Equality operator
+    bool operator!=(const ArrayT<T>& Other) const;              ///< Inequality operator
+
     unsigned long Size() const;                                 ///< Get size of array
     void          Clear();                                      ///< Clear array (and free allocated memory)
     void          Overwrite();                                  ///< Clear array (but reuse memory)
@@ -74,12 +78,14 @@
     void          PushBackEmptyExact(unsigned long Amount=1);
     void          DeleteBack(unsigned long Amount=1);
 
+
     // "Convenience" methods.
     void          PushBack(const ArrayT<T>& Other);
     void          InsertAt(unsigned long Index, const T Element);   // TODO: Rename to InsertAtAndKeepOrder()
     void          RemoveAt(unsigned long Index);
     void          RemoveAtAndKeepOrder(unsigned long Index);
-    void          QuickSort(bool (*IsLess)(const T& E1, const T& E2));
+    template<class Function>
+    void          QuickSort(Function IsLess);
  // void          QuickSort(unsigned long FirstIndex, unsigned long LastIndex, bool (*IsLess)(const T& E1, const T& E2));
     int           Find(const T& Element) const;
 };
@@ -123,7 +129,53 @@
     return *this;
 }
 
+template<class T> inline void ArrayT<T>::Swap(ArrayT<T> &Other)                             // Swaps arrays data
+{
+    T* NewElements = Other.Elements;
+    unsigned long NewSize = Other.NrOfElements;
+    unsigned long NewMaxSize = Other.MaxNrOfElements;
 
+    Other.Elements = Elements;
+    Other.NrOfElements = NrOfElements;
+    Other.MaxNrOfElements = MaxNrOfElements;
+
+    Elements = NewElements;
+    NrOfElements = NewSize;
+    MaxNrOfElements = NewMaxSize;
+}
+
+template<class T> inline bool ArrayT<T>::operator==(const ArrayT<T>& Other) const            // Equality operator
+{
+    // Check if the arrays are of the same size
+    if(NrOfElements != Other.NrOfElements)
+        return false;
+
+    // Check each element
+    for(unsigned long Nr=0; Nr<NrOfElements; Nr++)
+    {
+        if(Elements[Nr] != Other.Elements[Nr])
+            return false;
+    }
+
+    return true;
+}
+
+template<class T> inline bool ArrayT<T>::operator!=(const ArrayT<T>& Other) const            // Inequality operator
+{
+    // Check if the arrays are of the same size
+    if(NrOfElements != Other.NrOfElements)
+        return true;
+
+    // Check each element
+    for(unsigned long Nr=0; Nr<NrOfElements; Nr++)
+    {
+        if(Elements[Nr] != Other.Elements[Nr])
+            return true;
+    }
+
+    return false;
+}
+
 template<class T> inline unsigned long ArrayT<T>::Size() const
 {
     return NrOfElements;
@@ -280,7 +332,7 @@
 }
 
 
-template<class T> inline void ArrayT<T>::QuickSort(bool (*IsLess)(const T& E1, const T& E2))
+template<class T> template<class Function> inline void ArrayT<T>::QuickSort(Function IsLess)
 {
     static ArrayT<unsigned long> ToDoRanges;
 
Index: Libs/MaterialSystem/VertexBufferImpl.hpp
===================================================================
--- Libs/MaterialSystem/VertexBufferImpl.hpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/VertexBufferImpl.hpp	(revisiÃ³n: 0)
@@ -0,0 +1,77 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+/************************/
+/*** VertexBufferImpl ***/
+/************************/
+
+#ifndef _CA_MATSYS_VERTEX_BUFFER_IMPLEMENTATION_HPP_
+#define _CA_MATSYS_VERTEX_BUFFER_IMPLEMENTATION_HPP_
+
+#include "VertexBuffer.hpp"
+
+namespace MatSys
+{
+    class VertexBufferImplT: public VertexBufferI
+    {
+    public:
+        VertexBufferImplT(const VertexDescriptorT &VertexFormat);
+        ~VertexBufferImplT();
+
+        // Vertex format descriptor
+        virtual const VertexDescriptorT &GetVertexDescriptor() const;
+
+        // Vertex data access
+        virtual const void *LockRead() const;
+        virtual void *LockWrite();
+        virtual void *LockReadWrite();
+        virtual void Unlock() const;
+
+        // Number of vertices
+        virtual unsigned long GetBufferSize() const;
+        virtual unsigned long GetSize() const;
+        virtual void SetSize(unsigned long size);
+        virtual UsageTypeT GetUsage() const;
+
+        // Those are used to synchronize the version in the main memory
+        // with the video card
+        virtual bool IsValid() const;
+        virtual void Validated() const;
+        virtual void Invalidate();
+
+        virtual void *GetRendererData() const;
+        virtual void SetRendererData(void *data) const;
+
+    private:
+        const VertexDescriptorT &Descriptor;
+        unsigned long Size;
+        void *Data;
+        mutable bool IsLocked;
+        mutable bool IsValidBuffer;
+        mutable void *RendererData;
+    };
+
+};
+
+#endif
+
Index: Libs/MaterialSystem/Mesh.hpp
===================================================================
--- Libs/MaterialSystem/Mesh.hpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/Mesh.hpp	(copia de trabajo)
@@ -30,8 +30,10 @@
 
 #include "Templates/Array.hpp"
 #include "Math3D/Vector3.hpp"
+#include "VertexBuffer.hpp"
+#include "PrimitiveBuffer.hpp"
+#include "VertexFormats.hpp"
 
-
 namespace MatSys
 {
     /// This class represents a polygonal mesh.
@@ -59,55 +61,121 @@
     //           2. Clarify the exact requirements of VBOs          for each Renderer, inclusive OpenGL 2.0.
     //           3. Keep the differences/requirements/existance between static and animated meshes in mind.
     //           4. Armed with that knowledge, revise the meshes.
-    class MeshT
+    class MeshT: public VertexBufferI
     {
         public:
 
-        enum TypeT    { Points, Lines, LineStrip, LineLoop, Triangles, TriangleStrip, TriangleFan, Quads, QuadStrip, Polygon };
+        enum TypeT    { Points, Lines, LineStrip, LineLoop, Triangles, TriangleStrip, TriangleFan, Quads, QuadStrip, Polygon, Inherit };
         enum WindingT { CW, CCW };
 
-        struct VertexT
+        struct RangeT
         {
-            double Origin[4];           // The position (xyzw) in model space.
-            float  Color[4];            // The color (rgba).
+            RangeT(unsigned int S=0, unsigned int C=0, TypeT T=Inherit)
+                : Start(S), Count(C), Type(T) {}
 
-            float  TextureCoord[2];
-            float  LightMapCoord[2];
-            float  SHLMapCoord[2];
+            unsigned int Start, Count;
+            TypeT Type;
+        };
 
-            float  Normal[3];           // The normal vector in model space.
-            float  Tangent[3];
-            float  BiNormal[3];
+        typedef GenericVertexT VertexT;
 
-            float  UserAttribF[4];
-            int    UserAttribI[4];
+        TypeT           Type;
+        WindingT        Winding;    ///< The orientation (cw or ccw) of front faces.
+        ArrayT<VertexT> Vertices;
+        ArrayT<RangeT>  SubRanges;
+        UsageTypeT      UsageType;
+        VertexBufferI   *VertexBuffer;
+        PrimitiveBufferI *PrimitiveBuffer;
 
+        /// Constructor.
+        MeshT(TypeT T=Points, WindingT W=CW, UsageTypeT UT= Dynamic) : Type(T), Winding(W),
+            UsageType(UT), VertexBuffer(this), PrimitiveBuffer(NULL),
+            Mutex(false), IsValidMesh(false), RendererData(NULL)
+        {
+        }
+        ~MeshT();
 
-            // Methods for conveniently setting the components.
-            void SetOrigin(double x=0.0, double y=0.0, double z=0.0, double w=1.0) { Origin[0]=x; Origin[1]=y; Origin[2]=z; Origin[3]=w; }
-            void SetOrigin(const Vector3fT& Pos, float w=1.0) { Origin[0]=Pos.x; Origin[1]=Pos.y; Origin[2]=Pos.z; Origin[3]=w; }
-            void SetColor(float r, float g, float b, float a=1.0) { Color[0]=r; Color[1]=g; Color[2]=b; Color[3]=a; }
-            void SetTextureCoord(float s, float t) { TextureCoord[0]=s; TextureCoord[1]=t; }
-            void SetLightMapCoord(float s, float t) { LightMapCoord[0]=s; LightMapCoord[1]=t; }
-            void SetSHLMapCoord(float s, float t)  { SHLMapCoord[0]=s; SHLMapCoord[1]=t; }
-            void SetNormal(float x, float y, float z) { Normal[0]=x; Normal[1]=y; Normal[2]=z; }
-            void SetNormal(const Vector3T<float>& N) { Normal[0]=N.x; Normal[1]=N.y; Normal[2]=N.z; }
-            void SetTangent(float x, float y, float z) { Tangent[0]=x; Tangent[1]=y; Tangent[2]=z; }
-            void SetTangent(const Vector3T<float>& T) { Tangent[0]=T.x; Tangent[1]=T.y; Tangent[2]=T.z; }
-            void SetBiNormal(float x, float y, float z) { BiNormal[0]=x; BiNormal[1]=y; BiNormal[2]=z; }
-            void SetBiNormal(const Vector3T<float>& B) { BiNormal[0]=B.x; BiNormal[1]=B.y; BiNormal[2]=B.z; }
+        // Vertex format descriptor
+        const VertexDescriptorT &GetVertexDescriptor() const;
+
+        // Vertex data access
+        const void *LockRead() const;
+        void *LockWrite();
+        void *LockReadWrite();
+        void Unlock() const;
+
+        // Number of vertices
+        unsigned long GetBufferSize() const;
+        unsigned long GetSize() const;
+        void SetSize(unsigned long size);
+        UsageTypeT GetUsage() const;
+
+        // Those are used to synchronize the version in the main memory
+        // with the video card
+        bool IsValid() const;
+        void Validated() const;
+        void Invalidate();
+
+        void *GetRendererData() const;
+        void SetRendererData(void *data) const;
+
+
+    private:
+        mutable bool  Mutex; // Is the mesh locked?
+        mutable bool  IsValidMesh; // Is the mesh valid
+        mutable void *RendererData;
+    };
+
+#if 0
+    // This is the new mesh proposal. Vertex formats are described using a VertexDescriptorT
+    // structure associated with each vertex buffer.
+    // This approach can be directly mapped into OpenGL VBOs(or vertex arrays) but not sure about Direct3D.
+    // I decided to use this approach because Cafu could be gradually adapted using the temporal MeshT structure above
+    // which retains backward compatibility with the old approach, except in the dynamic meshes where it's required
+    // to call the Invalidate() method.
+    class MeshT
+    {
+        public:
+
+        enum TypeT    { Points, Lines, LineStrip, LineLoop, Triangles, TriangleStrip, TriangleFan, Quads, QuadStrip, Polygon, Inherit };
+        enum WindingT { CW, CCW };
+
+        struct RangeT
+        {
+            RangeT(unsigned int S=0, unsigned int C=0)
+                : Start(S), Count(C) {}
+
+            unsigned int Start, Count;
         };
 
+
         TypeT           Type;
         WindingT        Winding;    ///< The orientation (cw or ccw) of front faces.
-        ArrayT<VertexT> Vertices;
+        ArrayT<RangeT>  SubRanges;
+        VertexBufferI   *VertexBuffer;
+        PrimitiveBufferI *PrimitiveBuffer;
 
-
         /// Constructor.
-        MeshT(TypeT T=Points, WindingT W=CW) : Type(T), Winding(W)
+        MeshT(TypeT T=Points, WindingT W=CW, UsageTypeT UT= Dynamic) : Type(T), Winding(W),
+            UsageType(UT), VertexBuffer(NULL), PrimitiveBuffer(NULL), RendererData(NULL)
         {
         }
+        ~MeshT();
+
+        void *GetRendererData() const
+        {
+            return RendererData;
+        }
+
+        void SetRendererData(void *data) const
+        {
+            RendererData = data;
+        }
+
+    private:
+        mutable void *RendererData;
     };
+#endif
 }
 
 #endif
Index: Libs/MaterialSystem/PrimitiveBuffer.hpp
===================================================================
--- Libs/MaterialSystem/PrimitiveBuffer.hpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/PrimitiveBuffer.hpp	(revisiÃ³n: 0)
@@ -0,0 +1,67 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+#ifndef _CA_MATSYS_PRIMITIVE_BUFFER_HPP_
+#define _CA_MATSYS_PRIMITIVE_BUFFER_HPP_
+
+namespace MatSys
+{
+    class PrimitiveBufferI
+    {
+    public:
+        enum UsageTypeT { Static, Dynamic, Stream, Temporal };
+        enum IndexTypeT {UnsignedByte, UnsignedShort, UnsignedInt};
+        virtual ~PrimitiveBufferI() {}
+
+        // Primitives buffer access
+        virtual const void *LockRead() const = 0;
+        virtual void *LockWrite() = 0;
+        virtual void *LockReadWrite() = 0;
+        virtual void Unlock() const = 0;
+
+        // Buffer description
+        virtual unsigned long GetBufferSize() const = 0;
+        virtual unsigned long GetSize() const = 0;
+        virtual void SetSize(unsigned long size) = 0;
+
+        virtual IndexTypeT GetIndexType() const = 0;
+        virtual UsageTypeT GetUsage() const = 0;
+
+
+        // Those are used to synchronize the version in the main memory
+        // with the video card
+        virtual bool IsValid() const = 0;
+        virtual void Validated() const = 0;
+        virtual void Invalidate() = 0;
+
+        virtual void *GetRendererData() const = 0;
+        virtual void SetRendererData(void *data) const = 0;
+    };
+
+    extern PrimitiveBufferI *CreatePrimitiveBuffer(PrimitiveBufferI::IndexTypeT IndexType,
+                                                    PrimitiveBufferI::UsageTypeT Usage);
+
+} // namespace MatSys
+
+#endif //_CA_MATSYS_PRIMITIVE_BUFFER_HPP_
+
Index: Libs/MaterialSystem/Common/OpenGLEx.cpp
===================================================================
--- Libs/MaterialSystem/Common/OpenGLEx.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/Common/OpenGLEx.cpp	(copia de trabajo)
@@ -48,8 +48,8 @@
 bool cf::GL_EXT_stencil_wrap_AVAIL               =false;
 bool cf::GL_EXT_stencil_two_side_AVAIL           =false;
 bool cf::GL_ARB_vertex_and_fragment_program_AVAIL=false;
+bool cf::GL_ARB_vertex_buffer_object_AVAIL = false;
 
-
 static bool IsExtensionAvailable(const char* ExtensionName)
 {
     // Dies ist im wesentlichen der Code aus dem "OpenGL Programming Guide", Seite 568.
@@ -469,3 +469,37 @@
 
     cf::GL_ARB_vertex_and_fragment_program_AVAIL=true;
 }
+
+PFNGLBINDBUFFERARBPROC           cf::glBindBufferARB           = NULL; // Extension ARB_vertex_buffer_object
+PFNGLDELETEBUFFERSARBPROC        cf::glDeleteBuffersARB        = NULL;
+PFNGLGENBUFFERSARBPROC           cf::glGenBuffersARB           = NULL;
+PFNGLISBUFFERARBPROC             cf::glIsBufferARB             = NULL;
+PFNGLBUFFERDATAARBPROC           cf::glBufferDataARB           = NULL;
+PFNGLBUFFERSUBDATAARBPROC        cf::glBufferSubDataARB        = NULL;
+PFNGLGETBUFFERSUBDATAARBPROC     cf::glGetBufferSubDataARB     = NULL;
+PFNGLMAPBUFFERARBPROC            cf::glMapBufferARB            = NULL;
+PFNGLUNMAPBUFFERARBPROC          cf::glUnmapBufferARB          = NULL;
+PFNGLGETBUFFERPARAMETERIVARBPROC cf::glGetBufferParameterivARB = NULL;
+PFNGLGETBUFFERPOINTERVARBPROC    cf::glGetBufferPointervARB    = NULL;
+
+void cf::Init_GL_ARB_vertex_buffer_object()
+{
+    cf::GL_ARB_vertex_buffer_object_AVAIL=false;
+
+    if (!IsExtensionAvailable("GL_ARB_vertex_buffer_object"  )) return;
+
+    cf::glBindBufferARB           = (PFNGLBINDBUFFERARBPROC          ) GetProcAddress((StringPtr)"glBindBufferARB"); if (!cf::glBindBufferARB          ) return;
+    cf::glDeleteBuffersARB        = (PFNGLDELETEBUFFERSARBPROC       ) GetProcAddress((StringPtr)"glDeleteBuffersARB"); if (!cf::glDeleteBuffersARB       ) return;
+    cf::glGenBuffersARB           = (PFNGLGENBUFFERSARBPROC          ) GetProcAddress((StringPtr)"glGenBuffersARB"); if (!cf::glGenBuffersARB          ) return;
+    cf::glIsBufferARB             = (PFNGLISBUFFERARBPROC            ) GetProcAddress((StringPtr)"glIsBufferARB"); if (!cf::glIsBufferARB            ) return;
+    cf::glBufferDataARB           = (PFNGLBUFFERDATAARBPROC          ) GetProcAddress((StringPtr)"glBufferDataARB"); if (!cf::glBufferDataARB          ) return;
+    cf::glBufferSubDataARB        = (PFNGLBUFFERSUBDATAARBPROC       ) GetProcAddress((StringPtr)"glBufferSubDataARB"); if (!cf::glBufferSubDataARB       ) return;
+    cf::glGetBufferSubDataARB     = (PFNGLGETBUFFERSUBDATAARBPROC    ) GetProcAddress((StringPtr)"glGetBufferSubDataARB"); if (!cf::glGetBufferSubDataARB    ) return;
+    cf::glMapBufferARB            = (PFNGLMAPBUFFERARBPROC           ) GetProcAddress((StringPtr)"glMapBufferARB"); if (!cf::glMapBufferARB           ) return;
+    cf::glUnmapBufferARB          = (PFNGLUNMAPBUFFERARBPROC         ) GetProcAddress((StringPtr)"glUnmapBufferARB"); if (!cf::glUnmapBufferARB         ) return;
+    cf::glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC) GetProcAddress((StringPtr)"glGetBufferParameterivARB"); if (!cf::glGetBufferParameterivARB) return;
+    cf::glGetBufferPointervARB    = (PFNGLGETBUFFERPOINTERVARBPROC   ) GetProcAddress((StringPtr)"glGetBufferPointervARB"); if (!cf::glGetBufferPointervARB   ) return;
+
+    cf::GL_ARB_vertex_buffer_object_AVAIL=true;
+}
+
Index: Libs/MaterialSystem/Common/OpenGLState.cpp
===================================================================
--- Libs/MaterialSystem/Common/OpenGLState.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/Common/OpenGLState.cpp	(copia de trabajo)
@@ -501,3 +501,31 @@
 {
     glTexEnvfv(target, pname, param);
 }
+
+void OpenGLStateT::BindBuffer(GLenum target, GLuint vbo)
+{
+    static GLuint ArrayBuffer = 0;
+    static GLuint ElementArrayBuffer = 0;
+
+    if(target == GL_ARRAY_BUFFER_ARB /*&& vbo != ArrayBuffer*/)
+    {
+        ArrayBuffer = vbo;
+        cf::glBindBufferARB(target, vbo);
+    }
+    else if(target == GL_ELEMENT_ARRAY_BUFFER_ARB /*&& vbo != ElementArrayBuffer*/)
+    {
+        ElementArrayBuffer = vbo;
+        cf::glBindBufferARB(target, vbo);
+    }
+}
+
+void OpenGLStateT::ClientActiveTexture(GLenum Unit)
+{
+    static GLenum CurrentUnit = GL_TEXTURE0_ARB;
+    if(Unit != CurrentUnit)
+    {
+        CurrentUnit = Unit;
+        glClientActiveTexture(Unit);
+    }
+}
+
Index: Libs/MaterialSystem/Common/OpenGLEx.hpp
===================================================================
--- Libs/MaterialSystem/Common/OpenGLEx.hpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/Common/OpenGLEx.hpp	(copia de trabajo)
@@ -57,6 +57,7 @@
     extern bool GL_EXT_stencil_wrap_AVAIL;
     extern bool GL_EXT_stencil_two_side_AVAIL;
     extern bool GL_ARB_vertex_and_fragment_program_AVAIL;
+    extern bool GL_ARB_vertex_buffer_object_AVAIL;
 
     // Initialize extensions.
     void Init_GL_ARB_multitexture();
@@ -66,8 +67,8 @@
     void Init_GL_EXT_stencil_wrap();
     void Init_GL_EXT_stencil_two_side();
     void Init_GL_ARB_vertex_and_fragment_program();
+    void Init_GL_ARB_vertex_buffer_object();
 
-
     // Pointers to extension functions.
     extern PFNGLMULTITEXCOORD2DARBPROC           glMultiTexCoord2dARB;      // Extension "GL_ARB_multitexture".
     extern PFNGLMULTITEXCOORD2FARBPROC           glMultiTexCoord2fARB;
@@ -209,6 +210,19 @@
     extern PFNGLGETVERTEXATTRIBIVARBPROC          glGetVertexAttribivARB;
     extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC    glGetVertexAttribPointervARB;
     extern PFNGLISPROGRAMARBPROC                  glIsProgramARB;
+
+    extern PFNGLBINDBUFFERARBPROC           glBindBufferARB; // ARB_vertex_buffer_object
+    extern PFNGLDELETEBUFFERSARBPROC        glDeleteBuffersARB;
+    extern PFNGLGENBUFFERSARBPROC           glGenBuffersARB;
+    extern PFNGLISBUFFERARBPROC             glIsBufferARB;
+    extern PFNGLBUFFERDATAARBPROC           glBufferDataARB;
+    extern PFNGLBUFFERSUBDATAARBPROC        glBufferSubDataARB;
+    extern PFNGLGETBUFFERSUBDATAARBPROC     glGetBufferSubDataARB;
+    extern PFNGLMAPBUFFERARBPROC            glMapBufferARB;
+    extern PFNGLUNMAPBUFFERARBPROC          glUnmapBufferARB;
+    extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
+    extern PFNGLGETBUFFERPOINTERVARBPROC    glGetBufferPointervARB;
+
 }
 
 #endif
Index: Libs/MaterialSystem/Common/OpenGLState.hpp
===================================================================
--- Libs/MaterialSystem/Common/OpenGLState.hpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/Common/OpenGLState.hpp	(copia de trabajo)
@@ -83,6 +83,12 @@
  // void TexParameter*();
 
 
+    // Functions that apply only the current vertex buffer object.
+    void BindBuffer(GLenum target, GLuint vbo);
+
+    // Client side functions
+    void ClientActiveTexture(GLenum Unit);
+
     static const GLenum MeshToOpenGLType[];             ///< Translates from MeshT primitive types to OpenGL rendering primitives.
     static const GLenum WindingToOpenGL[];              ///< Translates from MeshT windings to OpenGL windings (cw or ccw).
     static const GLenum BlendFactorToOpenGL[];          ///< Translates from MaterialT blend factors to OpenGL blend factors.
Index: Libs/MaterialSystem/VertexBuffer.hpp
===================================================================
--- Libs/MaterialSystem/VertexBuffer.hpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/VertexBuffer.hpp	(revisiÃ³n: 0)
@@ -0,0 +1,116 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+/********************/
+/*** VertexBuffer ***/
+/********************/
+
+#ifndef _CA_MATSYS_VERTEX_BUFFER_HPP_
+#define _CA_MATSYS_VERTEX_BUFFER_HPP_
+
+#include "Math3D/Vector3.hpp"
+
+namespace MatSys
+{
+    // Data type of a memory offset to get the location into a vertex member
+    typedef long VertexOffset;
+
+// Macro to facilitate vertex attribute memory offset
+#define VertexElementOffset(s, elm) ((VertexOffset)&((s*)NULL)->elm) 
+
+    // This class represents a vertex format description
+    struct VertexDescriptorT
+    {
+        VertexDescriptorT(unsigned int size=0, VertexOffset origin = -1, VertexOffset origin4 = -1,
+                VertexOffset color = -1, VertexOffset textureCoord = -1, VertexOffset lightMapCoord = -1,
+                VertexOffset shlMapCoord = -1, VertexOffset normal = -1, VertexOffset tangent = -1,
+                VertexOffset binormal = -1, VertexOffset userAttribF = -1, VertexOffset userAttribI = -1)
+            : VertexSize(size), Origin(origin), Origin4(origin4), Color(color),
+                TextureCoord(textureCoord), LightMapCoord(lightMapCoord), SHLMapCoord(shlMapCoord),
+                Normal(normal), Tangent(tangent), BiNormal(binormal), UserAttribF(userAttribF),
+                UserAttribI(userAttribI)
+        {
+        }
+
+        unsigned int VertexSize; // Vertex size in bytes
+
+        // Vertex elements offsets. -1 means no presence
+        VertexOffset Origin; // float[3]
+        VertexOffset Origin4; // float[4]
+        VertexOffset Color; // float[4]
+        VertexOffset TextureCoord; // float[2]
+        VertexOffset LightMapCoord; // float[2]
+        VertexOffset SHLMapCoord; // float[2]
+
+        VertexOffset Normal; // float[3]
+        VertexOffset Tangent; // float[3]
+        VertexOffset BiNormal; // float[3]
+
+        VertexOffset UserAttribF; // float[4]
+        VertexOffset UserAttribI; // int[4]
+    };
+
+    // This class represents a vertex buffer
+    class VertexBufferI
+    {
+    public:
+        enum UsageTypeT { Static, Dynamic, Stream, Temporal };
+
+        virtual ~VertexBufferI() {}
+
+        // Vertex format descriptor
+        virtual const VertexDescriptorT &GetVertexDescriptor() const = 0;
+
+        // Vertex data access
+        virtual const void *LockRead() const = 0;
+        virtual void *LockWrite() = 0;
+        virtual void *LockReadWrite() = 0;
+        virtual void Unlock() const = 0;
+
+        // Number of vertices
+        virtual unsigned long GetBufferSize() const = 0;
+        virtual unsigned long GetSize() const = 0;
+        virtual void SetSize(unsigned long size) = 0;
+        virtual UsageTypeT GetUsage() const = 0;
+
+        // Those are used to synchronize the version in the main memory
+        // with the video card
+        virtual bool IsValid() const = 0;
+        virtual void Validated() const = 0;
+        virtual void Invalidate() = 0;
+
+        virtual void *GetRendererData() const = 0;
+        virtual void SetRendererData(void *data) const = 0;
+    };
+
+    extern VertexBufferI *CreateVertexBuffer(const VertexDescriptorT &VertexFormat,
+                                            VertexBufferI::UsageTypeT Usage);
+
+    template<typename T> inline VertexBufferI *CreateVertexBuffer(VertexBufferI::UsageTypeT Usage)
+    {
+        return CreateVertexBuffer(T::VertexDescriptor, Usage);
+    }
+};
+
+#endif
+
Index: Libs/MaterialSystem/RendererNull/RendererImpl.cpp
===================================================================
--- Libs/MaterialSystem/RendererNull/RendererImpl.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererNull/RendererImpl.cpp	(copia de trabajo)
@@ -475,6 +475,28 @@
 }
 
 
+void RendererImplT::OnDestroyMesh(MatSys::MeshT *Mesh)
+{
+}
+
+void RendererImplT::OnDestroyVertexBuffer(MatSys::VertexBufferI *Buffer)
+{
+}
+
+void RendererImplT::OnDestroyPrimitiveBuffer(MatSys::PrimitiveBufferI *Buffer)
+{
+}
+
+VertexBufferI *RendererImplT::CreateVertexBuffer(const VertexDescriptorT &Format, unsigned int Usage)
+{
+    return NULL;
+}
+
+PrimitiveBufferI *RendererImplT::CreatePrimitiveBuffer(PrimitiveBufferI::IndexTypeT IndexType, PrimitiveBufferI::UsageTypeT Usage)
+{
+    return NULL;
+}
+
 RenderMaterialT* RendererImplT::GetCurrentRenderMaterial() const
 {
     return NULL;
Index: Libs/MaterialSystem/RendererNull/RendererImpl.hpp
===================================================================
--- Libs/MaterialSystem/RendererNull/RendererImpl.hpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererNull/RendererImpl.hpp	(copia de trabajo)
@@ -123,8 +123,13 @@
     void SetCurrentSHLMaps(const ArrayT<MatSys::TextureMapI*>& SHLMaps);
     void SetCurrentSHLLookupMap(MatSys::TextureMapI* SHLLookupMap);
     void RenderMesh(const MatSys::MeshT& Mesh);
+    void OnDestroyMesh(MatSys::MeshT *Mesh);
+    void OnDestroyVertexBuffer(MatSys::VertexBufferI *Buffer);
+    void OnDestroyPrimitiveBuffer(MatSys::PrimitiveBufferI *Buffer);
+    MatSys::VertexBufferI *CreateVertexBuffer(const MatSys::VertexDescriptorT &Format, unsigned int Usage);
+    MatSys::PrimitiveBufferI *CreatePrimitiveBuffer(MatSys::PrimitiveBufferI::IndexTypeT IndexType,
+                                                    MatSys::PrimitiveBufferI::UsageTypeT Usage);
 
-
     // Internal interface.
     MatSys::RenderMaterialT* GetCurrentRenderMaterial() const;
 
Index: Libs/MaterialSystem/VertexFormats.cpp
===================================================================
--- Libs/MaterialSystem/VertexFormats.cpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/VertexFormats.cpp	(revisiÃ³n: 0)
@@ -0,0 +1,83 @@
+#include "VertexFormats.hpp"
+
+namespace MatSys
+{
+    // GenericVertexT descriptor.
+    VertexDescriptorT GenericVertexT::VertexDescriptor (
+        /*VertexSize*/ sizeof(GenericVertexT),
+        /*Origin*/ VertexElementOffset(GenericVertexT, Origin[0]),
+        /*Origin4*/ VertexElementOffset(GenericVertexT, Origin[0]),
+        /*Color*/ VertexElementOffset(GenericVertexT, Color[0]),
+        /*TextureCoord*/ VertexElementOffset(GenericVertexT, TextureCoord[0]),
+        /*LightMapCoord*/ VertexElementOffset(GenericVertexT, LightMapCoord[0]),
+        /*SHLMapCoord*/ VertexElementOffset(GenericVertexT, SHLMapCoord[0]),
+
+        /*Normal*/ VertexElementOffset(GenericVertexT, Normal[0]),
+        /*Tangent*/ VertexElementOffset(GenericVertexT, Tangent[0]),
+        /*BiNormal*/ VertexElementOffset(GenericVertexT, BiNormal[0]),
+
+        /*UserAttribF*/ VertexElementOffset(GenericVertexT, UserAttribF[0]),
+        /*UserAttribI*/ VertexElementOffset(GenericVertexT, UserAttribI[0])
+        );
+
+    // StaticVertexT descriptor.
+    VertexDescriptorT StaticVertexT::VertexDescriptor (
+        /*VertexSize*/ sizeof(StaticVertexT),
+        /*Origin*/ VertexElementOffset(StaticVertexT, Origin[0]),
+        /*Origin4*/ -1,
+        /*Color*/ -1,
+        /*TextureCoord*/ VertexElementOffset(StaticVertexT, TextureCoord[0]),
+        /*LightMapCoord*/ VertexElementOffset(StaticVertexT, LightMapCoord[0]),
+#ifdef SHL_ENABLED
+        /*SHLMapCoord*/ VertexElementOffset(StaticVertexT, SHLMapCoord[0]),
+#else
+        /*SHLMapCoord*/ -1,
+#endif
+        /*Normal*/ VertexElementOffset(StaticVertexT, Normal[0]),
+        /*Tangent*/ VertexElementOffset(StaticVertexT, Tangent[0]),
+        /*BiNormal*/ VertexElementOffset(StaticVertexT, BiNormal[0]),
+
+        /*UserAttribF*/ -1,
+        /*UserAttribI*/ -1
+        );
+
+    // StaticVertexColorT descriptor.
+    VertexDescriptorT StaticVertexColorT::VertexDescriptor (
+        /*VertexSize*/ sizeof(StaticVertexColorT),
+        /*Origin*/ VertexElementOffset(StaticVertexColorT, Origin[0]),
+        /*Origin4*/ -1,
+        /*Color*/ VertexElementOffset(StaticVertexColorT, Color[0]),
+        /*TextureCoord*/ VertexElementOffset(StaticVertexColorT, TextureCoord[0]),
+        /*LightMapCoord*/ VertexElementOffset(StaticVertexColorT, LightMapCoord[0]),
+#ifdef SHL_ENABLED
+        /*SHLMapCoord*/ VertexElementOffset(StaticVertexColorT, SHLMapCoord[0]),
+#else
+        /*SHLMapCoord*/ -1,
+#endif
+        /*Normal*/ VertexElementOffset(StaticVertexColorT, Normal[0]),
+        /*Tangent*/ VertexElementOffset(StaticVertexColorT, Tangent[0]),
+        /*BiNormal*/ VertexElementOffset(StaticVertexColorT, BiNormal[0]),
+
+        /*UserAttribF*/ -1,
+        /*UserAttribI*/ -1
+        );
+
+    // StencilShadowCpuT descriptor.
+    VertexDescriptorT StencilShadowCpuT::VertexDescriptor (
+        /*VertexSize*/ sizeof(StencilShadowCpuT),
+        /*Origin*/ VertexElementOffset(StencilShadowCpuT, Origin[0]),
+        /*Origin4*/ VertexElementOffset(StencilShadowCpuT, Origin[0]),
+        /*Color*/ -1,
+        /*TextureCoord*/ -1,
+        /*LightMapCoord*/ -1,
+        /*SHLMapCoord*/ -1,
+
+        /*Normal*/ -1,
+        /*Tangent*/ -1,
+        /*BiNormal*/ -1,
+
+        /*UserAttribF*/ -1,
+        /*UserAttribI*/ -1
+        );
+};
+
Index: Libs/MaterialSystem/Renderer.hpp
===================================================================
--- Libs/MaterialSystem/Renderer.hpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/Renderer.hpp	(copia de trabajo)
@@ -28,20 +28,20 @@
 #ifndef _CA_MATSYS_RENDERER_HPP_
 #define _CA_MATSYS_RENDERER_HPP_
 
+#include "PrimitiveBuffer.hpp"
 
-
 template<class T> class ArrayT;
 class MaterialT;
 class MatrixT;
 
-
 namespace MatSys
 {
     class MeshT;
+    class VertexDescriptorT;
+    class VertexBufferI;
     class RenderMaterialT;
     class TextureMapI;
 
-
     /// This class provides an interface to a renderer.
     /// The interface is specified as ABC in order to share the renderer across exe/dll boundaries.
     class RendererI
@@ -265,6 +265,12 @@
         virtual void EndShadowSilhouetteGeom()=0;  */
 
         virtual void RenderMesh(const MatSys::MeshT& Mesh)=0;
+        virtual void OnDestroyMesh(MatSys::MeshT *Mesh) = 0;
+        virtual void OnDestroyVertexBuffer(MatSys::VertexBufferI *Buffer) = 0;
+        virtual void OnDestroyPrimitiveBuffer(MatSys::PrimitiveBufferI *Buffer) = 0;
+        virtual VertexBufferI *CreateVertexBuffer(const VertexDescriptorT &Format, unsigned int Usage) = 0;
+        virtual PrimitiveBufferI *CreatePrimitiveBuffer(PrimitiveBufferI::IndexTypeT IndexType,
+                                                        PrimitiveBufferI::UsageTypeT Usage) = 0;
 
         /// This ABC does neither have nor need a destructor, because no implementation will ever be deleted via a pointer to a RendererI.
         /// (The implementations are singletons after all.)  See the Singleton pattern and the C++ FAQ 21.05 (the "precise rule") for more information.
@@ -277,6 +283,7 @@
     /// Just set this after you loaded the desired renderer DLL to the pointer returned by the DLLs GetRenderer() function.
     /// (And NULL it on unloading the DLL.)
     /// An analogous object exists for the TextureMapManager interface, see TextureMap.hpp.
+
     extern RendererI* Renderer;
 }
 
Index: Libs/MaterialSystem/VertexFormats.hpp
===================================================================
--- Libs/MaterialSystem/VertexFormats.hpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/VertexFormats.hpp	(revisiÃ³n: 0)
@@ -0,0 +1,156 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+/************/
+/*** GenericVertex ***/
+/************/
+
+#ifndef _CA_MATSYS_VERTEX_FORMATS_HPP_
+#define _CA_MATSYS_VERTEX_FORMATS_HPP_
+
+#include "Math3D/Vector3.hpp"
+#include "VertexBuffer.hpp"
+
+namespace MatSys
+{
+
+    // Generic vertex layout capable of storing any vertex data.
+    struct GenericVertexT
+    {
+        static VertexDescriptorT VertexDescriptor;
+
+        float  Origin[4];           // The position (xyzw) in model space.
+        float  Color[4];            // The color (rgba).
+
+        float  TextureCoord[2];
+        float  LightMapCoord[2];
+        float  SHLMapCoord[2];
+
+        float  Normal[3];           // The normal vector in model space.
+        float  Tangent[3];
+        float  BiNormal[3];
+
+        float  UserAttribF[4];
+        int    UserAttribI[4];
+
+
+        // Methods for conveniently setting the components.
+        void SetOrigin(float x=0.0, float y=0.0, float z=0.0, float w=1.0) { Origin[0]=x; Origin[1]=y; Origin[2]=z; Origin[3]=w; }
+        void SetOrigin(const Vector3fT& Pos, float w=1.0) { Origin[0]=Pos.x; Origin[1]=Pos.y; Origin[2]=Pos.z; Origin[3]=w; }
+        void SetColor(float r, float g, float b, float a=1.0) { Color[0]=r; Color[1]=g; Color[2]=b; Color[3]=a; }
+        void SetTextureCoord(float s, float t) { TextureCoord[0]=s; TextureCoord[1]=t; }
+        void SetLightMapCoord(float s, float t) { LightMapCoord[0]=s; LightMapCoord[1]=t; }
+        void SetSHLMapCoord(float s, float t)  { SHLMapCoord[0]=s; SHLMapCoord[1]=t; }
+        void SetNormal(float x, float y, float z) { Normal[0]=x; Normal[1]=y; Normal[2]=z; }
+        void SetNormal(const Vector3T<float>& N) { Normal[0]=N.x; Normal[1]=N.y; Normal[2]=N.z; }
+        void SetTangent(float x, float y, float z) { Tangent[0]=x; Tangent[1]=y; Tangent[2]=z; }
+        void SetTangent(const Vector3T<float>& T) { Tangent[0]=T.x; Tangent[1]=T.y; Tangent[2]=T.z; }
+        void SetBiNormal(float x, float y, float z) { BiNormal[0]=x; BiNormal[1]=y; BiNormal[2]=z; }
+        void SetBiNormal(const Vector3T<float>& B) { BiNormal[0]=B.x; BiNormal[1]=B.y; BiNormal[2]=B.z; }
+    };
+
+    // Static vertex face layout. Used by BSP based faces
+    struct StaticVertexT
+    {
+        static VertexDescriptorT VertexDescriptor;
+
+        float  Origin[3];           // The position (xyz) in model space.
+
+        float  TextureCoord[2];
+        float  LightMapCoord[2];
+
+#ifdef SHL_ENABLED
+        float SHLMapCoord[2];
+#endif
+
+        float  Normal[3];           // The normal vector in model space.
+        float  Tangent[3];
+        float  BiNormal[3];
+
+        // Methods for conveniently setting the components.
+        void SetOrigin(float x=0.0, float y=0.0, float z=0.0) { Origin[0]=x; Origin[1]=y; Origin[2]=z; }
+        void SetOrigin(const Vector3fT& Pos, float w=1.0) { Origin[0]=Pos.x; Origin[1]=Pos.y; Origin[2]=Pos.z; }
+        void SetTextureCoord(float s, float t) { TextureCoord[0]=s; TextureCoord[1]=t; }
+        void SetLightMapCoord(float s, float t) { LightMapCoord[0]=s; LightMapCoord[1]=t; }
+#ifdef SHL_ENABLED
+        void SetSHLMapCoord(float s, float t)  { SHLMapCoord[0]=s; SHLMapCoord[1]=t; }
+#endif
+        void SetNormal(float x, float y, float z) { Normal[0]=x; Normal[1]=y; Normal[2]=z; }
+        void SetNormal(const Vector3T<float>& N) { Normal[0]=N.x; Normal[1]=N.y; Normal[2]=N.z; }
+        void SetTangent(float x, float y, float z) { Tangent[0]=x; Tangent[1]=y; Tangent[2]=z; }
+        void SetTangent(const Vector3T<float>& T) { Tangent[0]=T.x; Tangent[1]=T.y; Tangent[2]=T.z; }
+        void SetBiNormal(float x, float y, float z) { BiNormal[0]=x; BiNormal[1]=y; BiNormal[2]=z; }
+        void SetBiNormal(const Vector3T<float>& B) { BiNormal[0]=B.x; BiNormal[1]=B.y; BiNormal[2]=B.z; }
+    };
+
+    // Static vertex with colors.
+    struct StaticVertexColorT
+    {
+        static VertexDescriptorT VertexDescriptor;
+
+        float  Origin[3];           // The position (xyz) in model space.
+        float  Color[4];            // The color (rgba).
+
+        float  TextureCoord[2];
+        float  LightMapCoord[2];
+
+#ifdef SHL_ENABLED
+        float SHLMapCoord[2];
+#endif
+
+        float  Normal[3];           // The normal vector in model space.
+        float  Tangent[3];
+        float  BiNormal[3];
+
+        // Methods for conveniently setting the components.
+        void SetOrigin(float x=0.0, float y=0.0, float z=0.0) { Origin[0]=x; Origin[1]=y; Origin[2]=z; }
+        void SetOrigin(const Vector3fT& Pos, float w=1.0) { Origin[0]=Pos.x; Origin[1]=Pos.y; Origin[2]=Pos.z; }
+        void SetColor(float r, float g, float b, float a=1.0) { Color[0]=r; Color[1]=g; Color[2]=b; Color[3]=a; }
+        void SetTextureCoord(float s, float t) { TextureCoord[0]=s; TextureCoord[1]=t; }
+        void SetLightMapCoord(float s, float t) { LightMapCoord[0]=s; LightMapCoord[1]=t; }
+#ifdef SHL_ENABLED
+        void SetSHLMapCoord(float s, float t)  { SHLMapCoord[0]=s; SHLMapCoord[1]=t; }
+#endif
+        void SetNormal(float x, float y, float z) { Normal[0]=x; Normal[1]=y; Normal[2]=z; }
+        void SetNormal(const Vector3T<float>& N) { Normal[0]=N.x; Normal[1]=N.y; Normal[2]=N.z; }
+        void SetTangent(float x, float y, float z) { Tangent[0]=x; Tangent[1]=y; Tangent[2]=z; }
+        void SetTangent(const Vector3T<float>& T) { Tangent[0]=T.x; Tangent[1]=T.y; Tangent[2]=T.z; }
+        void SetBiNormal(float x, float y, float z) { BiNormal[0]=x; BiNormal[1]=y; BiNormal[2]=z; }
+        void SetBiNormal(const Vector3T<float>& B) { BiNormal[0]=B.x; BiNormal[1]=B.y; BiNormal[2]=B.z; }
+    };
+
+    // Stencil shadow(CPU) vertex layout.
+    struct StencilShadowCpuT
+    {
+        static VertexDescriptorT VertexDescriptor;
+
+        float  Origin[4];           // The position (xyzw) in model space.
+
+        // Methods for conveniently setting the components.
+        void SetOrigin(float x=0.0, float y=0.0, float z=0.0, float w=1.0) { Origin[0]=x; Origin[1]=y; Origin[2]=z; Origin[3]=w; }
+        void SetOrigin(const Vector3fT& Pos, float w=1.0) { Origin[0]=Pos.x; Origin[1]=Pos.y; Origin[2]=Pos.z; Origin[3]=w; }
+    };
+}
+
+#endif
+
Index: Libs/MaterialSystem/PrimitiveBufferImpl.cpp
===================================================================
--- Libs/MaterialSystem/PrimitiveBufferImpl.cpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/PrimitiveBufferImpl.cpp	(revisiÃ³n: 0)
@@ -0,0 +1,148 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+/***************************/
+/*** PrimitiveBufferImpl ***/
+/***************************/
+
+#include <cassert>
+#include <stdlib.h>
+#include "PrimitiveBufferImpl.hpp"
+#include "Renderer.hpp"
+
+namespace MatSys
+{
+    unsigned long PrimitiveBufferImplT::IndexTypeToSize[3] =
+    {sizeof(unsigned char), sizeof(unsigned short), sizeof(unsigned int)};
+
+    PrimitiveBufferImplT::PrimitiveBufferImplT(IndexTypeT IT)
+        : IndexType(IT), IsLocked(false), IsValidBuffer(false), RendererData(NULL), Size(0), Buffer(NULL)
+    {
+    }
+
+    PrimitiveBufferImplT::~PrimitiveBufferImplT()
+    {
+        if(Buffer)
+            delete [] (unsigned char*)Buffer;
+
+        if(Renderer && RendererData)
+            Renderer->OnDestroyPrimitiveBuffer(this);
+    }
+
+    const void *PrimitiveBufferImplT::LockRead() const
+    {
+        assert(!IsLocked);
+        IsLocked = true;
+        return Buffer;
+    }
+
+    void *PrimitiveBufferImplT::LockWrite()
+    {
+        assert(!IsLocked);
+        IsLocked = true;
+        IsValidBuffer = false;
+        return Buffer;
+    }
+
+    void *PrimitiveBufferImplT::LockReadWrite()
+    {
+        assert(!IsLocked);
+        IsLocked = true;
+        IsValidBuffer = false;
+        return Buffer;
+    }
+
+    void PrimitiveBufferImplT::Unlock() const
+    {
+        assert(IsLocked);
+        IsLocked = false;
+    }
+
+    unsigned long PrimitiveBufferImplT::GetBufferSize() const
+    {
+        return Size*IndexTypeToSize[IndexType];
+    }
+
+    unsigned long PrimitiveBufferImplT::GetSize() const
+    {
+        return Size;
+    }
+
+    void PrimitiveBufferImplT::SetSize(unsigned long S)
+    {
+        Size = S;
+
+        if(Buffer)
+            delete [] (unsigned char*)Buffer;
+        Buffer = new unsigned char[GetBufferSize()];
+    }
+
+    PrimitiveBufferI::IndexTypeT PrimitiveBufferImplT::GetIndexType() const
+    {
+        return IndexType;
+    }
+
+    PrimitiveBufferI::UsageTypeT PrimitiveBufferImplT::GetUsage() const
+    {
+        return Stream;
+    }
+
+    bool PrimitiveBufferImplT::IsValid() const
+    {
+        return IsValidBuffer;
+    }
+
+    void PrimitiveBufferImplT::Validated() const
+    {
+        IsValidBuffer = true;
+    }
+
+    void PrimitiveBufferImplT::Invalidate()
+    {
+        IsValidBuffer = false;
+    }
+
+    void *PrimitiveBufferImplT::GetRendererData() const
+    {
+        return RendererData;
+    }
+
+    void PrimitiveBufferImplT::SetRendererData(void *Data) const
+    {
+        RendererData = Data;
+    }
+
+    PrimitiveBufferI *CreatePrimitiveBuffer(PrimitiveBufferI::IndexTypeT IndexType,
+                                            PrimitiveBufferI::UsageTypeT Usage)
+    {
+        if(Renderer && Usage != PrimitiveBufferI::Temporal)
+        {
+            PrimitiveBufferI *Ret = Renderer->CreatePrimitiveBuffer(IndexType, Usage);
+            if(Ret)
+                return Ret;
+        }
+        return new PrimitiveBufferImplT(IndexType);
+    }
+
+};
+
Index: Libs/MaterialSystem/RendererARBprogs/VertexBufferImpl.hpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/VertexBufferImpl.hpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/RendererARBprogs/VertexBufferImpl.hpp	(revisiÃ³n: 0)
@@ -0,0 +1,73 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+/************************/
+/*** VertexBufferImpl ***/
+/************************/
+
+#ifndef _CA_MATSYS_VERTEX_BUFFER_IMPLEMENTATION_HPP_
+#define _CA_MATSYS_VERTEX_BUFFER_IMPLEMENTATION_HPP_
+
+#include <GL/gl.h>
+#include "../VertexBuffer.hpp"
+
+class VertexBufferImplT: public MatSys::VertexBufferI
+{
+public:
+    VertexBufferImplT(const MatSys::VertexDescriptorT &VertexFormat, UsageTypeT Usage);
+    ~VertexBufferImplT();
+
+    // Vertex format descriptor
+    virtual const MatSys::VertexDescriptorT &GetVertexDescriptor() const;
+
+    // Vertex data access
+    virtual const void *LockRead() const;
+    virtual void *LockWrite();
+    virtual void *LockReadWrite();
+    virtual void Unlock() const;
+
+    // Number of vertices
+    virtual unsigned long GetBufferSize() const;
+    virtual unsigned long GetSize() const;
+    virtual void SetSize(unsigned long size);
+    virtual UsageTypeT GetUsage() const;
+
+    // Those are used to synchronize the version in the main memory
+    // with the video card
+    virtual bool IsValid() const;
+    virtual void Validated() const;
+    virtual void Invalidate();
+
+    virtual void *GetRendererData() const;
+    virtual void SetRendererData(void *data) const;
+
+private:
+    const MatSys::VertexDescriptorT &Descriptor;
+    UsageTypeT Usage;
+    mutable GLuint BufferObject;
+    mutable bool IsLocked;
+    unsigned long Size;
+};
+
+#endif
+
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -233,16 +233,17 @@
         OpenGLState->BindTexture(GL_TEXTURE_2D, RM->UseDefaultLightMap && Renderer.GetCurrentLightMap()!=NULL ? Renderer.GetCurrentLightMap()->GetOpenGLObject() : RM->LightTexMap->GetOpenGLObject());
 
 
+        // Draw the mesh
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE1_ARB, Mesh.Vertices[VertexNr].LightMapCoord);
-
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->SendLightMapCoords(GL_TEXTURE1_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Norm.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Norm.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Norm.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -234,15 +234,16 @@
         OpenGLState->BindTexture(GL_TEXTURE_2D, RM->NormTexMap->GetOpenGLObject());
 
 
+        // Draw the mesh
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Terrain.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Terrain.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Terrain.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -257,13 +257,15 @@
         cf::glProgramLocalParameter4fARB (GL_VERTEX_PROGRAM_ARB, 2, Material.ShaderParamExpr.Size()>=9 ? Material.ShaderParamExpr[8].Evaluate(Sym).GetAsFloat() : 4.0f, 0.0f, 0.0f, 0.0f);
 
 
+        // Draw the mesh
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm_Spec.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm_Spec.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm_Spec.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -175,6 +175,8 @@
         return false;
     }
 
+
+
     void Activate()
     {
         if (InitCounter<RendererImplT::GetInstance().GetInitCounter())
@@ -300,21 +302,21 @@
             cf::glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 0, EyePosCache);
         }
 
-
+        // Draw the mesh
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE1_ARB, Mesh.Vertices[VertexNr].LightMapCoord);
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->SendLightMapCoords(GL_TEXTURE1_ARB);
 
-                glNormal3fv(Mesh.Vertices[VertexNr].Normal);                                    // Normal
-                cf::glMultiTexCoord3fvARB(GL_TEXTURE6_ARB, Mesh.Vertices[VertexNr].Tangent);    // Tangent
-                cf::glMultiTexCoord3fvARB(GL_TEXTURE7_ARB, Mesh.Vertices[VertexNr].BiNormal);   // BiNormal
-
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+            Drawer->SendNormals();
+            Drawer->SendTangents(GL_TEXTURE6_ARB);
+            Drawer->SendBiNormals(GL_TEXTURE7_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm_Luma.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm_Luma.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm_Luma.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -264,16 +264,17 @@
         OpenGLState->BindTexture(GL_TEXTURE_2D, RM->LumaTexMap->GetOpenGLObject());
 
 
+        // Draw the mesh
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE1_ARB, Mesh.Vertices[VertexNr].LightMapCoord);
-
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->SendLightMapCoords(GL_TEXTURE1_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -159,6 +159,11 @@
 
     void RenderMesh(const MeshT& Mesh)
     {
+        // Check if the mesh format is acceptable
+        const VertexDescriptorT &Descriptor = Mesh.GetVertexDescriptor();
+        if(Descriptor.Origin < 0 || Descriptor.TextureCoord < 0)
+            return;
+
         const RendererImplT&         Renderer   =RendererImplT::GetInstance();
         RenderMaterialT*             RM         =Renderer.GetCurrentRenderMaterial();
         const MaterialT&             Material   =*(RM->Material);
@@ -223,16 +228,16 @@
         OpenGLState->Enable(GL_TEXTURE_2D);
         OpenGLState->BindTexture(GL_TEXTURE_2D, RM->DiffTexMap->GetOpenGLObject());
 
-
+        // Draw the mesh
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Solid.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Solid.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Solid.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -64,13 +64,14 @@
         VertexProgram=UploadProgram(GL_VERTEX_PROGRAM_ARB,
             "!!ARBvp1.0                                        \n"
             "PARAM mvp[4]={ state.matrix.mvp };                \n"
+            "PARAM mcolor=program.local[0];                    \n"
 
             "DP4 result.position.x, vertex.position, mvp[0];   \n"     // result.position = mul(state.matrix.mvp, vertex.position);
             "DP4 result.position.y, vertex.position, mvp[1];   \n"
             "DP4 result.position.z, vertex.position, mvp[2];   \n"
             "DP4 result.position.w, vertex.position, mvp[3];   \n"
 
-            "MOV result.color, vertex.color;                   \n"     // result.color = vertex.color;
+            "MUL result.color, vertex.color, mcolor;           \n"     // result.color = vertex.color*mcolor;
             "END                                               \n");
 
 
@@ -220,13 +221,27 @@
         OpenGLState->Disable(GL_TEXTURE_2D);
 
 
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                glColor4f(RedValue*Mesh.Vertices[VertexNr].Color[0], GreenValue*Mesh.Vertices[VertexNr].Color[1], BlueValue*Mesh.Vertices[VertexNr].Color[2], AlphaValue*Mesh.Vertices[VertexNr].Color[3]);
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        // The cgGLSetParameter*() functions are very slow, so cache their parameters in order to call them as little as possible.
+        static float MeshColorCache[4]={ 0.0, 0.0, 0.0, 1.0 };
+        if (RedValue!=MeshColorCache[0] || GreenValue!=MeshColorCache[1] || BlueValue!=MeshColorCache[2]
+            || AlphaValue != MeshColorCache[3])
+        {
+            MeshColorCache[0]=RedValue;
+            MeshColorCache[1]=GreenValue;
+            MeshColorCache[2]=BlueValue;
+            MeshColorCache[3]=AlphaValue;
+            cf::glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 0, MeshColorCache);
+        }
+
+        // Draw the mesh
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendColors();
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_SkyDome.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_SkyDome.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_SkyDome.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -242,14 +242,15 @@
             EyePosCache_w[2]=VW.m[2][3];
         }
 
-
+        // Draw the mesh
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Luma.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Luma.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Luma.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -242,16 +242,17 @@
         OpenGLState->BindTexture(GL_TEXTURE_2D, RM->LumaTexMap->GetOpenGLObject());
 
 
+        // Draw the mesh
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE1_ARB, Mesh.Vertices[VertexNr].LightMapCoord);
-
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->SendLightMapCoords(GL_TEXTURE1_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff_Norm.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff_Norm.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff_Norm.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -281,17 +281,19 @@
         }
 
 
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                glNormal3fv(Mesh.Vertices[VertexNr].Normal);                                // Normal
-                cf::glMultiTexCoord3fvARB(GL_TEXTURE6_ARB, Mesh.Vertices[VertexNr].Tangent);    // Tangent
-                cf::glMultiTexCoord3fvARB(GL_TEXTURE7_ARB, Mesh.Vertices[VertexNr].BiNormal);   // BiNormal
+        // Draw the mesh
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
 
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+            Drawer->SendNormals();
+            Drawer->SendTangents(GL_TEXTURE6_ARB);
+            Drawer->SendBiNormals(GL_TEXTURE7_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Norm_Luma.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Norm_Luma.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Norm_Luma.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -243,15 +243,16 @@
         OpenGLState->BindTexture(GL_TEXTURE_2D, RM->LumaTexMap->GetOpenGLObject());
 
 
+        // Draw the mesh
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm_Luma_Spec.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm_Luma_Spec.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm_Luma_Spec.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -307,21 +307,21 @@
             cf::glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 0, EyePosCache);
         }
 
-
+        // Draw the mesh
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE1_ARB, Mesh.Vertices[VertexNr].LightMapCoord);
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->SendLightMapCoords(GL_TEXTURE1_ARB);
 
-                glNormal3fv(Mesh.Vertices[VertexNr].Normal);                                    // Normal
-                cf::glMultiTexCoord3fvARB(GL_TEXTURE6_ARB, Mesh.Vertices[VertexNr].Tangent);    // Tangent
-                cf::glMultiTexCoord3fvARB(GL_TEXTURE7_ARB, Mesh.Vertices[VertexNr].BiNormal);   // BiNormal
-
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+            Drawer->SendNormals();
+            Drawer->SendTangents(GL_TEXTURE6_ARB);
+            Drawer->SendBiNormals(GL_TEXTURE7_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/StencilShadowVolumes.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/StencilShadowVolumes.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/StencilShadowVolumes.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -172,7 +172,7 @@
         OpenGLState->Enable(GL_STENCIL_TEST);
         OpenGLState->FrontFace(OpenGLStateT::WindingToOpenGL[Mesh.Winding]);
 
-
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
         if (cf::GL_EXT_stencil_two_side_AVAIL)
         {
             OpenGLState->Disable(GL_CULL_FACE);
@@ -188,10 +188,12 @@
             OpenGLState->StencilFunc(GL_ALWAYS, 0, ~0);
          // OpenGLState->StencilMask(~0);       // This is the default setting anyway.
 
-            glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-                for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-                    glVertex4dv(Mesh.Vertices[VertexNr].Origin);
-            glEnd();
+            Drawer->BeginDrawing(Mesh);
+            {
+                Drawer->SendPositions4();
+                Drawer->DrawMesh();
+            }
+            Drawer->EndDrawing();
         }
         else
         {
@@ -203,6 +205,8 @@
             // We could also render ALL pieces first in the first pass, then all in the second,
             // taking the OpenGL state changes out of the inner loop.
             // The good news is that that discussion is obsoleted by the two-sided stencil test extension above.
+            Drawer->BeginDrawing(Mesh);
+            Drawer->SendPositions4();
             for (char PassNr=0; PassNr<2; PassNr++)
             {
                 // Note that we have to cull the following polygons wrt. the *VIEWER* (not the light source)!
@@ -214,11 +218,9 @@
                 // 2. Clear the stencil buffer to 128, and compare later to reference value 128.
                 OpenGLState->StencilOp(GL_KEEP, PassNr==0 ? GL_INCR_WRAP : GL_DECR_WRAP, GL_KEEP);
 
-                glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-                    for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-                        glVertex4dv(Mesh.Vertices[VertexNr].Origin);
-                glEnd();
+                Drawer->DrawMesh();
             }
+            Drawer->EndDrawing();
         }
     }
 };
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -275,16 +275,16 @@
             cf::glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, LightDiffColorCache);
         }
 
-
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                glNormal3fv(Mesh.Vertices[VertexNr].Normal);    // Normal
-
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        // Draw the mesh
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->SendNormals();
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_WaterCubeReflect.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_WaterCubeReflect.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_WaterCubeReflect.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -342,15 +342,16 @@
         }
 
 
+        // Draw the mesh
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Luma.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Luma.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Luma.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -234,15 +234,16 @@
         OpenGLState->BindTexture(GL_TEXTURE_2D, RM->LumaTexMap->GetOpenGLObject());
 
 
+        // Draw the mesh
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff_Norm_Spec.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff_Norm_Spec.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff_Norm_Spec.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -348,17 +348,19 @@
         }
 
 
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                glNormal3fv(Mesh.Vertices[VertexNr].Normal);                                // Normal
-                cf::glMultiTexCoord3fvARB(GL_TEXTURE6_ARB, Mesh.Vertices[VertexNr].Tangent);    // Tangent
-                cf::glMultiTexCoord3fvARB(GL_TEXTURE7_ARB, Mesh.Vertices[VertexNr].BiNormal);   // BiNormal
+        // Draw the mesh
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
 
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+            Drawer->SendNormals();
+            Drawer->SendTangents(GL_TEXTURE6_ARB);
+            Drawer->SendBiNormals(GL_TEXTURE7_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/A_Diff_Light_Norm.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -255,16 +255,17 @@
         OpenGLState->BindTexture(GL_TEXTURE_2D, RM->NormTexMap->GetOpenGLObject());
 
 
+        // Draw the mesh
         glColor4f(RedValue, GreenValue, BlueValue, AlphaValue);
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE1_ARB, Mesh.Vertices[VertexNr].LightMapCoord);
-
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->SendLightMapCoords(GL_TEXTURE1_ARB);
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff_Spec.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff_Spec.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/Shaders/L_Diff_Spec.cpp	(copia de trabajo)
@@ -44,8 +44,8 @@
 #include "../../Mesh.hpp"
 #include "_CommonHelpers.hpp"
 #include "../../Common/OpenGLEx.hpp"
+#include "../MeshBuffer.hpp"
 
-
 using namespace MatSys;
 
 
@@ -339,16 +339,16 @@
             cf::glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 1, LightSpecColorCache);
         }
 
-
-        glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
-            for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-            {
-                glNormal3fv(Mesh.Vertices[VertexNr].Normal);    // Normal
-
-                cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
-            }
-        glEnd();
+        // Draw the mesh
+        MeshBufferManagerT *Drawer = MeshBufferManagerT::GetInstance();
+        Drawer->BeginDrawing(Mesh);
+        {
+            Drawer->SendPositions();
+            Drawer->SendTextureCoords(GL_TEXTURE0_ARB);
+            Drawer->SendNormals();
+            Drawer->DrawMesh();
+        }
+        Drawer->EndDrawing();
     }
 };
 
Index: Libs/MaterialSystem/RendererARBprogs/PrimitiveBufferImpl.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/PrimitiveBufferImpl.cpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/RendererARBprogs/PrimitiveBufferImpl.cpp	(revisiÃ³n: 0)
@@ -0,0 +1,142 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+/***************************/
+/*** PrimitiveBufferImpl ***/
+/***************************/
+
+#include <GL/gl.h>
+#include <cassert>
+#include <stdio.h>
+#include "../Common/OpenGLEx.hpp"
+#include "../Common/OpenGLState.hpp"
+#include "MeshBuffer.hpp"
+#include "PrimitiveBufferImpl.hpp"
+
+PrimitiveBufferImplT::PrimitiveBufferImplT(IndexTypeT IT, UsageTypeT UT)
+  : IndexType(IT), UsageType(UT), IsLocked(false), Size(0)
+{
+    cf::glGenBuffersARB(1, &BufferObject);
+}
+
+PrimitiveBufferImplT::~PrimitiveBufferImplT()
+{
+    MeshBufferManagerT::GetInstance()->DestroyPrimitiveBuffer(this);
+}
+
+// Primitives buffer access
+const void *PrimitiveBufferImplT::LockRead() const
+{
+    assert(!IsLocked);
+    IsLocked = true;
+
+    MeshBufferManagerT::GetInstance()->InvalidateClientState();
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+    OpenGLState->BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, BufferObject);
+    return cf::glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB);
+}
+
+void *PrimitiveBufferImplT::LockWrite()
+{
+    assert(!IsLocked);
+    IsLocked = true;
+
+    MeshBufferManagerT::GetInstance()->InvalidateClientState();
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+    OpenGLState->BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, BufferObject);
+    cf::glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GetBufferSize(), NULL,
+                            MeshBufferManagerT::UsageTypeToOpenGL[UsageType]);
+    return cf::glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+}
+
+void *PrimitiveBufferImplT::LockReadWrite()
+{
+    assert(!IsLocked);
+    IsLocked = true;
+
+    MeshBufferManagerT::GetInstance()->InvalidateClientState();
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+    OpenGLState->BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, BufferObject);
+    return cf::glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_READ_WRITE_ARB);
+}
+
+void PrimitiveBufferImplT::Unlock() const
+{
+    assert(IsLocked);
+    IsLocked = false;
+
+    MeshBufferManagerT::GetInstance()->InvalidateClientState();
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+    OpenGLState->BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, BufferObject);
+    cf::glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
+}
+
+// Buffer description
+unsigned long PrimitiveBufferImplT::GetBufferSize() const
+{
+    return Size*MeshBufferManagerT::IndexTypeSize[IndexType];
+}
+
+unsigned long PrimitiveBufferImplT::GetSize() const
+{
+    return Size;
+}
+
+void PrimitiveBufferImplT::SetSize(unsigned long S)
+{
+    Size = S;
+}
+
+PrimitiveBufferImplT::IndexTypeT PrimitiveBufferImplT::GetIndexType() const
+{
+    return IndexType;
+}
+
+PrimitiveBufferImplT::UsageTypeT PrimitiveBufferImplT::GetUsage() const
+{
+    return UsageType;
+}
+
+bool PrimitiveBufferImplT::IsValid() const
+{
+    return true;
+}
+
+void PrimitiveBufferImplT::Validated() const
+{
+}
+
+void PrimitiveBufferImplT::Invalidate()
+{
+}
+
+void *PrimitiveBufferImplT::GetRendererData() const
+{
+    return (void*)((unsigned long)BufferObject);
+}
+
+void PrimitiveBufferImplT::SetRendererData(void *Data) const
+{
+    BufferObject = (unsigned long)Data;
+}
+
Index: Libs/MaterialSystem/RendererARBprogs/MeshBuffer.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/MeshBuffer.cpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/RendererARBprogs/MeshBuffer.cpp	(revisiÃ³n: 0)
@@ -0,0 +1,635 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+/*******************************/
+/*** Renderer Implementation ***/
+/*******************************/
+
+// Required for #include <GL/gl.h> with MS VC++.
+#if defined(_WIN32) && defined(_MSC_VER)
+    #define WIN32_LEAN_AND_MEAN
+    #include <windows.h>
+    #if (_MSC_VER<1300)
+        #define for if (false) ; else for
+    #endif
+#endif
+
+#include <GL/gl.h>
+#include <cassert>
+#include <stdio.h>
+#include "../Common/OpenGLEx.hpp"
+#include "../Common/OpenGLState.hpp"
+#include "MeshBuffer.hpp"
+
+using namespace MatSys;
+
+// Helper template to get the vertex element pointer
+template<typename T>
+const T *GetElementAddress(const void *buffer, int offset)
+{
+    assert(offset >= 0);
+    return (const T*)((const char*)buffer + offset);
+}
+
+GLenum MeshBufferManagerT::UsageTypeToOpenGL[3] =
+{GL_STATIC_DRAW_ARB, GL_DYNAMIC_DRAW_ARB, GL_STREAM_DRAW_ARB };
+
+GLenum MeshBufferManagerT::IndexTypeToOpenGLType[3] =
+{GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT};
+
+unsigned long MeshBufferManagerT::IndexTypeSize[3] =
+{sizeof(unsigned char), sizeof(unsigned short), sizeof(unsigned long)};
+
+
+MeshBufferManagerT::MeshBufferManagerT()
+  : IsSendingMesh(false), Start(true)
+{
+}
+
+MeshBufferManagerT::~MeshBufferManagerT()
+{
+}
+
+MeshBufferManagerT *MeshBufferManagerT::GetInstance()
+{
+    static MeshBufferManagerT *Manager = NULL;
+    if(!Manager)
+        Manager = new MeshBufferManagerT();
+
+    return Manager;
+}
+
+void MeshBufferManagerT::ClientStateT::Clear()
+{
+    Mesh = NULL;
+    VertexBuffer = NULL;
+    VertexBufferData = NULL;
+
+    PrimitiveBuffer = NULL;
+    PrimitiveBufferData = NULL;
+
+    IsEnabled_Positions = false;
+    IsEnabled_Positions4 = false;
+    IsEnabled_Colors = false;
+    IsEnabled_Normals = false;
+    UseVBO = false;
+    for(int i = 0; i < 8; i++)
+        IsEnabled_Texcoords[i] = false;
+}
+
+// Revalidate the VertexBuffer
+void MeshBufferManagerT::RevalidateVertexBuffer()
+{
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+    const VertexBufferI *buffer = ClientState.VertexBuffer;
+    if(!buffer)
+        return;
+
+    void *renderData = buffer->GetRendererData();
+    GLuint vbo;
+    if(renderData == NULL)
+    {
+        // Create the vertex buffer object and bind it
+        cf::glGenBuffersARB(1, &vbo);
+        OpenGLState->BindBuffer(GL_ARRAY_BUFFER_ARB, vbo);
+        renderData = (void*)vbo;
+        buffer->SetRendererData(renderData);
+    }
+    else
+    {
+        // Retrieve the buffer object and bind it
+        vbo = (unsigned long)renderData;
+        OpenGLState->BindBuffer(GL_ARRAY_BUFFER_ARB, vbo);
+        if(buffer->IsValid())
+            return;
+    }
+
+    // Upload the buffer data
+    unsigned long size = buffer->GetBufferSize();
+    const void *data = buffer->LockRead();
+    cf::glBufferDataARB(GL_ARRAY_BUFFER_ARB, size, data, UsageTypeToOpenGL[buffer->GetUsage()]);
+
+    // Unlock the buffer
+    buffer->Unlock();
+    buffer->Validated();
+}
+
+// Revalidate the primitive buffer
+void MeshBufferManagerT::RevalidatePrimitiveBuffer()
+{
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+    const PrimitiveBufferI *buffer = ClientState.PrimitiveBuffer;
+    if(!buffer)
+        return;
+
+    void *renderData = buffer->GetRendererData();
+    GLuint vbo;
+    if(!renderData)
+    {
+        // Create the vertex buffer object and bind it
+        cf::glGenBuffersARB(1, &vbo);
+        OpenGLState->BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo);
+        renderData = (void*)vbo;
+        buffer->SetRendererData(renderData);
+    }
+    else
+    {
+        // Retrieve the buffer object and bind it
+        vbo = (long)renderData;
+        OpenGLState->BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, vbo);
+        if(buffer->IsValid())
+            return;
+    }
+
+    // Upload the buffer data
+    unsigned long size = buffer->GetBufferSize();
+    const void *data = buffer->LockRead();
+    cf::glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, size, data, UsageTypeToOpenGL[ClientState.Mesh->UsageType]);
+
+    // Unlock the buffer
+    buffer->Unlock();
+    buffer->Validated();
+}
+
+// Revalidate the vertex buffer objects
+void MeshBufferManagerT::RevalidateBufferObjects()
+{
+    if(cf::GL_ARB_vertex_buffer_object_AVAIL)
+    {
+        RevalidateVertexBuffer();
+        RevalidatePrimitiveBuffer();
+        ClientState.UseVBO = true;
+    }
+    else
+    {
+        if(ClientState.VertexBuffer)
+            ClientState.VertexBufferData = ClientState.VertexBuffer->LockRead();
+        if(ClientState.PrimitiveBuffer)
+            ClientState.PrimitiveBufferData = ClientState.PrimitiveBuffer->LockRead();
+        ClientState.UseVBO = false;
+    }
+}
+
+// Begin mesh data transfer
+void MeshBufferManagerT::BeginDrawing(const MatSys::MeshT &Mesh)
+{
+    assert(!IsSendingMesh);
+
+    // Check if the mesh is valid and is already sended
+    if(ClientState.Mesh == &Mesh && Mesh.IsValid())
+    {
+        IsSendingMesh = true;
+        return;
+    }
+
+    // Prevent OpenGL stack errors
+    if(!Start)
+        glPopClientAttrib(); // Pop the old client attribute
+    else
+        Start = false;
+
+    // Clear the client data
+    ClientState.Clear();
+
+    // Store the mesh metadata
+    ClientState.Mesh = &Mesh;
+    ClientState.VertexBuffer = Mesh.VertexBuffer;
+    ClientState.PrimitiveBuffer = Mesh.PrimitiveBuffer;
+
+    // Store the current client attributes
+    glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
+
+    // Set the sending flag
+    IsSendingMesh = true;
+
+    // Revalidate the vertex buffer objects
+    RevalidateBufferObjects();
+}
+
+// Draw the mesh
+void MeshBufferManagerT::DrawMesh()
+{
+    GLenum Mode = OpenGLStateT::MeshToOpenGLType[ClientState.Mesh->Type];
+    const ArrayT<MeshT::RangeT> &SubRanges = ClientState.Mesh->SubRanges;
+    unsigned long NumSubRanges = SubRanges.Size();
+    unsigned long NumVertices = ClientState.VertexBuffer->GetSize();
+    if(ClientState.PrimitiveBuffer)
+    {
+        GLenum IndexType = IndexTypeToOpenGLType[ClientState.PrimitiveBuffer->GetIndexType()];
+        unsigned long IndexSize = IndexTypeSize[ClientState.PrimitiveBuffer->GetIndexType()];
+        if(NumSubRanges == 0)
+        {
+            // Draw all of the elements.
+            glDrawRangeElements(Mode, 0, NumVertices, ClientState.PrimitiveBuffer->GetSize(),
+                                IndexType, ClientState.PrimitiveBufferData);
+        }
+        else
+        {
+            // Draw each sub range primitives.
+            for(unsigned long i = 0; i < NumSubRanges; i++)
+            {
+                GLenum SubMode = Mode;
+                if(SubRanges[i].Type != MeshT::Inherit)
+                    SubMode = OpenGLStateT::MeshToOpenGLType[SubRanges[i].Type];
+
+                // Adjust the start pointer
+                char *BufferStart = ((char*)ClientState.PrimitiveBufferData) + SubRanges[i].Start*IndexSize;
+                glDrawRangeElements(SubMode, 0, NumVertices, SubRanges[i].Count,
+                                    IndexType, BufferStart);
+            }
+        }
+    }
+    else if(ClientState.VertexBuffer)
+    {
+        if(NumSubRanges == 0)
+        {
+            // Draw all of the array.
+            glDrawArrays(Mode, 0, NumVertices);
+        }
+        else
+        {
+            // Draw each sub range primitives.
+            for(unsigned long i = 0; i < NumSubRanges; i++)
+            {
+                GLenum SubMode = Mode;
+                if(SubRanges[i].Type != MeshT::Inherit)
+                    SubMode = OpenGLStateT::MeshToOpenGLType[SubRanges[i].Type];
+                glDrawArrays(SubMode, SubRanges[i].Start, SubRanges[i].Count);
+            }
+        }
+    }
+}
+
+// End mesh data transfer
+void MeshBufferManagerT::EndDrawing()
+{
+    assert(IsSendingMesh);
+
+    // Unset the sending flag
+    IsSendingMesh = false;
+
+    // Unlock buffers if VBOs is not supported
+    if(!ClientState.UseVBO && ClientState.VertexBufferData)
+    {
+        ClientState.VertexBufferData = NULL;
+        ClientState.VertexBuffer->Unlock();
+    }
+
+    if(!ClientState.UseVBO && ClientState.PrimitiveBufferData)
+    {
+        ClientState.PrimitiveBufferData = NULL;
+        ClientState.PrimitiveBuffer->Unlock();
+    }
+}
+
+// Destroys the mesh buffer
+void MeshBufferManagerT::DestroyMesh(MatSys::MeshT *mesh)
+{
+}
+
+// Destroys the vertex buffer
+void MeshBufferManagerT::DestroyVertexBuffer(MatSys::VertexBufferI *Buffer)
+{
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+
+    // Check the extension
+    if(!cf::GL_ARB_vertex_buffer_object_AVAIL)
+        return;
+
+    // Retrieve the vertex buffer object name
+    void *renderData = Buffer->GetRendererData();
+    if(renderData)
+    {
+        GLuint vbo = (long)renderData;
+        if(ClientState.VertexBuffer == Buffer) // Unbind the vertex buffer object
+            OpenGLState->BindBuffer(GL_ARRAY_BUFFER_ARB, 0);
+
+        // Delete the vertex buffer object
+        cf::glDeleteBuffersARB(1, &vbo);
+    }
+
+    if(ClientState.VertexBuffer == Buffer)
+    {
+        glPopClientAttrib(); // Pops the client state
+        Start = true;
+        ClientState.Clear();
+    }
+
+}
+
+void MeshBufferManagerT::InvalidateClientState()
+{
+    if(!Start)
+    {
+        glPopClientAttrib(); // Pops the client state
+        Start = true;
+        ClientState.Clear();
+    }
+}
+
+// Destroys the primitive buffer
+void MeshBufferManagerT::DestroyPrimitiveBuffer(MatSys::PrimitiveBufferI *Buffer)
+{
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+
+    // Check the extension
+    if(!cf::GL_ARB_vertex_buffer_object_AVAIL)
+        return;
+
+    // Retrieve the vertex buffer object name
+    void *renderData = Buffer->GetRendererData();
+    if(renderData)
+    {
+        GLuint vbo = (long)renderData;
+        if(ClientState.PrimitiveBuffer == Buffer) // Unbind the vertex buffer object
+            OpenGLState->BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+
+        // Delete the vertex buffer object
+        cf::glDeleteBuffersARB(1, &vbo);
+    }
+
+    if(ClientState.PrimitiveBuffer == Buffer)
+    {
+        glPopClientAttrib(); // Pops the client state
+        Start = true;
+        ClientState.Clear();
+    }
+}
+
+void MeshBufferManagerT::SendPositions()
+{
+    // Extract the descriptor
+    if(ClientState.IsEnabled_Positions || !ClientState.VertexBuffer)
+        return;
+
+    const VertexDescriptorT &Format = ClientState.VertexBuffer->GetVertexDescriptor();
+
+    // For debugging. Check the presence of the origin
+    assert(Format.Origin >= 0);
+
+    // Update enabled flags
+    glEnableClientState(GL_VERTEX_ARRAY);
+    ClientState.IsEnabled_Positions = true;
+
+    // Send the data
+    if(ClientState.UseVBO)
+    {
+        // Use VBOs. The pointer is just an offset
+        glVertexPointer(3, GL_FLOAT, Format.VertexSize, (const void*)Format.Origin);
+    }
+    else if(ClientState.VertexBufferData)
+    {
+        // Use vertex arrays
+        glVertexPointer(3, GL_FLOAT, Format.VertexSize,
+            GetElementAddress<const void*> (ClientState.VertexBufferData, Format.Origin));
+    }
+}
+
+void MeshBufferManagerT::SendPositions4()
+{
+    // Extract the descriptor
+    if(ClientState.IsEnabled_Positions4 || !ClientState.VertexBuffer)
+        return;
+
+    const VertexDescriptorT &Format = ClientState.VertexBuffer->GetVertexDescriptor();
+
+    // For debugging. Check the presence of the origin
+    assert(Format.Origin4 >= 0);
+
+    // Update enabled flags
+    glEnableClientState(GL_VERTEX_ARRAY);
+    ClientState.IsEnabled_Positions4 = true;
+
+    // Send the data
+    if(ClientState.UseVBO)
+    {
+        // Use VBOs. The pointer is just an offset
+        glVertexPointer(4, GL_FLOAT, Format.VertexSize, (const void*)Format.Origin4);
+    }
+    else if(ClientState.VertexBufferData)
+    {
+        // Use vertex arrays
+        glVertexPointer(4, GL_FLOAT, Format.VertexSize,
+            GetElementAddress<const void*> (ClientState.VertexBufferData, Format.Origin4));
+    }
+}
+
+void MeshBufferManagerT::SendNormals()
+{
+    // Extract the descriptor
+    if(ClientState.IsEnabled_Normals || !ClientState.VertexBuffer)
+        return;
+
+    const VertexDescriptorT &Format = ClientState.VertexBuffer->GetVertexDescriptor();
+
+    // For debugging. Check the presence of the origin
+    assert(Format.Normal >= 0);
+
+    // Update enabled flags
+    glEnableClientState(GL_NORMAL_ARRAY);
+    ClientState.IsEnabled_Normals = true;
+
+    // Send the data
+    if(ClientState.UseVBO)
+    {
+        // Use VBOs. The pointer is just an offset
+        glNormalPointer(GL_FLOAT, Format.VertexSize, (const void*)Format.Normal);
+    }
+    else if(ClientState.VertexBufferData)
+    {
+        // Use vertex arrays
+        glNormalPointer(GL_FLOAT, Format.VertexSize,
+            GetElementAddress<const void*> (ClientState.VertexBufferData, Format.Normal));
+    }
+}
+
+void MeshBufferManagerT::SendColors()
+{
+    // Extract the descriptor
+    if(ClientState.IsEnabled_Colors || !ClientState.VertexBuffer)
+        return;
+
+    const VertexDescriptorT &Format = ClientState.VertexBuffer->GetVertexDescriptor();
+
+    // For debugging. Check the presence of the origin
+    assert(Format.Color >= 0);
+
+    // Update enabled flags
+    glEnableClientState(GL_COLOR_ARRAY);
+    ClientState.IsEnabled_Colors = true;
+
+    // Send the data
+    if(ClientState.UseVBO)
+    {
+        // Use VBOs. The pointer is just an offset
+        glColorPointer(4, GL_FLOAT, Format.VertexSize, (const void*)Format.Color);
+    }
+    else if(ClientState.VertexBufferData)
+    {
+        // Use vertex arrays
+        glColorPointer(4, GL_FLOAT, Format.VertexSize,
+            GetElementAddress<const void*> (ClientState.VertexBufferData, Format.Color));
+    }
+}
+
+void MeshBufferManagerT::SendTextureCoords(GLenum Unit)
+{
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+
+    // Check if the state is laready setted
+    int Id = Unit - GL_TEXTURE0_ARB;
+    assert(Id < 8);
+    if(ClientState.IsEnabled_Texcoords[Id] || !ClientState.VertexBuffer)
+        return;
+
+    // Extract the descriptor
+    const VertexDescriptorT &Format = ClientState.VertexBuffer->GetVertexDescriptor();
+
+    // For debugging. Check the presence of the origin
+    assert(Format.TextureCoord >= 0);
+
+    // Update enabled flags
+    OpenGLState->ClientActiveTexture(Unit);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    ClientState.IsEnabled_Texcoords[Id] = true;
+
+    // Send the data
+    if(ClientState.UseVBO)
+    {
+        // Use VBOs. The pointer is just an offset
+        glTexCoordPointer(2, GL_FLOAT, Format.VertexSize, (const void*)Format.TextureCoord);
+    }
+    else if(ClientState.VertexBufferData)
+    {
+        // Use vertex arrays
+        glTexCoordPointer(2, GL_FLOAT, Format.VertexSize,
+            GetElementAddress<const void*> (ClientState.VertexBufferData, Format.TextureCoord));
+    }
+}
+
+void MeshBufferManagerT::SendLightMapCoords(GLenum Unit)
+{
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+
+    // Check if the state is laready setted
+    int Id = Unit - GL_TEXTURE0_ARB;
+    assert(Id < 8);
+    if(ClientState.IsEnabled_Texcoords[Id] || !ClientState.VertexBuffer)
+        return;
+
+    // Extract the descriptor
+    const VertexDescriptorT &Format = ClientState.VertexBuffer->GetVertexDescriptor();
+
+    // For debugging. Check the presence of the origin
+    assert(Format.LightMapCoord >= 0);
+
+    // Update enabled flags
+    OpenGLState->ClientActiveTexture(Unit);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    ClientState.IsEnabled_Texcoords[Id] = true;
+
+    // Send the data
+    if(ClientState.UseVBO)
+    {
+        // Use VBOs. The pointer is just an offset
+        glTexCoordPointer(2, GL_FLOAT, Format.VertexSize, (const void*)Format.LightMapCoord);
+    }
+    else if(ClientState.VertexBufferData)
+    {
+        // Use vertex arrays
+        glTexCoordPointer(2, GL_FLOAT, Format.VertexSize,
+            GetElementAddress<const void*> (ClientState.VertexBufferData, Format.LightMapCoord));
+    }
+}
+
+void MeshBufferManagerT::SendBiNormals(GLenum Unit)
+{
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+
+    // Check if the state is laready setted
+    int Id = Unit - GL_TEXTURE0_ARB;
+    assert(Id < 8);
+    if(ClientState.IsEnabled_Texcoords[Id] || !ClientState.VertexBuffer)
+        return;
+
+    // Extract the descriptor
+    const VertexDescriptorT &Format = ClientState.VertexBuffer->GetVertexDescriptor();
+
+    // For debugging. Check the presence of the origin
+    assert(Format.BiNormal >= 0);
+
+    // Update enabled flags
+    OpenGLState->ClientActiveTexture(Unit);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    ClientState.IsEnabled_Texcoords[Id] = true;
+
+    // Send the data
+    if(ClientState.UseVBO)
+    {
+        // Use VBOs. The pointer is just an offset
+        glTexCoordPointer(3, GL_FLOAT, Format.VertexSize, (const void*)Format.BiNormal);
+    }
+    else if(ClientState.VertexBufferData)
+    {
+        // Use vertex arrays
+        glTexCoordPointer(3, GL_FLOAT, Format.VertexSize,
+            GetElementAddress<const void*> (ClientState.VertexBufferData, Format.BiNormal));
+    }
+}
+
+void MeshBufferManagerT::SendTangents(GLenum Unit)
+{
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+
+    // Check if the state is laready setted
+    int Id = Unit - GL_TEXTURE0_ARB;
+    assert(Id < 8);
+    if(ClientState.IsEnabled_Texcoords[Id] || !ClientState.VertexBuffer)
+        return;
+
+    // Extract the descriptor
+    const VertexDescriptorT &Format = ClientState.VertexBuffer->GetVertexDescriptor();
+
+    // For debugging. Check the presence of the origin
+    assert(Format.Tangent >= 0);
+
+    // Update enabled flags
+    OpenGLState->ClientActiveTexture(Unit);
+    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    ClientState.IsEnabled_Texcoords[Id] = true;
+
+    // Send the data
+    if(ClientState.UseVBO)
+    {
+        // Use VBOs. The pointer is just an offset
+        glTexCoordPointer(3, GL_FLOAT, Format.VertexSize, (const void*)Format.Tangent);
+    }
+    else if(ClientState.VertexBufferData)
+    {
+        // Use vertex arrays
+        glTexCoordPointer(3, GL_FLOAT, Format.VertexSize,
+            GetElementAddress<const void*> (ClientState.VertexBufferData, Format.Tangent));
+    }
+}
+
+
Index: Libs/MaterialSystem/RendererARBprogs/RendererImpl.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/RendererImpl.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/RendererImpl.cpp	(copia de trabajo)
@@ -48,8 +48,10 @@
 
 #include "../Common/OpenGLEx.hpp"
 #include "Templates/Array.hpp"
+#include "MeshBuffer.hpp"
+#include "VertexBufferImpl.hpp"
+#include "PrimitiveBufferImpl.hpp"
 
-
 using namespace MatSys;
 
 
@@ -289,6 +291,7 @@
     cf::Init_GL_EXT_stencil_wrap();
     cf::Init_GL_EXT_stencil_two_side();
     cf::Init_GL_ARB_vertex_and_fragment_program();
+    cf::Init_GL_ARB_vertex_buffer_object();
 
     if (cf::GL_ARB_texture_compression_AVAIL)
         glHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
@@ -1037,7 +1040,35 @@
     CurrentShader->RenderMesh(Mesh);
 }
 
+void RendererImplT::OnDestroyMesh(MatSys::MeshT *Mesh)
+{
+    MeshBufferManagerT::GetInstance()->DestroyMesh(Mesh);
+}
 
+void RendererImplT::OnDestroyVertexBuffer(MatSys::VertexBufferI *Buffer)
+{
+    MeshBufferManagerT::GetInstance()->DestroyVertexBuffer(Buffer);
+}
+
+void RendererImplT::OnDestroyPrimitiveBuffer(MatSys::PrimitiveBufferI *Buffer)
+{
+    MeshBufferManagerT::GetInstance()->DestroyPrimitiveBuffer(Buffer);
+}
+
+MatSys::VertexBufferI *RendererImplT::CreateVertexBuffer(const VertexDescriptorT &Format, unsigned int Usage)
+{
+    if(cf::GL_ARB_vertex_buffer_object_AVAIL)
+        return new VertexBufferImplT(Format, (VertexBufferI::UsageTypeT)Usage);
+    return NULL;
+}
+
+PrimitiveBufferI *RendererImplT::CreatePrimitiveBuffer(PrimitiveBufferI::IndexTypeT IndexType, PrimitiveBufferI::UsageTypeT Usage)
+{
+    if(cf::GL_ARB_vertex_buffer_object_AVAIL)
+        return new PrimitiveBufferImplT(IndexType, Usage);
+    return NULL;
+}
+
 RenderMaterialT* RendererImplT::GetCurrentRenderMaterial() const
 {
     return CurrentRenderMaterial;
Index: Libs/MaterialSystem/RendererARBprogs/PrimitiveBufferImpl.hpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/PrimitiveBufferImpl.hpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/RendererARBprogs/PrimitiveBufferImpl.hpp	(revisiÃ³n: 0)
@@ -0,0 +1,71 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+/************************/
+/*** PrimitiveBufferImpl ***/
+/************************/
+
+#ifndef _CA_MATSYS_PRIMITIVE_BUFFER_IMPLEMENTATION_HPP_
+#define _CA_MATSYS_PRIMITIVE_BUFFER_IMPLEMENTATION_HPP_
+
+#include <GL/gl.h>
+#include "../PrimitiveBuffer.hpp"
+
+class PrimitiveBufferImplT: public MatSys::PrimitiveBufferI
+{
+public:
+    PrimitiveBufferImplT(IndexTypeT IT, UsageTypeT UT);
+    virtual ~PrimitiveBufferImplT();
+
+    // Primitives buffer access
+    virtual const void *LockRead() const;
+    virtual void *LockWrite();
+    virtual void *LockReadWrite();
+    virtual void Unlock() const;
+
+    // Buffer description
+    virtual unsigned long GetBufferSize() const;
+    virtual unsigned long GetSize() const;
+    virtual void SetSize(unsigned long S);
+
+    virtual IndexTypeT GetIndexType() const;
+    virtual UsageTypeT GetUsage() const;
+
+    // Those are used to synchronize the version in the main memory
+    // with the video card
+    virtual bool IsValid() const;
+    virtual void Validated() const;
+    virtual void Invalidate();
+
+    virtual void *GetRendererData() const;
+    virtual void SetRendererData(void *Data) const;
+
+private:
+    IndexTypeT     IndexType;
+    UsageTypeT     UsageType;
+    mutable bool   IsLocked;
+    mutable GLuint BufferObject;
+    unsigned long  Size;
+};
+
+#endif 
Index: Libs/MaterialSystem/RendererARBprogs/VertexBufferImpl.cpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/VertexBufferImpl.cpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/RendererARBprogs/VertexBufferImpl.cpp	(revisiÃ³n: 0)
@@ -0,0 +1,115 @@
+#include <GL/gl.h>
+#include <cassert>
+#include <stdio.h>
+#include "../Common/OpenGLEx.hpp"
+#include "../Common/OpenGLState.hpp"
+#include "MeshBuffer.hpp"
+#include "VertexBufferImpl.hpp"
+
+using namespace MatSys;
+
+VertexBufferImplT::VertexBufferImplT(const VertexDescriptorT &VertexFormat, UsageTypeT U)
+    : Descriptor(VertexFormat), Usage(U), IsLocked(false), Size(0)
+{
+    cf::glGenBuffersARB(1, &BufferObject);
+}
+
+VertexBufferImplT::~VertexBufferImplT()
+{
+    MeshBufferManagerT::GetInstance()->DestroyVertexBuffer(this);
+}
+
+const VertexDescriptorT &VertexBufferImplT::GetVertexDescriptor() const
+{
+    return Descriptor;
+}
+
+const void *VertexBufferImplT::LockRead() const
+{
+    assert(!IsLocked);
+    IsLocked = true;
+
+    MeshBufferManagerT::GetInstance()->InvalidateClientState();
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+    OpenGLState->BindBuffer(GL_ARRAY_BUFFER_ARB, BufferObject);
+    return cf::glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB);
+}
+
+void *VertexBufferImplT::LockWrite()
+{
+    assert(!IsLocked);
+    IsLocked = true;
+
+    MeshBufferManagerT::GetInstance()->InvalidateClientState();
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+    OpenGLState->BindBuffer(GL_ARRAY_BUFFER_ARB, BufferObject);
+    cf::glBufferDataARB(GL_ARRAY_BUFFER_ARB, GetBufferSize(), NULL,
+                            MeshBufferManagerT::UsageTypeToOpenGL[Usage]);
+    return cf::glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+}
+
+void *VertexBufferImplT::LockReadWrite()
+{
+    assert(!IsLocked);
+    IsLocked = true;
+
+    MeshBufferManagerT::GetInstance()->InvalidateClientState();
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+    OpenGLState->BindBuffer(GL_ARRAY_BUFFER_ARB, BufferObject);
+    return cf::glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_WRITE_ARB);
+}
+
+void VertexBufferImplT::Unlock() const
+{
+    assert(IsLocked);
+    IsLocked = false;
+
+    MeshBufferManagerT::GetInstance()->InvalidateClientState();
+    OpenGLStateT *OpenGLState = OpenGLStateT::GetInstance();
+    OpenGLState->BindBuffer(GL_ARRAY_BUFFER_ARB, BufferObject);
+    cf::glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+}
+
+unsigned long VertexBufferImplT::GetBufferSize() const
+{
+    return Size*Descriptor.VertexSize;
+}
+
+unsigned long VertexBufferImplT::GetSize() const
+{
+    return Size;
+}
+
+void VertexBufferImplT::SetSize(unsigned long S)
+{
+    Size = S;
+}
+
+VertexBufferI::UsageTypeT VertexBufferImplT::GetUsage() const
+{
+    return Usage;
+}
+
+bool VertexBufferImplT::IsValid() const
+{
+    return true; // Always valid
+}
+
+void VertexBufferImplT::Validated() const
+{
+}
+
+void VertexBufferImplT::Invalidate()
+{
+}
+
+void *VertexBufferImplT::GetRendererData() const
+{
+    return (void*)((unsigned long)BufferObject);
+}
+
+void VertexBufferImplT::SetRendererData(void *data) const
+{
+    BufferObject = (unsigned long)data;
+}
+
Index: Libs/MaterialSystem/RendererARBprogs/MeshBuffer.hpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/MeshBuffer.hpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/RendererARBprogs/MeshBuffer.hpp	(revisiÃ³n: 0)
@@ -0,0 +1,118 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+/**********************/
+/*** MeshBuffer ***/
+/**********************/
+
+#ifndef _CA_MATSYS_BUFFERMAN_HPP_
+#define _CA_MATSYS_BUFFERMAN_HPP_
+
+#include <GL/gl.h>
+#include "../Mesh.hpp"
+
+class MeshBufferManagerT
+{
+public:
+    MeshBufferManagerT();
+    ~MeshBufferManagerT();
+
+    // Begin mesh data transfer
+    void BeginDrawing(const MatSys::MeshT &Mesh);
+
+    // Draw the mesh
+    void DrawMesh();
+
+    // End mesh data transfer
+    void EndDrawing();
+
+    // Destroys the mesh buffer
+    void DestroyMesh(MatSys::MeshT *mesh);
+
+    // Invalidates the client state
+    void InvalidateClientState();
+
+    // Destroys the vertex buffer
+    void DestroyVertexBuffer(MatSys::VertexBufferI *Buffer);
+
+    // Destroys the primitive buffer
+    void DestroyPrimitiveBuffer(MatSys::PrimitiveBufferI *Buffer);
+
+    // Functions to send mesh data
+    void SendPositions();
+    void SendPositions4();
+    void SendNormals();
+    void SendColors();
+    void SendTextureCoords(GLenum Unit);
+    void SendLightMapCoords(GLenum Unit);
+    void SendBiNormals(GLenum Unit);
+    void SendTangents(GLenum Unit);
+
+    static MeshBufferManagerT *GetInstance();
+    static GLenum UsageTypeToOpenGL[3];
+    static GLenum IndexTypeToOpenGLType[3];
+    static unsigned long IndexTypeSize[3];
+
+private:
+    struct ClientStateT
+    {
+        ClientStateT()
+          : Mesh(NULL), VertexBuffer(NULL), VertexBufferData(NULL),
+            PrimitiveBuffer(NULL), PrimitiveBufferData(NULL),
+            IsEnabled_Positions(false), IsEnabled_Positions4(false),
+            IsEnabled_Colors(false), IsEnabled_Normals(false), UseVBO(false)
+        {
+            for(int i = 0; i < 8; i++)
+                IsEnabled_Texcoords[i] = false;
+        }
+
+        void Clear();
+
+        const MatSys::MeshT *Mesh;
+        const MatSys::VertexBufferI *VertexBuffer;
+        const void *VertexBufferData;
+
+        const MatSys::PrimitiveBufferI *PrimitiveBuffer;
+        const void *PrimitiveBufferData;
+
+        bool IsEnabled_Positions;
+        bool IsEnabled_Positions4;
+        bool IsEnabled_Colors;
+        bool IsEnabled_Normals;
+        bool IsEnabled_Texcoords[8];
+        bool UseVBO;
+    };
+
+    ClientStateT ClientState;
+    bool IsSendingMesh;
+    bool Start;
+
+    void RevalidateVertexBuffer();
+    void RevalidatePrimitiveBuffer();
+    void RevalidateBufferObjects();
+};
+
+
+
+#endif
+
Index: Libs/MaterialSystem/RendererARBprogs/RendererImpl.hpp
===================================================================
--- Libs/MaterialSystem/RendererARBprogs/RendererImpl.hpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererARBprogs/RendererImpl.hpp	(copia de trabajo)
@@ -127,8 +127,13 @@
     void SetCurrentSHLMaps(const ArrayT<MatSys::TextureMapI*>& SHLMaps);
     void SetCurrentSHLLookupMap(MatSys::TextureMapI* SHLLookupMap);
     void RenderMesh(const MatSys::MeshT& Mesh);
+    void OnDestroyMesh(MatSys::MeshT *Mesh);
+    void OnDestroyVertexBuffer(MatSys::VertexBufferI *Buffer);
+    void OnDestroyPrimitiveBuffer(MatSys::PrimitiveBufferI *Buffer);
+    MatSys::VertexBufferI *CreateVertexBuffer(const MatSys::VertexDescriptorT &Format, unsigned int Usage);
+    MatSys::PrimitiveBufferI *CreatePrimitiveBuffer(MatSys::PrimitiveBufferI::IndexTypeT IndexType,
+                                                    MatSys::PrimitiveBufferI::UsageTypeT Usage);
 
-
     // Internal Interface
     MatSys::RenderMaterialT* GetCurrentRenderMaterial() const;
     TextureMap2DT*           GetCurrentLightMap() const;
Index: Libs/MaterialSystem/VertexBufferImpl.cpp
===================================================================
--- Libs/MaterialSystem/VertexBufferImpl.cpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/VertexBufferImpl.cpp	(revisiÃ³n: 0)
@@ -0,0 +1,151 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+/************************/
+/*** VertexBufferImpl ***/
+/************************/
+
+#include "VertexBufferImpl.hpp"
+#include "Renderer.hpp"
+
+namespace MatSys
+{
+
+    VertexBufferImplT::VertexBufferImplT(const VertexDescriptorT &VertexFormat)
+        : Descriptor(VertexFormat), Size(0), Data(NULL), IsLocked(false), IsValidBuffer(false), RendererData(NULL)
+    {
+    }
+
+    VertexBufferImplT::~VertexBufferImplT()
+    {
+        if(Data)
+            delete [] (unsigned char*)Data;
+
+        if(Renderer && RendererData)
+            Renderer->OnDestroyVertexBuffer(this);
+    }
+
+    // Vertex format descriptor
+    const VertexDescriptorT &VertexBufferImplT::GetVertexDescriptor() const
+    {
+        return Descriptor;
+    }
+
+    // Vertex data access
+    const void *VertexBufferImplT::LockRead() const
+    {
+        assert(!IsLocked);
+        IsLocked = true;
+        return Data;
+    }
+
+    void *VertexBufferImplT::LockWrite()
+    {
+        assert(!IsLocked);
+        IsLocked = true;
+        IsValidBuffer = false;
+        return Data;
+    }
+
+    void *VertexBufferImplT::LockReadWrite()
+    {
+        assert(!IsLocked);
+        IsLocked = true;
+        IsValidBuffer = false;
+        return Data;
+    }
+
+    void VertexBufferImplT::Unlock() const
+    {
+        assert(IsLocked);
+        IsLocked = false;
+    }
+
+    // Number of vertices
+    unsigned long VertexBufferImplT::GetBufferSize() const
+    {
+        return Size*Descriptor.VertexSize;
+    }
+
+    unsigned long VertexBufferImplT::GetSize() const
+    {
+        return Size;
+    }
+
+    void VertexBufferImplT::SetSize(unsigned long S)
+    {
+        if(Size != S)
+        {
+            Size = S;
+            if(Data)
+                delete [] (unsigned char*)Data;
+            Data = new unsigned char[GetBufferSize()];
+        }
+    }
+
+    VertexBufferI::UsageTypeT VertexBufferImplT::GetUsage() const
+    {
+        return Stream;
+    }
+
+
+    // Those are used to synchronize the version in the main memory
+    // with the video card
+    bool VertexBufferImplT::IsValid() const
+    {
+        return IsValidBuffer;
+    }
+
+    void VertexBufferImplT::Validated() const
+    {
+        IsValidBuffer = true;
+    }
+
+    void VertexBufferImplT::Invalidate()
+    {
+        IsValidBuffer = false;
+    }
+
+    void *VertexBufferImplT::GetRendererData() const
+    {
+        return RendererData;
+    }
+
+    void VertexBufferImplT::SetRendererData(void *RD) const
+    {
+        RendererData = RD;
+    }
+
+    VertexBufferI *CreateVertexBuffer(const VertexDescriptorT &VertexFormat,
+                                            VertexBufferI::UsageTypeT Usage)
+    {
+        if(MatSys::Renderer && Usage != VertexBufferI::Temporal)
+        {
+            VertexBufferI *Ret = MatSys::Renderer->CreateVertexBuffer(VertexFormat, Usage);
+            if(Ret)
+                return Ret;
+        }
+        return new VertexBufferImplT(VertexFormat);
+    }
+}
+
Index: Libs/MaterialSystem/PrimitiveBufferImpl.hpp
===================================================================
--- Libs/MaterialSystem/PrimitiveBufferImpl.hpp	(revisiÃ³n: 0)
+++ Libs/MaterialSystem/PrimitiveBufferImpl.hpp	(revisiÃ³n: 0)
@@ -0,0 +1,77 @@
+/*
+=================================================================================
+This file is part of Cafu, the open-source game and graphics engine for
+multiplayer, cross-platform, real-time 3D action.
+$Id$
+
+Copyright (C) 2002-2010 Carsten Fuchs Software.
+
+Cafu is free software: you can redistribute it and/or modify it under the terms
+of the GNU General Public License as published by the Free Software Foundation,
+either version 3 of the License, or (at your option) any later version.
+
+Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Cafu. If not, see <http://www.gnu.org/licenses/>.
+
+For support and more information about Cafu, visit us at <http://www.cafu.de>.
+=================================================================================
+*/
+
+/************************/
+/*** PrimitiveBufferImpl ***/
+/************************/
+
+#ifndef _CA_MATSYS_PRIMITIVE_BUFFER_IMPLEMENTATION_HPP_
+#define _CA_MATSYS_PRIMITIVE_BUFFER_IMPLEMENTATION_HPP_
+
+#include "PrimitiveBuffer.hpp"
+
+namespace MatSys
+{
+    class PrimitiveBufferImplT: public PrimitiveBufferI
+    {
+    public:
+        PrimitiveBufferImplT(IndexTypeT IT);
+        virtual ~PrimitiveBufferImplT();
+
+        // Primitives buffer access
+        virtual const void *LockRead() const;
+        virtual void *LockWrite();
+        virtual void *LockReadWrite();
+        virtual void Unlock() const;
+
+        // Buffer description
+        virtual unsigned long GetBufferSize() const;
+        virtual unsigned long GetSize() const;
+        virtual void SetSize(unsigned long size);
+
+        virtual IndexTypeT GetIndexType() const;
+        virtual UsageTypeT GetUsage() const;
+
+        // Those are used to synchronize the version in the main memory
+        // with the video card
+        virtual bool IsValid() const;
+        virtual void Validated() const;
+        virtual void Invalidate();
+
+        virtual void *GetRendererData() const;
+        virtual void SetRendererData(void *Data) const;
+
+        static unsigned long IndexTypeToSize[3];
+
+    private:
+        IndexTypeT    IndexType;
+        mutable bool  IsLocked;
+        mutable bool  IsValidBuffer;
+        mutable void* RendererData;
+        unsigned long Size;
+        void*         Buffer;
+
+    };
+};
+
+#endif 
Index: Libs/MaterialSystem/Mesh.cpp
===================================================================
--- Libs/MaterialSystem/Mesh.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/Mesh.cpp	(copia de trabajo)
@@ -25,3 +25,98 @@
 /*** Mesh ***/
 /************/
 
+#include "Mesh.hpp"
+#include "Renderer.hpp"
+
+namespace MatSys
+{
+
+    MeshT::~MeshT()
+    {
+        if(Renderer && RendererData)
+            Renderer->OnDestroyMesh(this);
+        if(VertexBuffer && VertexBuffer != this)
+            delete VertexBuffer;
+        if(PrimitiveBuffer)
+            delete PrimitiveBuffer;
+    }
+
+    const VertexDescriptorT &MeshT::GetVertexDescriptor() const
+    {
+        return VertexT::VertexDescriptor;
+    }
+
+    const void *MeshT::LockRead() const
+    {
+        assert(Mutex == false);
+        Mutex = true;
+        return (const void*)&Vertices[0];
+    }
+
+    void *MeshT::LockWrite()
+    {
+        assert(Mutex == false);
+        IsValidMesh = false;
+        Mutex = true;
+        return (void*)&Vertices[0];
+    }
+
+    void *MeshT::LockReadWrite()
+    {
+        assert(Mutex == false);
+        IsValidMesh = false;
+        Mutex = true;
+        return (void*)&Vertices[0];
+    }
+
+    void MeshT::Unlock() const
+    {
+        assert(Mutex);
+        Mutex = false;
+    }
+
+    unsigned long MeshT::GetSize() const
+    {
+        return Vertices.Size();
+    }
+
+    unsigned long MeshT::GetBufferSize() const
+    {
+        return Vertices.Size()*GetVertexDescriptor().VertexSize;
+    }
+
+    void MeshT::SetSize(unsigned long size)
+    {
+        // Do nothing
+    }
+
+    VertexBufferI::UsageTypeT MeshT::GetUsage() const
+    {
+        return UsageType;
+    }
+
+    bool MeshT::IsValid() const
+    {
+        return IsValidMesh;
+    }
+
+    void MeshT::Validated() const
+    {
+        IsValidMesh = true;
+    }
+
+    void MeshT::Invalidate()
+    {
+        IsValidMesh = false;
+    }
+
+    void *MeshT::GetRendererData() const
+    {
+        return RendererData;
+    }
+
+    void MeshT::SetRendererData(void *data) const
+    {
+        RendererData = data;
+    }
+};
Index: Libs/MaterialSystem/RendererOpenGL12/Shaders/StencilShadowVolumes.cpp
===================================================================
--- Libs/MaterialSystem/RendererOpenGL12/Shaders/StencilShadowVolumes.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererOpenGL12/Shaders/StencilShadowVolumes.cpp	(copia de trabajo)
@@ -131,7 +131,7 @@
 
             glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
                 for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-                    glVertex4dv(Mesh.Vertices[VertexNr].Origin);
+                    glVertex4fv(Mesh.Vertices[VertexNr].Origin);
             glEnd();
         }
         else
@@ -157,7 +157,7 @@
 
                 glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
                     for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
-                        glVertex4dv(Mesh.Vertices[VertexNr].Origin);
+                        glVertex4fv(Mesh.Vertices[VertexNr].Origin);
                 glEnd();
             }
         }
Index: Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Terrain.cpp
===================================================================
--- Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Terrain.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Terrain.cpp	(copia de trabajo)
@@ -187,7 +187,7 @@
         glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
             for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
             {
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                glVertex3fv(Mesh.Vertices[VertexNr].Origin);
             }
         glEnd();
 
@@ -224,7 +224,7 @@
             glBegin(OpenGLStateT::MeshToOpenGLType[Mesh.Type]);
                 for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
                 {
-                    glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                    glVertex3fv(Mesh.Vertices[VertexNr].Origin);
                 }
             glEnd();
         }
Index: Libs/MaterialSystem/RendererOpenGL12/Shaders/A_WaterCubeReflect.cpp
===================================================================
--- Libs/MaterialSystem/RendererOpenGL12/Shaders/A_WaterCubeReflect.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererOpenGL12/Shaders/A_WaterCubeReflect.cpp	(copia de trabajo)
@@ -167,7 +167,7 @@
             for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
             {
                 glTexCoord2f(Mesh.Vertices[VertexNr].TextureCoord[0]+0.6f*CurrentTime, Mesh.Vertices[VertexNr].TextureCoord[1]+0.8f*CurrentTime);
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                glVertex3fv(Mesh.Vertices[VertexNr].Origin);
             }
         glEnd();
     }
Index: Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Diff_Light_Fog.cpp
===================================================================
--- Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Diff_Light_Fog.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Diff_Light_Fog.cpp	(copia de trabajo)
@@ -184,7 +184,7 @@
                 cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
                 cf::glMultiTexCoord2fvARB(GL_TEXTURE1_ARB, Mesh.Vertices[VertexNr].LightMapCoord);
 
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                glVertex3fv(Mesh.Vertices[VertexNr].Origin);
             }
         glEnd();
 
Index: Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Diff_nLight_oLuma.cpp
===================================================================
--- Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Diff_nLight_oLuma.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Diff_nLight_oLuma.cpp	(copia de trabajo)
@@ -167,7 +167,7 @@
             for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
             {
                 glTexCoord2fv(Mesh.Vertices[VertexNr].TextureCoord);
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                glVertex3fv(Mesh.Vertices[VertexNr].Origin);
             }
         glEnd();
 
@@ -189,7 +189,7 @@
                 for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
                 {
                     glTexCoord2fv(Mesh.Vertices[VertexNr].TextureCoord);
-                    glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                    glVertex3fv(Mesh.Vertices[VertexNr].Origin);
                 }
             glEnd();
         }
Index: Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Solid.cpp
===================================================================
--- Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Solid.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Solid.cpp	(copia de trabajo)
@@ -164,7 +164,7 @@
             for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
             {
                 glColor4f(RedValue*Mesh.Vertices[VertexNr].Color[0], GreenValue*Mesh.Vertices[VertexNr].Color[1], BlueValue*Mesh.Vertices[VertexNr].Color[2], AlphaValue*Mesh.Vertices[VertexNr].Color[3]);
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                glVertex3fv(Mesh.Vertices[VertexNr].Origin);
             }
         glEnd();
     }
Index: Libs/MaterialSystem/RendererOpenGL12/Shaders/A_SkyDome.cpp
===================================================================
--- Libs/MaterialSystem/RendererOpenGL12/Shaders/A_SkyDome.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererOpenGL12/Shaders/A_SkyDome.cpp	(copia de trabajo)
@@ -172,7 +172,7 @@
                 const Vector3fT Dir_w  =InPos_w-EyePos_w;
 
                 glTexCoord3f(Dir_w.x, Dir_w.z, Dir_w.y);
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                glVertex3fv(Mesh.Vertices[VertexNr].Origin);
             }
         glEnd();
     }
Index: Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Diff_Light_oLuma.cpp
===================================================================
--- Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Diff_Light_oLuma.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererOpenGL12/Shaders/A_Diff_Light_oLuma.cpp	(copia de trabajo)
@@ -174,7 +174,7 @@
                 cf::glMultiTexCoord2fvARB(GL_TEXTURE0_ARB, Mesh.Vertices[VertexNr].TextureCoord);
                 cf::glMultiTexCoord2fvARB(GL_TEXTURE1_ARB, Mesh.Vertices[VertexNr].LightMapCoord);
 
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                glVertex3fv(Mesh.Vertices[VertexNr].Origin);
             }
         glEnd();
 
@@ -200,7 +200,7 @@
                 for (unsigned long VertexNr=0; VertexNr<Mesh.Vertices.Size(); VertexNr++)
                 {
                     glTexCoord2fv(Mesh.Vertices[VertexNr].TextureCoord);
-                    glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                    glVertex3fv(Mesh.Vertices[VertexNr].Origin);
                 }
             glEnd();
         }
Index: Libs/MaterialSystem/RendererOpenGL12/Shaders/L_Diff_oSpec.cpp
===================================================================
--- Libs/MaterialSystem/RendererOpenGL12/Shaders/L_Diff_oSpec.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererOpenGL12/Shaders/L_Diff_oSpec.cpp	(copia de trabajo)
@@ -172,7 +172,7 @@
 
                 glColor3f(Attenuation*DiffuseFactor*LightDiffuseColor[0], Attenuation*DiffuseFactor*LightDiffuseColor[1], Attenuation*DiffuseFactor*LightDiffuseColor[2]);
                 glTexCoord2fv(Mesh.Vertices[VertexNr].TextureCoord);
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                glVertex3fv(Mesh.Vertices[VertexNr].Origin);
             }
         glEnd();
 
@@ -215,7 +215,7 @@
 
                 glColor3f(Attenuation*SpecularFactor*LightSpecularColor[0], Attenuation*SpecularFactor*LightSpecularColor[1], Attenuation*SpecularFactor*LightSpecularColor[2]);
                 glTexCoord2fv(Mesh.Vertices[VertexNr].TextureCoord);
-                glVertex3dv(Mesh.Vertices[VertexNr].Origin);
+                glVertex3fv(Mesh.Vertices[VertexNr].Origin);
             }
         glEnd();
     }
Index: Libs/MaterialSystem/RendererOpenGL12/RendererImpl.cpp
===================================================================
--- Libs/MaterialSystem/RendererOpenGL12/RendererImpl.cpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererOpenGL12/RendererImpl.cpp	(copia de trabajo)
@@ -855,7 +855,28 @@
     CurrentShader->RenderMesh(Mesh);
 }
 
+void RendererImplT::OnDestroyMesh(MatSys::MeshT *Mesh)
+{
+}
 
+void RendererImplT::OnDestroyVertexBuffer(MatSys::VertexBufferI *Buffer)
+{
+}
+
+void RendererImplT::OnDestroyPrimitiveBuffer(MatSys::PrimitiveBufferI *Buffer)
+{
+}
+
+VertexBufferI *RendererImplT::CreateVertexBuffer(const VertexDescriptorT &Format, unsigned int Usage)
+{
+    return NULL;
+}
+
+PrimitiveBufferI *RendererImplT::CreatePrimitiveBuffer(PrimitiveBufferI::IndexTypeT IndexType, PrimitiveBufferI::UsageTypeT Usage)
+{
+    return NULL;
+}
+
 RenderMaterialT* RendererImplT::GetCurrentRenderMaterial() const
 {
     return CurrentRenderMaterial;
Index: Libs/MaterialSystem/RendererOpenGL12/RendererImpl.hpp
===================================================================
--- Libs/MaterialSystem/RendererOpenGL12/RendererImpl.hpp	(revisiÃ³n: 97)
+++ Libs/MaterialSystem/RendererOpenGL12/RendererImpl.hpp	(copia de trabajo)
@@ -128,8 +128,13 @@
     void SetCurrentSHLMaps(const ArrayT<MatSys::TextureMapI*>& SHLMaps);
     void SetCurrentSHLLookupMap(MatSys::TextureMapI* SHLLookupMap);
     void RenderMesh(const MatSys::MeshT& Mesh);
+    void OnDestroyMesh(MatSys::MeshT *Mesh);
+    void OnDestroyVertexBuffer(MatSys::VertexBufferI *Buffer);
+    void OnDestroyPrimitiveBuffer(MatSys::PrimitiveBufferI *Buffer);
+    MatSys::VertexBufferI *CreateVertexBuffer(const MatSys::VertexDescriptorT &Format, unsigned int Usage);
+    MatSys::PrimitiveBufferI *CreatePrimitiveBuffer(MatSys::PrimitiveBufferI::IndexTypeT IndexType,
+                                                    MatSys::PrimitiveBufferI::UsageTypeT Usage);
 
-
     // Internal interface.
     MatSys::RenderMaterialT* GetCurrentRenderMaterial() const;
     TextureMap2DT*           GetCurrentLightMap() const;
Index: Libs/SConscript
===================================================================
--- Libs/SConscript	(revisiÃ³n: 97)
+++ Libs/SConscript	(copia de trabajo)
@@ -59,7 +59,9 @@
 env.StaticLibrary(
     target="MatSys",
     source=Split("""MaterialSystem/Expression.cpp MaterialSystem/MapComposition.cpp MaterialSystem/Material.cpp MaterialSystem/MaterialManager.cpp
-                    MaterialSystem/MaterialManagerImpl.cpp MaterialSystem/Renderer.cpp MaterialSystem/TextureMap.cpp"""))
+                    MaterialSystem/MaterialManagerImpl.cpp MaterialSystem/Renderer.cpp MaterialSystem/TextureMap.cpp
+                    MaterialSystem/Mesh.cpp MaterialSystem/VertexFormats.cpp MaterialSystem/VertexBufferImpl.cpp
+                    MaterialSystem/PrimitiveBufferImpl.cpp"""))
 
 
 
@@ -73,7 +75,7 @@
     target="SceneGraph",
     source=Split("""SceneGraph/_aux.cpp SceneGraph/BezierPatchNode.cpp SceneGraph/BspTreeNode.cpp SceneGraph/FaceNode.cpp
                     SceneGraph/LightMapMan.cpp SceneGraph/Node.cpp SceneGraph/SHLMapMan.cpp SceneGraph/TerrainNode.cpp
-                    SceneGraph/PlantNode.cpp SceneGraph/ModelNode.cpp"""))
+                    SceneGraph/PlantNode.cpp SceneGraph/ModelNode.cpp SceneGraph/FaceBatchesNode.cpp"""))
 
 
 
@@ -95,6 +97,7 @@
     target="MaterialSystem/RendererARBprogs",
     source=[os.path.join("MaterialSystem/RendererARBprogs", x) for x in Split("""
                RendererARBprogs.cpp RendererImpl.cpp RenderMaterial.cpp Shader.cpp TextureMapImpl.cpp
+               MeshBuffer.cpp VertexBufferImpl.cpp PrimitiveBufferImpl.cpp
 
                Shaders/A_Terrain.cpp Shaders/A_Diff.cpp Shaders/A_Diff_Luma.cpp Shaders/A_Diff_Norm.cpp Shaders/A_Diff_Norm_Luma.cpp
                Shaders/A_Diff_Light.cpp Shaders/A_Diff_Light_Luma.cpp Shaders/A_Diff_Light_Norm.cpp Shaders/A_Diff_Light_Norm_Spec.cpp
Index: Libs/ParticleEngine/ParticleEngineMS.cpp
===================================================================
--- Libs/ParticleEngine/ParticleEngineMS.cpp	(revisiÃ³n: 97)
+++ Libs/ParticleEngine/ParticleEngineMS.cpp	(copia de trabajo)
@@ -235,6 +235,7 @@
             ParticleGroupMesh.Vertices[3].SetOrigin(Particle->Origin[0]-BillBoardVecX[0]-BillBoardVecY[0],
                                                     Particle->Origin[1]-BillBoardVecX[1]-BillBoardVecY[1],
                                                     Particle->Origin[2]-BillBoardVecX[2]-BillBoardVecY[2]);
+            ParticleGroupMesh.Invalidate();
 
             // Warning: This testing code requires "twoSided" materials!
             // ParticleGroupMesh.Vertices[4*ParticleNr+0].SetOrigin(Particle->Origin[0]-300.0, Particle->Origin[1], Particle->Origin[2]+300.0);
Index: Libs/Fonts/FontTT.cpp
===================================================================
--- Libs/Fonts/FontTT.cpp	(revisiÃ³n: 97)
+++ Libs/Fonts/FontTT.cpp	(copia de trabajo)
@@ -276,6 +276,7 @@
         GlyphMesh.Vertices[2].SetOrigin(x2, y2); GlyphMesh.Vertices[2].SetTextureCoord(gi.s2, gi.t2);
         GlyphMesh.Vertices[3].SetOrigin(x1, y2); GlyphMesh.Vertices[3].SetTextureCoord(gi.s1, gi.t2);
 
+        GlyphMesh.Invalidate();
         MatSys::Renderer->SetCurrentMaterial(gi.RM);
         MatSys::Renderer->RenderMesh(GlyphMesh);
 
Index: Libs/Fonts/Font.cpp
===================================================================
--- Libs/Fonts/Font.cpp	(revisiÃ³n: 97)
+++ Libs/Fonts/Font.cpp	(copia de trabajo)
@@ -138,6 +138,7 @@
         TextMesh.Vertices[4*c+3].SetOrigin( 0+c*10, 16); TextMesh.Vertices[4*c+3].SetTextureCoord(CoordX     , CoordY+Size);
     }
 
+    TextMesh.Invalidate();
     MatSys::Renderer->RenderMesh(TextMesh);
 }
 

