@@ -19,7 +19,7 @@ using namespace Ra::Core::Utils;
1919// we have no data to send to the gpu.
2020AttribArrayDisplayable::AttribArrayDisplayable ( const std::string& name,
2121 MeshRenderMode renderMode ) :
22- Displayable ( name ), m_renderMode {renderMode} {
22+ Displayable ( name ), m_renderMode { renderMode } {
2323 CORE_ASSERT ( m_renderMode == RM_POINTS || m_renderMode == RM_LINES ||
2424 m_renderMode == RM_LINE_LOOP || m_renderMode == RM_LINE_STRIP ||
2525 m_renderMode == RM_TRIANGLES || m_renderMode == RM_TRIANGLE_STRIP ||
@@ -73,7 +73,7 @@ void Mesh::loadGeometry( const Core::Vector3Array& vertices, const std::vector<u
7373 {
7474 // We store all indices in order. This means that for lines we have
7575 // (L00, L01, L10), (L11, L20, L21) etc. We fill the missing by wrapping around indices.
76- mindices.push_back ( {indices[i], indices[( i + 1 ) % nIdx], indices[( i + 2 ) % nIdx]} );
76+ mindices.push_back ( { indices[i], indices[( i + 1 ) % nIdx], indices[( i + 2 ) % nIdx] } );
7777 }
7878
7979 mesh.setIndices ( std::move ( mindices ) );
@@ -156,6 +156,180 @@ void AttribArrayDisplayable::setDirty( const AttribArrayDisplayable::MeshData& t
156156
157157 m_isDirty = true ;
158158}
159+ // ////////////// MultiIndexedGeometry ///////////////////////////////
160+
161+ GeometryDisplayable::GeometryDisplayable ( const std::string& name,
162+ typename Core::Geometry::MultiIndexedGeometry&& geom,
163+ typename base::MeshRenderMode renderMode ) :
164+ base ( name, renderMode ), m_geom( std::move( geom ) ) {}
165+
166+ GeometryDisplayable::~GeometryDisplayable () {}
167+
168+ void GeometryDisplayable::loadGeometry ( Core::Geometry::MultiIndexedGeometry&& mesh ) {
169+ m_geomLayers.clear ();
170+ m_geom = std::move ( mesh );
171+ setupCoreMeshObservers ();
172+ }
173+
174+ void GeometryDisplayable::setupCoreMeshObservers () {
175+ int idx = 0 ;
176+ m_dataDirty.resize ( m_geom.vertexAttribs ().getNumAttribs () );
177+ m_vbos.resize ( m_geom.vertexAttribs ().getNumAttribs () );
178+ // here capture ref to idx to propagate idx incrementation
179+ m_geom.vertexAttribs ().for_each_attrib ( [&idx, this ]( Ra::Core::Utils::AttribBase* b ) {
180+ auto name = b->getName ();
181+ m_handleToBuffer[name] = idx;
182+ m_dataDirty[idx] = true ;
183+
184+ // create a identity translation if name is not already translated.
185+ addToTranslationTable ( name );
186+
187+ b->attach ( AttribObserver ( this , idx ) );
188+ ++idx;
189+ } );
190+
191+ // add an observer on attrib manipulation.
192+ m_geom.vertexAttribs ().attachMember ( this , &GeometryDisplayable::addAttribObserver );
193+ m_isDirty = true ;
194+ }
195+
196+ void GeometryDisplayable::addToTranslationTable ( const std::string& name ) {
197+ auto it = m_translationTableMeshToShader.find ( name );
198+ if ( it == m_translationTableMeshToShader.end () )
199+ {
200+ m_translationTableMeshToShader[name] = name;
201+ m_translationTableShaderToMesh[name] = name;
202+ }
203+ }
204+
205+ void GeometryDisplayable::addAttribObserver ( const std::string& name ) {
206+ // this observer is called each time an attrib is added or removed from m_mesh
207+ auto attrib = m_geom.getAttribBase ( name );
208+ // if attrib not nullptr, then it's an attrib add, so attach an observer to it
209+
210+ if ( attrib )
211+ {
212+ auto itr = m_handleToBuffer.find ( name );
213+ if ( itr == m_handleToBuffer.end () )
214+ {
215+ m_handleToBuffer[name] = m_dataDirty.size ();
216+
217+ addToTranslationTable ( name );
218+
219+ m_dataDirty.push_back ( true );
220+ m_vbos.emplace_back ( nullptr );
221+ }
222+ auto idx = m_handleToBuffer[name];
223+ attrib->attach ( AttribObserver ( this , idx ) );
224+ }
225+ // else it's an attrib remove, do nothing, cleanup will be done in updateGL()
226+ else
227+ {}
228+ }
229+
230+ void GeometryDisplayable::setAttribNameCorrespondence ( const std::string& meshAttribName,
231+ const std::string& shaderAttribName ) {
232+
233+ // clean previously set translation
234+
235+ auto it1 = std::find_if ( m_translationTableShaderToMesh.begin (),
236+ m_translationTableShaderToMesh.end (),
237+ [&meshAttribName]( const TranslationTable::value_type& p ) {
238+ return p.second == meshAttribName;
239+ } );
240+
241+ if ( it1 != m_translationTableShaderToMesh.end () ) m_translationTableShaderToMesh.erase ( it1 );
242+
243+ auto it2 = std::find_if ( m_translationTableMeshToShader.begin (),
244+ m_translationTableMeshToShader.end (),
245+ [&shaderAttribName]( const TranslationTable::value_type& p ) {
246+ return p.second == shaderAttribName;
247+ } );
248+
249+ if ( it2 != m_translationTableMeshToShader.end () ) m_translationTableMeshToShader.erase ( it2 );
250+
251+ m_translationTableShaderToMesh[shaderAttribName] = meshAttribName;
252+ m_translationTableMeshToShader[meshAttribName] = shaderAttribName;
253+ }
254+
255+ bool GeometryDisplayable::addRenderLayer ( LayerKeyType key ) {
256+ if ( !m_geom.containsLayer ( key ) ) return false ;
257+ auto it = m_geomLayers.find ( key );
258+ if ( it == m_geomLayers.end () ) return false ;
259+
260+ VaoIndices* vao = new VaoIndices;
261+ auto & geomLayer = m_geom.getLayerWithLock ( key );
262+ int observerId = geomLayer.attach ( VaoIndices::IndicesObserver ( vao ) );
263+ m_geom.unlockLayer ( key );
264+
265+ m_geomLayers[key] = { observerId, vao };
266+
267+ return false ;
268+ }
269+ bool GeometryDisplayable::removeRenderLayer ( LayerKeyType key ) {
270+ auto it = m_geomLayers.find ( key );
271+ if ( it == m_geomLayers.end () ) return false ;
272+
273+ // the layer might have already been deleted
274+ if ( m_geom.containsLayer ( key ) )
275+ {
276+ auto & geomLayer = m_geom.getLayerWithLock ( key );
277+ geomLayer.detach ( it->second .first );
278+ m_geom.unlockLayer ( key );
279+ }
280+ delete ( it->second .second );
281+ m_geomLayers.erase ( it );
282+
283+ return true ;
284+ }
285+
286+ void GeometryDisplayable::updateGL_specific_impl () {
287+ CORE_ASSERT ( false , " not implemented yet" );
288+ // if ( !m_indices )
289+ // {
290+ // m_indices = globjects::Buffer::create();
291+ // m_indicesDirty = true;
292+ // }
293+ // if ( m_indicesDirty )
294+ // {
295+ // /// this one do not work since m_indices is not a std::vector
296+ // // m_indices->setData( m_mesh.m_indices, GL_DYNAMIC_DRAW );
297+ // m_numElements =
298+ // base::m_mesh.getIndices().size() *
299+ // base::CoreGeometry::IndexType::RowsAtCompileTime;
300+ //
301+ // m_indices->setData(
302+ // static_cast<gl::GLsizeiptr>( base::m_mesh.getIndices().size() *
303+ // sizeof( typename base::CoreGeometry::IndexType ) ),
304+ // base::m_mesh.getIndices().data(),
305+ // GL_STATIC_DRAW );
306+ // m_indicesDirty = false;
307+ // }
308+ // if ( !base::m_vao ) { base::m_vao = globjects::VertexArray::create(); }
309+ // base::m_vao->bind();
310+ // base::m_vao->bindElementBuffer( m_indices.get() );
311+ // base::m_vao->unbind();
312+ // / \todo implement !
313+ }
314+
315+ void GeometryDisplayable::render ( const ShaderProgram* ) {
316+ CORE_ASSERT ( false , " not implemented yet" );
317+ // if ( base::m_vao )
318+ // {
319+ // GL_CHECK_ERROR;
320+ // base::m_vao->bind();
321+ // base::autoVertexAttribPointer( prog );
322+ // GL_CHECK_ERROR;
323+ // base::m_vao->drawElements( static_cast<GLenum>( base::m_renderMode ),
324+ // GLsizei( m_numElements ),
325+ // GL_UNSIGNED_INT,
326+ // nullptr );
327+ // GL_CHECK_ERROR;
328+ // base::m_vao->unbind();
329+ // GL_CHECK_ERROR;
330+ // }
331+ // / \todo implement !
332+ }
159333
160334void PointCloud::render ( const ShaderProgram* prog ) {
161335 if ( m_vao )
0 commit comments