Loading [MathJax]/extensions/TeX/AMSmath.js
Radium Engine  1.5.28
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Mesh.hpp
1#pragma once
2
3#include <Core/Asset/GeometryData.hpp>
4#include <Core/Containers/VectorArray.hpp>
5#include <Core/Geometry/MeshPrimitives.hpp>
6#include <Core/Geometry/StandardAttribNames.hpp>
7#include <Core/Geometry/TriangleMesh.hpp>
8#include <Core/Utils/BijectiveAssociation.hpp>
9#include <Core/Utils/Color.hpp>
10#include <Core/Utils/Log.hpp>
11#include <Core/Utils/ObjectWithSemantic.hpp>
12#include <Engine/Data/DisplayableObject.hpp>
13#include <Engine/Data/ShaderProgram.hpp>
14#include <Engine/RaEngine.hpp>
15
16#include <globjects/Buffer.h>
17#include <globjects/Program.h>
18#include <globjects/VertexArray.h>
19#include <globjects/VertexAttributeBinding.h>
20
21#include <array>
22#include <iterator>
23#include <map>
24#include <vector>
25
26namespace Ra {
27namespace Engine {
28namespace Data {
29class ShaderProgram;
30
31using namespace Ra::Core::Utils;
32
35class RA_ENGINE_API Vao
36{
40 std::vector<bool> m_dataDirty;
41 std::map<std::string, int> m_handleToBuffer;
42};
43
51class RA_ENGINE_API AttribArrayDisplayable : public Displayable
52{
53 public:
57 enum MeshRenderMode : uint {
58 RM_POINTS = 0x0000,
59 RM_LINES = 0x0001, // decimal value: 1
60 RM_LINE_LOOP = 0x0002, // decimal value: 2
61 RM_LINE_STRIP = 0x0003, // decimal value: 3
62 RM_TRIANGLES = 0x0004, // decimal value: 4
63 RM_TRIANGLE_STRIP = 0x0005, // decimal value: 5
64 RM_TRIANGLE_FAN = 0x0006, // decimal value: 6
65 RM_QUADS = 0x0007, // decimal value: 7
66 RM_QUAD_STRIP = 0x0008, // decimal value: 8
67 RM_POLYGON = 0x0009, // decimal value: 9
68 RM_LINES_ADJACENCY = 0x000A, // decimal value: 10
69 RM_LINE_STRIP_ADJACENCY = 0x000B, // decimal value: 11
70 RM_TRIANGLES_ADJACENCY = 0x000C, // decimal value: 12
71 RM_TRIANGLE_STRIP_ADJACENCY = 0x000D, // decimal value: 13
72 RM_PATCHES = 0x000E, // decimal value: 14
73 };
74
75 public:
76 explicit AttribArrayDisplayable( const std::string& name,
77 MeshRenderMode renderMode = RM_TRIANGLES );
79 void operator=( const AttribArrayDisplayable& rhs ) = delete;
80
82
83 using Displayable::getName;
84
86 inline void setRenderMode( MeshRenderMode mode );
88 inline MeshRenderMode getRenderMode() const;
89
93
96 void setDirty( const Core::Geometry::MeshAttrib& type );
97
99 void setDirty( const std::string& name );
100
103 void setDirty( unsigned int index );
105
108 void updateGL() override = 0;
109
113 virtual const Core::Geometry::AttribArrayGeometry& getAttribArrayGeometry() const = 0;
114 virtual Core::Geometry::AttribArrayGeometry& getAttribArrayGeometry() = 0;
116
121 Ra::Core::Utils::optional<gl::GLuint> getVboHandle( const std::string& name );
122
126 Ra::Core::Utils::optional<gl::GLuint> getVaoHandle();
127
128 protected:
130 void updatePickingRenderMode();
131
132 class AttribObserver
133 {
134 public:
135 explicit AttribObserver( AttribArrayDisplayable* displayable, int idx ) :
136 m_displayable( displayable ), m_idx( idx ) {}
137 void operator()() {
138 if ( m_idx < int( m_displayable->m_dataDirty.size() ) ) {
139 m_displayable->m_dataDirty[m_idx] = true;
140 m_displayable->m_isDirty = true;
141 }
142 else {
144 LOG( logDEBUG ) << "Invalid dirty bit notified on " << m_displayable->getName();
145 }
146 }
147
148 private:
149 AttribArrayDisplayable* m_displayable;
150 int m_idx;
151 };
152
153 protected:
155
156 MeshRenderMode m_renderMode { MeshRenderMode::RM_TRIANGLES };
157
158 // m_vbos and m_dataDirty have the same size and are indexed thru m_handleToBuffer[attribName]
160 std::vector<bool> m_dataDirty;
161
162 // Geometry attrib name (std::string) to buffer id (int)
163 // buffer id are indices in m_vbos and m_dataDirty
165
169 bool m_isDirty { false };
170};
171
173class RA_ENGINE_API VaoIndices
174{
175 public:
177 inline void setIndicesDirty();
178
181 {
182 public:
184 explicit IndicesObserver( VaoIndices* displayable ) : m_displayable { displayable } {}
186 void operator()() { m_displayable->m_indicesDirty = true; }
187
188 private:
189 VaoIndices* m_displayable;
190 };
191
192 protected:
193 std::unique_ptr<globjects::Buffer> m_indices { nullptr };
194 bool m_indicesDirty { true };
197 size_t m_numElements { 0 };
198};
199
203template <typename I>
205{
206 using IndexType = I;
208
209 template <typename T>
210 inline void addAttrib( const std::string& name,
211 const typename Ra::Core::Utils::Attrib<T>::Container& data );
212 template <typename T>
213 inline void addAttrib( const std::string& name,
214 const typename Ra::Core ::Utils::Attrib<T>::Container&& data );
215 inline void updateGL() override;
216
217 inline void render( const ShaderProgram* prog ) override;
218
219 protected:
221 inline void autoVertexAttribPointer( const ShaderProgram* prog );
222 IndexContainerType m_cpu_indices;
223 AttribManager m_attribManager;
224};
225
227template <typename T>
229{
230 public:
232 using CoreGeometry = T;
233
234 explicit CoreGeometryDisplayable( const std::string& name,
235 MeshRenderMode renderMode = RM_TRIANGLES );
236
237 // no need to detach observer in dtor since CoreGeometry is owned by this, and CoreGeometry dtor
238 // will detachAll observers.
239
245
246 inline const Core::Geometry::AttribArrayGeometry& getAttribArrayGeometry() const override;
247 inline Core::Geometry::AttribArrayGeometry& getAttribArrayGeometry() override;
248
249 inline const CoreGeometry& getCoreGeometry() const;
250 inline CoreGeometry& getCoreGeometry();
252
254 template <typename A>
256 const typename Core::VectorArray<A>& data );
257 inline size_t getNumVertices() const override;
258
268 virtual void loadGeometry( CoreGeometry&& mesh );
269
271 void updateGL() override;
272
283 void setAttribNameCorrespondance( const std::string& meshAttribName,
284 const std::string& shaderAttribName );
285
286 protected:
287 virtual void updateGL_specific_impl() {}
288
289 void loadGeometry_common( CoreGeometry&& mesh );
290 void setupCoreMeshObservers();
291
294
298 void addAttribObserver( const std::string& name );
299
300 void addToTranslationTable( const std::string& name );
301
305
306 CoreGeometry m_mesh;
307};
308
310class RA_ENGINE_API PointCloud : public CoreGeometryDisplayable<Core::Geometry::PointCloud>
311{
313
314 public:
315 using base::CoreGeometryDisplayable;
316 inline explicit PointCloud(
317 const std::string& name,
318 typename base::CoreGeometry&& geom,
319 typename base::MeshRenderMode renderMode = base::MeshRenderMode::RM_POINTS );
320
321 inline explicit PointCloud( const std::string& name, MeshRenderMode renderMode = RM_POINTS );
322
324 void render( const ShaderProgram* prog ) override;
325
326 void loadGeometry( Core::Geometry::PointCloud&& mesh ) override;
327
328 protected:
329 void updateGL_specific_impl() override;
330};
331
333template <typename T>
335{
336 public:
338 using CoreGeometryDisplayable<T>::CoreGeometryDisplayable;
339 explicit IndexedGeometry(
340 const std::string& name,
341 typename base::CoreGeometry&& geom,
342 typename base::MeshRenderMode renderMode = base::MeshRenderMode::RM_TRIANGLES );
343
344 void render( const ShaderProgram* prog ) override;
345
346 void loadGeometry( T&& mesh ) override;
347
348 protected:
349 void updateGL_specific_impl() override;
350};
351
354template <typename T>
356{
357 public:
359 using CoreGeometryDisplayable<T>::CoreGeometryDisplayable;
360 explicit MultiIndexedGeometry(
361 const std::string& name,
362 typename base::CoreGeometry&& geom,
363 typename base::MeshRenderMode renderMode = base::MeshRenderMode::RM_TRIANGLES );
364 void render( const ShaderProgram* prog ) override;
365
366 void loadGeometry( T&& mesh ) override;
367
368 protected:
369 void updateGL_specific_impl() override;
370
374
376 struct RA_CORE_API KeyHash {
377 std::size_t operator()( const LayerKeyType& k ) const {
378 // Mix semantic collection into a single identifier string
379 std::ostringstream stream;
380 std::copy(
381 k.first.begin(), k.first.end(), std::ostream_iterator<std::string>( stream, "" ) );
382 std::string result = stream.str();
383 std::sort( result.begin(), result.end() );
384
385 // Combine with layer name hash
386 return std::hash<std::string> {}( result ) ^
387 ( std::hash<std::string> {}( k.second ) << 1 );
388 }
389 }; // namespace Data
391}; // namespace Engine
392
394class RA_ENGINE_API LineMesh : public IndexedGeometry<Core::Geometry::LineMesh>
395{
397
398 public:
399 using base::IndexedGeometry;
400 inline explicit LineMesh(
401 const std::string& name,
402 typename base::CoreGeometry&& geom,
403 typename base::MeshRenderMode renderMode = base::MeshRenderMode::RM_LINES );
404 inline explicit LineMesh(
405 const std::string& name,
406 typename base::MeshRenderMode renderMode = base::MeshRenderMode::RM_LINES );
407
408 protected:
409 private:
410};
411
413class RA_ENGINE_API Mesh : public IndexedGeometry<Core::Geometry::TriangleMesh>
414{
416
417 public:
418 using base::IndexedGeometry;
419 size_t getNumFaces() const override;
420
428 using base::loadGeometry;
429 [[deprecated]] void loadGeometry( const Core::Vector3Array& vertices,
430 const std::vector<uint>& indices );
431
432 protected:
433 private:
434};
435
440template <typename T>
441class RA_ENGINE_API GeneralMesh : public IndexedGeometry<T>
442{
443 using base = IndexedGeometry<T>;
444 using IndexType = Core::Vector3ui;
445
446 public:
447 using base::IndexedGeometry;
448 inline size_t getNumFaces() const override;
449
450 protected:
451 inline void updateGL_specific_impl() override;
452
453 private:
454 inline void triangulate();
455 Core::AlignedStdVector<IndexType> m_triangleIndices;
456};
457
460
463template <typename CoreMeshType>
465 CoreMeshType mesh;
466 typename CoreMeshType::IndexContainerType indices;
467
468 if ( !data->isLineMesh() ) {
469 auto& geo = data->getGeometry();
470 const auto& [layerKeyType, layerBase] =
471 geo.getFirstLayerOccurrence( mesh.getLayerKey().first );
472 const auto& layer = static_cast<
474 layerBase );
475 const auto& faces = layer.collection();
476 indices.reserve( faces.size() );
477 std::copy( faces.begin(), faces.end(), std::back_inserter( indices ) );
478 }
479#if 0
480 // TODO manage line meshes in a "usual" way, i.e. as an indexed geometry with specific
481 // rendering properties (i.e. shader, as it is the case for point clouds)
482 // Create a degenerated triangle to handle edges case.
483 else {
484 const auto& edges = ... access the LineIndexLayer
485 indices.reserve( edges.size() );
487 edges.begin(), edges.end(), std::back_inserter( indices ), []( Ra::Core::Vector2ui v ) {
488 return ( Ra::Core::Vector3ui { v( 0 ), v( 1 ), v( 1 ) } );
489 } );
490 }
491#endif
492
493 mesh.setIndices( std::move( indices ) );
494
495 // This copy only "usual" attributes. See Core::Geometry::AttribManager::copyAllAttributes
496 mesh.vertexAttribs().copyAllAttributes( data->getGeometry().vertexAttribs() );
497
498 return mesh;
499}
500
502namespace RenderMeshType {
503template <class CoreMeshT>
504struct getType {};
505
506template <>
507struct getType<Ra::Core::Geometry::LineMesh> {
508 using Type = Ra::Engine::Data::LineMesh;
509};
510
511template <>
512struct getType<Ra::Core::Geometry::TriangleMesh> {
513 using Type = Ra::Engine::Data::Mesh;
514};
515
516template <>
517struct getType<Ra::Core::Geometry::QuadMesh> {
518 using Type = Ra::Engine::Data::QuadMesh;
519};
520
521template <>
522struct getType<Ra::Core::Geometry::PolyMesh> {
523 using Type = Ra::Engine::Data::PolyMesh;
524};
525} // namespace RenderMeshType
526
528template <typename CoreMeshType>
529typename RenderMeshType::getType<CoreMeshType>::Type*
531 using MeshType = typename RenderMeshType::getType<CoreMeshType>::Type;
532
533 auto mesh = createCoreMeshFromGeometryData<CoreMeshType>( data );
534
535 MeshType* ret = new MeshType { name };
536 ret->loadGeometry( std::move( mesh ) );
537
538 return ret;
539}
540
542
543void AttribArrayDisplayable::setRenderMode( MeshRenderMode mode ) {
544 m_renderMode = mode;
545 updatePickingRenderMode();
546}
547
548AttribArrayDisplayable::MeshRenderMode AttribArrayDisplayable::getRenderMode() const {
549 return m_renderMode;
550}
551
553
554void VaoIndices::setIndicesDirty() {
555 m_indicesDirty = true;
556}
557
559
560template <typename I>
561template <typename T>
563 const std::string& name,
564 const typename Ra::Core::Utils::Attrib<T>::Container& data ) {
565 auto handle = m_attribManager.addAttrib<T>( name );
566 m_attribManager.getAttrib( handle ).setData( data );
567 m_handleToBuffer[name] = m_dataDirty.size();
568 m_dataDirty.push_back( true );
569 m_vbos.emplace_back( nullptr );
570 m_isDirty = true;
571}
572
573template <typename I>
574template <typename T>
575void IndexedAttribArrayDisplayable<I>::addAttrib(
576 const std::string& name,
577 const typename Ra::Core ::Utils::Attrib<T>::Container&& data ) {
578 auto handle = m_attribManager.addAttrib<T>( name );
579 m_attribManager.getAttrib( handle ).setData( std::move( data ) );
580 m_handleToBuffer[name] = m_dataDirty.size();
581 m_dataDirty.push_back( true );
582 m_vbos.emplace_back( nullptr );
583 m_isDirty = true;
584}
585
586template <typename I>
587void IndexedAttribArrayDisplayable<I>::updateGL() {
588 if ( m_isDirty ) {
589 // Check that our dirty bits are consistent.
590 ON_ASSERT( bool dirtyTest = false;
591 for ( const auto& d : m_dataDirty ) { dirtyTest = dirtyTest || d; } );
592 CORE_ASSERT( dirtyTest == m_isDirty, "Dirty flags inconsistency" );
593
594 if ( !m_indices ) {
595 m_indices = globjects::Buffer::create();
596 m_indicesDirty = true;
597 }
598 if ( m_indicesDirty ) {
599 m_indices->setData(
600 static_cast<gl::GLsizeiptr>( m_cpu_indices.size() * sizeof( IndexType ) ),
601 m_cpu_indices.data(),
602 GL_STATIC_DRAW );
603 m_indicesDirty = false;
604 }
605
606 m_numElements = m_cpu_indices.size();
607
608 if ( !m_vao ) { m_vao = globjects::VertexArray::create(); }
609 m_vao->bind();
610 m_vao->bindElementBuffer( m_indices.get() );
611 m_vao->unbind();
612
613 auto func = [this]( Ra::Core::Utils::AttribBase* b ) {
614 auto idx = m_handleToBuffer[b->getName()];
615
616 if ( m_dataDirty[idx] ) {
617 if ( !m_vbos[idx] ) { m_vbos[idx] = globjects::Buffer::create(); }
618 m_vbos[idx]->setData( b->getBufferSize(), b->dataPtr(), GL_DYNAMIC_DRAW );
619 m_dataDirty[idx] = false;
620 }
621 };
622 m_attribManager.for_each_attrib( func );
623 GL_CHECK_ERROR;
624 m_isDirty = false;
625 }
626}
627
628template <typename I>
630
631 auto glprog = prog->getProgramObject();
632 gl::GLint attribCount = glprog->get( GL_ACTIVE_ATTRIBUTES );
633
634 for ( GLint idx = 0; idx < attribCount; ++idx ) {
635 const gl::GLsizei bufSize = 256;
636 gl::GLchar name[bufSize];
637 gl::GLsizei length;
638 gl::GLint size;
639 gl::GLenum type;
640 glprog->getActiveAttrib( idx, bufSize, &length, &size, &type, name );
641 auto loc = glprog->getAttributeLocation( name );
642
643 auto attribName = name; // m_translationTableShaderToMesh[name];
644 auto attrib = m_attribManager.getAttribBase( attribName );
645
646 if ( attrib && attrib->getSize() > 0 ) {
647 m_vao->enable( loc );
648 auto binding = m_vao->binding( idx );
649 binding->setAttribute( loc );
650 CORE_ASSERT( m_vbos[m_handleToBuffer[attribName]].get(), "vbo is nullptr" );
651#ifdef CORE_USE_DOUBLE
652 binding->setBuffer( m_vbos[m_handleToBuffer[attribName]].get(),
653 0,
654 attrib->getNumberOfComponents() * sizeof( float ) );
655#else
656
657 binding->setBuffer(
658 m_vbos[m_handleToBuffer[attribName]].get(), 0, attrib->getStride() );
659#endif
660 binding->setFormat( attrib->getNumberOfComponents(), GL_SCALAR );
661 }
662 else { m_vao->disable( loc ); }
663 }
664}
665
666template <typename I>
668 if ( m_vao ) {
669 autoVertexAttribPointer( prog );
670 m_vao->bind();
671 m_vao->drawElements( static_cast<GLenum>( m_renderMode ),
672 GLsizei( m_numElements ),
673 GL_UNSIGNED_INT,
674 nullptr );
675 m_vao->unbind();
676 }
677}
678
680
681template <typename CoreGeometry>
682CoreGeometryDisplayable<CoreGeometry>::CoreGeometryDisplayable( const std::string& name,
683 MeshRenderMode renderMode ) :
684 base( name, renderMode ) {
685 setupCoreMeshObservers();
686}
687
688template <typename CoreGeometry>
693
694template <typename CoreGeometry>
696 return m_mesh;
697}
698
699template <typename CoreGeometry>
701CoreGeometryDisplayable<CoreGeometry>::getAttribArrayGeometry() const {
702 return m_mesh;
703}
704
705template <typename CoreGeometry>
707CoreGeometryDisplayable<CoreGeometry>::getAttribArrayGeometry() {
708 return m_mesh;
709}
710
711template <typename CoreGeometry>
712const CoreGeometry& CoreGeometryDisplayable<CoreGeometry>::getCoreGeometry() const {
713 return m_mesh;
714}
715
716template <typename CoreGeometry>
717CoreGeometry& CoreGeometryDisplayable<CoreGeometry>::getCoreGeometry() {
718 return m_mesh;
719}
720
721template <typename CoreGeometry>
722void CoreGeometryDisplayable<CoreGeometry>::addToTranslationTable( const std::string& name ) {
723 m_translationTable.insert( name, name );
724}
725
726template <typename CoreGeometry>
728 // this observer is called each time an attrib is added or removed from m_mesh
729 auto attrib = m_mesh.getAttribBase( name );
730 // if attrib not nullptr, then it's an attrib add, so attach an observer to it
731
732 if ( attrib ) {
733 auto itr = m_handleToBuffer.find( name );
734 if ( itr == m_handleToBuffer.end() ) {
735 m_handleToBuffer[name] = m_dataDirty.size();
736
737 addToTranslationTable( name );
738
739 m_dataDirty.push_back( true );
740 m_vbos.emplace_back( nullptr );
741 }
742 auto idx = m_handleToBuffer[name];
743 attrib->attach( AttribObserver( this, idx ) );
744 }
745 // else it's an attrib remove, do nothing, cleanup will be done in updateGL()
746 else {}
747}
748
749template <typename CoreGeometry>
751
752 auto glprog = prog->getProgramObject();
753 gl::GLint attribCount = glprog->get( GL_ACTIVE_ATTRIBUTES );
754
755 for ( GLint idx = 0; idx < attribCount; ++idx ) {
756 const gl::GLsizei bufSize = 256;
757 gl::GLchar name[bufSize];
758 gl::GLsizei length;
759 gl::GLint size;
760 gl::GLenum type;
761 glprog->getActiveAttrib( idx, bufSize, &length, &size, &type, name );
762 auto loc = glprog->getAttributeLocation( name );
763
764 auto attribNameOpt = m_translationTable.keyIfExists( name );
765 if ( attribNameOpt ) {
766 auto attribName = *attribNameOpt;
767 auto attrib = m_mesh.getAttribBase( attribName );
768 if ( attrib && attrib->getSize() > 0 ) {
769 m_vao->enable( loc );
770 auto binding = m_vao->binding( idx );
771 binding->setAttribute( loc );
772 CORE_ASSERT( m_vbos[m_handleToBuffer[attribName]].get(), "vbo is nullptr" );
773#ifdef CORE_USE_DOUBLE
774 binding->setBuffer( m_vbos[m_handleToBuffer[attribName]].get(),
775 0,
776 attrib->getNumberOfComponents() * sizeof( float ) );
777#else
778
779 binding->setBuffer(
780 m_vbos[m_handleToBuffer[attribName]].get(), 0, attrib->getStride() );
781#endif
782 binding->setFormat( attrib->getNumberOfComponents(), GL_SCALAR );
783 }
784 else { m_vao->disable( loc ); }
785 }
786 else { m_vao->disable( loc ); }
787 }
788}
789
790template <typename T>
792 m_mesh = std::move( mesh );
793 setupCoreMeshObservers();
794}
795
796template <typename T>
797
798void CoreGeometryDisplayable<T>::setupCoreMeshObservers() {
799 int idx = 0;
800 m_dataDirty.resize( m_mesh.vertexAttribs().getNumAttribs() );
801 m_vbos.resize( m_mesh.vertexAttribs().getNumAttribs() );
802 // here capture ref to idx to propagate idx incrementation
803 m_mesh.vertexAttribs().for_each_attrib( [&idx, this]( Ra::Core::Utils::AttribBase* b ) {
804 auto name = b->getName();
805 m_handleToBuffer[name] = idx;
806 m_dataDirty[idx] = true;
807
808 // create a identity translation if name is not already translated.
809 addToTranslationTable( name );
810
811 b->attach( AttribObserver( this, idx ) );
812 ++idx;
813 } );
814
815 // add an observer on attrib manipulation.
816 m_mesh.vertexAttribs().attachMember(
818 m_isDirty = true;
819}
820
822template <typename CoreGeometry>
823template <typename A>
826 const typename Core::VectorArray<A>& data ) {
827 return m_mesh.addAttrib( name, data );
828}
829
830template <typename CoreGeometry>
832 return m_mesh.vertices().size();
833}
834
835template <typename CoreGeometry>
837 CORE_ASSERT( false, "must be specialized" );
838}
839
840template <typename CoreGeometry>
842 if ( m_isDirty ) {
843 // Check that our dirty bits are consistent.
844 ON_ASSERT( bool dirtyTest = false;
845 for ( auto d : m_dataDirty ) { dirtyTest = dirtyTest || d; } );
846 CORE_ASSERT( dirtyTest == m_isDirty, "Dirty flags inconsistency" );
847 CORE_ASSERT( !( m_mesh.vertices().empty() ), "No vertex." );
848
849 updateGL_specific_impl();
850#ifdef CORE_USE_DOUBLE
851 // need convserion
852 auto func = [this]( Ra::Core::Utils::AttribBase* b ) {
853 auto idx = m_handleToBuffer[b->getName()];
854
855 if ( m_dataDirty[idx] ) {
856 if ( !m_vbos[idx] ) { m_vbos[idx] = globjects::Buffer::create(); }
857
858 auto stride = b->getStride();
859 auto eltSize = b->getNumberOfComponents();
860 auto size = b->getSize();
861 auto data = std::make_unique<float[]>( size * eltSize );
862 const void* ptr = b->dataPtr();
863 const char* cptr = reinterpret_cast<const char*>( ptr );
864
865 for ( size_t i = 0; i < size; i++ ) {
866 auto tptr = reinterpret_cast<const Scalar*>( cptr + i * stride );
867 for ( size_t j = 0; j < eltSize; ++j ) {
868 data[i * eltSize + j] = tptr[j];
869 }
870 }
871
872 m_vbos[idx]->setData(
873 size * eltSize * sizeof( float ), data.get(), GL_DYNAMIC_DRAW );
874
875 m_dataDirty[idx] = false;
876 }
877 };
878
879#else
880 auto func = [this]( Ra::Core::Utils::AttribBase* b ) {
881 auto idx = m_handleToBuffer[b->getName()];
882
883 if ( m_dataDirty[idx] ) {
884 if ( !m_vbos[idx] ) { m_vbos[idx] = globjects::Buffer::create(); }
885 m_vbos[idx]->setData( b->getBufferSize(), b->dataPtr(), GL_DYNAMIC_DRAW );
886 m_dataDirty[idx] = false;
887 }
888 };
889#endif
890 m_mesh.vertexAttribs().for_each_attrib( func );
891
892 // cleanup removed attrib
893 for ( auto buffer : m_handleToBuffer ) {
894 // do not remove name from handleToBuffer to keep index ...
895 // we could also update handleToBuffer, m_vbos, m_dataDirty
896 if ( !m_mesh.hasAttrib( buffer.first ) && m_vbos[buffer.second] ) {
897 m_vbos[buffer.second].reset( nullptr );
898 m_dataDirty[buffer.second] = false;
899 }
900 }
901
902 GL_CHECK_ERROR;
903 m_isDirty = false;
904 }
905}
906
907template <typename CoreGeometry>
909 const std::string& meshAttribName,
910 const std::string& shaderAttribName ) {
911
912 m_translationTable.replace( meshAttribName, shaderAttribName );
913}
914
916
917template <typename T>
919 typename base::CoreGeometry&& geom,
920 typename base::MeshRenderMode renderMode ) :
921 base( name, renderMode ) {
922 loadGeometry( std::move( geom ) );
923}
924
925template <typename T>
927 setIndicesDirty();
928 base::loadGeometry_common( std::move( mesh ) );
929
930 // indices
931 base::m_mesh.attach( IndicesObserver( this ) );
932}
933
934template <typename T>
936 if ( !m_indices ) {
937 m_indices = globjects::Buffer::create();
938 m_indicesDirty = true;
939 }
940 if ( m_indicesDirty ) {
942 // m_indices->setData( m_mesh.m_indices, GL_DYNAMIC_DRAW );
943 m_numElements =
944 base::m_mesh.getIndices().size() * base::CoreGeometry::IndexType::RowsAtCompileTime;
945
946 m_indices->setData(
947 static_cast<gl::GLsizeiptr>( base::m_mesh.getIndices().size() *
948 sizeof( typename base::CoreGeometry::IndexType ) ),
949 base::m_mesh.getIndices().data(),
950 GL_STATIC_DRAW );
951 m_indicesDirty = false;
952 }
953 if ( !base::m_vao ) { base::m_vao = globjects::VertexArray::create(); }
954 base::m_vao->bind();
955 base::m_vao->bindElementBuffer( m_indices.get() );
956 base::m_vao->unbind();
957}
958
959template <typename T>
961 if ( base::m_vao ) {
962 GL_CHECK_ERROR;
963 base::m_vao->bind();
964 base::autoVertexAttribPointer( prog );
965 GL_CHECK_ERROR;
966 base::m_vao->drawElements( static_cast<GLenum>( base::m_renderMode ),
967 GLsizei( m_numElements ),
968 GL_UNSIGNED_INT,
969 nullptr );
970 GL_CHECK_ERROR;
971 base::m_vao->unbind();
972 GL_CHECK_ERROR;
973 }
974}
975
977
978template <typename T>
980 typename base::CoreGeometry&& geom,
981 typename base::MeshRenderMode renderMode ) :
982 base( name, renderMode ) {
983 loadGeometry( std::move( geom ) );
984}
985
986template <typename T>
988 m_indices.clear();
989
990 base::loadGeometry_common( std::move( mesh ) );
991 CORE_ASSERT( false, "not implemented yet" );
992
994 // indices
995 // base::m_mesh.attach( IndicesObserver( this ) );
996}
997
998template <typename T>
1000 CORE_ASSERT( false, "not implemented yet" );
1001 // if ( !m_indices )
1002 // {
1003 // m_indices = globjects::Buffer::create();
1004 // m_indicesDirty = true;
1005 // }
1006 // if ( m_indicesDirty )
1007 // {
1008 // /// this one do not work since m_indices is not a std::vector
1009 // // m_indices->setData( m_mesh.m_indices, GL_DYNAMIC_DRAW );
1010 // m_numElements =
1011 // base::m_mesh.getIndices().size() *
1012 // base::CoreGeometry::IndexType::RowsAtCompileTime;
1013 //
1014 // m_indices->setData(
1015 // static_cast<gl::GLsizeiptr>( base::m_mesh.getIndices().size() *
1016 // sizeof( typename base::CoreGeometry::IndexType ) ),
1017 // base::m_mesh.getIndices().data(),
1018 // GL_STATIC_DRAW );
1019 // m_indicesDirty = false;
1020 // }
1021 // if ( !base::m_vao ) { base::m_vao = globjects::VertexArray::create(); }
1022 // base::m_vao->bind();
1023 // base::m_vao->bindElementBuffer( m_indices.get() );
1024 // base::m_vao->unbind();
1026}
1027
1028template <typename T>
1030 CORE_ASSERT( false, "not implemented yet" );
1031 // if ( base::m_vao )
1032 // {
1033 // GL_CHECK_ERROR;
1034 // base::m_vao->bind();
1035 // base::autoVertexAttribPointer( prog );
1036 // GL_CHECK_ERROR;
1037 // base::m_vao->drawElements( static_cast<GLenum>( base::m_renderMode ),
1038 // GLsizei( m_numElements ),
1039 // GL_UNSIGNED_INT,
1040 // nullptr );
1041 // GL_CHECK_ERROR;
1042 // base::m_vao->unbind();
1043 // GL_CHECK_ERROR;
1044 // }
1046}
1047
1049
1050PointCloud::PointCloud( const std::string& name,
1051 typename base::CoreGeometry&& geom,
1052 typename base::MeshRenderMode renderMode ) :
1053 base( name, renderMode ) {
1054 loadGeometry( std::move( geom ) );
1055}
1056
1057PointCloud::PointCloud( const std::string& name, typename base::MeshRenderMode renderMode ) :
1058 base( name, renderMode ) {}
1059
1061
1062LineMesh::LineMesh( const std::string& name,
1063 typename base::CoreGeometry&& geom,
1064 typename base::MeshRenderMode renderMode ) :
1065 base( name, std::move( geom ), renderMode ) {}
1066
1067LineMesh::LineMesh( const std::string& name, typename base::MeshRenderMode renderMode ) :
1068 base( name, renderMode ) {}
1069
1071
1072template <typename T>
1073size_t GeneralMesh<T>::getNumFaces() const {
1074 return this->getCoreGeometry().getIndices().size();
1075}
1076
1077template <typename T>
1079 if ( !this->m_indices ) {
1080 this->m_indices = globjects::Buffer::create();
1081 this->m_indicesDirty = true;
1082 }
1083 if ( this->m_indicesDirty ) {
1084 triangulate();
1086 // m_indices->setData( m_mesh.m_indices, GL_DYNAMIC_DRAW );
1087 this->m_numElements = m_triangleIndices.size() * GeneralMesh::IndexType::RowsAtCompileTime;
1088
1089 this->m_indices->setData( static_cast<gl::GLsizeiptr>( m_triangleIndices.size() *
1090 sizeof( GeneralMesh::IndexType ) ),
1091 m_triangleIndices.data(),
1092 GL_STATIC_DRAW );
1093 this->m_indicesDirty = false;
1094 }
1095 if ( !base::m_vao ) { base::m_vao = globjects::VertexArray::create(); }
1096 base::m_vao->bind();
1097 base::m_vao->bindElementBuffer( this->m_indices.get() );
1098 base::m_vao->unbind();
1099}
1100
1101template <typename T>
1103 m_triangleIndices.clear();
1104 m_triangleIndices.reserve( this->m_mesh.getIndices().size() );
1105 for ( const auto& face : this->m_mesh.getIndices() ) {
1106 if ( face.size() == 3 ) { m_triangleIndices.push_back( face ); }
1107 else {
1109 int minus { int( face.size() ) - 1 };
1110 int plus { 0 };
1111 while ( plus + 1 < minus ) {
1112 if ( ( plus - minus ) % 2 ) {
1113 m_triangleIndices.emplace_back( face[plus], face[plus + 1], face[minus] );
1114 ++plus;
1115 }
1116 else {
1117 m_triangleIndices.emplace_back( face[minus], face[plus], face[minus - 1] );
1118 --minus;
1119 }
1120 }
1121 }
1122 }
1123}
1124
1125template <>
1126inline void GeneralMesh<Core::Geometry::QuadMesh>::triangulate() {
1127 m_triangleIndices.clear();
1128 m_triangleIndices.reserve( 2 * this->m_mesh.getIndices().size() );
1129 // assume quads are convex
1130 for ( const auto& face : this->m_mesh.getIndices() ) {
1131 m_triangleIndices.emplace_back( face[0], face[1], face[2] );
1132 m_triangleIndices.emplace_back( face[0], face[2], face[3] );
1133 }
1134}
1135
1136} // namespace Data
1137} // namespace Engine
1138} // namespace Ra
T back_inserter(T... args)
T begin(T... args)
bool isLineMesh() const
Return true if the object is a Line Mesh.
Geometry::MultiIndexedGeometry & getGeometry()
Read/write access to the multiIndexedGeometry;.
This class represents vertex + attributes per vertex. Toplogy is handled in MultiIndexedGeometry subc...
Utils::AttribBase * getAttribBase(const std::string &name)
std::pair< LayerKeyType, const GeometryIndexLayerBase & > getFirstLayerOccurrence(const LayerSemanticCollection &semantics) const
Read-only access to a layer.
std::string getName() const
Return the attribute's name.
Definition Attribs.hpp:456
An attrib handle basically store an Index and a name.
Definition Attribs.hpp:154
The AttribManager provides attributes management by handles.
Definition Attribs.hpp:212
Bijective association between two sets {keys} and {values} having the same cardinality....
virtual const void * dataPtr() const =0
std::set< SemanticName > SemanticNameCollection
Store in set to allow for logarithmic search.
int attach(Observer observer)
Template class to manage the Displayable aspect of a Core Geomertry, such as TriangleMesh.
Definition Mesh.hpp:229
void updateGL() override
Update (i.e. send to GPU) the buffers marked as dirty.
Definition Mesh.hpp:841
BijectiveAssociation< std::string, std::string > m_translationTable
Definition Mesh.hpp:304
void addAttribObserver(const std::string &name)
Definition Mesh.hpp:727
void autoVertexAttribPointer(const ShaderProgram *prog)
assume m_vao is bound.
Definition Mesh.hpp:750
void setAttribNameCorrespondance(const std::string &meshAttribName, const std::string &shaderAttribName)
Definition Mesh.hpp:908
virtual void loadGeometry(CoreGeometry &&mesh)
Definition Mesh.hpp:836
Ra::Core::Utils::AttribHandle< A > addAttrib(const std::string &name, const typename Core::VectorArray< A > &data)
Helper function that calls Ra::Core::CoreGeometry::addAttrib()
Definition Mesh.hpp:825
const Core::Geometry::AbstractGeometry & getAbstractGeometry() const override
Definition Mesh.hpp:690
void updateGL_specific_impl() override
Definition Mesh.hpp:1078
void autoVertexAttribPointer(const ShaderProgram *prog)
assume m_vao is bound.
Definition Mesh.hpp:629
An engine mesh owning CoreGeometry, with indices.
Definition Mesh.hpp:335
void loadGeometry(T &&mesh) override
Definition Mesh.hpp:926
void updateGL_specific_impl() override
Definition Mesh.hpp:935
void render(const ShaderProgram *prog) override
Definition Mesh.hpp:960
LineMesh, own a Core::Geometry::LineMesh.
Definition Mesh.hpp:395
Mesh, own a Core::Geometry::TriangleMesh.
Definition Mesh.hpp:414
void render(const ShaderProgram *prog) override
Definition Mesh.hpp:1029
void loadGeometry(T &&mesh) override
Definition Mesh.hpp:987
A PointCloud without indices.
Definition Mesh.hpp:311
IndicesObserver(VaoIndices *displayable)
not tested
Definition Mesh.hpp:184
Concept class to ensure consistent naming of VaoIndices accross derived classes.
Definition Mesh.hpp:174
T copy(T... args)
T end(T... args)
T move(T... args)
CoreMeshType createCoreMeshFromGeometryData(const Ra::Core::Asset::GeometryData *data)
Definition Mesh.hpp:464
RenderMeshType::getType< CoreMeshType >::Type * createMeshFromGeometryData(const std::string &name, const Ra::Core::Asset::GeometryData *data)
create Mesh, PolyMesh Engine::Data::*Mesh * from GeometryData
Definition Mesh.hpp:530
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:4
STL namespace.
T reserve(T... args)
T sort(T... args)
T str(T... args)
T transform(T... args)