From 5fb8ebcd336cf4b86b1e5dd4ee392131af76badf Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 20 Jul 2022 11:18:11 +0200 Subject: [PATCH 01/28] [core] Fix IndexedGeometry. [core] Expose LayerKeyHash struct Allow to reuse layers hash function outside of MultiIndexedGeometry --- src/Core/Geometry/IndexedGeometry.cpp | 4 ++-- src/Core/Geometry/IndexedGeometry.hpp | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index eaf65538284..b8e7a5cb5f1 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -215,7 +215,7 @@ MultiIndexedGeometry::addLayer( std::unique_ptr&& layer, const bool withLock, const std::string& layerName ) { LayerKeyType key { layer->semantics(), layerName }; - std::pair elt { key, std::make_pair( false, std::move( layer ) ) }; + auto elt = std::make_pair( key, std::make_pair( false, std::move( layer ) ) ); auto [pos, inserted] = m_indices.insert( std::move( elt ) ); notify(); @@ -245,7 +245,7 @@ void MultiIndexedGeometry::deepClear() { ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// -std::size_t MultiIndexedGeometry::KeyHash::operator()( const LayerKeyType& k ) const { +std::size_t MultiIndexedGeometry::LayerKeyHash::operator()( const LayerKeyType& k ) const { // Mix semantic collection into a single identifier string std::ostringstream stream; std::copy( k.first.begin(), k.first.end(), std::ostream_iterator( stream, "" ) ); diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 52ab27bae42..0f8867a44d8 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -383,18 +383,19 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \brief Clear attributes stored as pointers void deepClear(); - using EntryType = std::pair>; + using LayerEntryType = std::pair>; - struct RA_CORE_API KeyHash { + struct RA_CORE_API LayerKeyHash { std::size_t operator()( const LayerKeyType& k ) const; }; + private: /// Collection of pairs /// \note There is no natural ordering for these elements, thus /// we need an unordered_map. In contrast to map, transparent hashing /// require c++20, so we need to implement them explicitely here /// https://en.cppreference.com/w/cpp/container/unordered_map/find - std::unordered_map m_indices; + std::unordered_map m_indices; }; /// \name Predefined index layers @@ -762,6 +763,7 @@ inline void IndexedGeometry::setIndices( IndexContainerType&& indices ) { auto& abstractLayer = getLayerWithLock( m_mainIndexLayerKey ); static_cast::DefaultLayerType&>( abstractLayer ).collection() = std::move( indices ); + indicesUnlock(); notify(); } @@ -769,6 +771,7 @@ template inline void IndexedGeometry::setIndices( const IndexContainerType& indices ) { auto& abstractLayer = getLayerWithLock( m_mainIndexLayerKey ); static_cast::DefaultLayerType&>( abstractLayer ).collection() = indices; + indicesUnlock(); notify(); } From 8de3a1166c5d68de344cfe244704499e2c250280 Mon Sep 17 00:00:00 2001 From: Nicolas Mellado Date: Mon, 19 Jul 2021 13:00:11 +0200 Subject: [PATCH 02/28] [engine] Prepare API of GeometryDisplayable [engine] Remove unused class IndexedAttribArrayDisplayable [engine] Prepare classes attributes (do not compile) Code does not compile as only the attributes have been defined, but the methods have not been updated. [core] Mark GeometryIndexLayerBase::size() as const [engine] define all virtual function for GeometryDisplayable (will be deleted). When transition will be complete, these accessor might not be necessary. [engine] GeometryDisplayable updateGL (not tested). [engine] GeometryDisplayable works, for HelloRadium. triangulate --- src/Core/Geometry/IndexedGeometry.hpp | 3 +- src/Engine/Data/Mesh.cpp | 310 +++++++++++++++++++++ src/Engine/Data/Mesh.hpp | 375 +++++++++----------------- 3 files changed, 437 insertions(+), 251 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 0f8867a44d8..c8f75726e34 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -385,6 +385,8 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util using LayerEntryType = std::pair>; + public: + /// Hash function for layer keys struct RA_CORE_API LayerKeyHash { std::size_t operator()( const LayerKeyType& k ) const; }; @@ -503,7 +505,6 @@ struct getType { /** * \brief A single layer MultiIndexedGeometry. - * * This class actually provide compatibility with old geometry with a main layer. * Main layer contains indices of a specific type (point, line, triangle, poly). * Derived classes explicit the kind of indices of the main layer. diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index cf2cbde539f..1e0080b6974 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -1,3 +1,4 @@ +#include "Core/Geometry/IndexedGeometry.hpp" #include #include @@ -149,6 +150,315 @@ void AttribArrayDisplayable::setDirty( const Ra::Core::Geometry::MeshAttrib& typ m_isDirty = true; } +//////////////// MultiIndexedGeometry /////////////////////////////// + +GeometryDisplayable::GeometryDisplayable( const std::string& name, + typename Core::Geometry::MultiIndexedGeometry&& geom ) : + base( name ) { + loadGeometry( std::move( geom ) ); +} + +GeometryDisplayable::~GeometryDisplayable() {} + +void triangulate( Core::Geometry::TriangleIndexLayer& out, + const Core::Geometry::PolyIndexLayer& in ) { + out.collection().clear(); + out.collection().reserve( in.collection().size() ); + for ( const auto& face : in.collection() ) { + if ( face.size() == 3 ) { out.collection().push_back( face ); } + else { + /// simple sew triangulation + int minus { int( face.size() ) - 1 }; + int plus { 0 }; + while ( plus + 1 < minus ) { + if ( ( plus - minus ) % 2 ) { + out.collection().emplace_back( face[plus], face[plus + 1], face[minus] ); + ++plus; + } + else { + out.collection().emplace_back( face[minus], face[plus], face[minus - 1] ); + --minus; + } + } + } + } +} + +void triangulate( Core::Geometry::TriangleIndexLayer& out, + const Core::Geometry::QuadIndexLayer& in ) { + out.collection().clear(); + out.collection().reserve( 2 * in.getSize() ); + // assume quads are convex + for ( const auto& face : in.collection() ) { + out.collection().emplace_back( face[0], face[1], face[2] ); + out.collection().emplace_back( face[0], face[2], face[3] ); + } +} + +void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh ) { + m_geomLayers.clear(); + m_geom = std::move( mesh ); + setupCoreMeshObservers(); + + /// \todo check if other layer ? at least triangulate + if ( m_geom.containsLayer( Core::Geometry::TriangleIndexLayer::staticSemanticName ) ) { + auto [key, layer] = m_geom.getFirstLayerOccurrence( + Core::Geometry::TriangleIndexLayer::staticSemanticName ); + addRenderLayer( key, AttribArrayDisplayable::RM_TRIANGLES ); + } + else if ( m_geom.containsLayer( Core::Geometry::QuadIndexLayer::staticSemanticName ) ) { + auto [key, layer] = + m_geom.getFirstLayerOccurrence( Core::Geometry::QuadIndexLayer::staticSemanticName ); + + const auto& quadLayer = + dynamic_cast( m_geom.getLayer( key ) ); + + auto triangleLayer = std::make_unique(); + triangulate( *triangleLayer, quadLayer ); + auto layerAdded = m_geom.addLayer( std::move( triangleLayer ), false, "triangulation" ); + if ( !layerAdded.first ) { LOG( logERROR ) << "failed to add triangleLayer"; } + else { + LayerKeyType triangleKey = { triangleLayer->semantics(), "triangulation" }; + addRenderLayer( triangleKey, AttribArrayDisplayable::RM_TRIANGLES ); + } + } + else if ( m_geom.containsLayer( Core::Geometry::PolyIndexLayer::staticSemanticName ) ) { + auto [key, layer] = + m_geom.getFirstLayerOccurrence( Core::Geometry::PolyIndexLayer::staticSemanticName ); + + const auto& polyLayer = + dynamic_cast( m_geom.getLayer( key ) ); + + auto triangleLayer = std::make_unique(); + triangulate( *triangleLayer, polyLayer ); + auto layerAdded = m_geom.addLayer( std::move( triangleLayer ), false, "triangulation" ); + if ( !layerAdded.first ) { LOG( logERROR ) << "failed to add triangleLayer"; } + else { + LayerKeyType triangleKey = { triangleLayer->semantics(), "triangulation" }; + addRenderLayer( triangleKey, AttribArrayDisplayable::RM_TRIANGLES ); + } + } + m_isDirty = true; +} + +void GeometryDisplayable::setupCoreMeshObservers() { + int idx = 0; + m_dataDirty.resize( m_geom.vertexAttribs().getNumAttribs() ); + m_vbos.resize( m_geom.vertexAttribs().getNumAttribs() ); + // here capture ref to idx to propagate idx incrementation + m_geom.vertexAttribs().for_each_attrib( [&idx, this]( Ra::Core::Utils::AttribBase* b ) { + auto name = b->getName(); + m_handleToBuffer[name] = idx; + m_dataDirty[idx] = true; + + // create a identity translation if name is not already translated. + addToTranslationTable( name ); + + b->attach( AttribObserver( this, idx ) ); + ++idx; + } ); + + // add an observer on attrib manipulation. + m_geom.vertexAttribs().attachMember( this, &GeometryDisplayable::addAttribObserver ); + m_isDirty = true; +} + +void GeometryDisplayable::addToTranslationTable( const std::string& name ) { + auto it = m_translationTableMeshToShader.find( name ); + if ( it == m_translationTableMeshToShader.end() ) { + m_translationTableMeshToShader[name] = name; + m_translationTableShaderToMesh[name] = name; + } +} + +void GeometryDisplayable::addAttribObserver( const std::string& name ) { + // this observer is called each time an attrib is added or removed from m_mesh + auto attrib = m_geom.getAttribBase( name ); + // if attrib not nullptr, then it's an attrib add, so attach an observer to it + + if ( attrib ) { + auto itr = m_handleToBuffer.find( name ); + if ( itr == m_handleToBuffer.end() ) { + m_handleToBuffer[name] = m_dataDirty.size(); + + addToTranslationTable( name ); + + m_dataDirty.push_back( true ); + m_vbos.emplace_back( nullptr ); + } + auto idx = m_handleToBuffer[name]; + attrib->attach( AttribObserver( this, idx ) ); + } + // else it's an attrib remove, do nothing, cleanup will be done in updateGL() + else {} +} + +void GeometryDisplayable::setAttribNameCorrespondence( const std::string& meshAttribName, + const std::string& shaderAttribName ) { + + // clean previously set translation + + auto it1 = std::find_if( m_translationTableShaderToMesh.begin(), + m_translationTableShaderToMesh.end(), + [&meshAttribName]( const TranslationTable::value_type& p ) { + return p.second == meshAttribName; + } ); + + if ( it1 != m_translationTableShaderToMesh.end() ) m_translationTableShaderToMesh.erase( it1 ); + + auto it2 = std::find_if( m_translationTableMeshToShader.begin(), + m_translationTableMeshToShader.end(), + [&shaderAttribName]( const TranslationTable::value_type& p ) { + return p.second == shaderAttribName; + } ); + + if ( it2 != m_translationTableMeshToShader.end() ) m_translationTableMeshToShader.erase( it2 ); + + m_translationTableShaderToMesh[shaderAttribName] = meshAttribName; + m_translationTableMeshToShader[meshAttribName] = shaderAttribName; +} + +bool GeometryDisplayable::addRenderLayer( LayerKeyType key, base::MeshRenderMode renderMode ) { + if ( !m_geom.containsLayer( key ) ) return false; + auto it = m_geomLayers.find( key ); + if ( it != m_geomLayers.end() ) return false; + + m_activeLayerKey = key; + auto& l = m_geomLayers.insert( { m_activeLayerKey, LayerEntryType() } ).first->second; + + l.observerId = -1; + l.renderMode = renderMode; + + return true; +} + +bool GeometryDisplayable::removeRenderLayer( LayerKeyType key ) { + auto it = m_geomLayers.find( key ); + if ( it == m_geomLayers.end() ) return false; + + // the layer might have already been deleted + if ( m_geom.containsLayer( key ) ) { + auto& geomLayer = m_geom.getLayerWithLock( key ); + geomLayer.detach( it->second.observerId ); + m_geom.unlockLayer( key ); + } + it->second.vao.reset(); + m_geomLayers.erase( it ); + + return true; +} + +void GeometryDisplayable::updateGL() { + if ( m_isDirty ) { + + const auto& abstractLayer = m_geom.getLayerWithLock( m_activeLayerKey ); + using LayerType = Ra::Core::Geometry::TriangleIndexLayer; + const auto& triangleLayer = dynamic_cast( abstractLayer ); + // create vao + auto& l = m_geomLayers[m_activeLayerKey]; + if ( !l.vao ) { l.vao = globjects::VertexArray::create(); } + + auto& vbo = l.indices; + if ( !vbo.buffer ) { + vbo.buffer = globjects::Buffer::create(); + vbo.dirty = true; + vbo.numElements = triangleLayer.getSize() * triangleLayer.getNumberOfComponents(); + } + + // upload data to gpu + if ( vbo.dirty ) { + vbo.buffer->setData( static_cast( triangleLayer.getSize() * + sizeof( LayerType::IndexType ) ), + triangleLayer.collection().data(), + GL_STATIC_DRAW ); + vbo.dirty = false; + } + m_geom.unlockLayer( m_activeLayerKey ); + + l.vao->bind(); + l.vao->bindElementBuffer( vbo.buffer.get() ); + l.vao->unbind(); + GL_CHECK_ERROR; + + auto func = [this]( Ra::Core::Utils::AttribBase* b ) { + auto idx = m_handleToBuffer[b->getName()]; + + if ( m_dataDirty[idx] ) { + if ( !m_vbos[idx] ) { m_vbos[idx] = globjects::Buffer::create(); } + m_vbos[idx]->setData( b->getBufferSize(), b->dataPtr(), GL_DYNAMIC_DRAW ); + m_dataDirty[idx] = false; + } + }; + + m_geom.vertexAttribs().for_each_attrib( func ); + + // cleanup removed attrib + for ( auto buffer : m_handleToBuffer ) { + // do not remove name from handleToBuffer to keep index ... + // we could also update handleToBuffer, m_vbos, m_dataDirty + if ( !m_geom.hasAttrib( buffer.first ) && m_vbos[buffer.second] ) { + m_vbos[buffer.second].reset( nullptr ); + m_dataDirty[buffer.second] = false; + } + } + + GL_CHECK_ERROR; + m_isDirty = false; + } +} + +void GeometryDisplayable::render( const ShaderProgram* prog ) { + if ( m_geomLayers[m_activeLayerKey].vao ) { + m_geomLayers[m_activeLayerKey].vao->bind(); + autoVertexAttribPointer( prog ); + m_geomLayers[m_activeLayerKey].vao->drawElements( + static_cast( base::m_renderMode ), + GLsizei( m_geomLayers[m_activeLayerKey].indices.numElements ), + GL_UNSIGNED_INT, + nullptr ); + m_geomLayers[m_activeLayerKey].vao->unbind(); + GL_CHECK_ERROR; + } +} + +void GeometryDisplayable::autoVertexAttribPointer( const ShaderProgram* prog ) { + + auto glprog = prog->getProgramObject(); + gl::GLint attribCount = glprog->get( GL_ACTIVE_ATTRIBUTES ); + + for ( GLint idx = 0; idx < attribCount; ++idx ) { + const gl::GLsizei bufSize = 256; + gl::GLchar name[bufSize]; + gl::GLsizei length; + gl::GLint size; + gl::GLenum type; + glprog->getActiveAttrib( idx, bufSize, &length, &size, &type, name ); + auto loc = glprog->getAttributeLocation( name ); + + auto attribName = m_translationTableShaderToMesh[name]; + auto attrib = m_geom.getAttribBase( attribName ); + + if ( attrib && attrib->getSize() > 0 ) { + m_geomLayers[m_activeLayerKey].vao->enable( loc ); + auto binding = m_geomLayers[m_activeLayerKey].vao->binding( idx ); + + binding->setAttribute( loc ); + CORE_ASSERT( m_vbos[m_handleToBuffer[attribName]].get(), "vbo is nullptr" ); +#ifdef CORE_USE_DOUBLE + binding->setBuffer( m_vbos[m_handleToBuffer[attribName]].get(), + 0, + attrib->getNumberOfComponents() * sizeof( float ) ); +#else + + binding->setBuffer( + m_vbos[m_handleToBuffer[attribName]].get(), 0, attrib->getStride() ); +#endif + binding->setFormat( attrib->getNumberOfComponents(), GL_SCALAR ); + } + else { m_geomLayers[m_activeLayerKey].vao->disable( loc ); } + } + GL_CHECK_ERROR; +} Ra::Core::Utils::optional AttribArrayDisplayable::getVaoHandle() { if ( m_vao ) return m_vao->id(); diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 5f97b7ddc70..92487a95607 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -47,6 +47,8 @@ class RA_ENGINE_API Vao * with a specific render mode (e.g. GL_TRIANGLES or GL_LINES). * It maintains the attributes and keeps them in sync with the GPU. * \note Attribute names are used to automatic location binding when using shaders. + * + * \TODO Remove rendermode attribute */ class RA_ENGINE_API AttribArrayDisplayable : public Displayable { @@ -75,9 +77,11 @@ class RA_ENGINE_API AttribArrayDisplayable : public Displayable public: explicit AttribArrayDisplayable( const std::string& name, MeshRenderMode renderMode = RM_TRIANGLES ); + AttribArrayDisplayable( const AttribArrayDisplayable& rhs ) = delete; void operator=( const AttribArrayDisplayable& rhs ) = delete; + // no need to detach listener since TriangleMesh is owned by Mesh. ~AttribArrayDisplayable() {} using Displayable::getName; @@ -186,10 +190,11 @@ class RA_ENGINE_API VaoIndices void operator()() { m_displayable->m_indicesDirty = true; } private: - VaoIndices* m_displayable; + VaoIndices* m_displayable { nullptr }; }; protected: + // vbo std::unique_ptr m_indices { nullptr }; bool m_indicesDirty { true }; /// number of elements to draw (i.e number of indices to use) @@ -197,32 +202,6 @@ class RA_ENGINE_API VaoIndices size_t m_numElements { 0 }; }; -/// This class handles an attrib array displayable on gpu only, without core -/// geometry. Use only when you don't need to access the cpu geometry again, or -/// when you need to specify special indices. -template -class IndexedAttribArrayDisplayable : public AttribArrayDisplayable, public VaoIndices -{ - using IndexType = I; - using IndexContainerType = Ra::Core::AlignedStdVector; - - template - inline void addAttrib( const std::string& name, - const typename Ra::Core::Utils::Attrib::Container& data ); - template - inline void addAttrib( const std::string& name, - const typename Ra::Core ::Utils::Attrib::Container&& data ); - inline void updateGL() override; - - inline void render( const ShaderProgram* prog ) override; - - protected: - /// assume m_vao is bound. - inline void autoVertexAttribPointer( const ShaderProgram* prog ); - IndexContainerType m_cpu_indices; - AttribManager m_attribManager; -}; - /// Template class to manage the Displayable aspect of a Core Geomertry, such as TriangleMesh. template class CoreGeometryDisplayable : public AttribArrayDisplayable @@ -350,44 +329,127 @@ class IndexedGeometry : public CoreGeometryDisplayable, public VaoIndices }; /// An engine mesh owning a MultiIndexedCoreGeometry, with multiple indices layer. -/// \todo Work in progress. -template -class MultiIndexedGeometry : public CoreGeometryDisplayable +class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable { public: - using base = CoreGeometryDisplayable; - using CoreGeometryDisplayable::CoreGeometryDisplayable; - explicit MultiIndexedGeometry( - const std::string& name, - typename base::CoreGeometry&& geom, - typename base::MeshRenderMode renderMode = base::MeshRenderMode::RM_TRIANGLES ); + using base = AttribArrayDisplayable; + + using LayerSemanticCollection = + typename Core::Geometry::MultiIndexedGeometry::LayerSemanticCollection; + using LayerSemantic = typename Core::Geometry::MultiIndexedGeometry::LayerSemantic; + using LayerKeyType = typename Core::Geometry::MultiIndexedGeometry::LayerKeyType; + using LayerKeyHash = Core::Geometry::MultiIndexedGeometry::LayerKeyHash; + + explicit GeometryDisplayable( const std::string& name, + typename Core::Geometry::MultiIndexedGeometry&& geom ); + virtual ~GeometryDisplayable(); void render( const ShaderProgram* prog ) override; - void loadGeometry( T&& mesh ) override; + ///@{ + /** Returns the underlying CoreGeometry as an Core::Geometry::AbstractGeometry */ + inline const Core::Geometry::AbstractGeometry& getAbstractGeometry() const override { + return m_geom; + } + inline Core::Geometry::AbstractGeometry& getAbstractGeometry() override { return m_geom; } + ///@} + inline const Core::Geometry::AttribArrayGeometry& getAttribArrayGeometry() const override { + return m_geom; + } + inline Core::Geometry::AttribArrayGeometry& getAttribArrayGeometry() override { return m_geom; } + + inline Core::Geometry::MultiIndexedGeometry& getCoreGeometry() { return m_geom; } + inline const Core::Geometry::MultiIndexedGeometry& getCoreGeometry() const { return m_geom; } + + /// Bind meshAttribName to shaderAttribName. + /// meshAttribName is a vertex attrib added to the underlying CoreGeometry + /// shaderAttribName is the name of the input paramter of the shader. + /// By default the same name is used, but this mecanism allows to override + /// this behavior. + /// Only one shaderAttribName can be bound to a meshAttribName and the other + /// way round. + /// \param meshAttribName: name of the attribute on the CoreGeometry side + /// \param shaderAttribName: name of the input vertex attribute on the + /// shader side. + void setAttribNameCorrespondence( const std::string& meshAttribName, + const std::string& shaderAttribName ); + + void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh ); + inline void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, + LayerKeyType key, + base::MeshRenderMode renderMode ) { + loadGeometry( std::move( mesh ) ); + addRenderLayer( key, renderMode ); + } + + /// \param r is a collection of keys and renderMode, e.g. { {key1, RM_TRIANGLES}, {key2, + /// RM_LINES} } + template + inline void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, + const RangeOfLayerKeys& r ) { + loadGeometry( std::move( mesh ) ); + for ( const auto& k : r ) + addRenderLayer( k.first, k.second ); + } + bool addRenderLayer( LayerKeyType key, base::MeshRenderMode renderMode ); + bool removeRenderLayer( LayerKeyType key ); + // bool setRenderMode( LayerKeyType key, RenderMode ); + // RenderMode getRenderMode( LayerKeyType key ); + + /// Update (i.e. send to GPU) the buffers marked as dirty + void updateGL() override; protected: - void updateGL_specific_impl() override; + void setupCoreMeshObservers(); - using LayerSemanticCollection = Core::Utils::ObjectWithSemantic::SemanticNameCollection; - using LayerSemantic = Core::Utils::ObjectWithSemantic::SemanticName; - using LayerKeyType = std::pair; - - using EntryType = std::pair; - struct RA_CORE_API KeyHash { - std::size_t operator()( const LayerKeyType& k ) const { - // Mix semantic collection into a single identifier string - std::ostringstream stream; - std::copy( - k.first.begin(), k.first.end(), std::ostream_iterator( stream, "" ) ); - std::string result = stream.str(); - std::sort( result.begin(), result.end() ); - - // Combine with layer name hash - return std::hash {}( result ) ^ - ( std::hash {}( k.second ) << 1 ); - } + /// assume m_vao is bound. + void autoVertexAttribPointer( const ShaderProgram* prog ); + + /// m_mesh Observer method, called whenever an attrib is added or removed from + /// m_mesh. + /// it adds an observer to the new attrib. + void addAttribObserver( const std::string& name ); + + void addToTranslationTable( const std::string& name ); + + private: + Core::Geometry::MultiIndexedGeometry m_geom; + + // for vertex attribs, with dirty + struct VBOEntryType { + bool dirty { false }; + std::unique_ptr buffer { nullptr }; }; - std::unordered_map m_indices; + + // for indices, with dirty and num elements + struct IndicesVBO { + bool dirty { false }; + std::unique_ptr buffer { nullptr }; + size_t numElements { 0 }; + }; + + /// LayerKey with it's corresponding indices. + struct LayerEntryType { + int observerId { -1 }; + std::unique_ptr vao { nullptr }; + IndicesVBO indices; + base::MeshRenderMode renderMode { RM_TRIANGLES }; + + inline LayerEntryType() = default; + }; + + /// The collection of indices layer we can use for rendering + std::unordered_map m_geomLayers; + + /// "main" triangle layer + LayerKeyType m_activeLayerKey; + + using VBOCollection = std::vector; + /// Collection of VBOs for per-vertex attributes + VBOCollection m_attribVBOs; + + using TranslationTable = std::map; + TranslationTable m_translationTableMeshToShader; + TranslationTable m_translationTableShaderToMesh; }; /// LineMesh, own a Core::Geometry::LineMesh @@ -522,6 +584,12 @@ template <> struct getType { using Type = Ra::Engine::Data::PolyMesh; }; + +template <> +struct getType { + using Type = Ra::Engine::Data::GeometryDisplayable; +}; + } // namespace RenderMeshType /// create Mesh, PolyMesh Engine::Data::*Mesh * from GeometryData @@ -555,127 +623,6 @@ void VaoIndices::setIndicesDirty() { m_indicesDirty = true; } -///////////////// IndexedAttribArrayDisplayable /////////////////////// - -template -template -void IndexedAttribArrayDisplayable::addAttrib( - const std::string& name, - const typename Ra::Core::Utils::Attrib::Container& data ) { - auto handle = m_attribManager.addAttrib( name ); - m_attribManager.getAttrib( handle ).setData( data ); - m_handleToBuffer[name] = m_dataDirty.size(); - m_dataDirty.push_back( true ); - m_vbos.emplace_back( nullptr ); - m_isDirty = true; -} - -template -template -void IndexedAttribArrayDisplayable::addAttrib( - const std::string& name, - const typename Ra::Core ::Utils::Attrib::Container&& data ) { - auto handle = m_attribManager.addAttrib( name ); - m_attribManager.getAttrib( handle ).setData( std::move( data ) ); - m_handleToBuffer[name] = m_dataDirty.size(); - m_dataDirty.push_back( true ); - m_vbos.emplace_back( nullptr ); - m_isDirty = true; -} - -template -void IndexedAttribArrayDisplayable::updateGL() { - if ( m_isDirty ) { - // Check that our dirty bits are consistent. - ON_ASSERT( bool dirtyTest = false; for ( const auto& d - : m_dataDirty ) { dirtyTest = dirtyTest || d; } ); - CORE_ASSERT( dirtyTest == m_isDirty, "Dirty flags inconsistency" ); - - if ( !m_indices ) { - m_indices = globjects::Buffer::create(); - m_indicesDirty = true; - } - if ( m_indicesDirty ) { - m_indices->setData( - static_cast( m_cpu_indices.size() * sizeof( IndexType ) ), - m_cpu_indices.data(), - GL_STATIC_DRAW ); - m_indicesDirty = false; - } - - m_numElements = m_cpu_indices.size(); - - if ( !m_vao ) { m_vao = globjects::VertexArray::create(); } - m_vao->bind(); - m_vao->bindElementBuffer( m_indices.get() ); - m_vao->unbind(); - - auto func = [this]( Ra::Core::Utils::AttribBase* b ) { - auto idx = m_handleToBuffer[b->getName()]; - - if ( m_dataDirty[idx] ) { - if ( !m_vbos[idx] ) { m_vbos[idx] = globjects::Buffer::create(); } - m_vbos[idx]->setData( b->getBufferSize(), b->dataPtr(), GL_DYNAMIC_DRAW ); - m_dataDirty[idx] = false; - } - }; - m_attribManager.for_each_attrib( func ); - GL_CHECK_ERROR; - m_isDirty = false; - } -} - -template -void IndexedAttribArrayDisplayable::autoVertexAttribPointer( const ShaderProgram* prog ) { - - auto glprog = prog->getProgramObject(); - gl::GLint attribCount = glprog->get( GL_ACTIVE_ATTRIBUTES ); - - for ( GLint idx = 0; idx < attribCount; ++idx ) { - const gl::GLsizei bufSize = 256; - gl::GLchar name[bufSize]; - gl::GLsizei length; - gl::GLint size; - gl::GLenum type; - glprog->getActiveAttrib( idx, bufSize, &length, &size, &type, name ); - auto loc = glprog->getAttributeLocation( name ); - - auto attribName = name; // m_translationTableShaderToMesh[name]; - auto attrib = m_attribManager.getAttribBase( attribName ); - - if ( attrib && attrib->getSize() > 0 ) { - m_vao->enable( loc ); - auto binding = m_vao->binding( idx ); - binding->setAttribute( loc ); - CORE_ASSERT( m_vbos[m_handleToBuffer[attribName]].get(), "vbo is nullptr" ); -#ifdef CORE_USE_DOUBLE - binding->setBuffer( m_vbos[m_handleToBuffer[attribName]].get(), - 0, - attrib->getNumberOfComponents() * sizeof( float ) ); -#else - - binding->setBuffer( - m_vbos[m_handleToBuffer[attribName]].get(), 0, attrib->getStride() ); -#endif - binding->setFormat( attrib->getNumberOfComponents(), GL_SCALAR ); - } - else { m_vao->disable( loc ); } - } -} - -template -void IndexedAttribArrayDisplayable::render( const ShaderProgram* prog ) { - if ( m_vao ) { - autoVertexAttribPointer( prog ); - m_vao->bind(); - m_vao->drawElements( static_cast( m_renderMode ), - GLsizei( m_numElements ), - GL_UNSIGNED_INT, - nullptr ); - m_vao->unbind(); - } -} - //////////////// CoreGeometryDisplayable /////////////////////////////// template @@ -973,78 +920,6 @@ void IndexedGeometry::render( const ShaderProgram* prog ) { } } -//////////////// MultiIndexedGeometry /////////////////////////////// - -template -MultiIndexedGeometry::MultiIndexedGeometry( const std::string& name, - typename base::CoreGeometry&& geom, - typename base::MeshRenderMode renderMode ) : - base( name, renderMode ) { - loadGeometry( std::move( geom ) ); -} - -template -void MultiIndexedGeometry::loadGeometry( T&& mesh ) { - m_indices.clear(); - - base::loadGeometry_common( std::move( mesh ) ); - CORE_ASSERT( false, "not implemented yet" ); - - /// \todo HERE - // indices - // base::m_mesh.attach( IndicesObserver( this ) ); -} - -template -void MultiIndexedGeometry::updateGL_specific_impl() { - CORE_ASSERT( false, "not implemented yet" ); - // if ( !m_indices ) - // { - // m_indices = globjects::Buffer::create(); - // m_indicesDirty = true; - // } - // if ( m_indicesDirty ) - // { - // /// this one do not work since m_indices is not a std::vector - // // m_indices->setData( m_mesh.m_indices, GL_DYNAMIC_DRAW ); - // m_numElements = - // base::m_mesh.getIndices().size() * - // base::CoreGeometry::IndexType::RowsAtCompileTime; - // - // m_indices->setData( - // static_cast( base::m_mesh.getIndices().size() * - // sizeof( typename base::CoreGeometry::IndexType ) ), - // base::m_mesh.getIndices().data(), - // GL_STATIC_DRAW ); - // m_indicesDirty = false; - // } - // if ( !base::m_vao ) { base::m_vao = globjects::VertexArray::create(); } - // base::m_vao->bind(); - // base::m_vao->bindElementBuffer( m_indices.get() ); - // base::m_vao->unbind(); - /// \todo implement ! -} - -template -void MultiIndexedGeometry::render( const ShaderProgram* ) { - CORE_ASSERT( false, "not implemented yet" ); - // if ( base::m_vao ) - // { - // GL_CHECK_ERROR; - // base::m_vao->bind(); - // base::autoVertexAttribPointer( prog ); - // GL_CHECK_ERROR; - // base::m_vao->drawElements( static_cast( base::m_renderMode ), - // GLsizei( m_numElements ), - // GL_UNSIGNED_INT, - // nullptr ); - // GL_CHECK_ERROR; - // base::m_vao->unbind(); - // GL_CHECK_ERROR; - // } - /// \todo implement ! -} - ///////// PointCloud ////////// PointCloud::PointCloud( const std::string& name, From 6689dde0e39a764eacd59e143b9c723ca7e66765 Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 31 Mar 2022 22:09:58 +0200 Subject: [PATCH 03/28] [engine] add GeometryDisplayableComponent --- src/Engine/Scene/GeometryComponent.cpp | 12 ++++++++++++ src/Engine/Scene/GeometryComponent.hpp | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Engine/Scene/GeometryComponent.cpp b/src/Engine/Scene/GeometryComponent.cpp index c9056fed4dd..e05447a6535 100644 --- a/src/Engine/Scene/GeometryComponent.cpp +++ b/src/Engine/Scene/GeometryComponent.cpp @@ -29,6 +29,18 @@ namespace Ra { namespace Engine { namespace Scene { +template <> +SurfaceMeshComponent::SurfaceMeshComponent( + const std::string& name, + Entity* entity, + Ra::Core::Geometry::MultiIndexedGeometry&& mesh, + Core::Asset::MaterialData* mat ) : + GeometryComponent( name, entity ), + m_displayMesh( new Data::GeometryDisplayable( name, std::move( mesh ) ) ) { + setContentName( name ); + finalizeROFromGeometry( mat, Core::Transform::Identity() ); +} + void GeometryComponent::setupIO( const std::string& id ) { const auto& cm = ComponentMessenger::getInstance(); auto roOut = std::bind( &GeometryComponent::roIndexRead, this ); diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index 16fa5104e15..7e3c73952cf 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -107,10 +107,11 @@ class SurfaceMeshComponent : public GeometryComponent std::shared_ptr m_displayMesh { nullptr }; }; -using TriangleMeshComponent = SurfaceMeshComponent; -using LineMeshComponent = SurfaceMeshComponent; -using QuadMeshComponent = SurfaceMeshComponent; -using PolyMeshComponent = SurfaceMeshComponent; +using TriangleMeshComponent = SurfaceMeshComponent; +using GeometryDisplayableComponent = SurfaceMeshComponent; +using LineMeshComponent = SurfaceMeshComponent; +using QuadMeshComponent = SurfaceMeshComponent; +using PolyMeshComponent = SurfaceMeshComponent; /// \warning, WIP /// \todo doc. @@ -217,6 +218,13 @@ SurfaceMeshComponent::SurfaceMeshComponent( generateMesh( data ); } +template <> +SurfaceMeshComponent::SurfaceMeshComponent( + const std::string& name, + Entity* entity, + Ra::Core::Geometry::MultiIndexedGeometry&& mesh, + Core::Asset::MaterialData* mat ); + template SurfaceMeshComponent::SurfaceMeshComponent( const std::string& name, Entity* entity, From 1a867231d6a11bf58f72e7037c23fbf27663c30c Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 31 Mar 2022 22:11:41 +0200 Subject: [PATCH 04/28] [tests] Use GeometryDisplayableComponent in HelloRadium (nothing drawn yet). --- examples/HelloRadium/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/HelloRadium/main.cpp b/examples/HelloRadium/main.cpp index 8c149f2a9b3..9a05c2d3879 100644 --- a/examples/HelloRadium/main.cpp +++ b/examples/HelloRadium/main.cpp @@ -41,8 +41,8 @@ int main( int argc, char* argv[] ) { //! [Create the engine entity for the cube] //! [Create a geometry component with the cube] - auto c = - new Ra::Engine::Scene::TriangleMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); + auto c = new Ra::Engine::Scene::GeometryDisplayableComponent( + "Cube Mesh", e, std::move( cube ), nullptr ); //! [Create a geometry component with the cube] //! [Register the entity/component association to the geometry system ] From ec4057a485d4a763b9720bd1ca536360189a5545 Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 20 Jul 2022 08:00:00 +0200 Subject: [PATCH 05/28] [core] Switch struct -> class for AbstractGeometry. --- src/Core/Geometry/AbstractGeometry.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Core/Geometry/AbstractGeometry.hpp b/src/Core/Geometry/AbstractGeometry.hpp index 6191e7a7f4d..df324a71249 100644 --- a/src/Core/Geometry/AbstractGeometry.hpp +++ b/src/Core/Geometry/AbstractGeometry.hpp @@ -13,8 +13,9 @@ namespace Geometry { /// \warning: Part of the current proposal for a modular implementation of /// displayable objects. /// -/// \note We use a struct because all members are public anyway -struct RA_CORE_API AbstractGeometry { +class RA_CORE_API AbstractGeometry +{ + public: /* * Note: Explicitly defaulted virtual destructor, copy/move constructors, * copy/move assignment operators From d020cea65d1e6d156e38d4ff6f41ca1cafc47187 Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 20 Jul 2022 15:47:20 +0200 Subject: [PATCH 06/28] [core] Use macro for clone implementation. debug type clone make clone everywhere --- examples/HelloRadium/main.cpp | 4 +- src/Core/Geometry/IndexedGeometry.cpp | 35 +++++-- src/Core/Geometry/IndexedGeometry.hpp | 21 +++- src/Core/Geometry/MeshPrimitives.cpp | 145 ++++++++++++++++++++++++++ src/Core/Geometry/MeshPrimitives.hpp | 13 +++ src/Engine/Data/Mesh.cpp | 29 +++++- 6 files changed, 235 insertions(+), 12 deletions(-) diff --git a/examples/HelloRadium/main.cpp b/examples/HelloRadium/main.cpp index 9a05c2d3879..e3b8aa77200 100644 --- a/examples/HelloRadium/main.cpp +++ b/examples/HelloRadium/main.cpp @@ -27,7 +27,9 @@ int main( int argc, char* argv[] ) { //! [Verifying the OpenGL version available to the engine] //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); + std::cerr << "CREATE CUBE\n"; + auto cube { std::move( Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ) ) }; + std::cerr << "DONE CUBE\n"; //! [Creating the cube] //! [Colorize the Cube] diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index b8e7a5cb5f1..d54f40de383 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -1,25 +1,37 @@ #include #include +#include + namespace Ra { namespace Core { namespace Geometry { MultiIndexedGeometry::MultiIndexedGeometry( const MultiIndexedGeometry& other ) : AttribArrayGeometry( other ) { + std::cerr << "MultiIndexedGeometry & other\n"; deepCopy( other ); } MultiIndexedGeometry::MultiIndexedGeometry( MultiIndexedGeometry&& other ) : - AttribArrayGeometry( std::move( other ) ), m_indices( std::move( other.m_indices ) ) {} + AttribArrayGeometry( std::move( other ) ), m_indices( std::move( other.m_indices ) ) { + + std::cerr << "MultiIndexedGeometry && other\n"; +} MultiIndexedGeometry::MultiIndexedGeometry( const AttribArrayGeometry& other ) : - AttribArrayGeometry( other ) {} + AttribArrayGeometry( other ) { + std::cerr << "MultiIndexedGeometry & other\n"; +} MultiIndexedGeometry::MultiIndexedGeometry( AttribArrayGeometry&& other ) : - AttribArrayGeometry( std::move( other ) ) {} + AttribArrayGeometry( std::move( other ) ) { + std::cerr << "MultiIndexedGeometry Atrib && other\n"; +} MultiIndexedGeometry& MultiIndexedGeometry::operator=( const MultiIndexedGeometry& other ) { + std::cerr << "MultiIndexedGeometry = & other\n"; + invalidateAabb(); AttribArrayGeometry::operator=( other ); deepCopy( other ); @@ -28,6 +40,8 @@ MultiIndexedGeometry& MultiIndexedGeometry::operator=( const MultiIndexedGeometr } MultiIndexedGeometry& MultiIndexedGeometry::operator=( MultiIndexedGeometry&& other ) { + std::cerr << "MultiIndexedGeometry = && other\n"; + invalidateAabb(); AttribArrayGeometry::operator=( std::move( other ) ); m_indices = std::move( other.m_indices ); @@ -125,8 +139,12 @@ size_t MultiIndexedGeometry::countLayers( const LayerSemanticCollection& semanti std::pair MultiIndexedGeometry::getFirstLayerOccurrence( const LayerSemantic& semanticName ) const { for ( const auto& [key, value] : m_indices ) { - if ( key.first.find( semanticName ) != key.first.end() ) + if ( key.first.find( semanticName ) != key.first.end() ) { + + auto& tmp = *( value.second.get() ); + std::cerr << "get typeinfo " << typeid( tmp ).name() << "\n"; return { key, *( value.second.get() ) }; + } } throw std::out_of_range( "Layer entry not found" ); } @@ -214,6 +232,9 @@ std::pair MultiIndexedGeometry::addLayer( std::unique_ptr&& layer, const bool withLock, const std::string& layerName ) { + + auto& tmp1 = *( layer.get() ); + std::cerr << "add layer typeinfo " << typeid( tmp1 ).name() << "\n"; LayerKeyType key { layer->semantics(), layerName }; auto elt = std::make_pair( key, std::make_pair( false, std::move( layer ) ) ); auto [pos, inserted] = m_indices.insert( std::move( elt ) ); @@ -223,8 +244,10 @@ MultiIndexedGeometry::addLayer( std::unique_ptr&& layer, CORE_ASSERT( !pos->second.first, "try to get already locked layer" ); pos->second.first = true; } - /// If not inserted, the pointer is deleted. So the caller must ensure this possible deletion - /// is safe before calling this method. + /// If not inserted, the pointer is deleted. So the caller must ensure this possible + /// deletion is safe before calling this method. + auto& tmp = *( pos->second.second.get() ); + std::cerr << "add layer inserted typeinfo " << typeid( tmp ).name() << "\n"; return { inserted, *( pos->second.second ) }; } diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index c8f75726e34..078e3ce90a4 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -63,7 +63,7 @@ struct GeometryIndexLayer : public GeometryIndexLayerBase { inline size_t getSize() const override final; - inline std::unique_ptr clone() override final; + inline std::unique_ptr clone() override; inline size_t getNumberOfComponents() const override final; @@ -383,6 +383,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \brief Clear attributes stored as pointers void deepClear(); + /// bool -> locked, ptr -> actual data using LayerEntryType = std::pair>; public: @@ -400,14 +401,25 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util std::unordered_map m_indices; }; +#define INDEX_LAYER_CLONE_IMPLEMENTATION( TYPE ) \ + inline std::unique_ptr clone() override { \ + auto copy = std::make_unique( *this ); \ + copy->collection() = collection(); \ + return copy; \ + } + /// \name Predefined index layers /// The use of these layers helps in generic management of geometries /// \{ /// \brief Index layer for a point cloud struct RA_CORE_API PointCloudIndexLayer : public GeometryIndexLayer { + using base = GeometryIndexLayer; /// \brief Constructor of an empty layer inline PointCloudIndexLayer(); + inline PointCloudIndexLayer( const PointCloudIndexLayer& other ) = default; + inline PointCloudIndexLayer& operator=( const PointCloudIndexLayer& other ) = default; + inline PointCloudIndexLayer& operator=( PointCloudIndexLayer&& other ) = default; /// \brief Constructor of an index layer with linearly spaced indices ranging from \f$0\f$ to /// \f$n-1\f$ @@ -417,6 +429,7 @@ struct RA_CORE_API PointCloudIndexLayer : public GeometryIndexLayer { void linearIndices( const AttribArrayGeometry& attr ); static constexpr const char* staticSemanticName = "PointCloud"; + INDEX_LAYER_CLONE_IMPLEMENTATION( PointCloudIndexLayer ) protected: template @@ -428,6 +441,7 @@ struct RA_CORE_API PointCloudIndexLayer : public GeometryIndexLayer { struct RA_CORE_API TriangleIndexLayer : public GeometryIndexLayer { inline TriangleIndexLayer(); static constexpr const char* staticSemanticName = "TriangleMesh"; + INDEX_LAYER_CLONE_IMPLEMENTATION( TriangleIndexLayer ) protected: template @@ -439,6 +453,7 @@ struct RA_CORE_API TriangleIndexLayer : public GeometryIndexLayer { struct RA_CORE_API QuadIndexLayer : public GeometryIndexLayer { inline QuadIndexLayer(); static constexpr const char* staticSemanticName = "QuadMesh"; + INDEX_LAYER_CLONE_IMPLEMENTATION( QuadIndexLayer ) protected: template @@ -451,6 +466,7 @@ struct RA_CORE_API QuadIndexLayer : public GeometryIndexLayer { struct RA_CORE_API PolyIndexLayer : public GeometryIndexLayer { inline PolyIndexLayer(); static constexpr const char* staticSemanticName = "PolyMesh"; + INDEX_LAYER_CLONE_IMPLEMENTATION( PolyIndexLayer ) protected: template @@ -462,6 +478,7 @@ struct RA_CORE_API PolyIndexLayer : public GeometryIndexLayer { struct RA_CORE_API LineIndexLayer : public GeometryIndexLayer { inline LineIndexLayer(); static constexpr const char* staticSemanticName = "LineMesh"; + INDEX_LAYER_CLONE_IMPLEMENTATION( LineIndexLayer ) protected: template @@ -470,6 +487,8 @@ struct RA_CORE_API LineIndexLayer : public GeometryIndexLayer { /// \} +#undef INDEX_LAYER_CLONE_IMPLEMENTATION + /// Temporary class providing the old API for TriangleMesh, LineMesh and PolyMesh /// This class will be marked as deprecated soon. namespace IndexLayerType { diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index 04dbe9eb249..c57b9968cab 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -1,3 +1,4 @@ +#include "Core/Geometry/IndexedGeometry.hpp" #include #include #include @@ -7,6 +8,8 @@ #include #include +#include + namespace Ra { namespace Core { namespace Geometry { @@ -90,6 +93,148 @@ TriangleMesh makeSharpBox( const Vector3& halfExts, return makeSharpBox( aabb, color, generateTexCoord ); } +MultiIndexedGeometry makeSharpBox2( const Aabb& aabb, + const Utils::optional& color, + bool generateTexCoord ) { + MultiIndexedGeometry result; + result.setVertices( { // Floor Face + aabb.corner( Aabb::BottomLeftFloor ), + aabb.corner( Aabb::TopLeftFloor ), + aabb.corner( Aabb::TopRightFloor ), + aabb.corner( Aabb::BottomRightFloor ), + + // Ceil Face + aabb.corner( Aabb::BottomLeftCeil ), + aabb.corner( Aabb::BottomRightCeil ), + aabb.corner( Aabb::TopRightCeil ), + aabb.corner( Aabb::TopLeftCeil ), + + // Left Face + aabb.corner( Aabb::TopLeftFloor ), + aabb.corner( Aabb::BottomLeftFloor ), + aabb.corner( Aabb::BottomLeftCeil ), + aabb.corner( Aabb::TopLeftCeil ), + + // Right Face + aabb.corner( Aabb::BottomRightFloor ), + aabb.corner( Aabb::TopRightFloor ), + aabb.corner( Aabb::TopRightCeil ), + aabb.corner( Aabb::BottomRightCeil ), + + // Bottom Face + aabb.corner( Aabb::BottomLeftFloor ), + aabb.corner( Aabb::BottomRightFloor ), + aabb.corner( Aabb::BottomRightCeil ), + aabb.corner( Aabb::BottomLeftCeil ), + + // Top face + aabb.corner( Aabb::TopLeftFloor ), + aabb.corner( Aabb::TopLeftCeil ), + aabb.corner( Aabb::TopRightCeil ), + aabb.corner( Aabb::TopRightFloor ) } ); + + result.setNormals( { // Floor face + Vector3( 0, 0, -1 ), + Vector3( 0, 0, -1 ), + Vector3( 0, 0, -1 ), + Vector3( 0, 0, -1 ), + // Ceil Face + Vector3( 0, 0, +1 ), + Vector3( 0, 0, +1 ), + Vector3( 0, 0, +1 ), + Vector3( 0, 0, +1 ), + // Left Face + Vector3( -1, 0, 0 ), + Vector3( -1, 0, 0 ), + Vector3( -1, 0, 0 ), + Vector3( -1, 0, 0 ), + // Right Face + Vector3( +1, 0, 0 ), + Vector3( +1, 0, 0 ), + Vector3( +1, 0, 0 ), + Vector3( +1, 0, 0 ), + // Bottom Face + Vector3( 0, -1, 0 ), + Vector3( 0, -1, 0 ), + Vector3( 0, -1, 0 ), + Vector3( 0, -1, 0 ), + // Top Face + Vector3( 0, +1, 0 ), + Vector3( 0, +1, 0 ), + Vector3( 0, +1, 0 ), + Vector3( 0, +1, 0 ) } ); + + if ( generateTexCoord ) { + Vector3Array texCoords { + // Floor face + Vector3( 0, 0, 0 ), + Vector3( 1, 0, 0 ), + Vector3( 1, 1, 0 ), + Vector3( 0, 1, 0 ), + // Ceil Face + Vector3( 0, 0, 0 ), + Vector3( 1, 0, 0 ), + Vector3( 1, 1, 0 ), + Vector3( 0, 1, 0 ), + // Left Face + Vector3( 0, 0, 0 ), + Vector3( 1, 0, 0 ), + Vector3( 1, 1, 0 ), + Vector3( 0, 1, 0 ), + // Right Face + Vector3( 0, 0, 0 ), + Vector3( 1, 0, 0 ), + Vector3( 1, 1, 0 ), + Vector3( 0, 1, 0 ), + // Bottom Face + Vector3( 0, 0, 0 ), + Vector3( 1, 0, 0 ), + Vector3( 1, 1, 0 ), + Vector3( 0, 1, 0 ), + // Top Face + Vector3( 0, 0, 0 ), + Vector3( 1, 0, 0 ), + Vector3( 1, 1, 0 ), + Vector3( 0, 1, 0 ), + }; + + result.addAttrib( "in_texcoord", std::move( texCoords ) ); + } + + auto layer = std::make_unique(); + + layer->collection() = { + Vector4ui( 0, 1, 2, 3 ), // Floor + Vector4ui( 4, 5, 6, 7 ), // Ceil + Vector4ui( 8, 9, 10, 11 ), // Left + Vector4ui( 12, 13, 14, 15 ), // Right + Vector4ui( 16, 17, 18, 19 ), // Bottom + Vector4ui( 20, 21, 22, 23 ) // Top + }; + auto semantic = layer->semantics(); + + std::for_each( layer->semantics().cbegin(), + layer->semantics().cend(), + []( const std::string& x ) { std::cerr << x << '\n'; } ); + + result.addLayer( std::move( layer ) ); + auto test = result.getFirstLayerOccurrence( semantic ); + auto& tmp = test.second; + std::cerr << "make typeinfo " << typeid( tmp ).name() << "\n"; + if ( bool( color ) ) result.colorize( *color ); + result.checkConsistency(); + std::cerr << "return make sharp box aabb \n"; + return MultiIndexedGeometry { std::move( result ) }; +} + +MultiIndexedGeometry makeSharpBox2( const Vector3& halfExts, + const Utils::optional& color, + bool generateTexCoord ) { + Aabb aabb( -halfExts, halfExts ); + std::cerr << "return make sharp box half \n"; + return makeSharpBox2( aabb, color, generateTexCoord ); +} + TriangleMesh makeSharpBox( const Aabb& aabb, const Utils::optional& color, bool generateTexCoord ) { diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index c585f9aee57..9d598bd211a 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -67,6 +68,18 @@ RA_CORE_API TriangleMesh makeSharpBox( const Aabb& aabb, const Utils::optional& color = {}, bool generateTexCoord = false ); +/// Create an axis-aligned cubic mesh with the given half extents, centered on the origin. +RA_CORE_API MultiIndexedGeometry makeSharpBox2( const Vector3& halfExts = Vector3( .5_ra, + .5_ra, + .5_ra ), + const Utils::optional& color = {}, + bool generateTexCoord = false ); + +/// Create an axis-aligned cubic mesh +RA_CORE_API MultiIndexedGeometry makeSharpBox2( const Aabb& aabb, + const Utils::optional& color = {}, + bool generateTexCoord = false ); + /// Create a parametric spherical mesh of given radius. Template parameters set the resolution. /// \param generateTexCoord: maps parametric (u,v) to texture corrdinates [0,1]^2 template diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index 1e0080b6974..5b09786e77c 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -11,6 +11,8 @@ #include #include +#include + namespace Ra { namespace Engine { namespace Data { @@ -207,27 +209,46 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m addRenderLayer( key, AttribArrayDisplayable::RM_TRIANGLES ); } else if ( m_geom.containsLayer( Core::Geometry::QuadIndexLayer::staticSemanticName ) ) { + std::cerr << "get quad layer\n"; auto [key, layer] = m_geom.getFirstLayerOccurrence( Core::Geometry::QuadIndexLayer::staticSemanticName ); - const auto& quadLayer = - dynamic_cast( m_geom.getLayer( key ) ); + std::cerr << "cast quad layer\n"; + std::for_each( layer.semantics().cbegin(), + layer.semantics().cend(), + []( const std::string& x ) { std::cerr << x << '\n'; } ); + + std::cerr << layer.getSize() << " " << layer.getNumberOfComponents() << " " + << layer.getBufferSize() << "\n"; + + std::cerr << "type info " << typeid( layer ).name() << "\n"; + std::cerr << "type info " << typeid( const Core::Geometry::QuadIndexLayer& ).name() << "\n"; + + const auto& quadLayer = dynamic_cast( layer ); + std::cerr << "cast done\n"; auto triangleLayer = std::make_unique(); + std::cerr << "triangulate layer\n"; triangulate( *triangleLayer, quadLayer ); + std::cerr << "add triangle layer\n"; + + LayerKeyType triangleKey = { triangleLayer->semantics(), "triangulation" }; auto layerAdded = m_geom.addLayer( std::move( triangleLayer ), false, "triangulation" ); + std::cerr << "add triangle layer done\n"; + if ( !layerAdded.first ) { LOG( logERROR ) << "failed to add triangleLayer"; } else { - LayerKeyType triangleKey = { triangleLayer->semantics(), "triangulation" }; addRenderLayer( triangleKey, AttribArrayDisplayable::RM_TRIANGLES ); + std::cerr << "triangulate done\n"; } + std::cerr << "yo\n"; } else if ( m_geom.containsLayer( Core::Geometry::PolyIndexLayer::staticSemanticName ) ) { auto [key, layer] = m_geom.getFirstLayerOccurrence( Core::Geometry::PolyIndexLayer::staticSemanticName ); const auto& polyLayer = - dynamic_cast( m_geom.getLayer( key ) ); + dynamic_cast( m_geom.getLayer( key ) ); auto triangleLayer = std::make_unique(); triangulate( *triangleLayer, polyLayer ); From 7ed84687ebcc9e28ad4de718933b2ab0b8b73299 Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 20 Jul 2022 17:35:33 +0200 Subject: [PATCH 07/28] [engine] double wireframe (ad hoc for quad mesh). clean code with using forward renderer handle poly and quad layers. --- Shaders/Lines/Wireframe.geom.glsl | 2 +- src/Engine/Data/Mesh.cpp | 99 +++++++++-------- src/Engine/Data/Mesh.hpp | 8 +- src/Engine/Rendering/ForwardRenderer.cpp | 133 ++++++++++++++++++++++- 4 files changed, 194 insertions(+), 48 deletions(-) diff --git a/Shaders/Lines/Wireframe.geom.glsl b/Shaders/Lines/Wireframe.geom.glsl index 3933f78bcdf..2698dc8aa21 100644 --- a/Shaders/Lines/Wireframe.geom.glsl +++ b/Shaders/Lines/Wireframe.geom.glsl @@ -20,6 +20,7 @@ in vec4 vPosition[2]; out vec4 gColor; out float pixelWidthDiv2; uniform vec2 viewport; +uniform float pixelWidth; vec4 vColor[2]; void main() { @@ -34,7 +35,6 @@ void main() { vec4 scss1 = css1 * css0.w; vec3 dir = ( scss1 - scss0 ).xyz; - float pixelWidth = 1.8; const float border = 4.; vec3 slope = normalize( vec3( -dir.y, dir.x, 0 ) ); vec4 n = vec4( vec3( pixelWidth + border ) / vp * slope, 0 ); diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index 5b09786e77c..359a3b561d2 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -206,6 +206,7 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m if ( m_geom.containsLayer( Core::Geometry::TriangleIndexLayer::staticSemanticName ) ) { auto [key, layer] = m_geom.getFirstLayerOccurrence( Core::Geometry::TriangleIndexLayer::staticSemanticName ); + m_activeLayerKey = key; addRenderLayer( key, AttribArrayDisplayable::RM_TRIANGLES ); } else if ( m_geom.containsLayer( Core::Geometry::QuadIndexLayer::staticSemanticName ) ) { @@ -238,6 +239,7 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m if ( !layerAdded.first ) { LOG( logERROR ) << "failed to add triangleLayer"; } else { + m_activeLayerKey = triangleKey; addRenderLayer( triangleKey, AttribArrayDisplayable::RM_TRIANGLES ); std::cerr << "triangulate done\n"; } @@ -252,10 +254,11 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m auto triangleLayer = std::make_unique(); triangulate( *triangleLayer, polyLayer ); + LayerKeyType triangleKey = { triangleLayer->semantics(), "triangulation" }; auto layerAdded = m_geom.addLayer( std::move( triangleLayer ), false, "triangulation" ); if ( !layerAdded.first ) { LOG( logERROR ) << "failed to add triangleLayer"; } else { - LayerKeyType triangleKey = { triangleLayer->semantics(), "triangulation" }; + m_activeLayerKey = triangleKey; addRenderLayer( triangleKey, AttribArrayDisplayable::RM_TRIANGLES ); } } @@ -344,12 +347,13 @@ bool GeometryDisplayable::addRenderLayer( LayerKeyType key, base::MeshRenderMode auto it = m_geomLayers.find( key ); if ( it != m_geomLayers.end() ) return false; - m_activeLayerKey = key; - auto& l = m_geomLayers.insert( { m_activeLayerKey, LayerEntryType() } ).first->second; + auto& l = m_geomLayers.insert( { key, LayerEntryType() } ).first->second; - l.observerId = -1; - l.renderMode = renderMode; + l.observerId = -1; + l.renderMode = renderMode; + l.indices.dirty = true; + setDirty( true ); return true; } @@ -372,34 +376,33 @@ bool GeometryDisplayable::removeRenderLayer( LayerKeyType key ) { void GeometryDisplayable::updateGL() { if ( m_isDirty ) { - const auto& abstractLayer = m_geom.getLayerWithLock( m_activeLayerKey ); - using LayerType = Ra::Core::Geometry::TriangleIndexLayer; - const auto& triangleLayer = dynamic_cast( abstractLayer ); // create vao - auto& l = m_geomLayers[m_activeLayerKey]; - if ( !l.vao ) { l.vao = globjects::VertexArray::create(); } - - auto& vbo = l.indices; - if ( !vbo.buffer ) { - vbo.buffer = globjects::Buffer::create(); - vbo.dirty = true; - vbo.numElements = triangleLayer.getSize() * triangleLayer.getNumberOfComponents(); - } + for ( auto& itr : m_geomLayers ) { + const auto& abstractLayer = m_geom.getLayerWithLock( itr.first ); + auto& l = itr.second; - // upload data to gpu - if ( vbo.dirty ) { - vbo.buffer->setData( static_cast( triangleLayer.getSize() * - sizeof( LayerType::IndexType ) ), - triangleLayer.collection().data(), - GL_STATIC_DRAW ); - vbo.dirty = false; - } - m_geom.unlockLayer( m_activeLayerKey ); + if ( !l.vao ) { l.vao = globjects::VertexArray::create(); } - l.vao->bind(); - l.vao->bindElementBuffer( vbo.buffer.get() ); - l.vao->unbind(); - GL_CHECK_ERROR; + auto& vbo = l.indices; + if ( !vbo.buffer ) { + vbo.buffer = globjects::Buffer::create(); + vbo.dirty = true; + vbo.numElements = abstractLayer.getSize() * abstractLayer.getNumberOfComponents(); + } + + // upload data to gpu + if ( vbo.dirty ) { + vbo.buffer->setData( static_cast( abstractLayer.getBufferSize() ), + abstractLayer.dataPtr(), + GL_STATIC_DRAW ); + vbo.dirty = false; + } + m_geom.unlockLayer( itr.first ); + l.vao->bind(); + l.vao->bindElementBuffer( vbo.buffer.get() ); + l.vao->unbind(); + GL_CHECK_ERROR; + } auto func = [this]( Ra::Core::Utils::AttribBase* b ) { auto idx = m_handleToBuffer[b->getName()]; @@ -429,20 +432,30 @@ void GeometryDisplayable::updateGL() { } void GeometryDisplayable::render( const ShaderProgram* prog ) { - if ( m_geomLayers[m_activeLayerKey].vao ) { - m_geomLayers[m_activeLayerKey].vao->bind(); - autoVertexAttribPointer( prog ); - m_geomLayers[m_activeLayerKey].vao->drawElements( - static_cast( base::m_renderMode ), - GLsizei( m_geomLayers[m_activeLayerKey].indices.numElements ), - GL_UNSIGNED_INT, - nullptr ); - m_geomLayers[m_activeLayerKey].vao->unbind(); + render( prog, m_activeLayerKey ); +} + +void GeometryDisplayable::render( const ShaderProgram* prog, const LayerKeyType& key ) { + GL_CHECK_ERROR; + if ( m_geomLayers[key].vao ) { + m_geomLayers[key].vao->bind(); + GL_CHECK_ERROR; + autoVertexAttribPointer( prog, key ); + GL_CHECK_ERROR; + + m_geomLayers[key].vao->drawElements( static_cast( m_geomLayers[key].renderMode ), + GLsizei( m_geomLayers[key].indices.numElements ), + GL_UNSIGNED_INT, + nullptr ); + GL_CHECK_ERROR; + m_geomLayers[key].vao->unbind(); GL_CHECK_ERROR; } + else { LOG( logERROR ) << "try to draw an invalid layer\n"; } } -void GeometryDisplayable::autoVertexAttribPointer( const ShaderProgram* prog ) { +void GeometryDisplayable::autoVertexAttribPointer( const ShaderProgram* prog, + const LayerKeyType& key ) { auto glprog = prog->getProgramObject(); gl::GLint attribCount = glprog->get( GL_ACTIVE_ATTRIBUTES ); @@ -460,8 +473,8 @@ void GeometryDisplayable::autoVertexAttribPointer( const ShaderProgram* prog ) { auto attrib = m_geom.getAttribBase( attribName ); if ( attrib && attrib->getSize() > 0 ) { - m_geomLayers[m_activeLayerKey].vao->enable( loc ); - auto binding = m_geomLayers[m_activeLayerKey].vao->binding( idx ); + m_geomLayers[key].vao->enable( loc ); + auto binding = m_geomLayers[key].vao->binding( idx ); binding->setAttribute( loc ); CORE_ASSERT( m_vbos[m_handleToBuffer[attribName]].get(), "vbo is nullptr" ); @@ -476,7 +489,7 @@ void GeometryDisplayable::autoVertexAttribPointer( const ShaderProgram* prog ) { #endif binding->setFormat( attrib->getNumberOfComponents(), GL_SCALAR ); } - else { m_geomLayers[m_activeLayerKey].vao->disable( loc ); } + else { m_geomLayers[key].vao->disable( loc ); } } GL_CHECK_ERROR; } diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 92487a95607..fd62da57027 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -344,6 +344,7 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable typename Core::Geometry::MultiIndexedGeometry&& geom ); virtual ~GeometryDisplayable(); void render( const ShaderProgram* prog ) override; + void render( const ShaderProgram* prog, const LayerKeyType& key ); ///@{ /** Returns the underlying CoreGeometry as an Core::Geometry::AbstractGeometry */ @@ -402,7 +403,7 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable void setupCoreMeshObservers(); /// assume m_vao is bound. - void autoVertexAttribPointer( const ShaderProgram* prog ); + void autoVertexAttribPointer( const ShaderProgram* prog, const LayerKeyType& key ); /// m_mesh Observer method, called whenever an attrib is added or removed from /// m_mesh. @@ -443,9 +444,10 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable /// "main" triangle layer LayerKeyType m_activeLayerKey; - using VBOCollection = std::vector; + /// \todo use this in place of m_vbos + // using VBOCollection = std::vector; /// Collection of VBOs for per-vertex attributes - VBOCollection m_attribVBOs; + // VBOCollection m_attribVBOs; using TranslationTable = std::map; TranslationTable m_translationTableMeshToShader; diff --git a/src/Engine/Rendering/ForwardRenderer.cpp b/src/Engine/Rendering/ForwardRenderer.cpp index 3facaf7cec2..55bd9fdae1f 100644 --- a/src/Engine/Rendering/ForwardRenderer.cpp +++ b/src/Engine/Rendering/ForwardRenderer.cpp @@ -1,3 +1,6 @@ +#include +#include +#include #include #include #include @@ -202,6 +205,29 @@ void computeIndices( Core::Geometry::LineMesh::IndexContainerType& indices, indices.erase( std::unique( indices.begin(), indices.end() ), indices.end() ); } +template +void computeIndices2( Core::Geometry::LineIndexLayer::IndexContainerType& indices, + const IndexContainerType& other ) { + + for ( const auto& index : other ) { + auto s = index.size(); + for ( unsigned int i = 0; i < s; ++i ) { + int i1 = index[i]; + int i2 = index[( i + 1 ) % s]; + if ( i1 > i2 ) std::swap( i1, i2 ); + indices.emplace_back( i1, i2 ); + } + } + + std::sort( indices.begin(), + indices.end(), + []( const Core::Geometry::LineMesh::IndexType& a, + const Core::Geometry::LineMesh::IndexType& b ) { + return a[0] < b[0] || ( a[0] == b[0] && a[1] < b[1] ); + } ); + indices.erase( std::unique( indices.begin(), indices.end() ), indices.end() ); +} + // store LineMesh and Core, define the observer functor to update data one core update for wireframe // linemesh template @@ -256,6 +282,32 @@ void setupLineMesh( std::shared_ptr& disp, CoreGeometry& core ) else { disp.reset(); } } +// create a linemesh to draw wireframe given a core mesh +template +void setupLineMesh( Data::GeometryDisplayable& displayable, const std::string& name ) { + + std::cerr << "setup line mesh\n"; + auto lineLayer = std::make_unique(); + auto& indices = lineLayer->collection(); + auto& coreGeometry = displayable.getCoreGeometry(); + + if ( coreGeometry.containsLayer( IndexLayer::staticSemanticName ) ) { + auto layerOccurence = + coreGeometry.getFirstLayerOccurrence( IndexLayer::staticSemanticName ); + auto& layer = dynamic_cast( layerOccurence.second ); + computeIndices2( indices, layer.collection() ); + + if ( indices.size() > 0 ) { + + Geometry::MultiIndexedGeometry::LayerKeyType lineKey = { + { Core::Geometry::LineIndexLayer::staticSemanticName }, name }; + auto layerAdded = coreGeometry.addLayer( std::move( lineLayer ), false, name ); + if ( !layerAdded.first ) { LOG( logERROR ) << "failed to add wireframe"; } + else { displayable.addRenderLayer( lineKey, Data::AttribArrayDisplayable::RM_LINES ); } + } + } +} + void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData ) { m_fbo->bind(); @@ -448,6 +500,7 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData if ( it == m_wireframes.end() ) { std::shared_ptr disp; + using dispmesh = Ra::Engine::Data::GeometryDisplayable; using trimesh = Ra::Engine::Data::IndexedGeometry; using polymesh = Ra::Engine::Data::IndexedGeometry; using quadmesh = Ra::Engine::Data::IndexedGeometry; @@ -456,6 +509,7 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData auto tm = std::dynamic_pointer_cast( displayable ); auto tp = std::dynamic_pointer_cast( displayable ); auto tq = std::dynamic_pointer_cast( displayable ); + auto td = std::dynamic_pointer_cast( displayable ); auto processLineMesh = []( auto cm, std::shared_ptr& lm ) { if ( cm->getRenderMode() == @@ -466,6 +520,7 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData if ( tm ) { processLineMesh( tm, disp ); } if ( tp ) { processLineMesh( tp, disp ); } if ( tq ) { processLineMesh( tq, disp ); } + // if ( td ) { setupLineMesh() } m_wireframes[ro.get()] = disp; wro = disp; @@ -485,6 +540,7 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData shader->setUniform( "transform.view", renderData.viewMatrix ); shader->setUniform( "transform.model", modelMatrix ); shader->setUniform( "viewport", Core::Vector2 { m_width, m_height } ); + shader->setUniform( "pixelWidth", 1.8f ); wro->render( shader ); GL_CHECK_ERROR; @@ -492,8 +548,83 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData } }; + auto drawWireframeNew = [this, &renderData]( const auto& ro ) { + auto displayable = ro->getMesh(); + using dispmesh = Ra::Engine::Data::GeometryDisplayable; + auto td = std::dynamic_pointer_cast( displayable ); + if ( td ) { + using namespace Core::Geometry; + using LayerKeyType = Core::Geometry::MultiIndexedGeometry::LayerKeyType; + using LineIndexLayer = Core::Geometry::LineIndexLayer; + + auto& coreGeom = td->getCoreGeometry(); + + LayerKeyType lineKey = { { LineIndexLayer::staticSemanticName }, + "wireframe triangles" }; + + LayerKeyType lineKey2 = { { LineIndexLayer::staticSemanticName }, + "wireframe main" }; + + bool hasTriangleLayer = + coreGeom.containsLayer( TriangleIndexLayer::staticSemanticName ); + bool hasQuadLayer = coreGeom.containsLayer( QuadIndexLayer::staticSemanticName ); + bool hasPolyLayer = coreGeom.containsLayer( PolyIndexLayer::staticSemanticName ); + + if ( hasTriangleLayer && !coreGeom.containsLayer( lineKey ) ) { + std::cerr << "setup line\n"; + setupLineMesh( *td, "wireframe triangles" ); + } + + if ( hasPolyLayer && !coreGeom.containsLayer( lineKey2 ) ) { + std::cerr << "setup main line from poly\n"; + setupLineMesh( *td, "wireframe main" ); + } + else if ( hasQuadLayer && !coreGeom.containsLayer( lineKey2 ) ) { + std::cerr << "setup main line from quad\n"; + setupLineMesh( *td, "wireframe main" ); + } + + const Data::ShaderProgram* shader = + m_shaderProgramManager->getShaderProgram( "Wireframe" ); + + if ( shader && ro->isVisible() ) { + GL_CHECK_ERROR; + td->updateGL(); + GL_CHECK_ERROR; + shader->bind(); + GL_CHECK_ERROR; + + Core::Matrix4 modelMatrix = ro->getTransformAsMatrix(); + shader->setUniform( "transform.proj", renderData.projMatrix ); + shader->setUniform( "transform.view", renderData.viewMatrix ); + shader->setUniform( "transform.model", modelMatrix ); + shader->setUniform( "viewport", Core::Vector2 { m_width, m_height } ); + if ( hasTriangleLayer && ( hasQuadLayer || hasPolyLayer ) ) + shader->setUniform( "pixelWidth", 1.2f ); + else + shader->setUniform( "pixelWidth", 2.8f ); + + GL_CHECK_ERROR; + td->render( shader, lineKey ); + + if ( ( hasQuadLayer || hasPolyLayer ) ) { + shader->setUniform( "pixelWidth", 2.8f ); + GL_CHECK_ERROR; + td->render( shader, lineKey2 ); + } + + GL_CHECK_ERROR; + } + } + else { + std::cerr << "could not convert to geom disp " + << Ra::Core::Utils::demangleType( displayable ) << "\n"; + } + }; + for ( const auto& ro : m_fancyRenderObjects ) { - drawWireframe( ro ); + // drawWireframe( ro ); + drawWireframeNew( ro ); } for ( const auto& ro : m_transparentRenderObjects ) { drawWireframe( ro ); From 509d68b45fee476986a890d8b02a5225dd33de4c Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 15 Sep 2022 10:21:20 +0200 Subject: [PATCH 08/28] [core][engine] Use demangleType. --- src/Core/Geometry/IndexedGeometry.cpp | 11 ++++++----- src/Engine/Data/Mesh.cpp | 11 +++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index d54f40de383..f6c233b208b 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -1,7 +1,8 @@ #include -#include -#include +#include + +#include namespace Ra { namespace Core { @@ -142,7 +143,7 @@ MultiIndexedGeometry::getFirstLayerOccurrence( const LayerSemantic& semanticName if ( key.first.find( semanticName ) != key.first.end() ) { auto& tmp = *( value.second.get() ); - std::cerr << "get typeinfo " << typeid( tmp ).name() << "\n"; + std::cerr << "get typeinfo " << Utils::demangleType( tmp ) << "\n"; return { key, *( value.second.get() ) }; } } @@ -234,7 +235,7 @@ MultiIndexedGeometry::addLayer( std::unique_ptr&& layer, const std::string& layerName ) { auto& tmp1 = *( layer.get() ); - std::cerr << "add layer typeinfo " << typeid( tmp1 ).name() << "\n"; + std::cerr << "add layer typeinfo " << Utils::demangleType( tmp1 ) << "\n"; LayerKeyType key { layer->semantics(), layerName }; auto elt = std::make_pair( key, std::make_pair( false, std::move( layer ) ) ); auto [pos, inserted] = m_indices.insert( std::move( elt ) ); @@ -247,7 +248,7 @@ MultiIndexedGeometry::addLayer( std::unique_ptr&& layer, /// If not inserted, the pointer is deleted. So the caller must ensure this possible /// deletion is safe before calling this method. auto& tmp = *( pos->second.second.get() ); - std::cerr << "add layer inserted typeinfo " << typeid( tmp ).name() << "\n"; + std::cerr << "add layer inserted typeinfo " << Utils::demangleType( tmp ) << "\n"; return { inserted, *( pos->second.second ) }; } diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index 359a3b561d2..533bc967134 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -1,17 +1,16 @@ -#include "Core/Geometry/IndexedGeometry.hpp" #include -#include - +#include #include #include +#include #include #include #include #include -#include +#include namespace Ra { namespace Engine { @@ -222,8 +221,8 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m std::cerr << layer.getSize() << " " << layer.getNumberOfComponents() << " " << layer.getBufferSize() << "\n"; - std::cerr << "type info " << typeid( layer ).name() << "\n"; - std::cerr << "type info " << typeid( const Core::Geometry::QuadIndexLayer& ).name() << "\n"; + std::cerr << "type info " << demangleType( layer ) << "\n"; + std::cerr << "type info " << demangleType() << "\n"; const auto& quadLayer = dynamic_cast( layer ); std::cerr << "cast done\n"; From a5aa861c9287ae73da14f8db7ac711d15121c5c0 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 11:10:57 +0200 Subject: [PATCH 09/28] [engine] user BijectiveAssociation for translation table. merge for GeometryDisplayable. --- src/Engine/Data/Mesh.cpp | 60 ++++++++++++++-------------------------- src/Engine/Data/Mesh.hpp | 6 ++-- 2 files changed, 23 insertions(+), 43 deletions(-) diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index 533bc967134..fef03956758 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -287,11 +287,7 @@ void GeometryDisplayable::setupCoreMeshObservers() { } void GeometryDisplayable::addToTranslationTable( const std::string& name ) { - auto it = m_translationTableMeshToShader.find( name ); - if ( it == m_translationTableMeshToShader.end() ) { - m_translationTableMeshToShader[name] = name; - m_translationTableShaderToMesh[name] = name; - } + m_translationTable.insert( name, name ); } void GeometryDisplayable::addAttribObserver( const std::string& name ) { @@ -319,26 +315,7 @@ void GeometryDisplayable::addAttribObserver( const std::string& name ) { void GeometryDisplayable::setAttribNameCorrespondence( const std::string& meshAttribName, const std::string& shaderAttribName ) { - // clean previously set translation - - auto it1 = std::find_if( m_translationTableShaderToMesh.begin(), - m_translationTableShaderToMesh.end(), - [&meshAttribName]( const TranslationTable::value_type& p ) { - return p.second == meshAttribName; - } ); - - if ( it1 != m_translationTableShaderToMesh.end() ) m_translationTableShaderToMesh.erase( it1 ); - - auto it2 = std::find_if( m_translationTableMeshToShader.begin(), - m_translationTableMeshToShader.end(), - [&shaderAttribName]( const TranslationTable::value_type& p ) { - return p.second == shaderAttribName; - } ); - - if ( it2 != m_translationTableMeshToShader.end() ) m_translationTableMeshToShader.erase( it2 ); - - m_translationTableShaderToMesh[shaderAttribName] = meshAttribName; - m_translationTableMeshToShader[meshAttribName] = shaderAttribName; + m_translationTable.replace( meshAttribName, shaderAttribName ); } bool GeometryDisplayable::addRenderLayer( LayerKeyType key, base::MeshRenderMode renderMode ) { @@ -468,29 +445,32 @@ void GeometryDisplayable::autoVertexAttribPointer( const ShaderProgram* prog, glprog->getActiveAttrib( idx, bufSize, &length, &size, &type, name ); auto loc = glprog->getAttributeLocation( name ); - auto attribName = m_translationTableShaderToMesh[name]; - auto attrib = m_geom.getAttribBase( attribName ); - - if ( attrib && attrib->getSize() > 0 ) { - m_geomLayers[key].vao->enable( loc ); - auto binding = m_geomLayers[key].vao->binding( idx ); + auto attribNameOpt = m_translationTable.keyIfExists( name ); + if ( attribNameOpt ) { + auto attribName = *attribNameOpt; + auto attrib = m_geom.getAttribBase( attribName ); + if ( attrib && attrib->getSize() > 0 ) { + m_geomLayers[key].vao->enable( loc ); + auto binding = m_geomLayers[key].vao->binding( idx ); - binding->setAttribute( loc ); - CORE_ASSERT( m_vbos[m_handleToBuffer[attribName]].get(), "vbo is nullptr" ); + binding->setAttribute( loc ); + CORE_ASSERT( m_vbos[m_handleToBuffer[attribName]].get(), "vbo is nullptr" ); #ifdef CORE_USE_DOUBLE - binding->setBuffer( m_vbos[m_handleToBuffer[attribName]].get(), - 0, - attrib->getNumberOfComponents() * sizeof( float ) ); + binding->setBuffer( m_vbos[m_handleToBuffer[attribName]].get(), + 0, + attrib->getNumberOfComponents() * sizeof( float ) ); #else - binding->setBuffer( - m_vbos[m_handleToBuffer[attribName]].get(), 0, attrib->getStride() ); + binding->setBuffer( + m_vbos[m_handleToBuffer[attribName]].get(), 0, attrib->getStride() ); #endif - binding->setFormat( attrib->getNumberOfComponents(), GL_SCALAR ); + binding->setFormat( attrib->getNumberOfComponents(), GL_SCALAR ); + } + else { m_geomLayers[key].vao->disable( loc ); } } else { m_geomLayers[key].vao->disable( loc ); } + GL_CHECK_ERROR; } - GL_CHECK_ERROR; } Ra::Core::Utils::optional AttribArrayDisplayable::getVaoHandle() { diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index fd62da57027..598ec3c44c5 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -449,9 +449,9 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable /// Collection of VBOs for per-vertex attributes // VBOCollection m_attribVBOs; - using TranslationTable = std::map; - TranslationTable m_translationTableMeshToShader; - TranslationTable m_translationTableShaderToMesh; + /// Core::Mesh attrib name to Render::Mesh attrib name + /// key: core mesh name, value: shader name + BijectiveAssociation m_translationTable {}; }; /// LineMesh, own a Core::Geometry::LineMesh From df8275eacf05e4b0532cbd7bf082aa42d84c2d22 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 12:33:56 +0200 Subject: [PATCH 10/28] [core][engine] Move triangulate to core. --- src/Core/Geometry/IndexedGeometry.hpp | 38 +++++++++++++++++++++++ src/Engine/Data/Mesh.cpp | 43 +++------------------------ src/Engine/Data/Mesh.hpp | 6 ++-- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 078e3ce90a4..5dc7253f1b1 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -13,6 +13,44 @@ namespace Ra { namespace Core { namespace Geometry { +template +VectorArray triangulate( const VectorArray& in ) { + VectorArray out; + + out.reserve( in.size() ); + for ( const auto& face : in ) { + if ( face.size() == 3 ) { out.push_back( face ); } + else { + /// simple sew triangulation + int minus { int( face.size() ) - 1 }; + int plus { 0 }; + while ( plus + 1 < minus ) { + if ( ( plus - minus ) % 2 ) { + out.emplace_back( face[plus], face[plus + 1], face[minus] ); + ++plus; + } + else { + out.emplace_back( face[minus], face[plus], face[minus - 1] ); + --minus; + } + } + } + } + return out; +} + +template <> +inline VectorArray triangulate( const VectorArray& in ) { + VectorArray out; + out.reserve( 2 * in.size() ); + // assume quads are convex + for ( const auto& face : in ) { + out.emplace_back( face[0], face[1], face[2] ); + out.emplace_back( face[0], face[2], face[3] ); + } + return out; +} + /// \brief Base class for index collections stored in MultiIndexedGeometry class RA_CORE_API GeometryIndexLayerBase : public Utils::ObservableVoid, public Utils::ObjectWithSemantic, diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index fef03956758..2704bf5ffb2 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -161,41 +161,6 @@ GeometryDisplayable::GeometryDisplayable( const std::string& name, GeometryDisplayable::~GeometryDisplayable() {} -void triangulate( Core::Geometry::TriangleIndexLayer& out, - const Core::Geometry::PolyIndexLayer& in ) { - out.collection().clear(); - out.collection().reserve( in.collection().size() ); - for ( const auto& face : in.collection() ) { - if ( face.size() == 3 ) { out.collection().push_back( face ); } - else { - /// simple sew triangulation - int minus { int( face.size() ) - 1 }; - int plus { 0 }; - while ( plus + 1 < minus ) { - if ( ( plus - minus ) % 2 ) { - out.collection().emplace_back( face[plus], face[plus + 1], face[minus] ); - ++plus; - } - else { - out.collection().emplace_back( face[minus], face[plus], face[minus - 1] ); - --minus; - } - } - } - } -} - -void triangulate( Core::Geometry::TriangleIndexLayer& out, - const Core::Geometry::QuadIndexLayer& in ) { - out.collection().clear(); - out.collection().reserve( 2 * in.getSize() ); - // assume quads are convex - for ( const auto& face : in.collection() ) { - out.collection().emplace_back( face[0], face[1], face[2] ); - out.collection().emplace_back( face[0], face[2], face[3] ); - } -} - void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh ) { m_geomLayers.clear(); m_geom = std::move( mesh ); @@ -229,7 +194,7 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m auto triangleLayer = std::make_unique(); std::cerr << "triangulate layer\n"; - triangulate( *triangleLayer, quadLayer ); + triangleLayer->collection() = Core::Geometry::triangulate( quadLayer.collection() ); std::cerr << "add triangle layer\n"; LayerKeyType triangleKey = { triangleLayer->semantics(), "triangulation" }; @@ -251,9 +216,9 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m const auto& polyLayer = dynamic_cast( m_geom.getLayer( key ) ); - auto triangleLayer = std::make_unique(); - triangulate( *triangleLayer, polyLayer ); - LayerKeyType triangleKey = { triangleLayer->semantics(), "triangulation" }; + auto triangleLayer = std::make_unique(); + triangleLayer->collection() = Core::Geometry::triangulate( polyLayer.collection() ); + LayerKeyType triangleKey = { triangleLayer->semantics(), "triangulation" }; auto layerAdded = m_geom.addLayer( std::move( triangleLayer ), false, "triangulation" ); if ( !layerAdded.first ) { LOG( logERROR ) << "failed to add triangleLayer"; } else { diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 598ec3c44c5..fdab4bd040b 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -515,8 +515,7 @@ class RA_ENGINE_API GeneralMesh : public IndexedGeometry inline void updateGL_specific_impl() override; private: - inline void triangulate(); - Core::AlignedStdVector m_triangleIndices; + Core::VectorArray m_triangleIndices; }; using PolyMesh = GeneralMesh; @@ -958,7 +957,8 @@ void GeneralMesh::updateGL_specific_impl() { this->m_indicesDirty = true; } if ( this->m_indicesDirty ) { - triangulate(); + m_triangleIndices = Core::Geometry::triangulate( this->m_mesh.getIndices() ); + /// this one do not work since m_indices is not a std::vector // m_indices->setData( m_mesh.m_indices, GL_DYNAMIC_DRAW ); this->m_numElements = m_triangleIndices.size() * GeneralMesh::IndexType::RowsAtCompileTime; From 0a6f87842b421f739c1ca05130be08e2c9ed1d16 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 17:07:40 +0200 Subject: [PATCH 11/28] [engine] Add empty ctor. --- src/Engine/Data/Mesh.cpp | 8 ++++++-- src/Engine/Data/Mesh.hpp | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index 2704bf5ffb2..b74599c55ed 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -153,6 +153,8 @@ void AttribArrayDisplayable::setDirty( const Ra::Core::Geometry::MeshAttrib& typ } //////////////// MultiIndexedGeometry /////////////////////////////// +GeometryDisplayable::GeometryDisplayable( const std::string& name ) : base( name ) {} + GeometryDisplayable::GeometryDisplayable( const std::string& name, typename Core::Geometry::MultiIndexedGeometry&& geom ) : base( name ) { @@ -207,7 +209,6 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m addRenderLayer( triangleKey, AttribArrayDisplayable::RM_TRIANGLES ); std::cerr << "triangulate done\n"; } - std::cerr << "yo\n"; } else if ( m_geom.containsLayer( Core::Geometry::PolyIndexLayer::staticSemanticName ) ) { auto [key, layer] = @@ -392,7 +393,10 @@ void GeometryDisplayable::render( const ShaderProgram* prog, const LayerKeyType& m_geomLayers[key].vao->unbind(); GL_CHECK_ERROR; } - else { LOG( logERROR ) << "try to draw an invalid layer\n"; } + else { + LOG( logERROR ) << "try to draw an invalid layer " << *key.first.begin() << " [" + << key.second << "]\n"; + } } void GeometryDisplayable::autoVertexAttribPointer( const ShaderProgram* prog, diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index fdab4bd040b..edf20eec714 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -340,6 +340,7 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable using LayerKeyType = typename Core::Geometry::MultiIndexedGeometry::LayerKeyType; using LayerKeyHash = Core::Geometry::MultiIndexedGeometry::LayerKeyHash; + explicit GeometryDisplayable( const std::string& name ); explicit GeometryDisplayable( const std::string& name, typename Core::Geometry::MultiIndexedGeometry&& geom ); virtual ~GeometryDisplayable(); From 2a1e9a45b81e218df52729256e73a0b94eb49907 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 17:08:39 +0200 Subject: [PATCH 12/28] [engine] use geometrydisplayable for components. --- src/Engine/Scene/GeometryComponent.cpp | 14 ++++++++++++++ src/Engine/Scene/GeometryComponent.hpp | 13 +++++++++---- src/Engine/Scene/GeometrySystem.cpp | 2 +- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/Engine/Scene/GeometryComponent.cpp b/src/Engine/Scene/GeometryComponent.cpp index e05447a6535..2e7900758b0 100644 --- a/src/Engine/Scene/GeometryComponent.cpp +++ b/src/Engine/Scene/GeometryComponent.cpp @@ -51,6 +51,20 @@ const Index* GeometryComponent::roIndexRead() const { return &m_roIndex; } +template <> +void SurfaceMeshComponent::generateMesh( + const Ra::Core::Asset::GeometryData* data ) { + m_contentName = data->getName(); + m_displayMesh = Ra::Core::make_shared( m_contentName ); + using CoreMeshType = Ra::Core::Geometry::MultiIndexedGeometry; + CoreMeshType mesh { data->getGeometry() }; + + m_displayMesh->loadGeometry( std::move( mesh ) ); + + finalizeROFromGeometry( data->hasMaterial() ? &( data->getMaterial() ) : nullptr, + data->getFrame() ); +} + /*-----------------------------------------------------------------------------------------------*/ /*--------------------------------- PointCloud Component----------------------------------------*/ /*-----------------------------------------------------------------------------------------------*/ diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index 7e3c73952cf..e058415e43a 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -1,5 +1,6 @@ #pragma once +#include "Core/Geometry/IndexedGeometry.hpp" #include #include #include @@ -107,11 +108,11 @@ class SurfaceMeshComponent : public GeometryComponent std::shared_ptr m_displayMesh { nullptr }; }; -using TriangleMeshComponent = SurfaceMeshComponent; +using TriangleMeshComponent = SurfaceMeshComponent; using GeometryDisplayableComponent = SurfaceMeshComponent; using LineMeshComponent = SurfaceMeshComponent; -using QuadMeshComponent = SurfaceMeshComponent; -using PolyMeshComponent = SurfaceMeshComponent; +using QuadMeshComponent = SurfaceMeshComponent; +using PolyMeshComponent = SurfaceMeshComponent; /// \warning, WIP /// \todo doc. @@ -219,7 +220,7 @@ SurfaceMeshComponent::SurfaceMeshComponent( } template <> -SurfaceMeshComponent::SurfaceMeshComponent( +RA_ENGINE_API SurfaceMeshComponent::SurfaceMeshComponent( const std::string& name, Entity* entity, Ra::Core::Geometry::MultiIndexedGeometry&& mesh, @@ -256,6 +257,10 @@ void SurfaceMeshComponent::generateMesh( const Ra::Core::Asset::Ge data->getFrame() ); } +template <> +void SurfaceMeshComponent::generateMesh( + const Ra::Core::Asset::GeometryData* data ); + template void SurfaceMeshComponent::finalizeROFromGeometry( const Core::Asset::MaterialData* data, diff --git a/src/Engine/Scene/GeometrySystem.cpp b/src/Engine/Scene/GeometrySystem.cpp index 78517d084d6..818ae5b4408 100644 --- a/src/Engine/Scene/GeometrySystem.cpp +++ b/src/Engine/Scene/GeometrySystem.cpp @@ -33,7 +33,7 @@ void GeometrySystem::handleAssetLoading( Entity* entity, // comp = new LineMeshComponent( componentName, entity, data ); // break; case Ra::Core::Asset::GeometryData::TRI_MESH: - comp = new TriangleMeshComponent( componentName, entity, data ); + comp = new GeometryDisplayableComponent( componentName, entity, data ); break; case Ra::Core::Asset::GeometryData::QUAD_MESH: comp = new QuadMeshComponent( componentName, entity, data ); From 6f0527047ff4468993f0a738450563b2b18d30ca Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 18:53:39 +0200 Subject: [PATCH 13/28] [engine] rename correspondance -> matching [engine] mesh override getNumVertices for GeometryDisplayable. remove uneeded export api on template --- src/Engine/Data/Mesh.cpp | 7 ++--- src/Engine/Data/Mesh.hpp | 55 ++++++++-------------------------------- 2 files changed, 15 insertions(+), 47 deletions(-) diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index b74599c55ed..0d3d54d5540 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -266,7 +266,8 @@ void GeometryDisplayable::addAttribObserver( const std::string& name ) { if ( itr == m_handleToBuffer.end() ) { m_handleToBuffer[name] = m_dataDirty.size(); - addToTranslationTable( name ); + // if there isn't a matching yet, add identity + if ( !m_translationTable.valueIfExists( name ) ) addToTranslationTable( name ); m_dataDirty.push_back( true ); m_vbos.emplace_back( nullptr ); @@ -278,8 +279,8 @@ void GeometryDisplayable::addAttribObserver( const std::string& name ) { else {} } -void GeometryDisplayable::setAttribNameCorrespondence( const std::string& meshAttribName, - const std::string& shaderAttribName ) { +void GeometryDisplayable::setAttribNameMatching( const std::string& meshAttribName, + const std::string& shaderAttribName ) { m_translationTable.replace( meshAttribName, shaderAttribName ); } diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index edf20eec714..f790ea51cf7 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -95,7 +95,7 @@ class RA_ENGINE_API AttribArrayDisplayable : public Displayable /// Mark attrib data as dirty, forcing an update of the OpenGL buffer. ///@{ - /// Use g_attribName to find the corresponding name and call setDirty(const std::string& name). + /// Use g_attribName to find the matching name and call setDirty(const std::string& name). /// \param type: the data to set to MeshAttrib void setDirty( const Core::Geometry::MeshAttrib& type ); @@ -118,7 +118,7 @@ class RA_ENGINE_API AttribArrayDisplayable : public Displayable virtual Core::Geometry::AttribArrayGeometry& getAttribArrayGeometry() = 0; ///@} - /// \brief Get opengl's vbo handle (uint) corresponding to attrib \b name. + /// \brief Get opengl's vbo handle (uint) matching to attrib \b name. /// /// If vbo is not initialized or name do not correponds to an actual attrib name, the returned /// optional is empty @@ -259,8 +259,8 @@ class CoreGeometryDisplayable : public AttribArrayDisplayable /// \param meshAttribName: name of the attribute on the CoreGeomtry side /// \param shaderAttribName: name of the input vertex attribute on the /// shader side. - void setAttribNameCorrespondance( const std::string& meshAttribName, - const std::string& shaderAttribName ); + void setAttribNameMatching( const std::string& meshAttribName, + const std::string& shaderAttribName ); protected: virtual void updateGL_specific_impl() {} @@ -372,8 +372,8 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable /// \param meshAttribName: name of the attribute on the CoreGeometry side /// \param shaderAttribName: name of the input vertex attribute on the /// shader side. - void setAttribNameCorrespondence( const std::string& meshAttribName, - const std::string& shaderAttribName ); + void setAttribNameMatching( const std::string& meshAttribName, + const std::string& shaderAttribName ); void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh ); inline void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, @@ -400,6 +400,8 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable /// Update (i.e. send to GPU) the buffers marked as dirty void updateGL() override; + inline size_t getNumVertices() const override { return m_geom.vertices().size(); } + protected: void setupCoreMeshObservers(); @@ -429,7 +431,7 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable size_t numElements { 0 }; }; - /// LayerKey with it's corresponding indices. + /// LayerKey with its corresponding indices. struct LayerEntryType { int observerId { -1 }; std::unique_ptr vao { nullptr }; @@ -503,7 +505,7 @@ class RA_ENGINE_API Mesh : public IndexedGeometry /// Each face of the polyhedron (typically quads) are assume to be planar and convex. /// Simple triangulation is performed on the fly before sending data to the GPU. template -class RA_ENGINE_API GeneralMesh : public IndexedGeometry +class GeneralMesh : public IndexedGeometry { using base = IndexedGeometry; using IndexType = Core::Vector3ui; @@ -854,7 +856,7 @@ void CoreGeometryDisplayable::updateGL() { } template -void CoreGeometryDisplayable::setAttribNameCorrespondance( +void CoreGeometryDisplayable::setAttribNameMatching( const std::string& meshAttribName, const std::string& shaderAttribName ) { @@ -976,41 +978,6 @@ void GeneralMesh::updateGL_specific_impl() { base::m_vao->unbind(); } -template -void GeneralMesh::triangulate() { - m_triangleIndices.clear(); - m_triangleIndices.reserve( this->m_mesh.getIndices().size() ); - for ( const auto& face : this->m_mesh.getIndices() ) { - if ( face.size() == 3 ) { m_triangleIndices.push_back( face ); } - else { - /// simple sew triangulation - int minus { int( face.size() ) - 1 }; - int plus { 0 }; - while ( plus + 1 < minus ) { - if ( ( plus - minus ) % 2 ) { - m_triangleIndices.emplace_back( face[plus], face[plus + 1], face[minus] ); - ++plus; - } - else { - m_triangleIndices.emplace_back( face[minus], face[plus], face[minus - 1] ); - --minus; - } - } - } - } -} - -template <> -inline void GeneralMesh::triangulate() { - m_triangleIndices.clear(); - m_triangleIndices.reserve( 2 * this->m_mesh.getIndices().size() ); - // assume quads are convex - for ( const auto& face : this->m_mesh.getIndices() ) { - m_triangleIndices.emplace_back( face[0], face[1], face[2] ); - m_triangleIndices.emplace_back( face[0], face[2], face[3] ); - } -} - } // namespace Data } // namespace Engine } // namespace Ra From 9d879cf3250f770e8ea7110638e0421b736dd3a7 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 18:54:24 +0200 Subject: [PATCH 14/28] [engine] GeometrySystem use GeometryDisplayable comp. --- src/Engine/Scene/GeometrySystem.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Engine/Scene/GeometrySystem.cpp b/src/Engine/Scene/GeometrySystem.cpp index 818ae5b4408..0d757e39406 100644 --- a/src/Engine/Scene/GeometrySystem.cpp +++ b/src/Engine/Scene/GeometrySystem.cpp @@ -30,16 +30,10 @@ void GeometrySystem::handleAssetLoading( Entity* entity, comp = new PointCloudComponent( componentName, entity, data ); break; case Ra::Core::Asset::GeometryData::LINE_MESH: - // comp = new LineMeshComponent( componentName, entity, data ); - // break; - case Ra::Core::Asset::GeometryData::TRI_MESH: - comp = new GeometryDisplayableComponent( componentName, entity, data ); - break; case Ra::Core::Asset::GeometryData::QUAD_MESH: - comp = new QuadMeshComponent( componentName, entity, data ); - break; + case Ra::Core::Asset::GeometryData::TRI_MESH: case Ra::Core::Asset::GeometryData::POLY_MESH: - comp = new PolyMeshComponent( componentName, entity, data ); + comp = new GeometryDisplayableComponent( componentName, entity, data ); break; case Ra::Core::Asset::GeometryData::TETRA_MESH: case Ra::Core::Asset::GeometryData::HEX_MESH: From eced115f780e909f5e7d2f6e9c7dc44d622ad326 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 19:17:31 +0200 Subject: [PATCH 15/28] [examples] Start using GeometryDisplayable in draw prim. --- .../DrawPrimitives/AllPrimitivesComponent.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index 3437251299c..0e18e1ff7bd 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -131,18 +131,18 @@ void AllPrimitivesComponent::initialize() { //// CUBES //// if ( ENABLE_CUBES ) { - std::shared_ptr cube1( new Mesh( "Cube" ) ); + std::shared_ptr cube1( new GeometryDisplayable( "Cube" ) ); auto coord = cellSize / 16_ra; cube1->loadGeometry( - Geometry::makeSharpBox( Vector3 { coord, coord, coord }, Color::Green() ) ); + Geometry::makeSharpBox2( Vector3 { coord, coord, coord }, Color::Green() ) ); auto renderObject1 = RenderObject::createRenderObject( "Cube1", this, RenderObjectType::Geometry, cube1, {} ); renderObject1->setLocalTransform( Transform { Translation( cellCorner ) } ); renderObject1->setMaterial( blinnPhongMaterial ); addRenderObject( renderObject1 ); - std::shared_ptr texCube( new Mesh( "Cube" ) ); - texCube->loadGeometry( Geometry::makeSharpBox( + std::shared_ptr texCube( new GeometryDisplayable( "Cube" ) ); + texCube->loadGeometry( Geometry::makeSharpBox2( Vector3 { 1.2_ra * coord, 1.2_ra * coord, 1.2_ra * coord }, Color::White(), true ) ); auto renderObjectTexCube = RenderObject::createRenderObject( "TexCube", this, RenderObjectType::Geometry, texCube, {} ); @@ -153,14 +153,15 @@ void AllPrimitivesComponent::initialize() { addRenderObject( renderObjectTexCube ); // another cube - std::shared_ptr cube2( new Mesh( "Cube" ) ); + std::shared_ptr cube2( new GeometryDisplayable( "Cube" ) ); coord = cellSize / 4_ra; - cube2->loadGeometry( Geometry::makeSharpBox( Vector3 { coord, coord, coord } ) ); + cube2->loadGeometry( Geometry::makeSharpBox2( Vector3 { coord, coord, coord } ) ); + const std::string myColourName { "colour" }; cube2->getCoreGeometry().addAttrib( myColourName, Vector4Array { cube2->getNumVertices(), Color::Red() } ); - cube2->setAttribNameCorrespondance( + cube2->setAttribNameMatching( myColourName, Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_COLOR ) ); auto renderObject2 = RenderObject::createRenderObject( "CubeRO_2", this, RenderObjectType::Geometry, cube2, {} ); From b58b111b704c28ba66e7237ba39c53220833029c Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:15:20 +0200 Subject: [PATCH 16/28] [engine] GeometryComponent clean include. --- src/Engine/Scene/GeometryComponent.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index e058415e43a..a0c14da74d1 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -1,14 +1,15 @@ #pragma once -#include "Core/Geometry/IndexedGeometry.hpp" #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -258,7 +259,7 @@ void SurfaceMeshComponent::generateMesh( const Ra::Core::Asset::Ge } template <> -void SurfaceMeshComponent::generateMesh( +RA_ENGINE_API void SurfaceMeshComponent::generateMesh( const Ra::Core::Asset::GeometryData* data ); template From 85ea8dd7bc95d395b39f2a6487a2cc7e46f4cfc5 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:15:38 +0200 Subject: [PATCH 17/28] [engine] Renderer remove debug print. remove forward old draw wireframe --- src/Engine/Rendering/ForwardRenderer.cpp | 75 ++++-------------------- 1 file changed, 10 insertions(+), 65 deletions(-) diff --git a/src/Engine/Rendering/ForwardRenderer.cpp b/src/Engine/Rendering/ForwardRenderer.cpp index 55bd9fdae1f..d578a9f6352 100644 --- a/src/Engine/Rendering/ForwardRenderer.cpp +++ b/src/Engine/Rendering/ForwardRenderer.cpp @@ -6,13 +6,17 @@ #include #include +#include #include +#include #include #include - +#include #include #include +#include #include +#include #include #include #include @@ -20,6 +24,7 @@ #include #include #include +#include #include #include @@ -30,6 +35,8 @@ #include +#include +#include #include #include @@ -285,8 +292,6 @@ void setupLineMesh( std::shared_ptr& disp, CoreGeometry& core ) // create a linemesh to draw wireframe given a core mesh template void setupLineMesh( Data::GeometryDisplayable& displayable, const std::string& name ) { - - std::cerr << "setup line mesh\n"; auto lineLayer = std::make_unique(); auto& indices = lineLayer->collection(); auto& coreGeometry = displayable.getCoreGeometry(); @@ -493,61 +498,6 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData glBlendFuncSeparate( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO ); GL_ASSERT( glDrawBuffers( 1, buffers ) ); // Draw color texture - auto drawWireframe = [this, &renderData]( const auto& ro ) { - std::shared_ptr wro; - - WireMap::iterator it = m_wireframes.find( ro.get() ); - if ( it == m_wireframes.end() ) { - std::shared_ptr disp; - - using dispmesh = Ra::Engine::Data::GeometryDisplayable; - using trimesh = Ra::Engine::Data::IndexedGeometry; - using polymesh = Ra::Engine::Data::IndexedGeometry; - using quadmesh = Ra::Engine::Data::IndexedGeometry; - - auto displayable = ro->getMesh(); - auto tm = std::dynamic_pointer_cast( displayable ); - auto tp = std::dynamic_pointer_cast( displayable ); - auto tq = std::dynamic_pointer_cast( displayable ); - auto td = std::dynamic_pointer_cast( displayable ); - - auto processLineMesh = []( auto cm, std::shared_ptr& lm ) { - if ( cm->getRenderMode() == - Data::AttribArrayDisplayable::MeshRenderMode::RM_TRIANGLES ) { - setupLineMesh( lm, cm->getCoreGeometry() ); - } - }; - if ( tm ) { processLineMesh( tm, disp ); } - if ( tp ) { processLineMesh( tp, disp ); } - if ( tq ) { processLineMesh( tq, disp ); } - // if ( td ) { setupLineMesh() } - - m_wireframes[ro.get()] = disp; - wro = disp; - } - else { wro = it->second; } - - const Data::ShaderProgram* shader = - m_shaderProgramManager->getShaderProgram( "Wireframe" ); - - if ( shader && wro ) { - shader->bind(); - if ( ro->isVisible() ) { - wro->updateGL(); - - Core::Matrix4 modelMatrix = ro->getTransformAsMatrix(); - shader->setUniform( "transform.proj", renderData.projMatrix ); - shader->setUniform( "transform.view", renderData.viewMatrix ); - shader->setUniform( "transform.model", modelMatrix ); - shader->setUniform( "viewport", Core::Vector2 { m_width, m_height } ); - shader->setUniform( "pixelWidth", 1.8f ); - wro->render( shader ); - - GL_CHECK_ERROR; - } - } - }; - auto drawWireframeNew = [this, &renderData]( const auto& ro ) { auto displayable = ro->getMesh(); using dispmesh = Ra::Engine::Data::GeometryDisplayable; @@ -571,16 +521,13 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData bool hasPolyLayer = coreGeom.containsLayer( PolyIndexLayer::staticSemanticName ); if ( hasTriangleLayer && !coreGeom.containsLayer( lineKey ) ) { - std::cerr << "setup line\n"; setupLineMesh( *td, "wireframe triangles" ); } if ( hasPolyLayer && !coreGeom.containsLayer( lineKey2 ) ) { - std::cerr << "setup main line from poly\n"; setupLineMesh( *td, "wireframe main" ); } else if ( hasQuadLayer && !coreGeom.containsLayer( lineKey2 ) ) { - std::cerr << "setup main line from quad\n"; setupLineMesh( *td, "wireframe main" ); } @@ -617,17 +564,15 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData } } else { - std::cerr << "could not convert to geom disp " - << Ra::Core::Utils::demangleType( displayable ) << "\n"; + // skip } }; for ( const auto& ro : m_fancyRenderObjects ) { - // drawWireframe( ro ); drawWireframeNew( ro ); } for ( const auto& ro : m_transparentRenderObjects ) { - drawWireframe( ro ); + drawWireframeNew( ro ); } } From c5b1275b1d83c581df93d6341ced6c9aa249b516 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:15:50 +0200 Subject: [PATCH 18/28] [engine] handle line index layer picking render mode. [engine] Mesh remove debug print. remove mesh debug message print mesh name on invalid layer --- src/Engine/Data/Mesh.cpp | 69 +++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index 0d3d54d5540..9dcdfdde310 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -168,46 +168,37 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m m_geom = std::move( mesh ); setupCoreMeshObservers(); - /// \todo check if other layer ? at least triangulate - if ( m_geom.containsLayer( Core::Geometry::TriangleIndexLayer::staticSemanticName ) ) { + if ( m_geom.containsLayer( Core::Geometry::LineIndexLayer::staticSemanticName ) ) { + auto [key, layer] = + m_geom.getFirstLayerOccurrence( Core::Geometry::LineIndexLayer::staticSemanticName ); + m_activeLayerKey = key; + setRenderMode( AttribArrayDisplayable::RM_LINES ); + + auto ok = addRenderLayer( key, AttribArrayDisplayable::RM_LINES ); + if ( !ok ) { LOG( logERROR ) << "loadGeometry could not add layer"; } + } + else if ( m_geom.containsLayer( Core::Geometry::TriangleIndexLayer::staticSemanticName ) ) { auto [key, layer] = m_geom.getFirstLayerOccurrence( Core::Geometry::TriangleIndexLayer::staticSemanticName ); m_activeLayerKey = key; addRenderLayer( key, AttribArrayDisplayable::RM_TRIANGLES ); } else if ( m_geom.containsLayer( Core::Geometry::QuadIndexLayer::staticSemanticName ) ) { - std::cerr << "get quad layer\n"; auto [key, layer] = m_geom.getFirstLayerOccurrence( Core::Geometry::QuadIndexLayer::staticSemanticName ); - std::cerr << "cast quad layer\n"; - std::for_each( layer.semantics().cbegin(), - layer.semantics().cend(), - []( const std::string& x ) { std::cerr << x << '\n'; } ); - - std::cerr << layer.getSize() << " " << layer.getNumberOfComponents() << " " - << layer.getBufferSize() << "\n"; - - std::cerr << "type info " << demangleType( layer ) << "\n"; - std::cerr << "type info " << demangleType() << "\n"; - const auto& quadLayer = dynamic_cast( layer ); - std::cerr << "cast done\n"; - auto triangleLayer = std::make_unique(); - std::cerr << "triangulate layer\n"; + auto triangleLayer = std::make_unique(); triangleLayer->collection() = Core::Geometry::triangulate( quadLayer.collection() ); - std::cerr << "add triangle layer\n"; LayerKeyType triangleKey = { triangleLayer->semantics(), "triangulation" }; auto layerAdded = m_geom.addLayer( std::move( triangleLayer ), false, "triangulation" ); - std::cerr << "add triangle layer done\n"; if ( !layerAdded.first ) { LOG( logERROR ) << "failed to add triangleLayer"; } else { m_activeLayerKey = triangleKey; addRenderLayer( triangleKey, AttribArrayDisplayable::RM_TRIANGLES ); - std::cerr << "triangulate done\n"; } } else if ( m_geom.containsLayer( Core::Geometry::PolyIndexLayer::staticSemanticName ) ) { @@ -227,6 +218,7 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m addRenderLayer( triangleKey, AttribArrayDisplayable::RM_TRIANGLES ); } } + else { LOG( logERROR ) << "no valid layer found"; } m_isDirty = true; } @@ -380,24 +372,27 @@ void GeometryDisplayable::render( const ShaderProgram* prog ) { void GeometryDisplayable::render( const ShaderProgram* prog, const LayerKeyType& key ) { GL_CHECK_ERROR; - if ( m_geomLayers[key].vao ) { - m_geomLayers[key].vao->bind(); - GL_CHECK_ERROR; - autoVertexAttribPointer( prog, key ); - GL_CHECK_ERROR; - - m_geomLayers[key].vao->drawElements( static_cast( m_geomLayers[key].renderMode ), - GLsizei( m_geomLayers[key].indices.numElements ), - GL_UNSIGNED_INT, - nullptr ); - GL_CHECK_ERROR; - m_geomLayers[key].vao->unbind(); - GL_CHECK_ERROR; - } - else { - LOG( logERROR ) << "try to draw an invalid layer " << *key.first.begin() << " [" - << key.second << "]\n"; + if ( m_geomLayers.find( key ) != m_geomLayers.end() ) { + if ( m_geomLayers[key].vao ) { + m_geomLayers[key].vao->bind(); + GL_CHECK_ERROR; + autoVertexAttribPointer( prog, key ); + GL_CHECK_ERROR; + m_geomLayers[key].vao->drawElements( + static_cast( m_geomLayers[key].renderMode ), + GLsizei( m_geomLayers[key].indices.numElements ), + GL_UNSIGNED_INT, + nullptr ); + GL_CHECK_ERROR; + m_geomLayers[key].vao->unbind(); + GL_CHECK_ERROR; + } + else { + LOG( logERROR ) << getName() << "try to draw an invalid layer " << *key.first.begin() + << " [" << key.second << "]\n"; + } } + else { LOG( logERROR ) << "layer was not added as a render layer"; } } void GeometryDisplayable::autoVertexAttribPointer( const ShaderProgram* prog, From 0c04358145830bccb1bbbddbdffa8680e0f3f066 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:16:14 +0200 Subject: [PATCH 19/28] [core] MeshPrimitives remove debug print. --- src/Core/Geometry/MeshPrimitives.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index c57b9968cab..956bb18bae9 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -1,5 +1,5 @@ -#include "Core/Geometry/IndexedGeometry.hpp" #include +#include #include #include #include // areApproxEqual @@ -8,8 +8,6 @@ #include #include -#include - namespace Ra { namespace Core { namespace Geometry { @@ -213,17 +211,9 @@ MultiIndexedGeometry makeSharpBox2( const Aabb& aabb, }; auto semantic = layer->semantics(); - std::for_each( layer->semantics().cbegin(), - layer->semantics().cend(), - []( const std::string& x ) { std::cerr << x << '\n'; } ); - result.addLayer( std::move( layer ) ); - auto test = result.getFirstLayerOccurrence( semantic ); - auto& tmp = test.second; - std::cerr << "make typeinfo " << typeid( tmp ).name() << "\n"; if ( bool( color ) ) result.colorize( *color ); result.checkConsistency(); - std::cerr << "return make sharp box aabb \n"; return MultiIndexedGeometry { std::move( result ) }; } @@ -231,7 +221,6 @@ MultiIndexedGeometry makeSharpBox2( const Vector3& halfExts, const Utils::optional& color, bool generateTexCoord ) { Aabb aabb( -halfExts, halfExts ); - std::cerr << "return make sharp box half \n"; return makeSharpBox2( aabb, color, generateTexCoord ); } From eb21bbd5e235037cae69442581ae61a36162a09c Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:16:32 +0200 Subject: [PATCH 20/28] [core] IndexedGeometry remove debug print. --- src/Core/Geometry/IndexedGeometry.cpp | 31 ++++----------------------- src/Core/Geometry/IndexedGeometry.hpp | 5 +---- 2 files changed, 5 insertions(+), 31 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index f6c233b208b..2726ebe15f1 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -1,7 +1,5 @@ #include -#include - #include namespace Ra { @@ -10,29 +8,19 @@ namespace Geometry { MultiIndexedGeometry::MultiIndexedGeometry( const MultiIndexedGeometry& other ) : AttribArrayGeometry( other ) { - std::cerr << "MultiIndexedGeometry & other\n"; deepCopy( other ); } MultiIndexedGeometry::MultiIndexedGeometry( MultiIndexedGeometry&& other ) : - AttribArrayGeometry( std::move( other ) ), m_indices( std::move( other.m_indices ) ) { - - std::cerr << "MultiIndexedGeometry && other\n"; -} + AttribArrayGeometry( std::move( other ) ), m_indices( std::move( other.m_indices ) ) {} MultiIndexedGeometry::MultiIndexedGeometry( const AttribArrayGeometry& other ) : - AttribArrayGeometry( other ) { - std::cerr << "MultiIndexedGeometry & other\n"; -} + AttribArrayGeometry( other ) {} MultiIndexedGeometry::MultiIndexedGeometry( AttribArrayGeometry&& other ) : - AttribArrayGeometry( std::move( other ) ) { - std::cerr << "MultiIndexedGeometry Atrib && other\n"; -} + AttribArrayGeometry( std::move( other ) ) {} MultiIndexedGeometry& MultiIndexedGeometry::operator=( const MultiIndexedGeometry& other ) { - std::cerr << "MultiIndexedGeometry = & other\n"; - invalidateAabb(); AttribArrayGeometry::operator=( other ); deepCopy( other ); @@ -41,8 +29,6 @@ MultiIndexedGeometry& MultiIndexedGeometry::operator=( const MultiIndexedGeometr } MultiIndexedGeometry& MultiIndexedGeometry::operator=( MultiIndexedGeometry&& other ) { - std::cerr << "MultiIndexedGeometry = && other\n"; - invalidateAabb(); AttribArrayGeometry::operator=( std::move( other ) ); m_indices = std::move( other.m_indices ); @@ -140,12 +126,8 @@ size_t MultiIndexedGeometry::countLayers( const LayerSemanticCollection& semanti std::pair MultiIndexedGeometry::getFirstLayerOccurrence( const LayerSemantic& semanticName ) const { for ( const auto& [key, value] : m_indices ) { - if ( key.first.find( semanticName ) != key.first.end() ) { - - auto& tmp = *( value.second.get() ); - std::cerr << "get typeinfo " << Utils::demangleType( tmp ) << "\n"; + if ( key.first.find( semanticName ) != key.first.end() ) return { key, *( value.second.get() ) }; - } } throw std::out_of_range( "Layer entry not found" ); } @@ -233,9 +215,6 @@ std::pair MultiIndexedGeometry::addLayer( std::unique_ptr&& layer, const bool withLock, const std::string& layerName ) { - - auto& tmp1 = *( layer.get() ); - std::cerr << "add layer typeinfo " << Utils::demangleType( tmp1 ) << "\n"; LayerKeyType key { layer->semantics(), layerName }; auto elt = std::make_pair( key, std::make_pair( false, std::move( layer ) ) ); auto [pos, inserted] = m_indices.insert( std::move( elt ) ); @@ -247,8 +226,6 @@ MultiIndexedGeometry::addLayer( std::unique_ptr&& layer, } /// If not inserted, the pointer is deleted. So the caller must ensure this possible /// deletion is safe before calling this method. - auto& tmp = *( pos->second.second.get() ); - std::cerr << "add layer inserted typeinfo " << Utils::demangleType( tmp ) << "\n"; return { inserted, *( pos->second.second ) }; } diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 5dc7253f1b1..5c9bc50499f 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -452,12 +452,8 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \brief Index layer for a point cloud struct RA_CORE_API PointCloudIndexLayer : public GeometryIndexLayer { - using base = GeometryIndexLayer; /// \brief Constructor of an empty layer inline PointCloudIndexLayer(); - inline PointCloudIndexLayer( const PointCloudIndexLayer& other ) = default; - inline PointCloudIndexLayer& operator=( const PointCloudIndexLayer& other ) = default; - inline PointCloudIndexLayer& operator=( PointCloudIndexLayer&& other ) = default; /// \brief Constructor of an index layer with linearly spaced indices ranging from \f$0\f$ to /// \f$n-1\f$ @@ -562,6 +558,7 @@ struct getType { /** * \brief A single layer MultiIndexedGeometry. + * * This class actually provide compatibility with old geometry with a main layer. * Main layer contains indices of a specific type (point, line, triangle, poly). * Derived classes explicit the kind of indices of the main layer. From a8168ef94b048cfb9c8c983f7d6201c0cf4bfb68 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:16:47 +0200 Subject: [PATCH 21/28] [examples] HelloRadium remove debug print. --- examples/HelloRadium/main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/HelloRadium/main.cpp b/examples/HelloRadium/main.cpp index e3b8aa77200..c7461ae86df 100644 --- a/examples/HelloRadium/main.cpp +++ b/examples/HelloRadium/main.cpp @@ -27,9 +27,7 @@ int main( int argc, char* argv[] ) { //! [Verifying the OpenGL version available to the engine] //! [Creating the cube] - std::cerr << "CREATE CUBE\n"; auto cube { std::move( Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ) ) }; - std::cerr << "DONE CUBE\n"; //! [Creating the cube] //! [Colorize the Cube] From ba7e3ce0e0dae4d1f5a8e205232e3705d2963236 Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 27 Oct 2022 11:02:12 +0200 Subject: [PATCH 22/28] [engine] Remove unused LineMeshComponent. --- src/Engine/Scene/GeometryComponent.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index a0c14da74d1..86508ef06e3 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -111,7 +111,6 @@ class SurfaceMeshComponent : public GeometryComponent using TriangleMeshComponent = SurfaceMeshComponent; using GeometryDisplayableComponent = SurfaceMeshComponent; -using LineMeshComponent = SurfaceMeshComponent; using QuadMeshComponent = SurfaceMeshComponent; using PolyMeshComponent = SurfaceMeshComponent; From 8304bdb3d536c0ad9e22cad17a35aa3b8a1ab206 Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 8 Dec 2022 09:24:39 +0100 Subject: [PATCH 23/28] [examples] add fixed light in skinning example. --- examples/SimpleSkinning/main.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/examples/SimpleSkinning/main.cpp b/examples/SimpleSkinning/main.cpp index e6da7f6e7e4..ef0da15ac66 100644 --- a/examples/SimpleSkinning/main.cpp +++ b/examples/SimpleSkinning/main.cpp @@ -5,12 +5,15 @@ #include #include #include +#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -71,6 +74,13 @@ class SkinningSystem : public Scene::System }; void setupScene( Ra::Engine::RadiumEngine* engine ) { + + DefaultLightManager* lightManager = + static_cast( engine->getSystem( "DefaultLightManager" ) ); + auto light = new Engine::Scene::DirectionalLight( + Ra::Engine::Scene::SystemEntity::getInstance(), "light" ); + lightManager->addLight( light ); + auto animationSystem = new SkinningSystem; engine->registerSystem( "Simple animation system", animationSystem ); From d61b0cc448001035a528528a0c2f68a9f498f05f Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 8 Dec 2022 09:25:15 +0100 Subject: [PATCH 24/28] [core] use inverse transpose for normal lbs. --- src/Core/Animation/LinearBlendSkinning.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Core/Animation/LinearBlendSkinning.cpp b/src/Core/Animation/LinearBlendSkinning.cpp index ca53ab54e07..47b106bdba3 100644 --- a/src/Core/Animation/LinearBlendSkinning.cpp +++ b/src/Core/Animation/LinearBlendSkinning.cpp @@ -1,3 +1,4 @@ +#include "Core/Types.hpp" #include #include @@ -33,9 +34,10 @@ void linearBlendSkinning( const SkinningRefData& refData, const Scalar w = it.value(); // prepare the pose w.r.t. the bind matrix and the mesh transform const Transform M = refData.m_meshTransformInverse * pose[j] * bindMatrix[j]; + const Matrix3 N = M.matrix().inverse().transpose().block<3, 3>( 0, 0 ); // apply LBS frameData.m_currentPosition[i] += w * ( M * vertices[i] ); - frameData.m_currentNormal[i] += w * ( M.linear() * normals[i] ); + frameData.m_currentNormal[i] += w * ( N * normals[i] ); frameData.m_currentTangent[i] += w * ( M.linear() * tangents[i] ); frameData.m_currentBitangent[i] += w * ( M.linear() * bitangents[i] ); } From ade232cf302e2d10f5fa6cd61f5b50af23571263 Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 8 Dec 2022 09:25:41 +0100 Subject: [PATCH 25/28] [core] comment typo in trianglemesh --- src/Core/Geometry/TriangleMesh.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Geometry/TriangleMesh.hpp b/src/Core/Geometry/TriangleMesh.hpp index 24b1a4a4e01..c10c9a4b8a1 100644 --- a/src/Core/Geometry/TriangleMesh.hpp +++ b/src/Core/Geometry/TriangleMesh.hpp @@ -13,7 +13,7 @@ namespace Ra { namespace Core { namespace Geometry { -/// \brief This class represents vertex + attributes per vertex. Toplogy is handled in +/// \brief This class represents vertex + attributes per vertex. Topology is handled in /// MultiIndexedGeometry subclass. /// /// Attributes are unique per vertex, so that same position with different From c4647b23ec9f19a0dab9971de7790c8b9c87dd01 Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 8 Dec 2022 09:29:07 +0100 Subject: [PATCH 26/28] [core][engine] use AttribArrayGeometry as skinning data. tmp disable rotation center skinning --- src/Core/Animation/SkinningData.hpp | 2 +- src/Engine/Scene/SkinningComponent.cpp | 114 ++++--------------------- src/Engine/Scene/SkinningComponent.hpp | 19 +---- 3 files changed, 21 insertions(+), 114 deletions(-) diff --git a/src/Core/Animation/SkinningData.hpp b/src/Core/Animation/SkinningData.hpp index d7437548643..dd238dc5d6a 100644 --- a/src/Core/Animation/SkinningData.hpp +++ b/src/Core/Animation/SkinningData.hpp @@ -13,7 +13,7 @@ namespace Animation { /// \brief Skinning data that get set at startup including the "reference state". struct SkinningRefData { /// The mesh in reference position. - Geometry::TriangleMesh m_referenceMesh; + Geometry::AttribArrayGeometry m_referenceMesh; /// The inverse of the mesh's transform. Transform m_meshTransformInverse; diff --git a/src/Engine/Scene/SkinningComponent.cpp b/src/Engine/Scene/SkinningComponent.cpp index 4646cc3eee4..dcd256405d8 100644 --- a/src/Engine/Scene/SkinningComponent.cpp +++ b/src/Engine/Scene/SkinningComponent.cpp @@ -1,11 +1,11 @@ -#include +#include "Core/Geometry/TriangleMesh.hpp" +#include #include #include #include #include -#include #include #include #include @@ -22,9 +22,6 @@ using namespace Ra::Core; using Geometry::AttribArrayGeometry; -using Geometry::PolyMesh; -using Geometry::QuadMesh; -using Geometry::TriangleMesh; using namespace Animation; using SpaceType = HandleArray::SpaceType; @@ -40,73 +37,21 @@ static const std::string tangentName = static const std::string bitangentName = Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_BITANGENT ); -TriangleMesh triangulate( const PolyMesh& polyMesh ) { - TriangleMesh res; - res.setVertices( polyMesh.vertices() ); - res.setNormals( polyMesh.normals() ); - res.copyAllAttributes( polyMesh ); - VectorArray indices; - // using the same triangulation as in Ra::Engine::GeneralMesh::triangulate - for ( const auto& face : polyMesh.getIndices() ) { - if ( face.size() == 3 ) { indices.push_back( face ); } - else { - int minus { int( face.size() ) - 1 }; - int plus { 0 }; - while ( plus + 1 < minus ) { - if ( ( plus - minus ) % 2 ) { - indices.emplace_back( face[plus], face[plus + 1], face[minus] ); - ++plus; - } - else { - indices.emplace_back( face[minus], face[plus], face[minus - 1] ); - --minus; - } - } - } - } - res.setIndices( std::move( indices ) ); - return res; -} - -TriangleMesh triangulate( const QuadMesh& quadMesh ) { - TriangleMesh res; - res.setVertices( quadMesh.vertices() ); - res.setNormals( quadMesh.normals() ); - res.copyAllAttributes( quadMesh ); - VectorArray indices; - // using the same triangulation as in Ra::Engine::GeneralMesh::triangulate - for ( const auto& face : quadMesh.getIndices() ) { - indices.emplace_back( face[0], face[1], face[2] ); - indices.emplace_back( face[0], face[2], face[3] ); - } - res.setIndices( std::move( indices ) ); - return res; -} - void SkinningComponent::initialize() { auto compMsg = ComponentMessenger::getInstance(); // get the current animation data. bool hasSkel = compMsg->canGet( getEntity(), m_skelName ); bool hasRefPose = compMsg->canGet( getEntity(), m_skelName ); - bool hasTriMesh = compMsg->canGet( getEntity(), m_meshName ); - m_meshIsPoly = compMsg->canGet( getEntity(), m_meshName ); - m_meshIsQuad = compMsg->canGet( getEntity(), m_meshName ); - - if ( hasSkel && hasRefPose && ( hasTriMesh || m_meshIsPoly || m_meshIsQuad ) ) { + bool hasGeom = compMsg->canGet( getEntity(), m_meshName ); + if ( hasSkel && hasRefPose && hasGeom ) { m_renderObjectReader = compMsg->getterCallback( getEntity(), m_meshName ); m_skeletonGetter = compMsg->getterCallback( getEntity(), m_skelName ); - if ( hasTriMesh ) { - m_triMeshWriter = compMsg->rwCallback( getEntity(), m_meshName ); - } - else if ( m_meshIsQuad ) { - m_quadMeshWriter = compMsg->rwCallback( getEntity(), m_meshName ); - } - else { m_polyMeshWriter = compMsg->rwCallback( getEntity(), m_meshName ); } + + m_geomWriter = compMsg->rwCallback( getEntity(), m_meshName ); // copy mesh triangles and find duplicates for normal computation. - if ( hasTriMesh ) { m_refData.m_referenceMesh = *m_triMeshWriter(); } - else if ( m_meshIsQuad ) { m_refData.m_referenceMesh = triangulate( *m_quadMeshWriter() ); } - else { m_refData.m_referenceMesh = triangulate( *m_polyMeshWriter() ); } + m_refData.m_referenceMesh = *m_geomWriter(); + /// TODO : use the tangent computation algorithms from Core as soon as it is available. if ( !m_refData.m_referenceMesh.hasAttrib( tangentName ) && !m_refData.m_referenceMesh.hasAttrib( bitangentName ) ) { @@ -143,8 +88,6 @@ void SkinningComponent::initialize() { m_refData.m_referenceMesh.addAttrib( bitangentName, std::move( bitangents ) ); } - m_topoMesh = Ra::Core::Geometry::TopologicalMesh { m_refData.m_referenceMesh }; - auto ro = getRoMgr()->getRenderObject( *m_renderObjectReader() ); // get other data m_refData.m_meshTransformInverse = ro->getLocalTransform().inverse(); @@ -171,13 +114,11 @@ void SkinningComponent::initialize() { m_baseMaterial = ro->getMaterial(); // prepare UV - auto attrUV = Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_TEXCOORD ); + AttribArrayGeometry* geom; - if ( hasTriMesh ) { geom = const_cast( m_triMeshWriter() ); } - else { - if ( m_meshIsPoly ) { geom = const_cast( m_polyMeshWriter() ); } - else { geom = const_cast( m_quadMeshWriter() ); } - } + geom = m_geomWriter(); + + auto attrUV = Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_TEXCOORD ); if ( geom->hasAttrib( attrUV ) ) { auto handle = geom->getAttribHandle( attrUV ); m_baseUV = geom->getAttrib( handle ).data(); @@ -231,7 +172,8 @@ void SkinningComponent::skin() { break; } case COR: { - centerOfRotationSkinning( m_refData, tangents, bitangents, m_frameData ); + ///\todo centerOfRotationSkinning( m_refData, tangents, bitangents, + /// m_frameData ); break; } case LBS: @@ -240,29 +182,13 @@ void SkinningComponent::skin() { break; } } - - if ( m_normalSkinning == GEOMETRIC ) { - m_topoMesh.updatePositions( m_frameData.m_currentPosition ); - m_topoMesh.updateWedgeNormals(); - m_topoMesh.updateTriangleMeshNormals( m_frameData.m_currentNormal ); -#pragma omp parallel for - for ( int i = 0; i < int( m_frameData.m_currentNormal.size() ); ++i ) { - Core::Math::getOrthogonalVectors( m_frameData.m_currentNormal[i], - m_frameData.m_currentTangent[i], - m_frameData.m_currentBitangent[i] ); - } - } } } void SkinningComponent::endSkinning() { if ( m_frameData.m_doSkinning ) { AttribArrayGeometry* geom; - if ( !m_meshIsPoly ) { - if ( !m_meshIsQuad ) { geom = const_cast( m_triMeshWriter() ); } - else { geom = const_cast( m_quadMeshWriter() ); } - } - else { geom = const_cast( m_polyMeshWriter() ); } + geom = m_geomWriter(); geom->setVertices( m_frameData.m_currentPosition ); geom->setNormals( m_frameData.m_currentNormal ); @@ -346,7 +272,8 @@ void SkinningComponent::setSkinningType( SkinningType type ) { if ( m_isReady ) { // compute the per-vertex center of rotation only if required. // FIXME: takes time, would be nice to store them in a file and reload. - if ( m_skinningType == COR && m_refData.m_CoR.empty() ) { computeCoR( m_refData ); } + ///\todo if ( m_skinningType == COR && m_refData.m_CoR.empty() ) { computeCoR( + /// m_refData ); } m_forceUpdate = true; } } @@ -370,12 +297,7 @@ void SkinningComponent::showWeights( bool on ) { auto attrUV = Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_TEXCOORD ); AttribHandle handle; - AttribArrayGeometry* geom; - if ( !m_meshIsPoly ) { - if ( !m_meshIsQuad ) { geom = const_cast( m_triMeshWriter() ); } - else { geom = const_cast( m_quadMeshWriter() ); } - } - else { geom = const_cast( m_polyMeshWriter() ); } + AttribArrayGeometry* geom = m_geomWriter(); if ( m_showingWeights ) { // update the displayed weights diff --git a/src/Engine/Scene/SkinningComponent.hpp b/src/Engine/Scene/SkinningComponent.hpp index 27b07092559..9f9608c6a45 100644 --- a/src/Engine/Scene/SkinningComponent.hpp +++ b/src/Engine/Scene/SkinningComponent.hpp @@ -197,23 +197,8 @@ class RA_ENGINE_API SkinningComponent : public Component /// Read FMC's RO idx. Getter m_renderObjectReader; - /// Whether the skinned mesh is a TriangleMesh or a PolyMesh. - bool m_meshIsPoly { false }; - - /// Whether the skinned mesh is a TriangleMesh or a PolyMesh. - bool m_meshIsQuad { false }; - - /// Getter/Setter to the skinned mesh, in case it is a TriangleMesh. - ReadWrite m_triMeshWriter; - - /// Getter/Setter to the skinned mesh, in case it is a PolyMesh. - ReadWrite m_polyMeshWriter; - - /// Getter/Setter to the skinned mesh, in case it is a QuadMesh. - ReadWrite m_quadMeshWriter; - - /// The Topological mesh used to geometrically recompute the normals. - Core::Geometry::TopologicalMesh m_topoMesh; + /// Getter/Setter to the skinned geom + ReadWrite m_geomWriter; /// The per-bone skinning weights. /// \note These are stored this way because we cannot build the weight matrix From e9f3e16efa7f0ac4f5658cb096b289960a98d11e Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 8 Dec 2022 09:30:13 +0100 Subject: [PATCH 27/28] [core] register rw on AttribArrayGeometry for SurfaceMeshComponent. --- src/Engine/Scene/GeometryComponent.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index 86508ef06e3..f333bd8bd2a 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -324,6 +324,12 @@ void SurfaceMeshComponent::setupIO( const std::string& id ) { cm->registerOutput( getEntity(), this, id, cbOut ); cm->registerReadWrite( getEntity(), this, id, cbRw ); + if ( std::is_convertible() && + !std::is_same() ) { + + cm->registerOutput( getEntity(), this, id, cbOut ); + cm->registerReadWrite( getEntity(), this, id, cbRw ); + } base::setupIO( id ); } From 076ec5e96e2e9cb52a63ed2c17c81599225d731a Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 16 May 2023 15:01:59 +0200 Subject: [PATCH 28/28] remove temporary non working code --- src/Core/filelist.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/filelist.cmake b/src/Core/filelist.cmake index 7aabbe1b640..ca60adf4e02 100644 --- a/src/Core/filelist.cmake +++ b/src/Core/filelist.cmake @@ -11,7 +11,7 @@ set(core_sources Animation/HandleWeightOperation.cpp Animation/LinearBlendSkinning.cpp Animation/PoseOperation.cpp - Animation/RotationCenterSkinning.cpp + # Animation/RotationCenterSkinning.cpp Animation/Sequence.cpp Animation/Skeleton.cpp Asset/AnimationData.cpp @@ -56,7 +56,7 @@ set(core_headers Animation/LinearBlendSkinning.hpp Animation/Pose.hpp Animation/PoseOperation.hpp - Animation/RotationCenterSkinning.hpp + # Animation/RotationCenterSkinning.hpp Animation/Sequence.hpp Animation/Skeleton.hpp Animation/SkinningData.hpp