Back to index

nux  3.0.0
GLVertexResourceManager.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "GLResource.h"
00024 #include "GLResourceManager.h"
00025 #include "GLDeviceObjects.h"
00026 #include "GpuDevice.h"
00027 #include "GLVertexResourceManager.h"
00028 #include "GraphicsEngine.h"
00029 
00030 namespace nux
00031 {
00032   NUX_IMPLEMENT_OBJECT_TYPE(VertexBuffer);
00033   NUX_IMPLEMENT_OBJECT_TYPE(IndexBuffer);
00034   NUX_IMPLEMENT_OBJECT_TYPE(VertexDeclaration);
00035   NUX_IMPLEMENT_OBJECT_TYPE(MeshBuffer);
00036   
00037   NUX_IMPLEMENT_OBJECT_TYPE(CachedVertexBuffer);
00038   NUX_IMPLEMENT_OBJECT_TYPE(CachedIndexBuffer);
00039   NUX_IMPLEMENT_OBJECT_TYPE(CachedVertexDeclaration);
00040   NUX_IMPLEMENT_OBJECT_TYPE(CachedMeshBuffer);
00041 
00042   VertexBuffer::VertexBuffer()
00043   {
00044     _Stride = 0;
00045   }
00046 
00047   VertexBuffer::~VertexBuffer()
00048   {
00049     _Data.clear();
00050   }
00051 
00052   VertexBuffer::VertexBuffer(int num_element, int size)
00053   {
00054     Allocate(num_element, size);
00055   }
00056 
00058   VertexBuffer::VertexBuffer(const VertexBuffer& Other)
00059   {
00060     _Data = Other._Data;
00061     _Stride = Other._Stride;
00062   }
00063 
00065   VertexBuffer& VertexBuffer::operator = (const VertexBuffer& Other)
00066   {
00067     _Data = Other._Data;
00068     _Stride = Other._Stride;
00069     return *this;
00070   }
00071 
00072   void VertexBuffer::Allocate(int num_element, int size)
00073   {
00074     nuxAssert(num_element > 0);
00075     nuxAssert(size > 0);
00076 
00077     if ((size <= 0) || (num_element <= 0))
00078     {
00079       _Data.clear();
00080       _Stride = 0;
00081       return;
00082     }
00083 
00084     // Make sure Size is a multiple of Stride
00085     int sz = size * num_element;
00086     _Stride = size;
00087 
00088     _Data.clear();
00089     _Data.resize(sz);
00090   }
00091 
00092   int VertexBuffer::GetSize() const
00093   {
00094     return _Data.size();
00095   }
00096 
00097   int VertexBuffer::GetStride() const
00098   {
00099     return _Stride;
00100   }
00101 
00102   int VertexBuffer::GetNumElement() const
00103   {
00104     return _Data.size() / _Stride;
00105   }
00106 
00107   const void* VertexBuffer::GetPtrRawData() const
00108   {
00109     if (_Data.size() == 0)
00110       return 0;
00111 
00112     return NUX_STATIC_CAST(const void*, &_Data[0]);
00113   }
00114 
00115   void* VertexBuffer::GetPtrRawData()
00116   {
00117     if (_Data.size() == 0)
00118       return 0;
00119 
00120     return NUX_CONST_CAST(void*, ((NUX_CONST_CAST(const VertexBuffer*, this))->GetPtrRawData()));
00121   }
00122 
00123   IndexBuffer::IndexBuffer()
00124   {
00125     _Stride = 0;
00126   }
00127 
00128   IndexBuffer::~IndexBuffer()
00129   {
00130     _Data.clear();
00131   }
00132 
00133   IndexBuffer::IndexBuffer(int num_element, int size)
00134   {
00135     Allocate(num_element, size);
00136   }
00137 
00139   IndexBuffer::IndexBuffer(const IndexBuffer& Other)
00140   {
00141     _Data = Other._Data;
00142     _Stride = Other._Stride;
00143   }
00144 
00146   IndexBuffer& IndexBuffer::operator = (const IndexBuffer& Other)
00147   {
00148     _Data = Other._Data;
00149     _Stride = Other._Stride;
00150     return *this;
00151   }
00152 
00153   void IndexBuffer::Allocate(int num_index, int size)
00154   {
00155     nuxAssert(num_index > 0);
00156     nuxAssert(size > 0);
00157     nuxAssert((size == 2) || (size == 4));
00158 
00159     if ((size <= 0) || (num_index <= 0))
00160     {
00161       _Data.clear();
00162       _Stride = 0;
00163       return;
00164     }
00165 
00166     _num_index = num_index;
00167     // Make sure Size is a multiple of Stride
00168     int sz = _num_index * size;
00169     _Stride = size;
00170 
00171     _Data.clear();
00172     _Data.resize(sz);
00173   }
00174 
00175   int IndexBuffer::GetSize() const
00176   {
00177     return _Data.size();
00178   }
00179 
00180   int IndexBuffer::GetStride() const
00181   {
00182     return _Stride;
00183   }
00184 
00185   int IndexBuffer::GetNumIndex() const
00186   {
00187     return _num_index;
00188   }
00189 
00190   const void* IndexBuffer::GetPtrRawData() const
00191   {
00192     return NUX_STATIC_CAST(const void*, &_Data[0]);
00193   }
00194 
00195   void* IndexBuffer::GetPtrRawData()
00196   {
00197     return NUX_CONST_CAST(void*, ((NUX_CONST_CAST(const IndexBuffer*, this))->GetPtrRawData()));
00198   }
00199 
00200   VertexDeclaration::VertexDeclaration()
00201   {
00202     _declaration.clear();
00203   }
00204 
00205   VertexDeclaration::~VertexDeclaration()
00206   {
00207     _declaration.clear();
00208   }
00209 
00210   void VertexDeclaration::AddVertexComponent(VERTEXELEMENT Component)
00211   {
00212     _declaration.push_back(Component);
00213   }
00214 
00215   CachedVertexBuffer::CachedVertexBuffer(NResourceSet* ResourceManager, VertexBuffer* SourceVtxBuffer)
00216   : CachedResourceData(ResourceManager)
00217   , _Size(0)
00218   , _Stride(0)
00219   {
00220     UpdateResource(SourceVtxBuffer);
00221   }
00222 
00223   CachedVertexBuffer::~CachedVertexBuffer()
00224   {
00225     // Not necessary for a smart pointer but do it anyway to be clear;
00226     _vertex_buffer = ObjectPtr<IOpenGLVertexBuffer> (0);
00227   }
00228 
00229   bool CachedVertexBuffer::UpdateResource(ResourceData* Source)
00230   {
00231     if (Source == 0)
00232     {
00233       _Stride = 0;
00234       _vertex_buffer.Release();
00235       return true;
00236     }
00237 
00238     VertexBuffer* SourceVtxBuffer = 0;
00239     nuxAssert(Source->Type().IsDerivedFromType(VertexBuffer::StaticObjectType));
00240 
00241     if (Source->Type().IsDerivedFromType(VertexBuffer::StaticObjectType))
00242     {
00243       SourceVtxBuffer = NUX_STATIC_CAST(VertexBuffer* , Source);
00244     }
00245     else
00246     {
00247       return false;
00248     }
00249 
00250     if ((SourceVtxBuffer->GetSize() == 0) || (SourceVtxBuffer->GetStride() == 0))
00251     {
00252       _Stride = 0;
00253       _vertex_buffer.Release();
00254       return true;
00255     }
00256 
00257     if (_Size != SourceVtxBuffer->GetSize())
00258     {
00259       // The current size of the cached buffer is not the same as the requested one.
00260       // Delete the previously allocated buffer and create a new one.
00261       _Size = SourceVtxBuffer->GetSize();
00262       _Stride = SourceVtxBuffer->GetStride();
00263 
00264       //Release the previous vertex buffer if any.
00265       _vertex_buffer.Release();
00266       _vertex_buffer = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexBuffer(_Size, VBO_USAGE_STATIC);
00267       LoadVertexData(SourceVtxBuffer);
00268     }
00269     else
00270     {
00271       // The buffer size has changed. Delete the previously allocated buffer and create a new one.
00272       _Stride = SourceVtxBuffer->GetStride();
00273       LoadVertexData(SourceVtxBuffer);
00274     }
00275 
00276     return true;
00277   }
00278 
00279   void CachedVertexBuffer::LoadVertexData(VertexBuffer* SourceVtxBuffer)
00280   {
00281     if ((SourceVtxBuffer == 0) || (SourceVtxBuffer->GetSize() == 0) || (SourceVtxBuffer->GetStride() == 0))
00282     {
00283       return;
00284     }
00285 
00286     unsigned char* pData;
00287 
00288     _vertex_buffer->Lock(0, 0, (void**) &pData);
00289     Memcpy(pData, SourceVtxBuffer->GetPtrRawData(), SourceVtxBuffer->GetSize());
00290     _vertex_buffer->Unlock();
00291   }
00292 
00293   int CachedVertexBuffer::GetElementSize() const
00294   {
00295     return _Size;
00296   }
00297 
00298   int CachedVertexBuffer::GetBufferStride() const
00299   {
00300     return _Stride;
00301   }
00302 
00303   CachedIndexBuffer::CachedIndexBuffer(NResourceSet* ResourceManager, IndexBuffer* SourceIdxBuffer)
00304     :   CachedResourceData(ResourceManager)
00305     ,   _Size(0)
00306     ,   _Stride(0)
00307   {
00308     UpdateResource(SourceIdxBuffer);
00309   }
00310 
00311   CachedIndexBuffer::~CachedIndexBuffer()
00312   {
00313     // Not necessary for a smart pointer but do it anyway to be clear;
00314     _index_buffer = ObjectPtr<IOpenGLIndexBuffer> (0);
00315   }
00316 
00317   bool CachedIndexBuffer::UpdateResource(ResourceData* Source)
00318   {
00319     if (Source == 0)
00320     {
00321       _Size = 0;
00322       _Stride = 0;
00323       _index_buffer.Release();
00324       return true;
00325     }
00326 
00327     IndexBuffer* SourceIdxBuffer = 0;
00328     nuxAssert(Source->Type().IsDerivedFromType(IndexBuffer::StaticObjectType));
00329 
00330     if (Source->Type().IsDerivedFromType(IndexBuffer::StaticObjectType))
00331     {
00332       SourceIdxBuffer = NUX_STATIC_CAST(IndexBuffer*, Source);
00333     }
00334     else
00335     {
00336       return false;
00337     }
00338 
00339     if ((SourceIdxBuffer->GetSize() == 0) || (SourceIdxBuffer->GetStride() == 0))
00340     {
00341       _Size = 0;
00342       _Stride = 0;
00343       _index_buffer.Release();
00344       return true;
00345     }
00346 
00347     if (_Size != SourceIdxBuffer->GetSize())
00348     {
00349       _Size = SourceIdxBuffer->GetSize();
00350       _Stride = SourceIdxBuffer->GetStride();
00351 
00352       //Release the previous vertex buffer if any.
00353       _index_buffer.Release();
00354       _index_buffer = GetGraphicsDisplay()->GetGpuDevice()->CreateIndexBuffer(_Size, VBO_USAGE_STATIC,
00355                     (SourceIdxBuffer->GetStride() == 2) ? INDEX_FORMAT_USHORT : INDEX_FORMAT_UINT);
00356       LoadIndexData(SourceIdxBuffer);
00357     }
00358     else
00359     {
00360       _Stride = SourceIdxBuffer->GetStride();
00361       LoadIndexData(SourceIdxBuffer);
00362     }
00363 
00364     _num_index = SourceIdxBuffer->GetNumIndex();
00365 
00366     return true;
00367   }
00368 
00369   void CachedIndexBuffer::LoadIndexData(IndexBuffer* SourceIdxBuffer)
00370   {
00371     if ((SourceIdxBuffer == 0) || (SourceIdxBuffer->GetSize() == 0) || (SourceIdxBuffer->GetStride() == 0))
00372     {
00373       return;
00374     }
00375 
00376     unsigned char* pData;
00377     _index_buffer->Lock(0, 0, (void**) &pData);
00378     Memcpy(pData, SourceIdxBuffer->GetPtrRawData(), SourceIdxBuffer->GetSize());
00379     _index_buffer->Unlock();
00380   }
00381 
00382   int CachedIndexBuffer::GetElementSize() const
00383   {
00384     return _Size;
00385   }
00386 
00387   int CachedIndexBuffer::GetBufferStride() const
00388   {
00389     return _Stride;
00390   }
00391 
00392   int CachedIndexBuffer::GetNumIndex() const
00393   {
00394     return _num_index;
00395   }
00396 
00397   CachedVertexDeclaration::CachedVertexDeclaration(NResourceSet* ResourceManager, VertexDeclaration* SourceVertexDeclaration)
00398     :   CachedResourceData(ResourceManager)
00399   {
00400     UpdateResource(SourceVertexDeclaration);
00401   }
00402 
00403   CachedVertexDeclaration::~CachedVertexDeclaration()
00404   {
00405     _declaration = ObjectPtr<IOpenGLVertexDeclaration> (0);
00406   }
00407 
00408   bool CachedVertexDeclaration::UpdateResource(ResourceData* Source)
00409   {
00410     if (Source == 0)
00411     {
00412       _declaration = ObjectPtr<IOpenGLVertexDeclaration> (0);
00413       return true;
00414     }
00415 
00416     VertexDeclaration* SourceVertexDeclaration = 0;
00417     nuxAssert(Source->Type().IsDerivedFromType(VertexDeclaration::StaticObjectType));
00418 
00419     if (Source->Type().IsDerivedFromType(VertexDeclaration::StaticObjectType))
00420     {
00421       SourceVertexDeclaration = NUX_STATIC_CAST(VertexDeclaration*, Source);
00422     }
00423     else
00424     {
00425       return false;
00426     }
00427 
00428     if (SourceVertexDeclaration == 0)
00429     {
00430       _declaration = ObjectPtr<IOpenGLVertexDeclaration> (0);
00431       return true;
00432     }
00433 
00434     _declaration = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexDeclaration(&SourceVertexDeclaration->_declaration[0]);
00435     return true;
00436   }
00437 
00438   MeshBuffer::MeshBuffer(NUX_FILE_LINE_DECL)
00439   : ResourceData(NUX_FILE_LINE_PARAM)
00440   {
00441     _vertex_buffer = 0;
00442     _index_buffer = 0;
00443     _vertex_declaration = 0;
00444   }
00445 
00446   MeshBuffer::~MeshBuffer()
00447   {
00448     if (_vertex_buffer)
00449       _vertex_buffer->UnReference();
00450     if (_index_buffer)
00451       _index_buffer->UnReference();
00452     if (_vertex_declaration)
00453       _vertex_declaration->UnReference();
00454   }
00455 
00456   bool MeshBuffer::Update(const MeshData* mesh_data)
00457   {
00458     int num_element = mesh_data->_num_element;
00459     int element_size = mesh_data->_element_size;
00460 
00461     _mesh_primitive_type = mesh_data->_mesh_primitive_type;
00462 
00463     _vertex_buffer = new VertexBuffer();
00464     _vertex_buffer->Allocate(num_element, element_size);
00465     memcpy(_vertex_buffer->GetPtrRawData(), mesh_data->_vertex_data, num_element * element_size);
00466 
00467     int num_index = mesh_data->_num_index;
00468     int index_size = mesh_data->_index_size;
00469 
00470     _index_buffer = new IndexBuffer();
00471     _index_buffer->Allocate(num_index, index_size);
00472     memcpy(_index_buffer->GetPtrRawData(), mesh_data->_index_data, num_index * index_size);
00473 
00474     _vertex_declaration = new VertexDeclaration();
00475 
00476     VERTEXELEMENT ve_position(0, 0, ATTRIB_CT_FLOAT, 4, 36);
00477 
00478     VERTEXELEMENT ve_normal(0, 16, ATTRIB_CT_FLOAT, 3, 36);
00479 
00480     VERTEXELEMENT ve_texcoord(0, 28, ATTRIB_CT_FLOAT, 2, 36);
00481 
00482     _vertex_declaration->AddVertexComponent(ve_position);
00483     _vertex_declaration->AddVertexComponent(ve_normal);
00484     _vertex_declaration->AddVertexComponent(ve_texcoord);
00485     _vertex_declaration->AddVertexComponent(DECL_END);
00486 
00487     return true;
00488   }
00489 
00490   ObjectPtr<CachedMeshBuffer> MeshBuffer::GetCachedMeshBuffer()
00491   {
00492     return GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(this);
00493   }
00494 
00495   CachedMeshBuffer::CachedMeshBuffer(NResourceSet* ResourceManager, MeshBuffer* resource)
00496   : CachedResourceData(ResourceManager)
00497   {
00498     UpdateResource(resource);
00499   }
00500 
00501   CachedMeshBuffer::~CachedMeshBuffer()
00502   {
00503   }
00504 
00505   bool CachedMeshBuffer::UpdateResource(ResourceData* source)
00506   {
00507     nuxAssert(source->Type().IsDerivedFromType(MeshBuffer::StaticObjectType));
00508 
00509     MeshBuffer* mesh_buffer = NUX_STATIC_CAST(MeshBuffer*, source);
00510 
00511     _cached_vertex_buffer = GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(mesh_buffer->_vertex_buffer);
00512     _cached_index_buffer = GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(mesh_buffer->_index_buffer);
00513     _cached_vertex_declaration = GetGraphicsDisplay()->GetGraphicsEngine()->CacheResource(mesh_buffer->_vertex_declaration);
00514     _cached_vertex_declaration->_declaration->SetVertexBuffer(0, _cached_vertex_buffer->_vertex_buffer);
00515     _cached_vertex_declaration->_declaration->SetVertexBuffer(1, _cached_vertex_buffer->_vertex_buffer);
00516     _cached_vertex_declaration->_declaration->SetVertexBuffer(2, _cached_vertex_buffer->_vertex_buffer);
00517 
00518     _mesh_primitive_type = mesh_buffer->_mesh_primitive_type;
00519 
00520     return true;
00521   }
00522 }
00523