From 422cbb35ef39afa76b0d626557d3fdafa06126f1 Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 20 Jul 2022 11:18:11 +0200 Subject: [PATCH 001/144] [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 b21dad719a0..dd6f5655184 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -216,7 +216,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(); @@ -246,7 +246,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 3664b99785c..90046e0e13a 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -384,18 +384,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 @@ -763,6 +764,7 @@ inline void IndexedGeometry::setIndices( IndexContainerType&& indices ) { auto& abstractLayer = getLayerWithLock( m_mainIndexLayerKey ); static_cast::DefaultLayerType&>( abstractLayer ).collection() = std::move( indices ); + indicesUnlock(); notify(); } @@ -770,6 +772,7 @@ template inline void IndexedGeometry::setIndices( const IndexContainerType& indices ) { auto& abstractLayer = getLayerWithLock( m_mainIndexLayerKey ); static_cast::DefaultLayerType&>( abstractLayer ).collection() = indices; + indicesUnlock(); notify(); } From 1b830fd9b7ee3557d268deea915c132d4f3a54b1 Mon Sep 17 00:00:00 2001 From: Nicolas Mellado Date: Mon, 19 Jul 2021 13:00:11 +0200 Subject: [PATCH 002/144] [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 90046e0e13a..05daaadaedb 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -386,6 +386,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; }; @@ -504,7 +506,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 781d5c2f8db..af2a0fd48d2 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 @@ -352,44 +331,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; } - protected: - void updateGL_specific_impl() override; + 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 ); - using LayerSemanticCollection = Core::Utils::ObjectWithSemantic::SemanticNameCollection; - using LayerSemantic = Core::Utils::ObjectWithSemantic::SemanticName; - using LayerKeyType = std::pair; - - using EntryType = std::pair; - struct 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 ); + 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 setupCoreMeshObservers(); + + /// 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 }; + }; + + // for indices, with dirty and num elements + struct IndicesVBO { + bool dirty { false }; + std::unique_ptr buffer { nullptr }; + size_t numElements { 0 }; }; - std::unordered_map m_indices; + + /// 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 @@ -524,6 +586,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 @@ -557,127 +625,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 @@ -1006,78 +953,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 e61a3b81cdb5c8dca260a714da2f9d91b7ba2d30 Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 31 Mar 2022 22:09:58 +0200 Subject: [PATCH 003/144] [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 84df63dc1f9..34621d6f760 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 0e689a96e37..8b75fd2c7eb 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -114,10 +114,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. @@ -224,6 +225,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 2a7d992f797884a63e22ca44a913f2a4e2afd9dd Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 31 Mar 2022 22:11:41 +0200 Subject: [PATCH 004/144] [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 9a70370152f9e3ea6f38fdd2dbfbd41ce0297257 Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 20 Jul 2022 08:00:00 +0200 Subject: [PATCH 005/144] [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 2667d0ab221779c7665f5c8f07e81fc22b46582b Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 20 Jul 2022 15:47:20 +0200 Subject: [PATCH 006/144] [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 dd6f5655184..424b3538f29 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -5,25 +5,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 ); @@ -32,6 +44,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 ); @@ -126,8 +140,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" ); } @@ -215,6 +233,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 ) ); @@ -224,8 +245,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 05daaadaedb..86d47ee1c34 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -64,7 +64,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; @@ -384,6 +384,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: @@ -401,14 +402,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$ @@ -418,6 +430,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 @@ -429,6 +442,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 @@ -440,6 +454,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 @@ -452,6 +467,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 @@ -463,6 +479,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 @@ -471,6 +488,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 7abe1940016..008fb32973c 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 310ebb593f3..294ffddcaec 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 7b382f176d5dc6355140176c5c92bc990d6fff08 Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 20 Jul 2022 17:35:33 +0200 Subject: [PATCH 007/144] [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 af2a0fd48d2..404f0c87c07 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -346,6 +346,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 */ @@ -404,7 +405,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. @@ -445,9 +446,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 f0328f8dd99..8d464c15a71 100644 --- a/src/Engine/Rendering/ForwardRenderer.cpp +++ b/src/Engine/Rendering/ForwardRenderer.cpp @@ -1,3 +1,6 @@ +#include +#include +#include #include #include #include @@ -181,6 +184,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 @@ -235,6 +261,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(); @@ -427,6 +479,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; @@ -435,6 +488,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() == @@ -445,6 +499,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; @@ -464,6 +519,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; @@ -471,8 +527,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 d9bf89c27b7350fad66a73e268915e43f61b4cc5 Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 15 Sep 2022 10:21:20 +0200 Subject: [PATCH 008/144] [core][engine] Use demangleType. --- src/Core/Geometry/IndexedGeometry.cpp | 13 ++++++------- src/Engine/Data/Mesh.cpp | 11 +++++------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index 424b3538f29..27a13c7e3b8 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -1,12 +1,11 @@ #include -#include -#include + +#include + #include #include #include -#include - namespace Ra { namespace Core { namespace Geometry { @@ -143,7 +142,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() ) }; } } @@ -235,7 +234,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 ) ); @@ -248,7 +247,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 5964da41582e81cd35a2a19b2bfa4e97c2ad6b39 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 11:10:57 +0200 Subject: [PATCH 009/144] [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 404f0c87c07..9fbe4485d8d 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -451,9 +451,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 9c2ded28d6bda3456ef1a1ca080e4fa4a9f1eced Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 12:33:56 +0200 Subject: [PATCH 010/144] [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 86d47ee1c34..bd1852ff7e2 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -14,6 +14,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 9fbe4485d8d..3fcf2a3ec1e 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -517,8 +517,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; @@ -991,7 +990,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 78107af038162f7c8bd28ac0f6a0e144f1177ae8 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 17:07:40 +0200 Subject: [PATCH 011/144] [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 3fcf2a3ec1e..a3a85247aee 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -342,6 +342,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 949d2ac11c0697f028d012b986feee87fb85eb2f Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 17:08:39 +0200 Subject: [PATCH 012/144] [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 34621d6f760..17e9e4d721f 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 8b75fd2c7eb..4e1a231e15d 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 @@ -114,11 +115,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. @@ -226,7 +227,7 @@ SurfaceMeshComponent::SurfaceMeshComponent( } template <> -SurfaceMeshComponent::SurfaceMeshComponent( +RA_ENGINE_API SurfaceMeshComponent::SurfaceMeshComponent( const std::string& name, Entity* entity, Ra::Core::Geometry::MultiIndexedGeometry&& mesh, @@ -275,6 +276,10 @@ void SurfaceMeshComponent::generateMesh( const Ra::Core::Asset::Ge data->getFrame() ); } +template <> +void SurfaceMeshComponent::generateMesh( + const Ra::Core::Asset::GeometryData* data ); + template std::shared_ptr SurfaceMeshComponent::convertMatdataToMaterial( 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 749b41bd7485bd1ae2ae0ad680e7be7761ad27b0 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 27 Apr 2025 19:32:17 +0200 Subject: [PATCH 013/144] [engine] fix geometry component (after rebase) --- src/Engine/Scene/GeometryComponent.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Engine/Scene/GeometryComponent.cpp b/src/Engine/Scene/GeometryComponent.cpp index 17e9e4d721f..0193504f2b9 100644 --- a/src/Engine/Scene/GeometryComponent.cpp +++ b/src/Engine/Scene/GeometryComponent.cpp @@ -38,7 +38,7 @@ SurfaceMeshComponent::SurfaceMeshCompo GeometryComponent( name, entity ), m_displayMesh( new Data::GeometryDisplayable( name, std::move( mesh ) ) ) { setContentName( name ); - finalizeROFromGeometry( mat, Core::Transform::Identity() ); + finalizeROFromGeometry( convertMatdataToMaterial( mat ), Core::Transform::Identity() ); } void GeometryComponent::setupIO( const std::string& id ) { @@ -61,8 +61,9 @@ void SurfaceMeshComponent::generateMes m_displayMesh->loadGeometry( std::move( mesh ) ); - finalizeROFromGeometry( data->hasMaterial() ? &( data->getMaterial() ) : nullptr, - data->getFrame() ); + finalizeROFromGeometry( + convertMatdataToMaterial( data->hasMaterial() ? &( data->getMaterial() ) : nullptr ), + data->getFrame() ); } /*-----------------------------------------------------------------------------------------------*/ From 45c29671622c70e47dd47e34911f2d7298d0bb87 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 18:53:39 +0200 Subject: [PATCH 014/144] [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 a3a85247aee..0fa1e682ec0 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 ); void autoVertexAttribCheck( const ShaderProgram* prog ); @@ -374,8 +374,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, @@ -402,6 +402,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(); @@ -431,7 +433,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 }; @@ -505,7 +507,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; @@ -887,7 +889,7 @@ void CoreGeometryDisplayable::updateGL() { } template -void CoreGeometryDisplayable::setAttribNameCorrespondance( +void CoreGeometryDisplayable::setAttribNameMatching( const std::string& meshAttribName, const std::string& shaderAttribName ) { @@ -1009,41 +1011,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 3c84cc234bf0071c8c66e87cfb780dfdd855903c Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 18:54:24 +0200 Subject: [PATCH 015/144] [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 6b64c6c9909f7f40b8feca39d8695a181e879802 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 18 Sep 2022 19:17:31 +0200 Subject: [PATCH 016/144] [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 5792aa92500..acc18c6618f 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -133,18 +133,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, {} ); @@ -155,14 +155,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 1b0815e67a1678d7aabe3c51ee4064a7ff6aadb9 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:15:20 +0200 Subject: [PATCH 017/144] [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 4e1a231e15d..d863b918316 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -1,15 +1,16 @@ #pragma once -#include "Core/Geometry/IndexedGeometry.hpp" #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -277,7 +278,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 6512f613c8eb4e987a8b5c780f6e9f4902a17f47 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:15:38 +0200 Subject: [PATCH 018/144] [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 8d464c15a71..d22621aa202 100644 --- a/src/Engine/Rendering/ForwardRenderer.cpp +++ b/src/Engine/Rendering/ForwardRenderer.cpp @@ -7,13 +7,17 @@ #include #include +#include #include +#include #include #include - +#include #include #include +#include #include +#include #include #include #include @@ -21,6 +25,7 @@ #include #include #include +#include #include #include @@ -31,6 +36,8 @@ #include +#include +#include #include #include @@ -264,8 +271,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(); @@ -472,61 +477,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; @@ -550,16 +500,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" ); } @@ -596,17 +543,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 9ad560e375d06301eb8adb1a576274aa9cfd6970 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:15:50 +0200 Subject: [PATCH 019/144] [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 c728ad4b256094556f336df9f4e1c90bdd2a6aeb Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:16:14 +0200 Subject: [PATCH 020/144] [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 008fb32973c..3cde32acd62 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 bc6889b1f89dfcc7232fa70aa9edb2143c17b12b Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:16:32 +0200 Subject: [PATCH 021/144] [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 27a13c7e3b8..fe57ac6ac3a 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -1,7 +1,5 @@ #include -#include - #include #include #include @@ -12,29 +10,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 ); @@ -43,8 +31,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 ); @@ -139,12 +125,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" ); } @@ -232,9 +214,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 ) ); @@ -246,8 +225,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 bd1852ff7e2..d020cce5707 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -453,12 +453,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$ @@ -563,6 +559,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 f3b7cc0008cde2f471e79904e5c9ae8c33842c3f Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 19 Sep 2022 09:16:47 +0200 Subject: [PATCH 022/144] [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 e9a6f959e345bbac1b96dc86c322de2124c963ef Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 27 Oct 2022 11:02:12 +0200 Subject: [PATCH 023/144] [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 d863b918316..805d2d051c8 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -118,7 +118,6 @@ class SurfaceMeshComponent : public GeometryComponent using TriangleMeshComponent = SurfaceMeshComponent; using GeometryDisplayableComponent = SurfaceMeshComponent; -using LineMeshComponent = SurfaceMeshComponent; using QuadMeshComponent = SurfaceMeshComponent; using PolyMeshComponent = SurfaceMeshComponent; From d6237d9f3e4075bd4204a0550bad03f119f8a61a Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 8 Dec 2022 09:24:39 +0100 Subject: [PATCH 024/144] [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 36ff8fe5a2b66adf1dc6e349cac624c712febb9f Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 8 Dec 2022 09:25:15 +0100 Subject: [PATCH 025/144] [core] use inverse transpose for normal lbs. --- src/Core/Animation/LinearBlendSkinning.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Core/Animation/LinearBlendSkinning.cpp b/src/Core/Animation/LinearBlendSkinning.cpp index 29659da80f8..20da70a25b9 100644 --- a/src/Core/Animation/LinearBlendSkinning.cpp +++ b/src/Core/Animation/LinearBlendSkinning.cpp @@ -1,5 +1,3 @@ -#include -#include #include #include #include @@ -43,9 +41,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 1d1e14e1424a3e04f3cee70e313a3a60419bd512 Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 8 Dec 2022 09:25:41 +0100 Subject: [PATCH 026/144] [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 add984e4d7c..32d5061e556 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 60ce865aadcf9078a03ed92b6a5862086d97ec5b Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 8 Dec 2022 09:29:07 +0100 Subject: [PATCH 027/144] [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 bfe90e56e12..5ef45e34a03 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 2aa0a2a2a1e16aecd13b1e21e3947c8d843cfeb0 Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 8 Dec 2022 09:30:13 +0100 Subject: [PATCH 028/144] [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 805d2d051c8..43da347c2e9 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -351,6 +351,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 0f1a771068b6385d9f1be0abf5b87ceb5f0c1b6e Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 16 May 2023 15:01:59 +0200 Subject: [PATCH 029/144] [core] Temporary remove non working file from base 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 2daa2a9b9d5..00bd624bfe6 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 @@ -60,7 +60,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 From 38c6286bddecd713610f89831aaf5028788bcd4d Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 3 May 2025 19:35:12 +0200 Subject: [PATCH 030/144] [core] Remove dead code. --- src/Core/Geometry/MeshPrimitives.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index 3cde32acd62..92957202e07 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -209,7 +209,6 @@ MultiIndexedGeometry makeSharpBox2( const Aabb& aabb, Vector4ui( 16, 17, 18, 19 ), // Bottom Vector4ui( 20, 21, 22, 23 ) // Top }; - auto semantic = layer->semantics(); result.addLayer( std::move( layer ) ); if ( bool( color ) ) result.colorize( *color ); From ce3381ac9323f15a2adeb107f88183755744f56f Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 3 May 2025 19:35:34 +0200 Subject: [PATCH 031/144] [core] Add missing include for std_any. --- src/Core/Utils/ObjectWithSemantic.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Core/Utils/ObjectWithSemantic.hpp b/src/Core/Utils/ObjectWithSemantic.hpp index 03dba6da268..81897a5851a 100644 --- a/src/Core/Utils/ObjectWithSemantic.hpp +++ b/src/Core/Utils/ObjectWithSemantic.hpp @@ -2,6 +2,7 @@ #include +#include #include #include From c2e10668691684351cac0fd2a07256fd64c768b9 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 3 May 2025 19:36:28 +0200 Subject: [PATCH 032/144] [engine] Add setter for active layer. --- src/Engine/Data/Mesh.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 0fa1e682ec0..3a5da751e90 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -404,6 +404,8 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable inline size_t getNumVertices() const override { return m_geom.vertices().size(); } + void set_active_layer( LayerKeyType layer_key ) { m_activeLayerKey = layer_key; } + protected: void setupCoreMeshObservers(); From 969142c970942ce90a8721425e355c42df70898c Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 3 May 2025 19:38:09 +0200 Subject: [PATCH 033/144] [engine] Use GeometryDisplayable for DrawPrimitive::Triangle. --- src/Core/Geometry/IndexedGeometry.cpp | 10 ++-- src/Core/Geometry/IndexedGeometry.hpp | 7 ++- src/Engine/Data/DrawPrimitives.cpp | 66 ++++++++++++++++----------- src/Engine/Data/DrawPrimitives.hpp | 12 +++-- 4 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index fe57ac6ac3a..6ee8d63da9a 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -210,10 +210,10 @@ void MultiIndexedGeometry::unlockLayer( const LayerKeyType& layerKey ) { ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// -std::pair -MultiIndexedGeometry::addLayer( std::unique_ptr&& layer, - const bool withLock, - const std::string& layerName ) { +auto MultiIndexedGeometry::addLayer( std::unique_ptr&& layer, + const bool withLock, + const std::string& layerName ) + -> std::pair { 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 ) ); @@ -226,7 +226,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. - return { inserted, *( pos->second.second ) }; + return { inserted, key }; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index d020cce5707..32c728623f2 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -404,10 +404,9 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// /// \warning Takes the ownership of the layer /// - std::pair - addLayer( std::unique_ptr&& layer, - const bool withLock = false, - const std::string& layerName = "" ); + auto addLayer( std::unique_ptr&& layer, + const bool withLock = false, + const std::string& layerName = "" ) -> std::pair; /// \brief Range on layer keys (read-only) /// diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index 6d1ec29c72a..f3518dffd10 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -111,29 +112,45 @@ LineMeshPtr Ray( const Core::Ray& ray, const Core::Utils::Color& color, Scalar l return make_shared( "Ray Primitive", std::move( geom ) ); } -AttribArrayDisplayablePtr Triangle( const Core::Vector3& a, - const Core::Vector3& b, - const Core::Vector3& c, - const Core::Utils::Color& color, - bool fill ) { - if ( fill ) { - Geometry::TriangleMesh geom; - geom.setVertices( { a, b, c } ); - geom.setIndices( { { 0, 1, 2 } } ); - geom.addAttrib( - Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), - Core::Vector4Array { geom.vertices().size(), color } ); - return make_shared( "Triangle Primitive", std::move( geom ) ); - } - else { - Geometry::LineMesh geom; - geom.setVertices( { a, b, c } ); - geom.setIndices( { { 0, 1 }, { 1, 2 }, { 2, 0 } } ); - geom.addAttrib( - Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), - Core::Vector4Array { geom.vertices().size(), color } ); - return make_shared( "Triangle Primitive", std::move( geom ) ); - } +GeometryDisplayablePtr Triangle( const Core::Vector3& a, + const Core::Vector3& b, + const Core::Vector3& c, + const Core::Utils::Color& color, + bool fill ) { + + MultiIndexedGeometry geom; + geom.setVertices( { a, b, c } ); + + auto face_layer = std::make_unique(); + face_layer->collection() = { { 0, 1, 2 } }; + geom.addLayer( std::move( face_layer ) ); + + auto boundary_layer = std::make_unique(); + boundary_layer->collection() = { { 0, 1 }, { 1, 2 }, { 2, 0 } }; + geom.addLayer( std::move( boundary_layer ) ); + + geom.addAttrib( + Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), + Core::Vector4Array { geom.vertices().size(), color } ); + + auto [face_key, dummy_1] = + geom.getFirstLayerOccurrence( Core::Geometry::TriangleIndexLayer::staticSemanticName ); + auto [boundary_key, dummy_2] = + geom.getFirstLayerOccurrence( Core::Geometry::LineIndexLayer::staticSemanticName ); + + auto ret = make_shared( "Triangle" ); + std::vector< + std::pair> + r { { face_key, AttribArrayDisplayable::RM_TRIANGLES }, + { boundary_key, AttribArrayDisplayable::RM_LINES } }; + ret->loadGeometry( std::move( geom ), r ); + + auto [key, layer] = ret->getCoreGeometry().getFirstLayerOccurrence( + Core::Geometry::TriangleIndexLayer::staticSemanticName ); + + if ( fill ) { ret->set_active_layer( face_key ); } + + return ret; } /// \todo continue to convert mesh creation and remove call to deprecated Mesh::loadGeometry @@ -211,7 +228,6 @@ LineMeshPtr CircleArc( const Core::Vector3& center, Scalar angle, uint segments, const Core::Utils::Color& color ) { - Geometry::LineMesh geom; Core::Vector3Array vertices( segments + 1 ); Geometry::LineMesh::IndexContainerType indices; @@ -434,7 +450,6 @@ MeshPtr Grid( const Core::Vector3& center, const Core::Utils::Color& color, Scalar cellSize, uint res ) { - CORE_ASSERT( res > 1, "Grid has to be at least a 2x2 grid." ); Core::Vector3Array vertices; std::vector indices; @@ -552,7 +567,6 @@ MeshPtr Spline( const Core::Geometry::Spline<3, 3>& spline, } MeshPtr LineStrip( const Core::Vector3Array& vertices, const Core::Vector4Array& colors ) { - std::vector indices( vertices.size() ); std::iota( indices.begin(), indices.end(), 0 ); auto r = ( vertices.size() % 3 ); diff --git a/src/Engine/Data/DrawPrimitives.hpp b/src/Engine/Data/DrawPrimitives.hpp index 90866409d27..37f200940c1 100644 --- a/src/Engine/Data/DrawPrimitives.hpp +++ b/src/Engine/Data/DrawPrimitives.hpp @@ -24,6 +24,7 @@ namespace Data { class Mesh; class AttribArrayDisplayable; class LineMesh; +class GeometryDisplayable; /// A set of convenient functions to instantiate simple displays such as points, lines, etc. /// note that objects will be drawn in their entity's local frame. @@ -32,6 +33,7 @@ namespace DrawPrimitives { using MeshPtr = std::shared_ptr; using LineMeshPtr = std::shared_ptr; using AttribArrayDisplayablePtr = std::shared_ptr; +using GeometryDisplayablePtr = std::shared_ptr; ///\{ /// Renturn a render object to display the given geometry @@ -63,11 +65,11 @@ RA_ENGINE_API LineMeshPtr Ray( const Core::Ray& ray, /// Displays given triangle ABC, either in wireframe (fill = false) /// or filled with the color(fill = true). -RA_ENGINE_API AttribArrayDisplayablePtr Triangle( const Core::Vector3& a, - const Core::Vector3& b, - const Core::Vector3& c, - const Core::Utils::Color& color, - bool fill = false ); +RA_ENGINE_API GeometryDisplayablePtr Triangle( const Core::Vector3& a, + const Core::Vector3& b, + const Core::Vector3& c, + const Core::Utils::Color& color, + bool fill = false ); /// Displays a strip of n quads, starting at A and with directions X and Y. RA_ENGINE_API MeshPtr QuadStrip( const Core::Vector3& a, From df5ff4baca451466712a73c37c585171b7df0c49 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 4 May 2025 00:22:50 +0200 Subject: [PATCH 034/144] [engine] Remove LineMesh (use GeometryDisplayable instead). --- src/Engine/Data/DrawPrimitives.cpp | 98 +++++++++++------------- src/Engine/Data/DrawPrimitives.hpp | 57 +++++++------- src/Engine/Data/Mesh.hpp | 55 ++++--------- src/Engine/Rendering/DebugRender.cpp | 2 +- src/Engine/Rendering/ForwardRenderer.cpp | 80 +------------------ src/Engine/Scene/CameraComponent.cpp | 2 +- 6 files changed, 90 insertions(+), 204 deletions(-) diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index f3518dffd10..463911022b3 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -1,18 +1,18 @@ +#include "Core/CoreMacros.hpp" #include +#include #include #include #include #include #include +#include #include #include #include -#include -#include - #include #include @@ -29,10 +29,6 @@ Rendering::RenderObject* Primitive( Scene::Component* component, const MeshPtr& return Primitive( component, std::dynamic_pointer_cast( mesh ) ); } -Rendering::RenderObject* Primitive( Scene::Component* component, const LineMeshPtr& mesh ) { - return Primitive( component, std::dynamic_pointer_cast( mesh ) ); -} - Rendering::RenderObject* Primitive( Scene::Component* component, const AttribArrayDisplayablePtr& mesh ) { Rendering::RenderTechnique rt; @@ -49,7 +45,8 @@ Rendering::RenderObject* Primitive( Scene::Component* component, return ro; } -LineMeshPtr Point( const Core::Vector3& point, const Core::Utils::Color& color, Scalar scale ) { +GeometryDisplayablePtr +Point( const Core::Vector3& point, const Core::Utils::Color& color, Scalar scale ) { Geometry::LineMesh geom; geom.setVertices( { ( point + ( scale * Core::Vector3::UnitX() ) ), @@ -63,10 +60,10 @@ LineMeshPtr Point( const Core::Vector3& point, const Core::Utils::Color& color, Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); - return make_shared( "Point Primitive", std::move( geom ) ); + return make_shared( "Point Primitive", std::move( geom ) ); } -LineMeshPtr +GeometryDisplayablePtr Line( const Core::Vector3& a, const Core::Vector3& b, const Core::Utils::Color& color ) { Geometry::LineMesh geom; geom.setVertices( { a, b } ); @@ -75,10 +72,10 @@ Line( const Core::Vector3& a, const Core::Vector3& b, const Core::Utils::Color& Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); - return make_shared( "Line Primitive", std::move( geom ) ); + return make_shared( "Line Primitive", std::move( geom ) ); } -LineMeshPtr +GeometryDisplayablePtr Vector( const Core::Vector3& start, const Core::Vector3& v, const Core::Utils::Color& color ) { Core::Vector3 end = start + v; Core::Vector3 a, b; @@ -98,10 +95,10 @@ Vector( const Core::Vector3& start, const Core::Vector3& v, const Core::Utils::C Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); - return make_shared( "Vector Primitive", std::move( geom ) ); + return make_shared( "Vector Primitive", std::move( geom ) ); } -LineMeshPtr Ray( const Core::Ray& ray, const Core::Utils::Color& color, Scalar len ) { +GeometryDisplayablePtr Ray( const Core::Ray& ray, const Core::Utils::Color& color, Scalar len ) { Geometry::LineMesh geom; Core::Vector3 end = ray.pointAt( len ); geom.setVertices( { ray.origin(), end } ); @@ -109,7 +106,7 @@ LineMeshPtr Ray( const Core::Ray& ray, const Core::Utils::Color& color, Scalar l geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); - return make_shared( "Ray Primitive", std::move( geom ) ); + return make_shared( "Ray Primitive", std::move( geom ) ); } GeometryDisplayablePtr Triangle( const Core::Vector3& a, @@ -121,34 +118,31 @@ GeometryDisplayablePtr Triangle( const Core::Vector3& a, MultiIndexedGeometry geom; geom.setVertices( { a, b, c } ); - auto face_layer = std::make_unique(); - face_layer->collection() = { { 0, 1, 2 } }; - geom.addLayer( std::move( face_layer ) ); + auto face_layer = std::make_unique(); + face_layer->collection() = { { 0, 1, 2 } }; + auto [face_check, face_key] = geom.addLayer( std::move( face_layer ) ); + CORE_ASSERT( face_check, "failed to add triangle layer" ); - auto boundary_layer = std::make_unique(); - boundary_layer->collection() = { { 0, 1 }, { 1, 2 }, { 2, 0 } }; - geom.addLayer( std::move( boundary_layer ) ); + auto boundary_layer = std::make_unique(); + boundary_layer->collection() = { { 0, 1 }, { 1, 2 }, { 2, 0 } }; + auto [boundary_check, boundary_key] = geom.addLayer( std::move( boundary_layer ) ); + CORE_ASSERT( boundary_check, "failed to add line layer" ); geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); - auto [face_key, dummy_1] = - geom.getFirstLayerOccurrence( Core::Geometry::TriangleIndexLayer::staticSemanticName ); - auto [boundary_key, dummy_2] = - geom.getFirstLayerOccurrence( Core::Geometry::LineIndexLayer::staticSemanticName ); - auto ret = make_shared( "Triangle" ); - std::vector< - std::pair> - r { { face_key, AttribArrayDisplayable::RM_TRIANGLES }, - { boundary_key, AttribArrayDisplayable::RM_LINES } }; - ret->loadGeometry( std::move( geom ), r ); - auto [key, layer] = ret->getCoreGeometry().getFirstLayerOccurrence( - Core::Geometry::TriangleIndexLayer::staticSemanticName ); + using LayerKeysType = std::array< + std::pair, + 2>; + + ret->loadGeometry( std::move( geom ), + LayerKeysType { { { face_key, AttribArrayDisplayable::RM_TRIANGLES }, + { boundary_key, AttribArrayDisplayable::RM_LINES } } } ); - if ( fill ) { ret->set_active_layer( face_key ); } + if ( fill ) { ret->set_active_layer_key( face_key ); } return ret; } @@ -184,11 +178,11 @@ MeshPtr QuadStrip( const Core::Vector3& a, return mesh; } -LineMeshPtr Circle( const Core::Vector3& center, - const Core::Vector3& normal, - Scalar radius, - uint segments, - const Core::Utils::Color& color ) { +GeometryDisplayablePtr Circle( const Core::Vector3& center, + const Core::Vector3& normal, + Scalar radius, + uint segments, + const Core::Utils::Color& color ) { CORE_ASSERT( segments >= 2, "Cannot draw a circle with less than 3 points" ); Geometry::LineMesh geom; @@ -219,15 +213,15 @@ LineMeshPtr Circle( const Core::Vector3& center, Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); - return make_shared( "Circle Primitive", std::move( geom ) ); + return make_shared( "Circle Primitive", std::move( geom ) ); } -LineMeshPtr CircleArc( const Core::Vector3& center, - const Core::Vector3& normal, - Scalar radius, - Scalar angle, - uint segments, - const Core::Utils::Color& color ) { +GeometryDisplayablePtr CircleArc( const Core::Vector3& center, + const Core::Vector3& normal, + Scalar radius, + Scalar angle, + uint segments, + const Core::Utils::Color& color ) { Geometry::LineMesh geom; Core::Vector3Array vertices( segments + 1 ); Geometry::LineMesh::IndexContainerType indices; @@ -256,7 +250,7 @@ LineMeshPtr CircleArc( const Core::Vector3& center, Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); - return make_shared( "Arc Circle Primitive", std::move( geom ) ); + return make_shared( "Arc Circle Primitive", std::move( geom ) ); } MeshPtr Sphere( const Core::Vector3& center, Scalar radius, const Core::Utils::Color& color ) { @@ -366,10 +360,10 @@ MeshPtr Disk( const Core::Vector3& center, return mesh; } -LineMeshPtr Normal( const Core::Vector3& point, - const Core::Vector3& normal, - const Core::Utils::Color& color, - Scalar scale ) { +GeometryDisplayablePtr Normal( const Core::Vector3& point, + const Core::Vector3& normal, + const Core::Utils::Color& color, + Scalar scale ) { // Display an arrow (just like the Vector() function) // plus the normal plane. Core::Vector3 a, b; @@ -411,7 +405,7 @@ LineMeshPtr Normal( const Core::Vector3& point, Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); - return make_shared( "Normal Primitive", std::move( geom ) ); + return make_shared( "Normal Primitive", std::move( geom ) ); } MeshPtr Frame( const Core::Transform& frameFromEntity, Scalar scale ) { diff --git a/src/Engine/Data/DrawPrimitives.hpp b/src/Engine/Data/DrawPrimitives.hpp index 37f200940c1..652fbc4c5f3 100644 --- a/src/Engine/Data/DrawPrimitives.hpp +++ b/src/Engine/Data/DrawPrimitives.hpp @@ -23,7 +23,6 @@ class Component; namespace Data { class Mesh; class AttribArrayDisplayable; -class LineMesh; class GeometryDisplayable; /// A set of convenient functions to instantiate simple displays such as points, lines, etc. @@ -31,37 +30,35 @@ class GeometryDisplayable; /// For "instant" debug drawing, \see DebugDisplay. namespace DrawPrimitives { using MeshPtr = std::shared_ptr; -using LineMeshPtr = std::shared_ptr; using AttribArrayDisplayablePtr = std::shared_ptr; using GeometryDisplayablePtr = std::shared_ptr; ///\{ /// Renturn a render object to display the given geometry RA_ENGINE_API Rendering::RenderObject* Primitive( Scene::Component* comp, const MeshPtr& mesh ); -RA_ENGINE_API Rendering::RenderObject* Primitive( Scene::Component* comp, const LineMeshPtr& mesh ); RA_ENGINE_API Rendering::RenderObject* Primitive( Scene::Component* comp, const AttribArrayDisplayablePtr& mesh ); ///\} /// Displays given point shown as the crossing of 3 lines of length 'scale' -RA_ENGINE_API LineMeshPtr Point( const Core::Vector3& point, - const Core::Utils::Color& color, - Scalar scale = 0.1f ); +RA_ENGINE_API GeometryDisplayablePtr Point( const Core::Vector3& point, + const Core::Utils::Color& color, + Scalar scale = 0.1f ); /// Displays given line -RA_ENGINE_API LineMeshPtr Line( const Core::Vector3& a, - const Core::Vector3& b, - const Core::Utils::Color& color ); +RA_ENGINE_API GeometryDisplayablePtr Line( const Core::Vector3& a, + const Core::Vector3& b, + const Core::Utils::Color& color ); /// Displays given vector shown as an arrow originating from 'start' -RA_ENGINE_API LineMeshPtr Vector( const Core::Vector3& start, - const Core::Vector3& v, - const Core::Utils::Color& color ); +RA_ENGINE_API GeometryDisplayablePtr Vector( const Core::Vector3& start, + const Core::Vector3& v, + const Core::Utils::Color& color ); /// Displays given ray as a straight line. -RA_ENGINE_API LineMeshPtr Ray( const Core::Ray& ray, - const Core::Utils::Color& color, - Scalar len = 1000_ra ); +RA_ENGINE_API GeometryDisplayablePtr Ray( const Core::Ray& ray, + const Core::Utils::Color& color, + Scalar len = 1000_ra ); /// Displays given triangle ABC, either in wireframe (fill = false) /// or filled with the color(fill = true). @@ -81,21 +78,21 @@ RA_ENGINE_API MeshPtr QuadStrip( const Core::Vector3& a, /// Displays circle computed with given center and radius, /// in plane normal to given vector in wireframe /// \note normal must be a normalized vector. -RA_ENGINE_API LineMeshPtr Circle( const Core::Vector3& center, - const Core::Vector3& normal, - Scalar radius, - uint segments, - const Core::Utils::Color& color ); +RA_ENGINE_API GeometryDisplayablePtr Circle( const Core::Vector3& center, + const Core::Vector3& normal, + Scalar radius, + uint segments, + const Core::Utils::Color& color ); /// Displays arc of a circle computed with given center, radius and angle /// in plane normal to given vector in wireframe /// \note normal must be a normalized vector. -RA_ENGINE_API LineMeshPtr CircleArc( const Core::Vector3& center, - const Core::Vector3& normal, - Scalar radius, - Scalar angle, - uint segments, - const Core::Utils::Color& color ); +RA_ENGINE_API GeometryDisplayablePtr CircleArc( const Core::Vector3& center, + const Core::Vector3& normal, + Scalar radius, + Scalar angle, + uint segments, + const Core::Utils::Color& color ); /// Displays geodesic sphere computed with given center and radius RA_ENGINE_API MeshPtr Sphere( const Core::Vector3& center, @@ -126,10 +123,10 @@ RA_ENGINE_API MeshPtr Disk( const Core::Vector3& center, /// Displays a normal vector emanating from the given point as a vector arrow /// and a normal plane of size 'scale'. -RA_ENGINE_API LineMeshPtr Normal( const Core::Vector3& point, - const Core::Vector3& normal, - const Core::Utils::Color& color, - Scalar scale = 0.1f ); +RA_ENGINE_API GeometryDisplayablePtr Normal( const Core::Vector3& point, + const Core::Vector3& normal, + const Core::Utils::Color& color, + Scalar scale = 0.1f ); /// Displays a 3D frame representing the given transform. /// Each axis has length 'scale' and are in usual colors diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 3a5da751e90..39c2c0765a0 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -378,22 +378,26 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable 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} } + /// \todo c++20 switch to range concept 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 ); - } +} + inline void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, + LayerKeyType key, + base::MeshRenderMode renderMode ) { + using LayerKeysType = std::array< + std::pair, + 1>; + loadGeometry( std::move( mesh ), LayerKeysType { { { key, renderMode } } } ); + } + bool addRenderLayer( LayerKeyType key, base::MeshRenderMode renderMode ); bool removeRenderLayer( LayerKeyType key ); // bool setRenderMode( LayerKeyType key, RenderMode ); @@ -404,7 +408,8 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable inline size_t getNumVertices() const override { return m_geom.vertices().size(); } - void set_active_layer( LayerKeyType layer_key ) { m_activeLayerKey = layer_key; } + void set_active_layer_key( LayerKeyType layer_key ) { m_activeLayerKey = layer_key; } + LayerKeyType active_layer_key() { return m_activeLayerKey; } protected: void setupCoreMeshObservers(); @@ -461,25 +466,6 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable BijectiveAssociation m_translationTable {}; }; -/// LineMesh, own a Core::Geometry::LineMesh -class RA_ENGINE_API LineMesh : public IndexedGeometry -{ - using base = IndexedGeometry; - - public: - using base::IndexedGeometry; - inline explicit LineMesh( - const std::string& name, - typename base::CoreGeometry&& geom, - typename base::MeshRenderMode renderMode = base::MeshRenderMode::RM_LINES ); - inline explicit LineMesh( - const std::string& name, - typename base::MeshRenderMode renderMode = base::MeshRenderMode::RM_LINES ); - - protected: - private: -}; - /// Mesh, own a Core::Geometry::TriangleMesh class RA_ENGINE_API Mesh : public IndexedGeometry { @@ -573,11 +559,6 @@ namespace RenderMeshType { template struct getType {}; -template <> -struct getType { - using Type = Ra::Engine::Data::LineMesh; -}; - template <> struct getType { using Type = Ra::Engine::Data::Mesh; @@ -971,16 +952,6 @@ PointCloud::PointCloud( const std::string& name, PointCloud::PointCloud( const std::string& name, typename base::MeshRenderMode renderMode ) : base( name, renderMode ) {} -///////// LineMesh /////////// - -LineMesh::LineMesh( const std::string& name, - typename base::CoreGeometry&& geom, - typename base::MeshRenderMode renderMode ) : - base( name, std::move( geom ), renderMode ) {} - -LineMesh::LineMesh( const std::string& name, typename base::MeshRenderMode renderMode ) : - base( name, renderMode ) {} - ///////// PolyMesh /////////// template diff --git a/src/Engine/Rendering/DebugRender.cpp b/src/Engine/Rendering/DebugRender.cpp index a9f6953f7c2..5e373fd542c 100644 --- a/src/Engine/Rendering/DebugRender.cpp +++ b/src/Engine/Rendering/DebugRender.cpp @@ -167,7 +167,7 @@ void DebugRender::renderLines( const Core::Matrix4f& viewMatrix, geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_COLOR ), colors ); - Data::LineMesh mesh( "temp", std::move( geom ) ); + Data::GeometryDisplayable mesh( "temp", std::move( geom ) ); mesh.updateGL(); ///\todo diff --git a/src/Engine/Rendering/ForwardRenderer.cpp b/src/Engine/Rendering/ForwardRenderer.cpp index d22621aa202..8517a5ce5d3 100644 --- a/src/Engine/Rendering/ForwardRenderer.cpp +++ b/src/Engine/Rendering/ForwardRenderer.cpp @@ -168,29 +168,6 @@ void ForwardRenderer::updateStepInternal( const Data::ViewingParameters& renderD if ( m_fancyRenderObjects.size() < m_wireframes.size() ) { m_wireframes.clear(); } } -template -void computeIndices( Core::Geometry::LineMesh::IndexContainerType& indices, - 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() ); -} - template void computeIndices2( Core::Geometry::LineIndexLayer::IndexContainerType& indices, const IndexContainerType& other ) { @@ -214,60 +191,6 @@ void computeIndices2( Core::Geometry::LineIndexLayer::IndexContainerType& indice 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 -class VerticesUpdater -{ - public: - VerticesUpdater( std::shared_ptr disp, CoreGeometry& core ) : - m_disp { disp }, m_core { core } {}; - - void operator()() { m_disp->getCoreGeometry().setVertices( m_core.vertices() ); } - std::shared_ptr m_disp; - CoreGeometry& m_core; -}; - -template -class IndicesUpdater -{ - public: - IndicesUpdater( std::shared_ptr disp, CoreGeometry& core ) : - m_disp { disp }, m_core { core } {}; - - void operator()() { - auto lineIndices = m_disp->getCoreGeometry().getIndicesWithLock(); - computeIndices( lineIndices, m_core.getIndices() ); - m_disp->getCoreGeometry().indicesUnlock(); - } - std::shared_ptr m_disp; - CoreGeometry& m_core; -}; - -// create a linemesh to draw wireframe given a core mesh -template -void setupLineMesh( std::shared_ptr& disp, CoreGeometry& core ) { - - Core::Geometry::LineMesh lines; - Core::Geometry::LineMesh::IndexContainerType indices; - - lines.setVertices( core.vertices() ); - computeIndices( indices, core.getIndices() ); - if ( indices.size() > 0 ) { - lines.setIndices( std::move( indices ) ); - disp = - Ra::Core::make_shared( std::string( "wireframe" ), std::move( lines ) ); - disp->updateGL(); - - // add observer - auto handle = core.template getAttribHandle( - Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_POSITION ) ); - core.vertexAttribs().getAttrib( handle ).attach( VerticesUpdater( disp, core ) ); - core.attach( IndicesUpdater( disp, core ) ); - } - else { disp.reset(); } -} - // create a linemesh to draw wireframe given a core mesh template void setupLineMesh( Data::GeometryDisplayable& displayable, const std::string& name ) { @@ -513,7 +436,7 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData const Data::ShaderProgram* shader = m_shaderProgramManager->getShaderProgram( "Wireframe" ); - if ( shader && ro->isVisible() ) { + if ( hasTriangleLayer && shader && ro->isVisible() ) { GL_CHECK_ERROR; td->updateGL(); GL_CHECK_ERROR; @@ -543,6 +466,7 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData } } else { + std::cerr << "not dispmesh " << displayable->getName() << "\n"; // skip } }; diff --git a/src/Engine/Scene/CameraComponent.cpp b/src/Engine/Scene/CameraComponent.cpp index eada0a8e68f..6bba8fa0121 100644 --- a/src/Engine/Scene/CameraComponent.cpp +++ b/src/Engine/Scene/CameraComponent.cpp @@ -54,7 +54,7 @@ void CameraComponent::initialize() { { 5, 6 }, { 6, 7 } } ); - auto m = std::make_shared( m_name + "_mesh" ); + auto m = std::make_shared( m_name + "_mesh" ); m->loadGeometry( std::move( triMesh ) ); // Create the RO From cdfa0a05569fc85389631e0fb21ea3716515ed69 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 4 May 2025 00:23:30 +0200 Subject: [PATCH 035/144] [examples] Use GeometryDisplayable for Poly example. --- examples/DrawPrimitives/AllPrimitivesComponent.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index acc18c6618f..e31aa219621 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -650,9 +650,8 @@ void AllPrimitivesComponent::initialize() { auto hepta = VectorNui( 7 ); hepta << 3, 2, 4, 5, 6, 7, 8; polyMesh.setIndices( { quad, hepta } ); + auto poly1 = make_shared( "Poly", std::move( polyMesh ) ); - std::shared_ptr poly1( - new Data::PolyMesh( "Poly", std::move( polyMesh ) ) ); poly1->getCoreGeometry().addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_COLOR ), Vector4Array { poly1->getNumVertices(), colorBoost * Color { 1_ra, 0.6_ra, 0.1_ra } } ); @@ -665,11 +664,12 @@ void AllPrimitivesComponent::initialize() { addRenderObject( renderObject1 ); - Ra::Core::Geometry::TopologicalMesh topo { poly1->getCoreGeometry() }; + Ra::Core::Geometry::TopologicalMesh topo { poly1->getCoreGeometry(), + poly1->active_layer_key() }; topo.triangulate(); topo.checkIntegrity(); auto triangulated = topo.toTriangleMesh(); - std::shared_ptr poly2( new Mesh( "Poly", std::move( triangulated ) ) ); + auto poly2 = make_shared( "Poly", std::move( triangulated ) ); poly2->getCoreGeometry().addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_COLOR ), Vector4Array { poly2->getNumVertices(), colorBoost * Color { 0_ra, 0.6_ra, 0.1_ra } } ); @@ -869,7 +869,7 @@ void AllPrimitivesComponent::initialize() { auto addMesh = [this, colorBoost, plainMaterial]( Vector3 pos, TopologicalMesh topo1 ) { topo1.checkIntegrity(); auto mesh1 = topo1.toTriangleMesh(); - std::shared_ptr poly( new Mesh( "TEST", std::move( mesh1 ) ) ); + auto poly = make_shared( "topo mesh", std::move( mesh1 ) ); auto renderObject2 = RenderObject::createRenderObject( "TEST", this, RenderObjectType::Geometry, poly, {} ); From 9bdb07cd1bbd355f4ce59ef1e96020332839d8fb Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 4 May 2025 14:08:50 +0200 Subject: [PATCH 036/144] [engine] Sphere use GeometryDisplayable. --- src/Engine/Data/DrawPrimitives.cpp | 22 ++++++++++++++-------- src/Engine/Data/DrawPrimitives.hpp | 17 ++++++++++------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index 463911022b3..7fbba814c15 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -29,6 +29,11 @@ Rendering::RenderObject* Primitive( Scene::Component* component, const MeshPtr& return Primitive( component, std::dynamic_pointer_cast( mesh ) ); } +Rendering::RenderObject* Primitive( Scene::Component* component, + const GeometryDisplayablePtr& mesh ) { + return Primitive( component, std::dynamic_pointer_cast( mesh ) ); +} + Rendering::RenderObject* Primitive( Scene::Component* component, const AttribArrayDisplayablePtr& mesh ) { Rendering::RenderTechnique rt; @@ -253,8 +258,9 @@ GeometryDisplayablePtr CircleArc( const Core::Vector3& center, return make_shared( "Arc Circle Primitive", std::move( geom ) ); } -MeshPtr Sphere( const Core::Vector3& center, Scalar radius, const Core::Utils::Color& color ) { - auto geom = makeGeodesicSphere( radius, 4, color ); +GeometryDisplayablePtr +Sphere( const Core::Vector3& center, Scalar radius, const Core::Utils::Color& color ) { + auto geom = makeGeodesicSphere( radius, 3, color ); auto handle = geom.getAttribHandle( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_POSITION ) ); auto& vertices = geom.getAttrib( handle ); @@ -263,13 +269,13 @@ MeshPtr Sphere( const Core::Vector3& center, Scalar radius, const Core::Utils::C std::for_each( data.begin(), data.end(), [center]( Core::Vector3& v ) { v += center; } ); vertices.unlock(); - return make_shared( "Sphere Primitive", std::move( geom ) ); + return make_shared( "Sphere Primitive", std::move( geom ) ); } -MeshPtr ParametricSphere( const Core::Vector3& center, - Scalar radius, - const Core::Utils::Color& color, - bool generateTexCoord ) { +GeometryDisplayablePtr ParametricSphere( const Core::Vector3& center, + Scalar radius, + const Core::Utils::Color& color, + bool generateTexCoord ) { auto geom = makeParametricSphere<32, 32>( radius, color, generateTexCoord ); auto handle = geom.getAttribHandle( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_POSITION ) ); @@ -279,7 +285,7 @@ MeshPtr ParametricSphere( const Core::Vector3& center, std::for_each( data.begin(), data.end(), [center]( Core::Vector3& v ) { v += center; } ); vertices.unlock(); - return make_shared( "Sphere Primitive", std::move( geom ) ); + return make_shared( "Sphere Primitive", std::move( geom ) ); } MeshPtr Capsule( const Core::Vector3& p1, diff --git a/src/Engine/Data/DrawPrimitives.hpp b/src/Engine/Data/DrawPrimitives.hpp index 652fbc4c5f3..0d338c58656 100644 --- a/src/Engine/Data/DrawPrimitives.hpp +++ b/src/Engine/Data/DrawPrimitives.hpp @@ -36,8 +36,11 @@ using GeometryDisplayablePtr = std::shared_ptr; ///\{ /// Renturn a render object to display the given geometry RA_ENGINE_API Rendering::RenderObject* Primitive( Scene::Component* comp, const MeshPtr& mesh ); +RA_ENGINE_API Rendering::RenderObject* Primitive( Scene::Component* comp, + const GeometryDisplayablePtr& mesh ); RA_ENGINE_API Rendering::RenderObject* Primitive( Scene::Component* comp, const AttribArrayDisplayablePtr& mesh ); + ///\} /// Displays given point shown as the crossing of 3 lines of length 'scale' @@ -95,16 +98,16 @@ RA_ENGINE_API GeometryDisplayablePtr CircleArc( const Core::Vector3& center, const Core::Utils::Color& color ); /// Displays geodesic sphere computed with given center and radius -RA_ENGINE_API MeshPtr Sphere( const Core::Vector3& center, - Scalar radius, - const Core::Utils::Color& color ); +RA_ENGINE_API GeometryDisplayablePtr Sphere( const Core::Vector3& center, + Scalar radius, + const Core::Utils::Color& color ); /// Displays uv sphere computed with given center and radius /// \param generateTexCoord: ask texture coordinate generation -RA_ENGINE_API MeshPtr ParametricSphere( const Core::Vector3& center, - Scalar radius, - const Core::Utils::Color& color, - bool generateTexCoord = false ); +RA_ENGINE_API GeometryDisplayablePtr ParametricSphere( const Core::Vector3& center, + Scalar radius, + const Core::Utils::Color& color, + bool generateTexCoord = false ); /// Displays a capsule computed with given endpoints and radius. RA_ENGINE_API MeshPtr Capsule( const Core::Vector3& p1, From c833e424e8bf808401f5ec99b89982ad29982c44 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 4 May 2025 22:51:25 +0200 Subject: [PATCH 037/144] [engine] Fix set render mode when set active key (to update picking render mode). --- src/Engine/Data/Mesh.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 39c2c0765a0..7342241421d 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -408,7 +408,10 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable inline size_t getNumVertices() const override { return m_geom.vertices().size(); } - void set_active_layer_key( LayerKeyType layer_key ) { m_activeLayerKey = layer_key; } + void set_active_layer_key( LayerKeyType layer_key ) { + m_activeLayerKey = layer_key; + setRenderMode( m_geomLayers[layer_key].renderMode ); + } LayerKeyType active_layer_key() { return m_activeLayerKey; } protected: From 51d2a16375b928131cc91adb05dc3a0ce49e7f60 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 5 May 2025 09:21:07 +0200 Subject: [PATCH 038/144] [core][engine] Move grid to mesh primitives, small refactor also. Plane/Quad uses QuadMesh. Add ArrayOfLayerKeys to ease setup. --- src/Core/Geometry/MeshPrimitives.cpp | 108 +++++++++++++++++------- src/Core/Geometry/MeshPrimitives.hpp | 54 ++++++------ src/Core/Geometry/TriangleMesh.hpp | 2 + src/Engine/Data/DrawPrimitives.cpp | 58 +++---------- src/Engine/Data/DrawPrimitives.hpp | 12 +-- src/Engine/Data/Mesh.cpp | 10 ++- src/Engine/Data/Mesh.hpp | 10 +-- src/Engine/Rendering/Renderer.cpp | 5 +- src/Gui/Viewer/Gizmo/ScaleGizmo.cpp | 7 +- src/Gui/Viewer/Gizmo/TranslateGizmo.cpp | 5 +- 10 files changed, 148 insertions(+), 123 deletions(-) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index 92957202e07..2670aac471d 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -12,27 +12,27 @@ namespace Ra { namespace Core { namespace Geometry { -TriangleMesh makeXNormalQuad( const Vector2& halfExts, - const Utils::optional& color, - bool generateTexCoord ) { +QuadMesh makeXNormalQuad( const Vector2& halfExts, + const Utils::optional& color, + bool generateTexCoord ) { Transform T = Transform::Identity(); T.linear().col( 0 ).swap( T.linear().col( 1 ) ); T.linear().col( 1 ).swap( T.linear().col( 2 ) ); return makePlaneGrid( 1, 1, halfExts, T, color, generateTexCoord ); } -TriangleMesh makeYNormalQuad( const Vector2& halfExts, - const Utils::optional& color, - bool generateTexCoord ) { +QuadMesh makeYNormalQuad( const Vector2& halfExts, + const Utils::optional& color, + bool generateTexCoord ) { Transform T = Transform::Identity(); T.linear().col( 1 ).swap( T.linear().col( 2 ) ); T.linear().col( 0 ).swap( T.linear().col( 1 ) ); return makePlaneGrid( 1, 1, halfExts, T, color, generateTexCoord ); } -TriangleMesh makeZNormalQuad( const Vector2& halfExts, - const Utils::optional& color, - bool generateTexCoord ) { +QuadMesh makeZNormalQuad( const Vector2& halfExts, + const Utils::optional& color, + bool generateTexCoord ) { return makePlaneGrid( 1, 1, halfExts, Transform::Identity(), color, generateTexCoord ); } @@ -861,26 +861,71 @@ TriangleMesh makeCone( const Vector3& base, return result; } -TriangleMesh makePlaneGrid( const uint rows, - const uint cols, - const Vector2& halfExts, - const Transform& T, - const Utils::optional& color, - bool generateTexCoord ) { - TriangleMesh result; +LineMesh makeGrid( const Core::Vector3& center, + const Core::Vector3& x, + const Core::Vector3& y, + const Core::Utils::Color& color, + Scalar cell_size, + uint res ) { + + CORE_ASSERT( res > 1, "Grid has to be at least a 2x2 grid." ); + + LineMesh result; TriangleMesh::PointAttribHandle::Container vertices; - TriangleMesh::NormalAttribHandle::Container normals; - TriangleMesh::IndexContainerType indices; + auto indices = LineMesh::IndexContainerType {}; + + vertices.reserve( 4 * ( res + 1 ) ); + indices.reserve( 2 * ( res + 1 ) ); + + const Scalar halfWidth { ( cell_size * res ) / 2.f }; + const Core::Vector3 deltaPosX { cell_size * x }; + const Core::Vector3 startPosX { center - halfWidth * x }; + const Core::Vector3 endPosX { center + halfWidth * x }; + const Core::Vector3 deltaPosY { cell_size * y }; + const Core::Vector3 startPosY { center - halfWidth * y }; + const Core::Vector3 endPosY { center + halfWidth * y }; + Core::Vector3 currentPosX { startPosX }; + for ( uint i = 0; i < res + 1; ++i ) { + vertices.emplace_back( startPosY + currentPosX ); + vertices.emplace_back( endPosY + currentPosX ); + indices.emplace_back( uint( vertices.size() ) - 2, uint( vertices.size() ) - 1 ); + currentPosX += deltaPosX; + } + + Core::Vector3 currentPosY = startPosY; + for ( uint i = 0; i < res + 1; ++i ) { + vertices.emplace_back( startPosX + currentPosY ); + vertices.emplace_back( endPosX + currentPosY ); + indices.emplace_back( uint( vertices.size() ) - 2, uint( vertices.size() ) - 1 ); + currentPosY += deltaPosY; + } + + result.setVertices( std::move( vertices ) ); + result.setIndices( std::move( indices ) ); + + result.colorize( color ); + return result; +} + +QuadMesh makePlaneGrid( const uint rows, + const uint cols, + const Vector2& halfExts, + const Transform& T, + const Utils::optional& color, + bool generateTexCoord ) { + QuadMesh result; + + QuadMesh::PointAttribHandle::Container vertices; + QuadMesh::NormalAttribHandle::Container normals; Ra::Core::Vector3Array texCoords; const uint R = ( rows + 1 ); const uint C = ( cols + 1 ); const uint v_size = C * R; - const uint t_size = 2 * cols * rows; + const uint t_size = cols * rows; vertices.resize( v_size ); normals.resize( v_size ); - indices.reserve( t_size ); texCoords.reserve( v_size ); const Vector3 X = T.linear().col( 0 ).normalized(); @@ -905,20 +950,25 @@ TriangleMesh makePlaneGrid( const uint rows, } } - for ( uint i = 0; i < rows; ++i ) { - for ( uint j = 0; j < cols; ++j ) { - indices.emplace_back( - v.at( { i, j } ), v.at( { i, j + 1 } ), v.at( { i + 1, j + 1 } ) ); - indices.emplace_back( - v.at( { i, j } ), v.at( { i + 1, j + 1 } ), v.at( { i + 1, j } ) ); - } - } result.setVertices( std::move( vertices ) ); result.setNormals( std::move( normals ) ); - result.setIndices( std::move( indices ) ); if ( generateTexCoord ) result.addAttrib( getAttribName( MeshAttrib::VERTEX_TEXCOORD ), std::move( texCoords ) ); if ( bool( color ) ) result.colorize( *color ); + + auto& face_layer = result.getIndicesWithLock(); + face_layer.reserve( t_size ); + + for ( uint i = 0; i < rows; ++i ) { + for ( uint j = 0; j < cols; ++j ) { + face_layer.emplace_back( v.at( { i, j } ), + v.at( { i, j + 1 } ), + v.at( { i + 1, j + 1 } ), + v.at( { i + 1, j } ) ); + } + } + + result.indicesUnlock(); result.checkConsistency(); return result; diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index 294ffddcaec..3b6338b1ec8 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -8,8 +8,6 @@ #include #include -#include - namespace Ra { namespace Core { namespace Geometry { @@ -25,30 +23,37 @@ namespace Geometry { /// \param color: if set, colorize vertices /// \param generateTexCoord: create uv tex coordinates on the grid, -halfExts have uv = (0,0), /// +halfExts have uv=(1,1) -RA_CORE_API TriangleMesh makePlaneGrid( const uint rows = 1, - const uint cols = 1, - const Vector2& halfExts = Vector2( .5_ra, .5_ra ), - const Transform& T = Transform::Identity(), - const Utils::optional& color = {}, - bool generateTexCoord = false ); +RA_CORE_API QuadMesh makePlaneGrid( const uint rows = 1, + const uint cols = 1, + const Vector2& halfExts = Vector2( .5_ra, .5_ra ), + const Transform& T = Transform::Identity(), + const Utils::optional& color = {}, + bool generateTexCoord = false ); + +RA_CORE_API LineMesh makeGrid( const Core::Vector3& center, + const Core::Vector3& x, + const Core::Vector3& y, + const Core::Utils::Color& color, + Scalar cell_size, + uint res ); /// Create a 2D quad mesh given half extents, centered on the origin with x axis as normal /// \see makePlaneGrid -RA_CORE_API TriangleMesh makeXNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), - const Utils::optional& color = {}, - bool generateTexCoord = false ); +RA_CORE_API QuadMesh makeXNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), + const Utils::optional& color = {}, + bool generateTexCoord = false ); /// Create a 2D quad mesh given half extents, centered on the origin with y axis as normal /// \see makePlaneGrid -RA_CORE_API TriangleMesh makeYNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), - const Utils::optional& color = {}, - bool generateTexCoord = false ); +RA_CORE_API QuadMesh makeYNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), + const Utils::optional& color = {}, + bool generateTexCoord = false ); /// Create a 2D quad mesh given half extents, centered on the origin with z axis as normal /// \see makePlaneGrid -RA_CORE_API TriangleMesh makeZNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), - const Utils::optional& color = {}, - bool generateTexCoord = false ); +RA_CORE_API QuadMesh makeZNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), + 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 TriangleMesh makeBox( const Vector3& halfExts = Vector3( .5_ra, .5_ra, .5_ra ), @@ -87,10 +92,10 @@ TriangleMesh makeParametricSphere( Scalar radius = const Utils::optional& color = {}, bool generateTexCoord = false ); -/// Create a parametric torus mesh. The minor radius is the radius of the inside of the tube and the -/// major radius is the radius of the whole torus. The torus will be centered at the origin and have -/// Z as rotation axis. Template parameters set the resolution of the mesh. -/// \param generateTexCoord: maps parametric (u,v) to texture corrdinates [0,1]^2 +/// Create a parametric torus mesh. The minor radius is the radius of the inside of the tube and +/// the major radius is the radius of the whole torus. The torus will be centered at the origin +/// and have Z as rotation axis. Template parameters set the resolution of the mesh. \param +/// generateTexCoord: maps parametric (u,v) to texture corrdinates [0,1]^2 template TriangleMesh makeParametricTorus( Scalar majorRadius, Scalar minorRadius, @@ -102,10 +107,9 @@ RA_CORE_API TriangleMesh makeGeodesicSphere( Scalar radius uint numSubdiv = 3, const Utils::optional& color = {} ); -/// Create a cylinder approximation (sideSegments-faced prism) with base faces centered on a and b -/// with given radius. -/// Fill (the tube part) is split into equally sapced fill segments. -/// Side and fill make a sharp edge. +/// Create a cylinder approximation (sideSegments-faced prism) with base faces centered on a and +/// b with given radius. Fill (the tube part) is split into equally sapced fill segments. Side +/// and fill make a sharp edge. RA_CORE_API TriangleMesh makeCylinder( const Vector3& a, const Vector3& b, Scalar radius, diff --git a/src/Core/Geometry/TriangleMesh.hpp b/src/Core/Geometry/TriangleMesh.hpp index 32d5061e556..8f9def05f7d 100644 --- a/src/Core/Geometry/TriangleMesh.hpp +++ b/src/Core/Geometry/TriangleMesh.hpp @@ -441,6 +441,8 @@ inline void AttribArrayGeometry::normalsUnlock() { inline void AttribArrayGeometry::initDefaultAttribs() { m_verticesHandle = m_vertexAttribs.addAttrib( getAttribName( MeshAttrib::VERTEX_POSITION ) ); + + /// \todo remove normals ? m_normalsHandle = m_vertexAttribs.addAttrib( getAttribName( MeshAttrib::VERTEX_NORMAL ) ); invalidateAabb(); diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index 7fbba814c15..5618a7c38c9 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -139,13 +139,10 @@ GeometryDisplayablePtr Triangle( const Core::Vector3& a, auto ret = make_shared( "Triangle" ); - using LayerKeysType = std::array< - std::pair, - 2>; - ret->loadGeometry( std::move( geom ), - LayerKeysType { { { face_key, AttribArrayDisplayable::RM_TRIANGLES }, - { boundary_key, AttribArrayDisplayable::RM_LINES } } } ); + GeometryDisplayable::ArrayOfLayerKeys<2> { + { { face_key, AttribArrayDisplayable::RM_TRIANGLES }, + { boundary_key, AttribArrayDisplayable::RM_LINES } } } ); if ( fill ) { ret->set_active_layer_key( face_key ); } @@ -444,48 +441,15 @@ MeshPtr Frame( const Core::Transform& frameFromEntity, Scalar scale ) { return mesh; } -MeshPtr Grid( const Core::Vector3& center, - const Core::Vector3& x, - const Core::Vector3& y, - const Core::Utils::Color& color, - Scalar cellSize, - uint res ) { - CORE_ASSERT( res > 1, "Grid has to be at least a 2x2 grid." ); - Core::Vector3Array vertices; - std::vector indices; - - const Scalar halfWidth { ( cellSize * res ) / 2.f }; - const Core::Vector3 deltaPosX { cellSize * x }; - const Core::Vector3 startPosX { center - halfWidth * x }; - const Core::Vector3 endPosX { center + halfWidth * x }; - const Core::Vector3 deltaPosY { cellSize * y }; - const Core::Vector3 startPosY { center - halfWidth * y }; - const Core::Vector3 endPosY { center + halfWidth * y }; - Core::Vector3 currentPosX { startPosX }; - for ( uint i = 0; i < res + 1; ++i ) { - vertices.push_back( startPosY + currentPosX ); - vertices.push_back( endPosY + currentPosX ); - indices.push_back( uint( vertices.size() ) - 2 ); - indices.push_back( uint( vertices.size() ) - 1 ); - currentPosX += deltaPosX; - } - - Core::Vector3 currentPosY = startPosY; - for ( uint i = 0; i < res + 1; ++i ) { - vertices.push_back( startPosX + currentPosY ); - vertices.push_back( endPosX + currentPosY ); - indices.push_back( uint( vertices.size() ) - 2 ); - indices.push_back( uint( vertices.size() ) - 1 ); - currentPosY += deltaPosY; - } - - Core::Vector4Array colors( vertices.size(), color ); - - MeshPtr mesh( new Mesh( "GridPrimitive", Mesh::RM_LINES ) ); - mesh->loadGeometry( vertices, indices ); - mesh->getCoreGeometry().addAttrib( - Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), colors ); +GeometryDisplayablePtr Grid( const Core::Vector3& center, + const Core::Vector3& x, + const Core::Vector3& y, + const Core::Utils::Color& color, + Scalar cellSize, + uint res ) { + auto geom = makeGrid( center, x, y, color, cellSize, res ); + auto mesh = make_shared( "GridPrimitive", std::move( geom ) ); return mesh; } diff --git a/src/Engine/Data/DrawPrimitives.hpp b/src/Engine/Data/DrawPrimitives.hpp index 0d338c58656..673baea8fd5 100644 --- a/src/Engine/Data/DrawPrimitives.hpp +++ b/src/Engine/Data/DrawPrimitives.hpp @@ -140,12 +140,12 @@ RA_ENGINE_API MeshPtr Frame( const Core::Transform& frameFromEntity, Scalar scal /// Create a res*res square grid centered on center, /// in plane defined by the vectors x and y. -RA_ENGINE_API MeshPtr Grid( const Core::Vector3& center, - const Core::Vector3& x, - const Core::Vector3& y, - const Core::Utils::Color& color, - Scalar cellSize = 1.f, - uint res = 10 ); +RA_ENGINE_API GeometryDisplayablePtr Grid( const Core::Vector3& center, + const Core::Vector3& x, + const Core::Vector3& y, + const Core::Utils::Color& color, + Scalar cellSize = 1.f, + uint res = 10 ); /// Display a wireframe AABB RA_ENGINE_API MeshPtr AABB( const Core::Aabb& aabb, const Core::Utils::Color& color ); diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index 9dcdfdde310..bb265590348 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -167,6 +167,7 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m m_geomLayers.clear(); m_geom = std::move( mesh ); setupCoreMeshObservers(); + bool ok = false; if ( m_geom.containsLayer( Core::Geometry::LineIndexLayer::staticSemanticName ) ) { auto [key, layer] = @@ -174,13 +175,15 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m m_activeLayerKey = key; setRenderMode( AttribArrayDisplayable::RM_LINES ); - auto ok = addRenderLayer( key, AttribArrayDisplayable::RM_LINES ); + ok = addRenderLayer( key, AttribArrayDisplayable::RM_LINES ); if ( !ok ) { LOG( logERROR ) << "loadGeometry could not add layer"; } } - else if ( m_geom.containsLayer( Core::Geometry::TriangleIndexLayer::staticSemanticName ) ) { + // if triangle also, add and set as default + if ( m_geom.containsLayer( Core::Geometry::TriangleIndexLayer::staticSemanticName ) ) { auto [key, layer] = m_geom.getFirstLayerOccurrence( Core::Geometry::TriangleIndexLayer::staticSemanticName ); m_activeLayerKey = key; + setRenderMode( AttribArrayDisplayable::RM_TRIANGLES ); addRenderLayer( key, AttribArrayDisplayable::RM_TRIANGLES ); } else if ( m_geom.containsLayer( Core::Geometry::QuadIndexLayer::staticSemanticName ) ) { @@ -218,7 +221,8 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m addRenderLayer( triangleKey, AttribArrayDisplayable::RM_TRIANGLES ); } } - else { LOG( logERROR ) << "no valid layer found"; } + // if no line, nor any other + else if ( !ok ) { LOG( logERROR ) << "no valid layer found"; } m_isDirty = true; } diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 7342241421d..fb0b883d5cf 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -341,7 +341,10 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable using LayerSemantic = typename Core::Geometry::MultiIndexedGeometry::LayerSemantic; using LayerKeyType = typename Core::Geometry::MultiIndexedGeometry::LayerKeyType; using LayerKeyHash = Core::Geometry::MultiIndexedGeometry::LayerKeyHash; - + template + using ArrayOfLayerKeys = std::array< + std::pair, + N>; explicit GeometryDisplayable( const std::string& name ); explicit GeometryDisplayable( const std::string& name, typename Core::Geometry::MultiIndexedGeometry&& geom ); @@ -392,10 +395,7 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable inline void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, LayerKeyType key, base::MeshRenderMode renderMode ) { - using LayerKeysType = std::array< - std::pair, - 1>; - loadGeometry( std::move( mesh ), LayerKeysType { { { key, renderMode } } } ); + loadGeometry( std::move( mesh ), ArrayOfLayerKeys<1> { { { key, renderMode } } } ); } bool addRenderLayer( LayerKeyType key, base::MeshRenderMode renderMode ); diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 4e7d43545c0..52a1d95739d 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -175,10 +175,9 @@ void Renderer::initialize( uint width, uint height ) { m_secondaryTextures["Picking Texture"] = m_pickingTexture.get(); // Quad mesh - Core::Geometry::TriangleMesh mesh = - Core::Geometry::makeZNormalQuad( Core::Vector2( -1.f, 1.f ) ); + auto mesh = Core::Geometry::makeZNormalQuad( Core::Vector2( -1.f, 1.f ) ); - auto qm = std::make_unique( "quad" ); + auto qm = std::make_unique( "quad" ); qm->loadGeometry( std::move( mesh ) ); m_quadMesh = std::move( qm ); // we need to move, as loadGeometry is not a member of Displayable m_quadMesh->updateGL(); diff --git a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp index 25c51700009..b6599a943d2 100644 --- a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp @@ -1,10 +1,11 @@ #include +#include +#include #include #include #include -#include #include #include #include @@ -61,7 +62,7 @@ ScaleGizmo::ScaleGizmo( Engine::Scene::Component* c, T.translation()[( i + 1 ) % 3] += arrowFrac * arrowScale * 3; T.translation()[( i + 2 ) % 3] += arrowFrac * arrowScale * 3; - Core::Geometry::TriangleMesh plane = Core::Geometry::makePlaneGrid( + auto plane = Core::Geometry::makePlaneGrid( 1, 1, Core::Vector2( arrowFrac * arrowScale, arrowFrac * arrowScale ), T ); // \FIXME this hack is here to be sure the plane will be selected (see shader) @@ -69,7 +70,7 @@ ScaleGizmo::ScaleGizmo( Engine::Scene::Component* c, normals.getMap().fill( 0_ra ); plane.normalsUnlock(); - std::shared_ptr mesh( new Engine::Data::Mesh( "Gizmo Plane" ) ); + auto mesh = std::make_shared( "Gizmo Plane" ); mesh->loadGeometry( std::move( plane ) ); Engine::Rendering::RenderObject* planeDrawable = new Engine::Rendering::RenderObject( diff --git a/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp b/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp index 0ec94d916fa..13ddcfa7920 100644 --- a/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -57,7 +58,7 @@ TranslateGizmo::TranslateGizmo( Engine::Scene::Component* c, T.translation()[( i + 1 ) % 3] += arrowScale / 8_ra * 3_ra; T.translation()[( i + 2 ) % 3] += arrowScale / 8_ra * 3_ra; - Core::Geometry::TriangleMesh plane = Core::Geometry::makePlaneGrid( + auto plane = Core::Geometry::makePlaneGrid( 1, 1, Core::Vector2( arrowScale / 8_ra, arrowScale / 8_ra ), T ); // \FIXME this hack is here to be sure the plane will be selected (see shader) @@ -66,7 +67,7 @@ TranslateGizmo::TranslateGizmo( Engine::Scene::Component* c, normals.getMap().fill( 0_ra ); plane.normalsUnlock(); - std::shared_ptr mesh( new Engine::Data::Mesh( "Gizmo Plane" ) ); + auto mesh = Ra::Core::make_shared( "Gizmo Plane" ); mesh->loadGeometry( std::move( plane ) ); Engine::Rendering::RenderObject* planeDrawable = new Engine::Rendering::RenderObject( From 845148c1c2a32c7dc0649faac140fa256f97deaf Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 5 May 2025 22:11:34 +0200 Subject: [PATCH 039/144] [core] *Mesh are now using aliases to IndexedGeometry<>. Factorize TopologicalMesh::to*Mesh. Update topomesh unittest. --- src/Core/Geometry/IndexedGeometry.hpp | 15 +-- src/Core/Geometry/RayCast.hpp | 2 +- src/Core/Geometry/TopologicalMesh.cpp | 168 +------------------------- src/Core/Geometry/TopologicalMesh.hpp | 105 ++++++++++++++-- tests/unittest/Core/topomesh.cpp | 95 ++++++++------- 5 files changed, 152 insertions(+), 233 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 32c728623f2..39497fb7b51 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -601,17 +601,10 @@ class IndexedGeometry : public MultiIndexedGeometry class RA_CORE_API IndexedPointCloud : public IndexedGeometry {}; -class RA_CORE_API TriangleMesh : public IndexedGeometry -{}; - -class RA_CORE_API QuadMesh : public IndexedGeometry -{}; - -class RA_CORE_API PolyMesh : public IndexedGeometry -{}; - -class RA_CORE_API LineMesh : public IndexedGeometry -{}; +using TriangleMesh = IndexedGeometry; +using QuadMesh = IndexedGeometry; +using PolyMesh = IndexedGeometry; +using LineMesh = IndexedGeometry; // GeometryIndexLayerBase inline GeometryIndexLayerBase::GeometryIndexLayerBase( const GeometryIndexLayerBase& other ) : diff --git a/src/Core/Geometry/RayCast.hpp b/src/Core/Geometry/RayCast.hpp index a7d672458dd..e46f20efaf3 100644 --- a/src/Core/Geometry/RayCast.hpp +++ b/src/Core/Geometry/RayCast.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -14,7 +15,6 @@ namespace Core { // If a ray starts inside the shape, the resulting hit will be at the ray's origin (t=0). namespace Geometry { -class TriangleMesh; /// Intersect a ray with an axis-aligned bounding box. bool RA_CORE_API RayCastAabb( const Ray& r, diff --git a/src/Core/Geometry/TopologicalMesh.cpp b/src/Core/Geometry/TopologicalMesh.cpp index 2dd0d687ab6..f68800566c1 100644 --- a/src/Core/Geometry/TopologicalMesh.cpp +++ b/src/Core/Geometry/TopologicalMesh.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -203,173 +204,6 @@ void moveContainerToMesh( Ra::Core::Geometry::MultiIndexedGeometry& out, } } -TriangleMesh TopologicalMesh::toTriangleMesh() { - // first cleanup deleted element - garbage_collection(); - - TriangleMesh out; - TriangleMesh::IndexContainerType indices; - - /// add attribs to out - TriangleMesh::PointAttribHandle::Container wedgePosition; - AlignedStdVector::Container> wedgeFloatAttribData( - m_wedges.m_floatAttribNames.size() ); - AlignedStdVector::Container> wedgeVector2AttribData( - m_wedges.m_vector2AttribNames.size() ); - AlignedStdVector::Container> wedgeVector3AttribData( - m_wedges.m_vector3AttribNames.size() ); - AlignedStdVector::Container> wedgeVector4AttribData( - m_wedges.m_vector4AttribNames.size() ); - - /// Wedges are output vertices ! - for ( WedgeIndex widx { 0 }; widx < WedgeIndex { m_wedges.size() }; ++widx ) { - const auto& wd = m_wedges.getWedgeData( widx ); - wedgePosition.push_back( wd.m_position ); - copyWedgeDataToAttribContainer( wedgeFloatAttribData, wd.m_floatAttrib ); - copyWedgeDataToAttribContainer( wedgeVector2AttribData, wd.m_vector2Attrib ); - copyWedgeDataToAttribContainer( wedgeVector3AttribData, wd.m_vector3Attrib ); - copyWedgeDataToAttribContainer( wedgeVector4AttribData, wd.m_vector4Attrib ); - } - - out.setVertices( std::move( wedgePosition ) ); - moveContainerToMesh( out, m_wedges.m_floatAttribNames, wedgeFloatAttribData ); - moveContainerToMesh( out, m_wedges.m_vector2AttribNames, wedgeVector2AttribData ); - moveContainerToMesh( out, m_wedges.m_vector3AttribNames, wedgeVector3AttribData ); - moveContainerToMesh( out, m_wedges.m_vector4AttribNames, wedgeVector4AttribData ); - - for ( TopologicalMesh::FaceIter f_it = faces_sbegin(); f_it != faces_end(); ++f_it ) { - int tindices[3]; - int i = 0; - - for ( TopologicalMesh::ConstFaceHalfedgeIter fh_it = cfh_iter( *f_it ); fh_it.is_valid(); - ++fh_it ) { - CORE_ASSERT( i < 3, "Non-triangular face found." ); - tindices[i] = property( m_wedgeIndexPph, *fh_it ); - i++; - } - indices.emplace_back( tindices[0], tindices[1], tindices[2] ); - } - - out.setIndices( std::move( indices ) ); - - return out; -} - -LineMesh TopologicalMesh::toLineMesh() { - // first cleanup deleted element - garbage_collection(); - - LineMesh out; - LineMesh::IndexContainerType indices; - - TriangleMesh::PointAttribHandle::Container wedgePosition; - AlignedStdVector::Container> wedgeFloatAttribData( - m_wedges.m_floatAttribNames.size() ); - AlignedStdVector::Container> wedgeVector2AttribData( - m_wedges.m_vector2AttribNames.size() ); - AlignedStdVector::Container> wedgeVector3AttribData( - m_wedges.m_vector3AttribNames.size() ); - AlignedStdVector::Container> wedgeVector4AttribData( - m_wedges.m_vector4AttribNames.size() ); - - /// Wedges are output vertices ! - for ( WedgeIndex widx { 0 }; widx < WedgeIndex( m_wedges.size() ); ++widx ) { - const auto& wd = m_wedges.getWedgeData( widx ); - wedgePosition.push_back( wd.m_position ); - copyWedgeDataToAttribContainer( wedgeFloatAttribData, wd.m_floatAttrib ); - copyWedgeDataToAttribContainer( wedgeVector2AttribData, wd.m_vector2Attrib ); - copyWedgeDataToAttribContainer( wedgeVector3AttribData, wd.m_vector3Attrib ); - copyWedgeDataToAttribContainer( wedgeVector4AttribData, wd.m_vector4Attrib ); - } - - out.setVertices( std::move( wedgePosition ) ); - moveContainerToMesh( out, m_wedges.m_floatAttribNames, wedgeFloatAttribData ); - moveContainerToMesh( out, m_wedges.m_vector2AttribNames, wedgeVector2AttribData ); - moveContainerToMesh( out, m_wedges.m_vector3AttribNames, wedgeVector3AttribData ); - moveContainerToMesh( out, m_wedges.m_vector4AttribNames, wedgeVector4AttribData ); - - for ( TopologicalMesh::EdgeIter e_it = edges_sbegin(); e_it != edges_end(); ++e_it ) { - int tindices[2]; - - // take care of boundaries - auto he0 = halfedge_handle( *e_it, 0 ); - if ( OpenMesh::ArrayKernel::is_boundary( he0 ) ) { - he0 = prev_halfedge_handle( opposite_halfedge_handle( he0 ) ); - } - if ( OpenMesh::ArrayKernel::is_boundary( he0 ) ) continue; - auto he1 = halfedge_handle( *e_it, 1 ); - if ( OpenMesh::ArrayKernel::is_boundary( he1 ) ) { - he1 = prev_halfedge_handle( opposite_halfedge_handle( he1 ) ); - } - if ( OpenMesh::ArrayKernel::is_boundary( he1 ) ) continue; - - tindices[0] = property( m_wedgeIndexPph, he0 ); - tindices[1] = property( m_wedgeIndexPph, he1 ); - - indices.emplace_back( tindices[0], tindices[1] ); - } - - out.setIndices( std::move( indices ) ); - - return out; -} -PolyMesh TopologicalMesh::toPolyMesh() { - // first cleanup deleted element - garbage_collection(); - - PolyMesh out; - PolyMesh::IndexContainerType indices; - - /// add attribs to out - std::vector> wedgeFloatAttribHandles; - std::vector> wedgeVector2AttribHandles; - std::vector> wedgeVector3AttribHandles; - std::vector> wedgeVector4AttribHandles; - - TriangleMesh::PointAttribHandle::Container wedgePosition; - AlignedStdVector::Container> wedgeFloatAttribData( - m_wedges.m_floatAttribNames.size() ); - AlignedStdVector::Container> wedgeVector2AttribData( - m_wedges.m_vector2AttribNames.size() ); - AlignedStdVector::Container> wedgeVector3AttribData( - m_wedges.m_vector3AttribNames.size() ); - AlignedStdVector::Container> wedgeVector4AttribData( - m_wedges.m_vector4AttribNames.size() ); - - /// Wedges are output vertices ! - for ( WedgeIndex widx { 0 }; widx < WedgeIndex( m_wedges.size() ); ++widx ) { - const auto& wd = m_wedges.getWedgeData( widx ); - wedgePosition.push_back( wd.m_position ); - copyWedgeDataToAttribContainer( wedgeFloatAttribData, wd.m_floatAttrib ); - copyWedgeDataToAttribContainer( wedgeVector2AttribData, wd.m_vector2Attrib ); - copyWedgeDataToAttribContainer( wedgeVector3AttribData, wd.m_vector3Attrib ); - copyWedgeDataToAttribContainer( wedgeVector4AttribData, wd.m_vector4Attrib ); - } - - out.setVertices( std::move( wedgePosition ) ); - moveContainerToMesh( out, m_wedges.m_floatAttribNames, wedgeFloatAttribData ); - moveContainerToMesh( out, m_wedges.m_vector2AttribNames, wedgeVector2AttribData ); - moveContainerToMesh( out, m_wedges.m_vector3AttribNames, wedgeVector3AttribData ); - moveContainerToMesh( out, m_wedges.m_vector4AttribNames, wedgeVector4AttribData ); - - for ( TopologicalMesh::FaceIter f_it = faces_sbegin(); f_it != faces_end(); ++f_it ) { - int i = 0; - PolyMesh::IndexType faceIndices( valence( *f_it ) ); - // iterator over vertex (through halfedge to get access to halfedge normals) - for ( TopologicalMesh::ConstFaceHalfedgeIter fh_it = cfh_iter( *f_it ); fh_it.is_valid(); - ++fh_it ) { - faceIndices( i ) = property( m_wedgeIndexPph, *fh_it ); - i++; - } - // LOG( logDEBUG ) << "add polymesh face " << faceIndices.transpose(); - indices.push_back( faceIndices ); - } - - out.setIndices( std::move( indices ) ); - - return out; -} - void TopologicalMesh::updateTriangleMesh( Ra::Core::Geometry::MultiIndexedGeometry& out ) { TriangleMesh::PointAttribHandle::Container wedgePosition; AlignedStdVector::Container> wedgeFloatAttribData( diff --git a/src/Core/Geometry/TopologicalMesh.hpp b/src/Core/Geometry/TopologicalMesh.hpp index 33a6209548e..c4dccbabcc1 100644 --- a/src/Core/Geometry/TopologicalMesh.hpp +++ b/src/Core/Geometry/TopologicalMesh.hpp @@ -1,5 +1,6 @@ #pragma once +#include "Core/Geometry/IndexedGeometry.hpp" #include #include #include @@ -77,9 +78,7 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT - explicit TopologicalMesh( [[deprecated( - "Use MultiIndexedGeometry instead" )]] const Ra::Core::Geometry::IndexedGeometry& - mesh ); + explicit TopologicalMesh( const Ra::Core::Geometry::IndexedGeometry& mesh ); /** * \brief Convenience constructor @@ -103,8 +102,7 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT - explicit TopologicalMesh( [[deprecated( "Use MultiIndexedGeometry instead" )]] const Ra::Core:: - Geometry::IndexedGeometry& mesh, + explicit TopologicalMesh( const Ra::Core::Geometry::IndexedGeometry& mesh, NonManifoldFaceCommand command ); /** @@ -134,20 +132,36 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT + IndexedGeometry toIndexedMesh(); + PolyMesh toPolyMesh() { return toIndexedMesh(); } + LineMesh toLineMesh() { return toIndexedMesh(); } + QuadMesh toQuadMesh() { return toIndexedMesh(); } + TriangleMesh toTriangleMesh() { return toIndexedMesh(); } + + ///\todo move the who next methods as templated lambda when switch to c++20 + template + void copyWedgeDataToAttribContainer( AlignedStdVector::Container>& c, + const VectorArray& wd ) { + for ( size_t i = 0; i < wd.size(); ++i ) { + c[i].push_back( wd[i] ); + } + } - LineMesh toLineMesh(); + template + void moveContainerToMesh( Ra::Core::Geometry::MultiIndexedGeometry& out, + const std::vector& names, + AlignedStdVector::Container>& wedgeAttribData ) { + for ( size_t i = 0; i < wedgeAttribData.size(); ++i ) { + auto attrHandle = out.template addAttrib( names[i] ); + out.getAttrib( attrHandle ).setData( std::move( wedgeAttribData[i] ) ); + } + } /** * Update triangle mesh data, assuming the mesh and this topo mesh has the @@ -1232,6 +1246,11 @@ void TopologicalMesh::initWithWedge( LOG( logDEBUG ) << "TopologicalMesh: process " << faces.size() << " triangular faces "; processFaces( faces ); } + else if ( abstractLayer.hasSemantic( QuadIndexLayer::staticSemanticName ) ) { + const auto& faces = static_cast( abstractLayer ).collection(); + LOG( logDEBUG ) << "TopologicalMesh: process " << faces.size() << " polygonal faces "; + processFaces( faces ); + } else if ( abstractLayer.hasSemantic( PolyIndexLayer::staticSemanticName ) ) { const auto& faces = static_cast( abstractLayer ).collection(); LOG( logDEBUG ) << "TopologicalMesh: process " << faces.size() << " polygonal faces "; @@ -1449,6 +1468,66 @@ TopologicalMesh::getWedgeIndexPph() const { return m_wedgeIndexPph; } +template +IndexedGeometry TopologicalMesh::toIndexedMesh() { // first cleanup deleted element + + garbage_collection(); + + IndexedGeometry out; + typename IndexedGeometry::IndexContainerType indices; + + /// add attribs to out + std::vector> wedgeFloatAttribHandles; + std::vector> wedgeVector2AttribHandles; + std::vector> wedgeVector3AttribHandles; + std::vector> wedgeVector4AttribHandles; + + TriangleMesh::PointAttribHandle::Container wedgePosition; + AlignedStdVector::Container> wedgeFloatAttribData( + m_wedges.m_floatAttribNames.size() ); + AlignedStdVector::Container> wedgeVector2AttribData( + m_wedges.m_vector2AttribNames.size() ); + AlignedStdVector::Container> wedgeVector3AttribData( + m_wedges.m_vector3AttribNames.size() ); + AlignedStdVector::Container> wedgeVector4AttribData( + m_wedges.m_vector4AttribNames.size() ); + + /// Wedges are output vertices ! + for ( WedgeIndex widx { 0 }; widx < WedgeIndex( m_wedges.size() ); ++widx ) { + const auto& wd = m_wedges.getWedgeData( widx ); + wedgePosition.push_back( wd.m_position ); + copyWedgeDataToAttribContainer( wedgeFloatAttribData, wd.m_floatAttrib ); + copyWedgeDataToAttribContainer( wedgeVector2AttribData, wd.m_vector2Attrib ); + copyWedgeDataToAttribContainer( wedgeVector3AttribData, wd.m_vector3Attrib ); + copyWedgeDataToAttribContainer( wedgeVector4AttribData, wd.m_vector4Attrib ); + } + + out.setVertices( std::move( wedgePosition ) ); + moveContainerToMesh( out, m_wedges.m_floatAttribNames, wedgeFloatAttribData ); + moveContainerToMesh( out, m_wedges.m_vector2AttribNames, wedgeVector2AttribData ); + moveContainerToMesh( out, m_wedges.m_vector3AttribNames, wedgeVector3AttribData ); + moveContainerToMesh( out, m_wedges.m_vector4AttribNames, wedgeVector4AttribData ); + + for ( TopologicalMesh::FaceIter f_it = faces_sbegin(); f_it != faces_end(); ++f_it ) { + int i = 0; + IndexType faceIndices( valence( *f_it ) ); + CORE_ASSERT( faceIndices.size() == valence( *f_it ), "Invalid face size." ); + + // iterator over vertex (through halfedge to get access to halfedge normals) + for ( TopologicalMesh::ConstFaceHalfedgeIter fh_it = cfh_iter( *f_it ); fh_it.is_valid(); + ++fh_it ) { + faceIndices( i ) = property( m_wedgeIndexPph, *fh_it ); + i++; + } + + indices.push_back( faceIndices ); + } + + out.setIndices( std::move( indices ) ); + + return out; +} + } // namespace Geometry } // namespace Core } // namespace Ra diff --git a/tests/unittest/Core/topomesh.cpp b/tests/unittest/Core/topomesh.cpp index 908e57f33f3..26cb038c026 100644 --- a/tests/unittest/Core/topomesh.cpp +++ b/tests/unittest/Core/topomesh.cpp @@ -13,8 +13,11 @@ using namespace Ra::Core; using namespace Ra::Core::Utils; using namespace Ra::Core::Geometry; -bool isSameMesh( const Ra::Core::Geometry::TriangleMesh& meshOne, - const Ra::Core::Geometry::TriangleMesh& meshTwo, +template +bool isSameMesh( const Ra::Core::Geometry::MultiIndexedGeometry& meshOne, + const VectorArray& indices_mesh_one, + const Ra::Core::Geometry::MultiIndexedGeometry& meshTwo, + const VectorArray& indices_mesh_two, bool expected = true ) { bool result = true; @@ -32,7 +35,7 @@ bool isSameMesh( const Ra::Core::Geometry::TriangleMesh& meshOne, return false; } - if ( meshOne.getIndices().size() != meshTwo.getIndices().size() ) { + if ( indices_mesh_one.size() != indices_mesh_two.size() ) { if ( expected ) { LOG( logINFO ) << "isSameMesh failed getIndices().size()"; } return false; } @@ -44,23 +47,25 @@ bool isSameMesh( const Ra::Core::Geometry::TriangleMesh& meshOne, bool hasNormals = meshOne.normals().size() > 0; i = 0; - while ( result && i < int( meshOne.getIndices().size() ) ) { + while ( result && i < int( indices_mesh_one.size() ) ) { std::vector::iterator it; stackVertices.clear(); - stackVertices.push_back( meshOne.vertices()[meshOne.getIndices()[i][0]] ); - stackVertices.push_back( meshOne.vertices()[meshOne.getIndices()[i][1]] ); - stackVertices.push_back( meshOne.vertices()[meshOne.getIndices()[i][2]] ); + if ( indices_mesh_two[i].size() != indices_mesh_one[i].size() ) { return false; } + auto index = indices_mesh_one[i]; + for ( auto coord : index ) { + stackVertices.push_back( meshOne.vertices()[coord] ); + } if ( hasNormals ) { stackNormals.clear(); - stackNormals.push_back( meshOne.normals()[meshOne.getIndices()[i][0]] ); - stackNormals.push_back( meshOne.normals()[meshOne.getIndices()[i][1]] ); - stackNormals.push_back( meshOne.normals()[meshOne.getIndices()[i][2]] ); + for ( auto coord : index ) { + stackNormals.push_back( meshOne.normals()[coord] ); + } } - for ( int j = 0; j < 3; ++j ) { + for ( int j = 0; j < indices_mesh_two[i].size(); ++j ) { it = find( stackVertices.begin(), stackVertices.end(), - meshTwo.vertices()[meshTwo.getIndices()[i][j]] ); + meshTwo.vertices()[indices_mesh_two[i][j]] ); if ( it != stackVertices.end() ) { stackVertices.erase( it ); } else { @@ -71,10 +76,10 @@ bool isSameMesh( const Ra::Core::Geometry::TriangleMesh& meshOne, } if ( hasNormals ) { - for ( int j = 0; j < 3; ++j ) { + for ( int j = 0; j < indices_mesh_two[i].size(); ++j ) { it = find( stackNormals.begin(), stackNormals.end(), - meshTwo.normals()[meshTwo.getIndices()[i][j]] ); + meshTwo.normals()[indices_mesh_two[i][j]] ); if ( it != stackNormals.end() ) { stackNormals.erase( it ); } else { @@ -231,18 +236,19 @@ bool isSameMeshWedge( const Ra::Core::Geometry::IndexedGeometry& meshOne, return true; } +template +void testConverter1( const Ra::Core::Geometry::IndexedGeometry& mesh ) { + auto topologicalMesh = TopologicalMesh( mesh ); + auto newMesh = topologicalMesh.toIndexedMesh(); + REQUIRE( ( isSameMesh( mesh, mesh.getIndices(), newMesh, newMesh.getIndices(), false ) ) ); + REQUIRE( topologicalMesh.checkIntegrity() ); +}; + TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][TopologicalMesh]" ) { using Ra::Core::Vector3; using Ra::Core::Geometry::TopologicalMesh; using Ra::Core::Geometry::TriangleMesh; - auto testConverter = []( const TriangleMesh& mesh ) { - auto topologicalMesh = TopologicalMesh( mesh ); - auto newMesh = topologicalMesh.toTriangleMesh(); - REQUIRE( isSameMesh( mesh, newMesh ) ); - REQUIRE( topologicalMesh.checkIntegrity() ); - }; - SECTION( "Test OpenMesh specialization" ) { Vector3 v1 { 1_ra, 0_ra, 0_ra }; Vector3 v2 { 0_ra, 1_ra, 0_ra }; @@ -258,12 +264,12 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To } SECTION( "Closed mesh" ) { - testConverter( Ra::Core::Geometry::makeBox() ); - testConverter( Ra::Core::Geometry::makeSharpBox() ); + testConverter1( Ra::Core::Geometry::makeBox() ); + testConverter1( Ra::Core::Geometry::makeSharpBox() ); } SECTION( "Mesh with boundaries" ) { - testConverter( Ra::Core::Geometry::makePlaneGrid( 2, 2 ) ); + testConverter1( Ra::Core::Geometry::makePlaneGrid( 2, 2 ) ); } SECTION( "With user def attribs" ) { @@ -316,7 +322,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To auto topologicalMesh = TopologicalMesh( mesh ); auto newMesh = topologicalMesh.toTriangleMesh(); - REQUIRE( isSameMesh( mesh, newMesh ) ); + REQUIRE( isSameMesh( mesh, mesh.getIndices(), newMesh, newMesh.getIndices() ) ); REQUIRE( topologicalMesh.checkIntegrity() ); // oversize attrib not suported @@ -341,7 +347,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To TopologicalMesh::WedgeIndex { 0 }, getAttribName( VERTEX_NORMAL ), Vector3( 0, 0, 0 ) ); auto newMeshModified = topologicalMesh.toTriangleMesh(); - REQUIRE( isSameMesh( mesh, newMesh ) ); + REQUIRE( isSameMesh( mesh, mesh.getIndices(), newMesh, newMesh.getIndices() ) ); REQUIRE( isSameMeshWedge( mesh, newMesh ) ); REQUIRE( !isSameMeshWedge( mesh, newMeshModified ) ); REQUIRE( topologicalMesh.checkIntegrity() ); @@ -421,7 +427,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To OpenMesh::FPropHandleT fProp; REQUIRE( mesh.vertexAttribs().hasSameAttribs( mesh1.vertexAttribs() ) ); - REQUIRE( isSameMesh( mesh, mesh1 ) ); + REQUIRE( isSameMesh( mesh, mesh.getIndices(), mesh1, mesh1.getIndices() ) ); REQUIRE( mesh1.normals().size() == 0 ); } @@ -608,19 +614,25 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Manifold", return m; }; - // test if candidateMesh -> TopologicalMesh -> TriangleMesh isSameMesh than referenceMesh, - // with and without the command. + // test if candidateMesh -> TopologicalMesh -> TriangleMesh isSameMesh than + // referenceMesh, with and without the command. auto testConverter = []( const TriangleMesh& referenceMesh, const TriangleMesh& candidateMesh, NonManifoldCommand1 command ) { // test with functor TopologicalMesh topoWithCommand { candidateMesh, command }; auto convertedMeshWithCommand = topoWithCommand.toTriangleMesh(); - REQUIRE( isSameMesh( referenceMesh, convertedMeshWithCommand ) ); + REQUIRE( isSameMesh( referenceMesh, + referenceMesh.getIndices(), + convertedMeshWithCommand, + convertedMeshWithCommand.getIndices() ) ); // test without functor TopologicalMesh topoWithoutCommand { candidateMesh }; auto convertedMeshWithoutCommand = topoWithoutCommand.toTriangleMesh(); - REQUIRE( isSameMesh( referenceMesh, convertedMeshWithoutCommand ) ); + REQUIRE( isSameMesh( referenceMesh, + referenceMesh.getIndices(), + convertedMeshWithoutCommand, + convertedMeshWithoutCommand.getIndices() ) ); return convertedMeshWithoutCommand; }; @@ -688,7 +700,8 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Manifold", REQUIRE( !mesh3.vertexAttribs().hasSameAttribs( mesh4.vertexAttribs() ) ); // TODO : build a functor that add the faces as independant faces in the topomesh and - // define a manifold mesh that is similar to the result of processing of this non manifold. + // define a manifold mesh that is similar to the result of processing of this non + // manifold. // } SECTION( "Non manifold vertex : Bow tie" ) { @@ -1279,15 +1292,9 @@ TEST_CASE( "Core/TopologicalMesh/CollapseWedge", "[unittests]" ) { addSplitScene( points2, colors2, indices4, points1[5], points1[2] ); } } - -TEST_CASE( "Core/Geometry/TopologicalMesh/Updates", - "[unittests][Core][Core/Geometry][TopologicalMesh]" ) { - using Ra::Core::Vector3; - using Ra::Core::Geometry::TopologicalMesh; - using Ra::Core::Geometry::TriangleMesh; - - auto testConverter = []( TriangleMesh mesh ) { - auto topologicalMesh = TopologicalMesh( mesh ); +template +void testConverter( IndexedGeometry&& mesh ) { + auto topologicalMesh = TopologicalMesh { mesh }; auto& vertices = mesh.verticesWithLock(); for ( auto& v : vertices ) { v = TriangleMesh::Point( 0_ra, 1_ra, 2_ra ); @@ -1296,6 +1303,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Updates", // update topo mesh positions from mesh topologicalMesh.updatePositions( mesh.vertices() ); + for ( auto itr = topologicalMesh.vertices_begin(); itr != topologicalMesh.vertices_end(); ++itr ) { REQUIRE( @@ -1321,6 +1329,11 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Updates", } }; +TEST_CASE( "Core/Geometry/TopologicalMesh/Updates", "[unittests][Core][Core/Geometry][TopologicalMesh]" ) { + using Ra::Core::Vector3; + using Ra::Core::Geometry::TopologicalMesh; + using Ra::Core::Geometry::TriangleMesh; + SECTION( "Closed mesh" ) { testConverter( Ra::Core::Geometry::makeBox() ); testConverter( Ra::Core::Geometry::makeSharpBox() ); From 46d5ce3c92b0f5aecab43e2fae8775f9bac3a620 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 5 May 2025 22:49:01 +0200 Subject: [PATCH 040/144] [engine] Fix priority to rm triangles fill draw primitives. --- src/Engine/Data/DrawPrimitives.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index 5618a7c38c9..30e24eaef1f 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -145,6 +145,7 @@ GeometryDisplayablePtr Triangle( const Core::Vector3& a, { boundary_key, AttribArrayDisplayable::RM_LINES } } } ); if ( fill ) { ret->set_active_layer_key( face_key ); } + else { ret->set_active_layer_key( boundary_key ); } return ret; } From bc737c8de137796d2afb985c12f950791845c385 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 5 May 2025 22:50:18 +0200 Subject: [PATCH 041/144] [engine] Add createMeshFromGeometry2 for geometry displayable. Also better wireframe line width. --- src/Engine/Data/Mesh.hpp | 8 ++++++++ src/Engine/Rendering/ForwardRenderer.cpp | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index fb0b883d5cf..0b98990e03e 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -598,6 +598,14 @@ createMeshFromGeometryData( const std::string& name, const Ra::Core::Asset::Geom return ret; } +template +std::shared_ptr +createMeshFromGeometryData2( const std::string& name, const Ra::Core::Asset::GeometryData* data ) { + auto mesh = createCoreMeshFromGeometryData( data ); + auto ret = std::make_shared( name, std::move( mesh ) ); + return ret; +} + //////////////// AttribArrayDisplayable /////////////////////////////// void AttribArrayDisplayable::setRenderMode( MeshRenderMode mode ) { diff --git a/src/Engine/Rendering/ForwardRenderer.cpp b/src/Engine/Rendering/ForwardRenderer.cpp index 8517a5ce5d3..3c697bb8bed 100644 --- a/src/Engine/Rendering/ForwardRenderer.cpp +++ b/src/Engine/Rendering/ForwardRenderer.cpp @@ -449,15 +449,15 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData shader->setUniform( "transform.model", modelMatrix ); shader->setUniform( "viewport", Core::Vector2 { m_width, m_height } ); if ( hasTriangleLayer && ( hasQuadLayer || hasPolyLayer ) ) - shader->setUniform( "pixelWidth", 1.2f ); + shader->setUniform( "pixelWidth", 1.5f ); else - shader->setUniform( "pixelWidth", 2.8f ); + shader->setUniform( "pixelWidth", 1.8f ); GL_CHECK_ERROR; td->render( shader, lineKey ); if ( ( hasQuadLayer || hasPolyLayer ) ) { - shader->setUniform( "pixelWidth", 2.8f ); + shader->setUniform( "pixelWidth", 2.1f ); GL_CHECK_ERROR; td->render( shader, lineKey2 ); } From e01dbb59ea49efb16fc932f060180f26d75e8277 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 5 May 2025 22:50:58 +0200 Subject: [PATCH 042/144] [examples] create GeometryDisplayable instead of AttribArrayDisplayable for loaded logo. --- examples/DrawPrimitives/AllPrimitivesComponent.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index e31aa219621..3596c6ca310 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -699,19 +699,16 @@ void AllPrimitivesComponent::initialize() { auto geomData = data->getGeometryData(); for ( const auto& gd : geomData ) { - std::shared_ptr mesh { nullptr }; + std::shared_ptr mesh { nullptr }; switch ( gd->getType() ) { case Ra::Core::Asset::GeometryData::TRI_MESH: - mesh = std::shared_ptr { - createMeshFromGeometryData( "logo", gd ) }; + mesh = createMeshFromGeometryData2( "logo", gd ); break; case Ra::Core::Asset::GeometryData::QUAD_MESH: - mesh = std::shared_ptr { - createMeshFromGeometryData( "logo", gd ) }; + mesh = createMeshFromGeometryData2( "logo", gd ); break; case Ra::Core::Asset::GeometryData::POLY_MESH: - mesh = std::shared_ptr { - createMeshFromGeometryData( "logo", gd ) }; + mesh = createMeshFromGeometryData2( "logo", gd ); break; default: break; From 5edc761353e45bbe7b0dd0b4e118b8d1c5b51bc0 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 6 May 2025 16:37:08 +0200 Subject: [PATCH 043/144] [engine][core][gui] Use QuadMesh and GeometryDisplayable for Torus and Capsule. --- .../DrawPrimitives/AllPrimitivesComponent.cpp | 9 +++-- src/Core/Geometry/MeshPrimitives.hpp | 34 +++++++++---------- src/Engine/Data/DrawPrimitives.cpp | 10 +++--- src/Engine/Data/DrawPrimitives.hpp | 8 ++--- src/Gui/Viewer/Gizmo/RotateGizmo.cpp | 10 +++--- 5 files changed, 35 insertions(+), 36 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index 3596c6ca310..ae75dadd15f 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -1056,8 +1056,8 @@ void AllPrimitivesComponent::initialize() { { using Ra::Engine::Data::Mesh; { - auto torusGeom = makeParametricTorus<32, 16>( .04_ra, .01_ra, Color::White() ); - auto torusMesh = make_shared( "Torus", std::move( torusGeom ) ); + auto geom = makeParametricTorus<16, 8>( .04_ra, .01_ra, Color::White() ); + auto torusMesh = make_shared( "Torus", std::move( geom ) ); auto torus = RenderObject::createRenderObject( "test_torus", this, RenderObjectType::Geometry, torusMesh, {} ); torus->setMaterial( blinnPhongMaterial ); @@ -1068,10 +1068,9 @@ void AllPrimitivesComponent::initialize() { } { - auto texTorusGeom = - makeParametricTorus<64, 16>( .1_ra, .05_ra, Color::White(), true ); + auto geom = makeParametricTorus<32, 12>( .1_ra, .05_ra, Color::White(), true ); auto texTorusMesh = - make_shared( "Textured Torus", std::move( texTorusGeom ) ); + make_shared( "Textured Torus", std::move( geom ) ); auto texTorus = RenderObject::createRenderObject( "test_tex_torus", this, RenderObjectType::Geometry, texTorusMesh, {} ); texTorus->setMaterial( blinnPhongTexturedMaterial ); diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index 3b6338b1ec8..b88c5723c89 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -97,10 +97,10 @@ TriangleMesh makeParametricSphere( Scalar radius = /// and have Z as rotation axis. Template parameters set the resolution of the mesh. \param /// generateTexCoord: maps parametric (u,v) to texture corrdinates [0,1]^2 template -TriangleMesh makeParametricTorus( Scalar majorRadius, - Scalar minorRadius, - const Utils::optional& color = {}, - bool generateTexCoord = false ); +QuadMesh makeParametricTorus( Scalar majorRadius, + Scalar minorRadius, + const Utils::optional& color = {}, + bool generateTexCoord = false ); /// Create a spherical mesh by subdivision of an icosahedron. RA_CORE_API TriangleMesh makeGeodesicSphere( Scalar radius = 1_ra, @@ -285,14 +285,14 @@ makeParametricSphere( Scalar radius, const Utils::optional& color, } template -TriangleMesh makeParametricTorus( Scalar majorRadius, - Scalar minorRadius, - const Utils::optional& color, - bool generateTexCoord ) { - TriangleMesh result; - TriangleMesh::PointAttribHandle::Container vertices; - TriangleMesh::NormalAttribHandle::Container normals; - TriangleMesh::IndexContainerType indices; +QuadMesh makeParametricTorus( Scalar majorRadius, + Scalar minorRadius, + const Utils::optional& color, + bool generateTexCoord ) { + QuadMesh result; + QuadMesh::PointAttribHandle::Container vertices; + QuadMesh::NormalAttribHandle::Container normals; + QuadMesh::IndexContainerType indices; Ra::Core::Vector3Array texCoords; vertices.reserve( ( U + 1 ) * ( V + 1 ) ); @@ -319,12 +319,10 @@ TriangleMesh makeParametricTorus( Scalar majorRadius, texCoords.emplace_back( iu * du, iv * dv, 0_ra ); if ( iu != U && iv != V ) { - indices.push_back( Vector3ui( iu * ( V + 1 ) + iv, - ( iu + 1 ) * ( V + 1 ) + iv, - iu * ( V + 1 ) + ( iv + 1 ) ) ); - indices.push_back( Vector3ui( ( iu + 1 ) * ( V + 1 ) + iv, - ( iu + 1 ) * ( V + 1 ) + ( iv + 1 ), - iu * ( V + 1 ) + ( iv + 1 ) ) ); + indices.emplace_back( iu * ( V + 1 ) + iv, + ( iu + 1 ) * ( V + 1 ) + iv, + ( iu + 1 ) * ( V + 1 ) + ( iv + 1 ), + iu * ( V + 1 ) + ( iv + 1 ) ); } } } diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index 30e24eaef1f..50d59e37ad2 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -286,10 +286,10 @@ GeometryDisplayablePtr ParametricSphere( const Core::Vector3& center, return make_shared( "Sphere Primitive", std::move( geom ) ); } -MeshPtr Capsule( const Core::Vector3& p1, - const Core::Vector3& p2, - Scalar radius, - const Core::Utils::Color& color ) { +GeometryDisplayablePtr Capsule( const Core::Vector3& p1, + const Core::Vector3& p2, + Scalar radius, + const Core::Utils::Color& color ) { const Scalar l = ( p2 - p1 ).norm(); TriangleMesh geom = makeCapsule( l, radius, 32, color ); @@ -322,7 +322,7 @@ MeshPtr Capsule( const Core::Vector3& p1, } ); normalAttrib.unlock(); - return make_shared( "Capsule Primitive", std::move( geom ) ); + return make_shared( "Capsule Primitive", std::move( geom ) ); } MeshPtr Disk( const Core::Vector3& center, diff --git a/src/Engine/Data/DrawPrimitives.hpp b/src/Engine/Data/DrawPrimitives.hpp index 673baea8fd5..a4595490826 100644 --- a/src/Engine/Data/DrawPrimitives.hpp +++ b/src/Engine/Data/DrawPrimitives.hpp @@ -110,10 +110,10 @@ RA_ENGINE_API GeometryDisplayablePtr ParametricSphere( const Core::Vector3& cent bool generateTexCoord = false ); /// Displays a capsule computed with given endpoints and radius. -RA_ENGINE_API MeshPtr Capsule( const Core::Vector3& p1, - const Core::Vector3& p2, - Scalar radius, - const Core::Utils::Color& color ); +RA_ENGINE_API GeometryDisplayablePtr Capsule( const Core::Vector3& p1, + const Core::Vector3& p2, + Scalar radius, + const Core::Utils::Color& color ); /// Displays disk (filled circle) computed with given center and radius, /// in plane normal to given vector in wireframe diff --git a/src/Gui/Viewer/Gizmo/RotateGizmo.cpp b/src/Gui/Viewer/Gizmo/RotateGizmo.cpp index 67d966536cd..35ad710300a 100644 --- a/src/Gui/Viewer/Gizmo/RotateGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/RotateGizmo.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -12,6 +13,7 @@ namespace Ra { namespace Gui { +using namespace Ra::Core; RotateGizmo::RotateGizmo( Engine::Scene::Component* c, const Core::Transform& worldTo, @@ -22,8 +24,8 @@ RotateGizmo::RotateGizmo( Engine::Scene::Component* c, constexpr Scalar torusAspectRatio = .08_ra; // For x,y,z for ( uint i = 0; i < 3; ++i ) { - Core::Geometry::TriangleMesh torus = Core::Geometry::makeParametricTorus<32>( - torusOutRadius, torusAspectRatio * torusOutRadius ); + auto torus = Core::Geometry::makeParametricTorus<32>( torusOutRadius, + torusAspectRatio * torusOutRadius ); // Transform the torus from z-axis to axis i. auto& data = torus.verticesWithLock(); for ( auto& v : data ) { @@ -32,8 +34,8 @@ RotateGizmo::RotateGizmo( Engine::Scene::Component* c, } torus.verticesUnlock(); - auto mesh = std::shared_ptr( new Engine::Data::Mesh( "Gizmo Torus" ) ); - mesh->loadGeometry( std::move( torus ) ); + auto mesh = + make_shared( "Gizmo Torus", std::move( torus ) ); auto torusDrawable = new Engine::Rendering::RenderObject( "Gizmo Torus", m_comp, Engine::Rendering::RenderObjectType::UI ); From 131efe223bb63628b213e3b33b0507a64f5a77ad Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 6 May 2025 17:35:19 +0200 Subject: [PATCH 044/144] [core][engine] Add FanOrStrip, Disk use GeometryDisplayable. Add restart to layer data, and allow to draw triangle fan for instance. --- src/Core/Geometry/IndexedGeometry.hpp | 13 +++++++ src/Engine/Data/DrawPrimitives.cpp | 35 +++++++++++------- src/Engine/Data/DrawPrimitives.hpp | 10 +++--- src/Engine/Data/Mesh.cpp | 51 ++++++++++++++++++++++----- src/Engine/Data/Mesh.hpp | 11 ++++-- 5 files changed, 93 insertions(+), 27 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 39497fb7b51..bfa8861a4eb 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -507,6 +507,19 @@ struct RA_CORE_API PolyIndexLayer : public GeometryIndexLayer { inline explicit PolyIndexLayer( SemanticNames... names ); }; +struct RA_CORE_API StripOrFanIndexLayer : public GeometryIndexLayer { + inline StripOrFanIndexLayer() : + GeometryIndexLayer( StripOrFanIndexLayer::staticSemanticName ) {} + + static constexpr const char* staticSemanticName = "TriangleStrip"; + INDEX_LAYER_CLONE_IMPLEMENTATION( StripOrFanIndexLayer ) + + protected: + template + inline explicit StripOrFanIndexLayer( SemanticNames... names ) : + GeometryIndexLayer( StripOrFanIndexLayer::staticSemanticName, names... ) {} +}; + /// \brief Index layer for line mesh. /// \note, This layer ensures that all faces have exactly 2 vertices struct RA_CORE_API LineIndexLayer : public GeometryIndexLayer { diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index 50d59e37ad2..5363ad4b8f0 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -1,10 +1,11 @@ -#include "Core/CoreMacros.hpp" #include #include +#include #include #include #include +#include #include #include @@ -258,7 +259,7 @@ GeometryDisplayablePtr CircleArc( const Core::Vector3& center, GeometryDisplayablePtr Sphere( const Core::Vector3& center, Scalar radius, const Core::Utils::Color& color ) { - auto geom = makeGeodesicSphere( radius, 3, color ); + auto geom = makeGeodesicSphere( radius, 2, color ); auto handle = geom.getAttribHandle( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_POSITION ) ); auto& vertices = geom.getAttrib( handle ); @@ -325,12 +326,14 @@ GeometryDisplayablePtr Capsule( const Core::Vector3& p1, return make_shared( "Capsule Primitive", std::move( geom ) ); } -MeshPtr Disk( const Core::Vector3& center, - const Core::Vector3& normal, - Scalar radius, - uint segments, - const Core::Utils::Color& color ) { +GeometryDisplayablePtr Disk( const Core::Vector3& center, + const Core::Vector3& normal, + Scalar radius, + uint segments, + const Core::Utils::Color& color ) { CORE_ASSERT( segments > 2, "Cannot draw a circle with less than 3 points" ); + // MultiIndexedGeometry geom; + // GeometryIndexLayer fan_indices; uint seg = segments + 1; Core::Vector3Array vertices( seg ); @@ -354,13 +357,21 @@ MeshPtr Disk( const Core::Vector3& center, } indices[seg] = 1; - Core::Vector4Array colors( vertices.size(), color ); + MultiIndexedGeometry geom; + geom.setVertices( std::move( vertices ) ); + auto fan_layer = std::make_unique(); + fan_layer->collection().push_back( Eigen::Map( &indices[0], indices.size() ) ); - MeshPtr mesh( new Mesh( "Disk Primitive", Mesh::RM_TRIANGLE_FAN ) ); - mesh->loadGeometry( vertices, indices ); - mesh->getCoreGeometry().addAttrib( - Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), colors ); + auto [fan_check, fan_key] = geom.addLayer( std::move( fan_layer ) ); + CORE_ASSERT( fan_check, "failed to add triangle layer" ); + + geom.addAttrib( + Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), + Core::Vector4Array { geom.vertices().size(), color } ); + auto mesh = make_shared( "Disk Primitive" ); + mesh->loadGeometry( std::move( geom ), fan_key, Mesh::RM_TRIANGLE_FAN ); + mesh->set_active_layer_key( fan_key ); return mesh; } diff --git a/src/Engine/Data/DrawPrimitives.hpp b/src/Engine/Data/DrawPrimitives.hpp index a4595490826..9e22877c048 100644 --- a/src/Engine/Data/DrawPrimitives.hpp +++ b/src/Engine/Data/DrawPrimitives.hpp @@ -118,11 +118,11 @@ RA_ENGINE_API GeometryDisplayablePtr Capsule( const Core::Vector3& p1, /// Displays disk (filled circle) computed with given center and radius, /// in plane normal to given vector in wireframe /// \note normal must be a normalized vector. -RA_ENGINE_API MeshPtr Disk( const Core::Vector3& center, - const Core::Vector3& normal, - Scalar radius, - uint segments, - const Core::Utils::Color& color ); +RA_ENGINE_API GeometryDisplayablePtr Disk( const Core::Vector3& center, + const Core::Vector3& normal, + Scalar radius, + uint segments, + const Core::Utils::Color& color ); /// Displays a normal vector emanating from the given point as a vector arrow /// and a normal plane of size 'scale'. diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index bb265590348..f314e5eccb1 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -331,9 +332,31 @@ void GeometryDisplayable::updateGL() { // upload data to gpu if ( vbo.dirty ) { - vbo.buffer->setData( static_cast( abstractLayer.getBufferSize() ), - abstractLayer.dataPtr(), - GL_STATIC_DRAW ); + const auto& layer = m_geom.getLayer( itr.first ); + bool is_strip = + layer.hasSemantic( Core::Geometry::StripOrFanIndexLayer::staticSemanticName ); + if ( is_strip ) { + l.restart = m_geom.vertices().size(); + + const auto& indices = + static_cast&>( + abstractLayer ); + std::vector buffer; + for ( const auto& strip : indices.collection() ) { + for ( const auto& indice : strip ) { + buffer.push_back( indice ); + } + buffer.push_back( l.restart ); + vbo.buffer->setData( buffer, GL_STATIC_DRAW ); + vbo.numElements = buffer.size(); + } + } + else { + vbo.buffer->setData( + static_cast( abstractLayer.getBufferSize() ), + abstractLayer.dataPtr(), + GL_STATIC_DRAW ); + } vbo.dirty = false; } m_geom.unlockLayer( itr.first ); @@ -382,11 +405,23 @@ void GeometryDisplayable::render( const ShaderProgram* prog, const LayerKeyType& 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 ); + if ( m_geomLayers[key].restart == LayerEntryType::no_restart ) { + m_geomLayers[key].vao->drawElements( + static_cast( m_geomLayers[key].renderMode ), + GLsizei( m_geomLayers[key].indices.numElements ), + GL_UNSIGNED_INT, + nullptr ); + } + else { + glEnable( GL_PRIMITIVE_RESTART ); + glPrimitiveRestartIndex( m_geomLayers[key].restart ); + m_geomLayers[key].vao->drawElements( + static_cast( m_geomLayers[key].renderMode ), + GLsizei( m_geomLayers[key].indices.numElements ), + GL_UNSIGNED_INT, + nullptr ); + glDisable( GL_PRIMITIVE_RESTART ); + } GL_CHECK_ERROR; m_geomLayers[key].vao->unbind(); GL_CHECK_ERROR; diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 0b98990e03e..6cbb5c534b0 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -388,10 +388,15 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable template inline void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, const RangeOfLayerKeys& r ) { - loadGeometry( std::move( mesh ) ); + m_geomLayers.clear(); + m_geom = std::move( mesh ); + setupCoreMeshObservers(); + for ( const auto& k : r ) addRenderLayer( k.first, k.second ); -} + + set_active_layer_key( r[0].first ); + } inline void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, LayerKeyType key, base::MeshRenderMode renderMode ) { @@ -449,6 +454,8 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable std::unique_ptr vao { nullptr }; IndicesVBO indices; base::MeshRenderMode renderMode { RM_TRIANGLES }; + static const uint no_restart = 0; + uint restart { 0 }; inline LayerEntryType() = default; }; From 6611d852f11d19a1610759b56fc3e67e92af5c95 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 6 May 2025 18:10:11 +0200 Subject: [PATCH 045/144] [core] Factorize index layer code using macro. --- src/Core/Geometry/IndexedGeometry.cpp | 9 -- src/Core/Geometry/IndexedGeometry.hpp | 137 ++++++++------------------ src/Core/Geometry/MeshPrimitives.hpp | 6 ++ 3 files changed, 45 insertions(+), 107 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index 6ee8d63da9a..1bc3f1806d5 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -256,15 +256,6 @@ std::size_t MultiIndexedGeometry::LayerKeyHash::operator()( const LayerKeyType& return std::hash {}( result ) ^ ( std::hash {}( k.second ) << 1 ); } -////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// - -void PointCloudIndexLayer::linearIndices( const AttribArrayGeometry& attr ) { - auto nbVert = attr.vertices().size(); - collection().resize( nbVert ); - collection().getMap() = IndexContainerType::Matrix::LinSpaced( nbVert, 0, nbVert - 1 ); -} - } // namespace Geometry } // namespace Core } // namespace Ra diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index bfa8861a4eb..0a3d185953a 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -446,95 +446,71 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util return copy; \ } +#define OPEN_DECLARATION_INDEX_LAYER( NAME, TYPE ) \ + struct RA_CORE_API NAME : public GeometryIndexLayer { \ + inline NAME() : GeometryIndexLayer( NAME::staticSemanticName ) {} \ + static constexpr const char* staticSemanticName = #NAME; \ + INDEX_LAYER_CLONE_IMPLEMENTATION( NAME ) \ + protected: \ + template \ + inline explicit NAME( SemanticNames... names ) : \ + GeometryIndexLayer( NAME::staticSemanticName, names... ) {} \ + \ + public: + +#define DECLARE_INDEX_LAYER( NAME, TYPE ) \ + OPEN_DECLARATION_INDEX_LAYER( NAME, TYPE ) \ + } \ + ; + /// \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 { - /// \brief Constructor of an empty layer - inline PointCloudIndexLayer(); - - /// \brief Constructor of an index layer with linearly spaced indices ranging from \f$0\f$ to - /// \f$n-1\f$ - inline explicit PointCloudIndexLayer( size_t n ); - - /// \brief Generate linearly spaced indices with same size as \p attr vertex buffer - void linearIndices( const AttribArrayGeometry& attr ); +OPEN_DECLARATION_INDEX_LAYER( PointCloudIndexLayer, Vector1ui ) +/// \brief Constructor of an index layer with linearly spaced indices ranging from \f$0\f$ to +/// \f$n-1\f$ +inline explicit PointCloudIndexLayer( size_t n ) : + GeometryIndexLayer( PointCloudIndexLayer::staticSemanticName ) { + collection().resize( n ); + collection().getMap() = IndexContainerType::Matrix::LinSpaced( n, 0, n - 1 ); +} - static constexpr const char* staticSemanticName = "PointCloud"; - INDEX_LAYER_CLONE_IMPLEMENTATION( PointCloudIndexLayer ) +/// \brief Generate linearly spaced indices with same size as \p attr vertex buffer +void linearIndices( const AttribArrayGeometry& attr ) { + auto nbVert = attr.vertices().size(); + collection().resize( nbVert ); + collection().getMap() = IndexContainerType::Matrix::LinSpaced( nbVert, 0, nbVert - 1 ); +} - protected: - template - inline PointCloudIndexLayer( SemanticNames... names ); }; /// \brief Index layer for triangle mesh. /// \note, This layer ensures that all faces have exactly 3 vertices -struct RA_CORE_API TriangleIndexLayer : public GeometryIndexLayer { - inline TriangleIndexLayer(); - static constexpr const char* staticSemanticName = "TriangleMesh"; - INDEX_LAYER_CLONE_IMPLEMENTATION( TriangleIndexLayer ) - - protected: - template - inline explicit TriangleIndexLayer( SemanticNames... names ); -}; +DECLARE_INDEX_LAYER( TriangleIndexLayer, Vector3ui ) /// \brief Index layer for quadrilateral mesh. /// \note, This layer ensures that all faces have exactly 4 vertices -struct RA_CORE_API QuadIndexLayer : public GeometryIndexLayer { - inline QuadIndexLayer(); - static constexpr const char* staticSemanticName = "QuadMesh"; - INDEX_LAYER_CLONE_IMPLEMENTATION( QuadIndexLayer ) - - protected: - template - inline explicit QuadIndexLayer( SemanticNames... names ); -}; +DECLARE_INDEX_LAYER( QuadIndexLayer, Vector4ui ) /// \brief Index layer for polygonal mesh. /// \note, Using this layer, all faces might have more than 4 vertices or have different number of /// vertices. -struct RA_CORE_API PolyIndexLayer : public GeometryIndexLayer { - inline PolyIndexLayer(); - static constexpr const char* staticSemanticName = "PolyMesh"; - INDEX_LAYER_CLONE_IMPLEMENTATION( PolyIndexLayer ) +DECLARE_INDEX_LAYER( PolyIndexLayer, VectorNui ) - protected: - template - inline explicit PolyIndexLayer( SemanticNames... names ); -}; - -struct RA_CORE_API StripOrFanIndexLayer : public GeometryIndexLayer { - inline StripOrFanIndexLayer() : - GeometryIndexLayer( StripOrFanIndexLayer::staticSemanticName ) {} - - static constexpr const char* staticSemanticName = "TriangleStrip"; - INDEX_LAYER_CLONE_IMPLEMENTATION( StripOrFanIndexLayer ) - - protected: - template - inline explicit StripOrFanIndexLayer( SemanticNames... names ) : - GeometryIndexLayer( StripOrFanIndexLayer::staticSemanticName, names... ) {} -}; +/** one Ni index -> one strip */ +DECLARE_INDEX_LAYER( StripOrFanIndexLayer, VectorNui ) /// \brief Index layer for line mesh. /// \note, This layer ensures that all faces have exactly 2 vertices -struct RA_CORE_API LineIndexLayer : public GeometryIndexLayer { - inline LineIndexLayer(); - static constexpr const char* staticSemanticName = "LineMesh"; - INDEX_LAYER_CLONE_IMPLEMENTATION( LineIndexLayer ) - - protected: - template - inline explicit LineIndexLayer( SemanticNames... names ); -}; +DECLARE_INDEX_LAYER( LineIndexLayer, Vector2ui ) /// \} #undef INDEX_LAYER_CLONE_IMPLEMENTATION +#undef OPEN_DECLARATION_INDEX_LAYER +#undef DECLARE_INDEX_LAYER /// Temporary class providing the old API for TriangleMesh, LineMesh and PolyMesh /// This class will be marked as deprecated soon. @@ -759,41 +735,6 @@ MultiIndexedGeometry::unlockLayer( const MultiIndexedGeometry::LayerSemanticColl } // PointCloudIndexLayer -inline PointCloudIndexLayer::PointCloudIndexLayer() : - GeometryIndexLayer( PointCloudIndexLayer::staticSemanticName ) {} -inline PointCloudIndexLayer::PointCloudIndexLayer( size_t n ) : - GeometryIndexLayer( PointCloudIndexLayer::staticSemanticName ) { - collection().resize( n ); - collection().getMap() = IndexContainerType::Matrix::LinSpaced( n, 0, n - 1 ); -} -template -inline PointCloudIndexLayer::PointCloudIndexLayer( SemanticNames... names ) : - GeometryIndexLayer( PointCloudIndexLayer::staticSemanticName, names... ) {} -// TriangleIndexLayer -inline TriangleIndexLayer::TriangleIndexLayer() : - GeometryIndexLayer( TriangleIndexLayer::staticSemanticName ) {} -template -inline TriangleIndexLayer::TriangleIndexLayer( SemanticNames... names ) : - GeometryIndexLayer( TriangleIndexLayer::staticSemanticName, names... ) {} -// QuadIndexLayer -inline QuadIndexLayer::QuadIndexLayer() : - GeometryIndexLayer( QuadIndexLayer::staticSemanticName ) {} -template -inline QuadIndexLayer::QuadIndexLayer( SemanticNames... names ) : - GeometryIndexLayer( QuadIndexLayer::staticSemanticName, names... ) {} -// PolyIndexLayer -inline PolyIndexLayer::PolyIndexLayer() : - GeometryIndexLayer( PolyIndexLayer::staticSemanticName ) {} -template -inline PolyIndexLayer::PolyIndexLayer( SemanticNames... names ) : - GeometryIndexLayer( PolyIndexLayer::staticSemanticName, names... ) {} -// LineIndexLayer -inline LineIndexLayer::LineIndexLayer() : - GeometryIndexLayer( LineIndexLayer::staticSemanticName ) {} -template -inline LineIndexLayer::LineIndexLayer( SemanticNames... names ) : - GeometryIndexLayer( LineIndexLayer::staticSemanticName, names... ) {} -// IndexedGeometry template inline IndexedGeometry::IndexedGeometry() { auto layer = std::make_unique(); diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index b88c5723c89..37a694e1041 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -102,6 +102,12 @@ QuadMesh makeParametricTorus( Scalar majorRadius, const Utils::optional& color = {}, bool generateTexCoord = false ); +// QuadMesh makeParametricTorus( Scalar majorRadius, +// Scalar minorRadius, +// int U = 16, +// int V = 16, +// const Utils::optional& color = {}, +// bool generateTexCoord = false ); /// Create a spherical mesh by subdivision of an icosahedron. RA_CORE_API TriangleMesh makeGeodesicSphere( Scalar radius = 1_ra, uint numSubdiv = 3, From 04970ff45023c30e9cb7af5c06ffbd7f03ff02d2 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 6 May 2025 22:33:25 +0200 Subject: [PATCH 046/144] [core] Add offset to append for GeometryIndexLayer. --- src/Core/Geometry/IndexedGeometry.cpp | 15 ++++++++++++-- src/Core/Geometry/IndexedGeometry.hpp | 28 +++++++++++++++++++++------ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index 1bc3f1806d5..3d30cc22d28 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -56,6 +57,12 @@ void MultiIndexedGeometry::copy( const MultiIndexedGeometry& other ) { void MultiIndexedGeometry::checkConsistency() const {} bool MultiIndexedGeometry::append( const MultiIndexedGeometry& other ) { + + int offset = other.vertices().size(); + // first append attribs + AttribArrayGeometry::append( other ); + + // then indices, and offset. bool dataHasBeenCopied = false; for ( const auto& [key, value] : other.m_indices ) { auto it = m_indices.find( key ); @@ -63,16 +70,20 @@ bool MultiIndexedGeometry::append( const MultiIndexedGeometry& other ) { { m_indices[key] = std::make_pair( value.first, std::unique_ptr { value.second->clone() } ); - dataHasBeenCopied = true; + m_indices[key].second->offset( offset ); + ///\todo offest indices. } else { // try to append to an existing layer: should always work - if ( it->second.second->append( *( value.second ) ) ) { dataHasBeenCopied = true; } + if ( it->second.second->append( *( value.second ), offset ) ) { + dataHasBeenCopied = true; + } else { CORE_ASSERT( false, "Inconsistency: layers with different semantics shares the same key" ); } + ///\todo offest indices. } } diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 0a3d185953a..f4256895cea 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -74,7 +74,8 @@ class RA_CORE_API GeometryIndexLayerBase : public Utils::ObservableVoid, /// \brief Append content from another layer /// \return false if data cannot be appended, e.g., different semantics - virtual bool append( const GeometryIndexLayerBase& other ) = 0; + virtual bool append( const GeometryIndexLayerBase& other, int offset = 0 ) = 0; + virtual void offset( int offset, uint start_index = 0 ) = 0; /// \brief Compare if two layers have the same content virtual inline bool operator==( const GeometryIndexLayerBase& other ) const; @@ -95,8 +96,8 @@ struct GeometryIndexLayer : public GeometryIndexLayerBase { inline IndexContainerType& collection(); const IndexContainerType& collection() const; - inline bool append( const GeometryIndexLayerBase& other ) final; - + inline bool append( const GeometryIndexLayerBase& other, int offset = 0 ) final; + inline void offset( int offset, uint start_index = 0 ) final; /// \warning Does not account for elements permutations inline bool operator==( const GeometryIndexLayerBase& other ) const final; @@ -634,16 +635,31 @@ GeometryIndexLayer::collection() const { } template -inline bool GeometryIndexLayer::append( const GeometryIndexLayerBase& other ) { +inline bool GeometryIndexLayer::append( const GeometryIndexLayerBase& other, int offset ) { if ( shareSemantic( other ) ) { const auto& othercasted = static_cast&>( other ); - m_collection.insert( - m_collection.end(), othercasted.collection().begin(), othercasted.collection().end() ); + + // m_collection.insert( + // m_collection.end(), othercasted.collection().begin(), othercasted.collection().end() + // ); + + std::transform( othercasted.collection().cbegin(), + othercasted.collection().cend(), + std::back_inserter( m_collection ), + [offset]( const T& indice ) -> T { return indice.array() + offset; } ); return true; } return false; } +template +inline void GeometryIndexLayer::offset( int offset, uint start_index ) { + std::transform( m_collection.cbegin() + start_index, + m_collection.cend(), + m_collection.begin() + start_index, + [offset]( const T& indice ) -> T { return indice.array() + offset; } ); +} + template inline bool GeometryIndexLayer::operator==( const GeometryIndexLayerBase& other ) const { if ( shareSemantic( other ) ) { From 824525f1a0c6d8bb15159f15708cd70515f14a1e Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 6 May 2025 22:34:14 +0200 Subject: [PATCH 047/144] [engine] Add triangle layer to disc (not only fan) for wireframe. --- src/Engine/Data/DrawPrimitives.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index 5363ad4b8f0..43f7a88c5ee 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -294,7 +294,6 @@ GeometryDisplayablePtr Capsule( const Core::Vector3& p1, const Scalar l = ( p2 - p1 ).norm(); TriangleMesh geom = makeCapsule( l, radius, 32, color ); - // Compute the transform so that // (0,0,-l/2) maps to p1 and (0,0,l/2) maps to p2 @@ -362,15 +361,23 @@ GeometryDisplayablePtr Disk( const Core::Vector3& center, auto fan_layer = std::make_unique(); fan_layer->collection().push_back( Eigen::Map( &indices[0], indices.size() ) ); - auto [fan_check, fan_key] = geom.addLayer( std::move( fan_layer ) ); - CORE_ASSERT( fan_check, "failed to add triangle layer" ); + auto face_layer = std::make_unique(); + for ( size_t i = 1; i < indices.size() - 1; ++i ) { + face_layer->collection().emplace_back( 0, indices[i], indices[i + 1] ); + } + + auto [fan_check, fan_key] = geom.addLayer( std::move( fan_layer ) ); + auto [face_check, face_key] = geom.addLayer( std::move( face_layer ) ); geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); auto mesh = make_shared( "Disk Primitive" ); - mesh->loadGeometry( std::move( geom ), fan_key, Mesh::RM_TRIANGLE_FAN ); + mesh->loadGeometry( + std::move( geom ), + GeometryDisplayable::ArrayOfLayerKeys<2> { + { { fan_key, Mesh::RM_TRIANGLE_FAN }, { face_key, Mesh::RM_TRIANGLES } } } ); mesh->set_active_layer_key( fan_key ); return mesh; } @@ -459,7 +466,6 @@ GeometryDisplayablePtr Grid( const Core::Vector3& center, const Core::Utils::Color& color, Scalar cellSize, uint res ) { - auto geom = makeGrid( center, x, y, color, cellSize, res ); auto mesh = make_shared( "GridPrimitive", std::move( geom ) ); return mesh; From e59c17625c158e599e37d09186cdee061d824161 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 21 Apr 2026 08:39:57 +0200 Subject: [PATCH 048/144] [core] Typo in comment. --- src/Core/Geometry/TopologicalMesh.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Geometry/TopologicalMesh.hpp b/src/Core/Geometry/TopologicalMesh.hpp index c4dccbabcc1..29e508fc2b1 100644 --- a/src/Core/Geometry/TopologicalMesh.hpp +++ b/src/Core/Geometry/TopologicalMesh.hpp @@ -144,7 +144,7 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT(); } TriangleMesh toTriangleMesh() { return toIndexedMesh(); } - ///\todo move the who next methods as templated lambda when switch to c++20 + ///\todo move the two next methods as templated lambda when switch to c++20 template void copyWedgeDataToAttribContainer( AlignedStdVector::Container>& c, const VectorArray& wd ) { From 1a2677049c031d9f67d971c2d3ca1d6429e578ca Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 21 Apr 2026 09:02:15 +0200 Subject: [PATCH 049/144] [core] Cleanup and remove duplicate code in TopologicalMesh. --- src/Core/Geometry/TopologicalMesh.cpp | 18 ------------ src/Core/Geometry/TopologicalMesh.hpp | 42 ++++++++++++++------------- 2 files changed, 22 insertions(+), 38 deletions(-) diff --git a/src/Core/Geometry/TopologicalMesh.cpp b/src/Core/Geometry/TopologicalMesh.cpp index f68800566c1..41c907837c3 100644 --- a/src/Core/Geometry/TopologicalMesh.cpp +++ b/src/Core/Geometry/TopologicalMesh.cpp @@ -186,24 +186,6 @@ TopologicalMesh::TopologicalMesh() { add_property( m_wedgeIndexPph ); } -template -void copyWedgeDataToAttribContainer( AlignedStdVector::Container>& c, - const VectorArray& wd ) { - for ( size_t i = 0; i < wd.size(); ++i ) { - c[i].push_back( wd[i] ); - } -} - -template -void moveContainerToMesh( Ra::Core::Geometry::MultiIndexedGeometry& out, - const std::vector& names, - AlignedStdVector::Container>& wedgeAttribData ) { - for ( size_t i = 0; i < wedgeAttribData.size(); ++i ) { - auto attrHandle = out.template addAttrib( names[i] ); - out.getAttrib( attrHandle ).setData( std::move( wedgeAttribData[i] ) ); - } -} - void TopologicalMesh::updateTriangleMesh( Ra::Core::Geometry::MultiIndexedGeometry& out ) { TriangleMesh::PointAttribHandle::Container wedgePosition; AlignedStdVector::Container> wedgeFloatAttribData( diff --git a/src/Core/Geometry/TopologicalMesh.hpp b/src/Core/Geometry/TopologicalMesh.hpp index 29e508fc2b1..4df433a3bdf 100644 --- a/src/Core/Geometry/TopologicalMesh.hpp +++ b/src/Core/Geometry/TopologicalMesh.hpp @@ -144,25 +144,6 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT(); } TriangleMesh toTriangleMesh() { return toIndexedMesh(); } - ///\todo move the two next methods as templated lambda when switch to c++20 - template - void copyWedgeDataToAttribContainer( AlignedStdVector::Container>& c, - const VectorArray& wd ) { - for ( size_t i = 0; i < wd.size(); ++i ) { - c[i].push_back( wd[i] ); - } - } - - template - void moveContainerToMesh( Ra::Core::Geometry::MultiIndexedGeometry& out, - const std::vector& names, - AlignedStdVector::Container>& wedgeAttribData ) { - for ( size_t i = 0; i < wedgeAttribData.size(); ++i ) { - auto attrHandle = out.template addAttrib( names[i] ); - out.getAttrib( attrHandle ).setData( std::move( wedgeAttribData[i] ) ); - } - } - /** * Update triangle mesh data, assuming the mesh and this topo mesh has the * same topology. @@ -412,6 +393,26 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT + void copyWedgeDataToAttribContainer( AlignedStdVector::Container>& c, + const VectorArray& wd ) { + for ( size_t i = 0; i < wd.size(); ++i ) { + c[i].push_back( wd[i] ); + } + } + + template + void moveContainerToMesh( Ra::Core::Geometry::MultiIndexedGeometry& out, + const std::vector& names, + AlignedStdVector::Container>& wedgeAttribData ) { + for ( size_t i = 0; i < wedgeAttribData.size(); ++i ) { + auto attrHandle = out.template addAttrib( names[i] ); + out.getAttrib( attrHandle ).setData( std::move( wedgeAttribData[i] ) ); + } + } + // base on openmesh version void collapse_edge( HalfedgeHandle, bool ); void collapse_loop( HalfedgeHandle ); @@ -1469,8 +1470,9 @@ TopologicalMesh::getWedgeIndexPph() const { } template -IndexedGeometry TopologicalMesh::toIndexedMesh() { // first cleanup deleted element +IndexedGeometry TopologicalMesh::toIndexedMesh() { + // first cleanup deleted element garbage_collection(); IndexedGeometry out; From a5cf93ceda5db2039430fb97347b4a8cbd90a721 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 21 Apr 2026 09:17:50 +0200 Subject: [PATCH 050/144] [core][...] Rename TriangleMesh.?pp to AttribArayGeometry.?pp Do not include IndexedGeometry in AttribArrayGeometry Update includes path. --- src/Core/Animation/SkinningData.hpp | 2 +- src/Core/Asset/GeometryData.hpp | 3 +- ...iangleMesh.cpp => AttribArrayGeometry.cpp} | 2 +- ...iangleMesh.hpp => AttribArrayGeometry.hpp} | 2 - src/Core/Geometry/DistanceQueries.hpp | 2 +- src/Core/Geometry/IndexedGeometry.cpp | 2 +- src/Core/Geometry/IndexedGeometry.hpp | 2 +- src/Core/Geometry/MeshPrimitives.hpp | 2 +- src/Core/Geometry/RayCast.cpp | 2 +- src/Core/Geometry/TopologicalMesh.hpp | 2 +- .../Geometry/deprecated/TopologicalMesh.hpp | 5 +- src/Core/filelist.cmake | 3 +- src/Engine/Data/DisplayableObject.hpp | 2 +- src/Engine/Data/Mesh.hpp | 2 +- src/Engine/Scene/GeometryComponent.hpp | 2 +- src/Engine/Scene/SkeletonComponent.cpp | 2 +- src/Engine/Scene/SkinningComponent.cpp | 2 +- src/Engine/Scene/SkinningComponent.hpp | 2 +- src/Engine/pch.hpp | 2 +- src/IO/deprecated/OBJFileManager.hpp | 2 +- src/IO/deprecated/OFFFileManager.hpp | 2 +- tests/unittest/Core/topomesh.cpp | 61 ++++++++++--------- 22 files changed, 54 insertions(+), 54 deletions(-) rename src/Core/Geometry/{TriangleMesh.cpp => AttribArrayGeometry.cpp} (96%) rename src/Core/Geometry/{TriangleMesh.hpp => AttribArrayGeometry.hpp} (99%) diff --git a/src/Core/Animation/SkinningData.hpp b/src/Core/Animation/SkinningData.hpp index dd238dc5d6a..e103d109dae 100644 --- a/src/Core/Animation/SkinningData.hpp +++ b/src/Core/Animation/SkinningData.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include namespace Ra { diff --git a/src/Core/Asset/GeometryData.hpp b/src/Core/Asset/GeometryData.hpp index 24551949d88..b084d1ae284 100644 --- a/src/Core/Asset/GeometryData.hpp +++ b/src/Core/Asset/GeometryData.hpp @@ -3,8 +3,9 @@ #include #include #include +#include +#include #include -#include #include #include #include diff --git a/src/Core/Geometry/TriangleMesh.cpp b/src/Core/Geometry/AttribArrayGeometry.cpp similarity index 96% rename from src/Core/Geometry/TriangleMesh.cpp rename to src/Core/Geometry/AttribArrayGeometry.cpp index 7a72678a91e..7cb6ad27199 100644 --- a/src/Core/Geometry/TriangleMesh.cpp +++ b/src/Core/Geometry/AttribArrayGeometry.cpp @@ -1,6 +1,6 @@ #include +#include #include -#include #include namespace Ra { diff --git a/src/Core/Geometry/TriangleMesh.hpp b/src/Core/Geometry/AttribArrayGeometry.hpp similarity index 99% rename from src/Core/Geometry/TriangleMesh.hpp rename to src/Core/Geometry/AttribArrayGeometry.hpp index 8f9def05f7d..dbf8fe0ee48 100644 --- a/src/Core/Geometry/TriangleMesh.hpp +++ b/src/Core/Geometry/AttribArrayGeometry.hpp @@ -461,5 +461,3 @@ inline void AttribArrayGeometry::append_attrib( Utils::AttribBase* attr ) { } // namespace Geometry } // namespace Core } // namespace Ra - -#include "IndexedGeometry.hpp" diff --git a/src/Core/Geometry/DistanceQueries.hpp b/src/Core/Geometry/DistanceQueries.hpp index 4a0b1964310..ff0ffec7fc0 100644 --- a/src/Core/Geometry/DistanceQueries.hpp +++ b/src/Core/Geometry/DistanceQueries.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index 3d30cc22d28..5dc08946081 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -1,5 +1,5 @@ +#include #include -#include #include #include diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index f4256895cea..366e2c7acee 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index 37a694e1041..5a77bc6bf74 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include #include #include #include diff --git a/src/Core/Geometry/RayCast.cpp b/src/Core/Geometry/RayCast.cpp index 38a393188c4..87815c40313 100644 --- a/src/Core/Geometry/RayCast.cpp +++ b/src/Core/Geometry/RayCast.cpp @@ -1,5 +1,5 @@ +#include #include -#include #include // Math::sign namespace Ra { diff --git a/src/Core/Geometry/TopologicalMesh.hpp b/src/Core/Geometry/TopologicalMesh.hpp index 4df433a3bdf..5b754a056e7 100644 --- a/src/Core/Geometry/TopologicalMesh.hpp +++ b/src/Core/Geometry/TopologicalMesh.hpp @@ -2,9 +2,9 @@ #include "Core/Geometry/IndexedGeometry.hpp" #include +#include #include #include -#include #include #include #include diff --git a/src/Core/Geometry/deprecated/TopologicalMesh.hpp b/src/Core/Geometry/deprecated/TopologicalMesh.hpp index 3a9c14fd850..a6150f16242 100644 --- a/src/Core/Geometry/deprecated/TopologicalMesh.hpp +++ b/src/Core/Geometry/deprecated/TopologicalMesh.hpp @@ -3,9 +3,10 @@ #include #include +#include +#include #include #include -#include #include #include #include @@ -19,8 +20,6 @@ #include #include -#include -#include #include namespace Ra { diff --git a/src/Core/filelist.cmake b/src/Core/filelist.cmake index 00bd624bfe6..011027c3c16 100644 --- a/src/Core/filelist.cmake +++ b/src/Core/filelist.cmake @@ -27,6 +27,7 @@ set(core_sources Containers/DynamicVisitor.cpp Containers/VariableSet.cpp Containers/VariableSetEnumManagement.cpp + Geometry/AttribArrayGeometry.cpp Geometry/CatmullClarkSubdivider.cpp Geometry/IndexedGeometry.cpp Geometry/LoopSubdivider.cpp @@ -34,7 +35,6 @@ set(core_sources Geometry/PolyLine.cpp Geometry/RayCast.cpp Geometry/TopologicalMesh.cpp - Geometry/TriangleMesh.cpp Geometry/Volume.cpp Geometry/deprecated/TopologicalMesh.cpp Random/RandomPointSet.cpp @@ -92,6 +92,7 @@ set(core_headers Containers/VectorArray.hpp CoreMacros.hpp Geometry/AbstractGeometry.hpp + Geometry/AttribArrayGeometry.hpp Geometry/CatmullClarkSubdivider.hpp Geometry/Curve2D.hpp Geometry/DistanceQueries.hpp diff --git a/src/Engine/Data/DisplayableObject.hpp b/src/Engine/Data/DisplayableObject.hpp index 517a31d3ded..eb17bb65447 100644 --- a/src/Engine/Data/DisplayableObject.hpp +++ b/src/Engine/Data/DisplayableObject.hpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include namespace Ra { diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 6cbb5c534b0..04e2c463554 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -2,9 +2,9 @@ #include #include +#include #include #include -#include #include #include #include diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index 43da347c2e9..637b025380e 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -3,8 +3,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/Engine/Scene/SkeletonComponent.cpp b/src/Engine/Scene/SkeletonComponent.cpp index 6d22ed9dbf3..5a6729adec3 100644 --- a/src/Engine/Scene/SkeletonComponent.cpp +++ b/src/Engine/Scene/SkeletonComponent.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include // areApproxEqual #include diff --git a/src/Engine/Scene/SkinningComponent.cpp b/src/Engine/Scene/SkinningComponent.cpp index 5ef45e34a03..6c8276d4c2a 100644 --- a/src/Engine/Scene/SkinningComponent.cpp +++ b/src/Engine/Scene/SkinningComponent.cpp @@ -1,4 +1,4 @@ -#include "Core/Geometry/TriangleMesh.hpp" +#include "Core/Geometry/AttribArrayGeometry.hpp" #include #include diff --git a/src/Engine/Scene/SkinningComponent.hpp b/src/Engine/Scene/SkinningComponent.hpp index 9f9608c6a45..7c19b5c1177 100644 --- a/src/Engine/Scene/SkinningComponent.hpp +++ b/src/Engine/Scene/SkinningComponent.hpp @@ -4,8 +4,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/Engine/pch.hpp b/src/Engine/pch.hpp index b32a04b7c1a..64441d54355 100644 --- a/src/Engine/pch.hpp +++ b/src/Engine/pch.hpp @@ -7,8 +7,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/IO/deprecated/OBJFileManager.hpp b/src/IO/deprecated/OBJFileManager.hpp index 48bc45caaad..298a56383b5 100644 --- a/src/IO/deprecated/OBJFileManager.hpp +++ b/src/IO/deprecated/OBJFileManager.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include diff --git a/src/IO/deprecated/OFFFileManager.hpp b/src/IO/deprecated/OFFFileManager.hpp index 435af19e050..183ea13dec1 100644 --- a/src/IO/deprecated/OFFFileManager.hpp +++ b/src/IO/deprecated/OFFFileManager.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/tests/unittest/Core/topomesh.cpp b/tests/unittest/Core/topomesh.cpp index 26cb038c026..70f111e497a 100644 --- a/tests/unittest/Core/topomesh.cpp +++ b/tests/unittest/Core/topomesh.cpp @@ -1,8 +1,8 @@ +#include #include #include #include #include -#include #include #include #include @@ -60,7 +60,7 @@ bool isSameMesh( const Ra::Core::Geometry::MultiIndexedGeometry& meshOne, stackNormals.clear(); for ( auto coord : index ) { stackNormals.push_back( meshOne.normals()[coord] ); - } + } } for ( int j = 0; j < indices_mesh_two[i].size(); ++j ) { it = find( stackVertices.begin(), @@ -1295,41 +1295,42 @@ TEST_CASE( "Core/TopologicalMesh/CollapseWedge", "[unittests]" ) { template void testConverter( IndexedGeometry&& mesh ) { auto topologicalMesh = TopologicalMesh { mesh }; - auto& vertices = mesh.verticesWithLock(); - for ( auto& v : vertices ) { - v = TriangleMesh::Point( 0_ra, 1_ra, 2_ra ); - } - mesh.verticesUnlock(); + auto& vertices = mesh.verticesWithLock(); + for ( auto& v : vertices ) { + v = TriangleMesh::Point( 0_ra, 1_ra, 2_ra ); + } + mesh.verticesUnlock(); - // update topo mesh positions from mesh - topologicalMesh.updatePositions( mesh.vertices() ); + // update topo mesh positions from mesh + topologicalMesh.updatePositions( mesh.vertices() ); - for ( auto itr = topologicalMesh.vertices_begin(); itr != topologicalMesh.vertices_end(); - ++itr ) { - REQUIRE( - topologicalMesh.point( *itr ).isApprox( TriangleMesh::Point( 0_ra, 1_ra, 2_ra ) ) ); - // modify for next test. - topologicalMesh.point( *itr ) = TopologicalMesh::Point( 3_ra, 4_ra, 5_ra ); - } + for ( auto itr = topologicalMesh.vertices_begin(); itr != topologicalMesh.vertices_end(); + ++itr ) { + REQUIRE( + topologicalMesh.point( *itr ).isApprox( TriangleMesh::Point( 0_ra, 1_ra, 2_ra ) ) ); + // modify for next test. + topologicalMesh.point( *itr ) = TopologicalMesh::Point( 3_ra, 4_ra, 5_ra ); + } - // the other way round - topologicalMesh.updateTriangleMesh( mesh ); + // the other way round + topologicalMesh.updateTriangleMesh( mesh ); - // not update since wedges are not updated yet - for ( auto itr = mesh.vertices().begin(); itr != mesh.vertices().end(); ++itr ) { - REQUIRE( itr->isApprox( TriangleMesh::Point( 0_ra, 1_ra, 2_ra ) ) ); - } + // not update since wedges are not updated yet + for ( auto itr = mesh.vertices().begin(); itr != mesh.vertices().end(); ++itr ) { + REQUIRE( itr->isApprox( TriangleMesh::Point( 0_ra, 1_ra, 2_ra ) ) ); + } - topologicalMesh.copyPointsPositionToWedges(); - topologicalMesh.updateTriangleMesh( mesh ); + topologicalMesh.copyPointsPositionToWedges(); + topologicalMesh.updateTriangleMesh( mesh ); - // not update since wedges are not updated yet - for ( auto itr = mesh.vertices().begin(); itr != mesh.vertices().end(); ++itr ) { - REQUIRE( itr->isApprox( TriangleMesh::Point( 3_ra, 4_ra, 5_ra ) ) ); - } - }; + // not update since wedges are not updated yet + for ( auto itr = mesh.vertices().begin(); itr != mesh.vertices().end(); ++itr ) { + REQUIRE( itr->isApprox( TriangleMesh::Point( 3_ra, 4_ra, 5_ra ) ) ); + } +}; -TEST_CASE( "Core/Geometry/TopologicalMesh/Updates", "[unittests][Core][Core/Geometry][TopologicalMesh]" ) { +TEST_CASE( "Core/Geometry/TopologicalMesh/Updates", + "[unittests][Core][Core/Geometry][TopologicalMesh]" ) { using Ra::Core::Vector3; using Ra::Core::Geometry::TopologicalMesh; using Ra::Core::Geometry::TriangleMesh; From 227791e84ed5b13529a7692caaea9e58de39d864 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 21 Apr 2026 11:47:28 +0200 Subject: [PATCH 051/144] [core] wip on attrib geom in skinning --- src/Engine/Scene/SkinningComponent.cpp | 6 +++++- src/Engine/Scene/SkinningComponent.hpp | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Engine/Scene/SkinningComponent.cpp b/src/Engine/Scene/SkinningComponent.cpp index 6c8276d4c2a..bb2fc491bc8 100644 --- a/src/Engine/Scene/SkinningComponent.cpp +++ b/src/Engine/Scene/SkinningComponent.cpp @@ -1,4 +1,5 @@ #include "Core/Geometry/AttribArrayGeometry.hpp" +#include "Core/Geometry/IndexedGeometry.hpp" #include #include @@ -47,7 +48,10 @@ void SkinningComponent::initialize() { m_renderObjectReader = compMsg->getterCallback( getEntity(), m_meshName ); m_skeletonGetter = compMsg->getterCallback( getEntity(), m_skelName ); - m_geomWriter = compMsg->rwCallback( getEntity(), m_meshName ); + // m_geomWriter = compMsg->rwCallback( getEntity(), m_meshName + // ); + m_geomWriter = + compMsg->rwCallback( getEntity(), m_meshName ); // copy mesh triangles and find duplicates for normal computation. m_refData.m_referenceMesh = *m_geomWriter(); diff --git a/src/Engine/Scene/SkinningComponent.hpp b/src/Engine/Scene/SkinningComponent.hpp index 7c19b5c1177..f5523e812ae 100644 --- a/src/Engine/Scene/SkinningComponent.hpp +++ b/src/Engine/Scene/SkinningComponent.hpp @@ -1,5 +1,6 @@ #pragma once +#include "Core/Geometry/IndexedGeometry.hpp" #include #include #include @@ -198,7 +199,9 @@ class RA_ENGINE_API SkinningComponent : public Component Getter m_renderObjectReader; /// Getter/Setter to the skinned geom - ReadWrite m_geomWriter; + // ReadWrite m_geomWriter; + // ReadWrite m_geomWriter; + ReadWrite m_geomWriter; /// The per-bone skinning weights. /// \note These are stored this way because we cannot build the weight matrix From 14d1e7b29542960ede49bbf6a3525c81d1fad11b Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 8 May 2026 10:36:07 +0200 Subject: [PATCH 052/144] [core] Add default layer key (init as invalid) to multi index geom. Set default layer on deep copy. --- src/Core/Geometry/IndexedGeometry.cpp | 5 ++ src/Core/Geometry/IndexedGeometry.hpp | 88 ++++++++++++++++----------- 2 files changed, 57 insertions(+), 36 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index 5dc08946081..18a6e846619 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -228,6 +228,10 @@ auto MultiIndexedGeometry::addLayer( std::unique_ptr&& l 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 ) ); + + // set default layer if its the first insterted layer + if ( inserted && m_indices.size() == 1 ) m_default_layer_key = key; + notify(); if ( withLock ) { @@ -247,6 +251,7 @@ void MultiIndexedGeometry::deepCopy( const MultiIndexedGeometry& other ) { m_indices[key] = std::make_pair( value.first, std::unique_ptr { value.second->clone() } ); } + set_default_layer_key( other.default_layer_key() ); } void MultiIndexedGeometry::deepClear() { diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 366e2c7acee..942905ee197 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -123,6 +123,32 @@ struct GeometryIndexLayer : public GeometryIndexLayerBase { IndexContainerType m_collection; }; +#define INDEX_LAYER_CLONE_IMPLEMENTATION( TYPE ) \ + inline std::unique_ptr clone() override { \ + auto copy = std::make_unique( *this ); \ + copy->collection() = collection(); \ + return copy; \ + } + +#define OPEN_DECLARATION_INDEX_LAYER( NAME, TYPE ) \ + struct RA_CORE_API NAME : public GeometryIndexLayer { \ + inline NAME() : GeometryIndexLayer( NAME::staticSemanticName ) {} \ + static constexpr const char* staticSemanticName = #NAME; \ + INDEX_LAYER_CLONE_IMPLEMENTATION( NAME ) \ + protected: \ + template \ + inline explicit NAME( SemanticNames... names ) : \ + GeometryIndexLayer( NAME::staticSemanticName, names... ) {} \ + \ + public: + +#define DECLARE_INDEX_LAYER( NAME, TYPE ) \ + OPEN_DECLARATION_INDEX_LAYER( NAME, TYPE ) \ + } \ + ; + +DECLARE_INDEX_LAYER( InvalidIndexLayer, Vector1ui ); + /// \brief AbstractGeometry with per-vertex attributes and layers of indices. /// Each layer represents a different topology or indexing logic, e.g. triangle/line/quad /// meshes, point-clouds. @@ -400,7 +426,12 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util public: /// \brief Add layer /// + /// If not inserted, the pointer is deleted. So the caller must ensure this possible + /// deletion is safe before calling this method. + /// /// Notify observers of the update. + /// If first added layer, default layer key is set to this layer. + /// /// \return false if a layer with same semantics and name already exists. /// /// \warning Takes the ownership of the layer @@ -415,6 +446,15 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \snippet tests/unittest/Core/indexview.cpp Iterating over layer keys [[nodiscard]] inline auto layerKeys() const; + /// returs default layer key, initialized to InvalidLayerKey, + const LayerKeyType& default_layer_key() const { return m_default_layer_key; } + + /// Set default layer key, the indexed geometry must contains the key, otherwith default key is + /// not modifiend + void set_default_layer_key( const LayerKeyType& layer_key ) { + if ( containsLayer( layer_key ) ) m_default_layer_key = layer_key; + } + private: /// \brief Duplicate attributes stored as pointers void deepCopy( const MultiIndexedGeometry& other ); @@ -438,32 +478,11 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// 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; + LayerKeyType m_default_layer_key = std::make_pair( + { InvalidIndexLayer::staticSemanticName }, + "invalid" ); }; -#define INDEX_LAYER_CLONE_IMPLEMENTATION( TYPE ) \ - inline std::unique_ptr clone() override { \ - auto copy = std::make_unique( *this ); \ - copy->collection() = collection(); \ - return copy; \ - } - -#define OPEN_DECLARATION_INDEX_LAYER( NAME, TYPE ) \ - struct RA_CORE_API NAME : public GeometryIndexLayer { \ - inline NAME() : GeometryIndexLayer( NAME::staticSemanticName ) {} \ - static constexpr const char* staticSemanticName = #NAME; \ - INDEX_LAYER_CLONE_IMPLEMENTATION( NAME ) \ - protected: \ - template \ - inline explicit NAME( SemanticNames... names ) : \ - GeometryIndexLayer( NAME::staticSemanticName, names... ) {} \ - \ - public: - -#define DECLARE_INDEX_LAYER( NAME, TYPE ) \ - OPEN_DECLARATION_INDEX_LAYER( NAME, TYPE ) \ - } \ - ; - /// \name Predefined index layers /// The use of these layers helps in generic management of geometries /// \{ @@ -583,9 +602,6 @@ class IndexedGeometry : public MultiIndexedGeometry inline void setIndices( IndexContainerType&& indices ); inline void setIndices( const IndexContainerType& indices ); inline const LayerKeyType& getLayerKey() const; - - private: - LayerKeyType m_mainIndexLayerKey; }; class RA_CORE_API IndexedPointCloud : public IndexedGeometry @@ -753,32 +769,32 @@ MultiIndexedGeometry::unlockLayer( const MultiIndexedGeometry::LayerSemanticColl // PointCloudIndexLayer template inline IndexedGeometry::IndexedGeometry() { - auto layer = std::make_unique(); - m_mainIndexLayerKey = { layer->semantics(), "" }; - addLayer( std::move( layer ) ); + auto layer = std::make_unique(); + auto added = addLayer( std::move( layer ) ); + if ( added.first ) { set_default_layer_key( added.second ); } } template inline const typename IndexedGeometry::IndexContainerType& IndexedGeometry::getIndices() const { - const auto& abstractLayer = getLayer( m_mainIndexLayerKey ); + const auto& abstractLayer = getLayer( default_layer_key() ); return static_cast::DefaultLayerType&>( abstractLayer ).collection(); } template inline typename IndexedGeometry::IndexContainerType& IndexedGeometry::getIndicesWithLock() { - auto& abstractLayer = getLayerWithLock( m_mainIndexLayerKey ); + auto& abstractLayer = getLayerWithLock( default_layer_key() ); return static_cast::DefaultLayerType&>( abstractLayer ).collection(); } template inline void IndexedGeometry::indicesUnlock() { - unlockLayer( m_mainIndexLayerKey ); + unlockLayer( default_layer_key() ); } template inline void IndexedGeometry::setIndices( IndexContainerType&& indices ) { - auto& abstractLayer = getLayerWithLock( m_mainIndexLayerKey ); + auto& abstractLayer = getLayerWithLock( default_layer_key() ); static_cast::DefaultLayerType&>( abstractLayer ).collection() = std::move( indices ); indicesUnlock(); @@ -787,7 +803,7 @@ inline void IndexedGeometry::setIndices( IndexContainerType&& indices ) { template inline void IndexedGeometry::setIndices( const IndexContainerType& indices ) { - auto& abstractLayer = getLayerWithLock( m_mainIndexLayerKey ); + auto& abstractLayer = getLayerWithLock( default_layer_key() ); static_cast::DefaultLayerType&>( abstractLayer ).collection() = indices; indicesUnlock(); notify(); @@ -795,7 +811,7 @@ inline void IndexedGeometry::setIndices( const IndexContainerType& indices ) template inline const typename IndexedGeometry::LayerKeyType& IndexedGeometry::getLayerKey() const { - return m_mainIndexLayerKey; + return default_layer_key(); } } // namespace Geometry From 55a1badfb3ae3c029c76317869949df26c43fa93 Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 8 May 2026 10:36:48 +0200 Subject: [PATCH 053/144] [core] Switch skinnig reference mesth to multiindexgeometry. --- src/Core/Animation/RotationCenterSkinning.cpp | 5 +++-- src/Core/Animation/SkinningData.hpp | 3 ++- src/Core/filelist.cmake | 5 ++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Core/Animation/RotationCenterSkinning.cpp b/src/Core/Animation/RotationCenterSkinning.cpp index 1f60fe6dcd3..39b64285575 100644 --- a/src/Core/Animation/RotationCenterSkinning.cpp +++ b/src/Core/Animation/RotationCenterSkinning.cpp @@ -1,3 +1,4 @@ +#include "Core/Geometry/IndexedGeometry.hpp" #include #include @@ -52,9 +53,9 @@ void computeCoR( SkinningRefData& dataInOut, Scalar sigma, Scalar weightEpsilon // // convert the mesh to TopologicalMesh for easy processing. - Geometry::TriangleMesh triMesh; + Geometry::MultiIndexedGeometry triMesh; triMesh.copy( dataInOut.m_referenceMesh ); - Geometry::TopologicalMesh topoMesh( triMesh ); + Geometry::TopologicalMesh topoMesh( triMesh, triMesh.default_layer_key() ); // hashing function for Vector3 struct hash_vec { diff --git a/src/Core/Animation/SkinningData.hpp b/src/Core/Animation/SkinningData.hpp index e103d109dae..33713364440 100644 --- a/src/Core/Animation/SkinningData.hpp +++ b/src/Core/Animation/SkinningData.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace Ra { @@ -13,7 +14,7 @@ namespace Animation { /// \brief Skinning data that get set at startup including the "reference state". struct SkinningRefData { /// The mesh in reference position. - Geometry::AttribArrayGeometry m_referenceMesh; + Core::Geometry::MultiIndexedGeometry m_referenceMesh; /// The inverse of the mesh's transform. Transform m_meshTransformInverse; diff --git a/src/Core/filelist.cmake b/src/Core/filelist.cmake index 011027c3c16..05422b1d6f0 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 @@ -60,7 +60,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 @@ -106,7 +106,6 @@ set(core_headers Geometry/Spline.hpp Geometry/StandardAttribNames.hpp Geometry/TopologicalMesh.hpp - Geometry/TriangleMesh.hpp Geometry/Volume.hpp Geometry/deprecated/TopologicalMesh.hpp Math/DualQuaternion.hpp From 09e2e6e1f3a5de6aea61c8988a024e146c3db9a1 Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 8 May 2026 11:43:29 +0200 Subject: [PATCH 054/144] [engine] Clean includes and remove commented code in Skinning. --- src/Engine/Scene/SkinningComponent.cpp | 16 ++++++---------- src/Engine/Scene/SkinningComponent.hpp | 2 -- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/Engine/Scene/SkinningComponent.cpp b/src/Engine/Scene/SkinningComponent.cpp index bb2fc491bc8..e63d55c9c22 100644 --- a/src/Engine/Scene/SkinningComponent.cpp +++ b/src/Engine/Scene/SkinningComponent.cpp @@ -1,16 +1,15 @@ -#include "Core/Geometry/AttribArrayGeometry.hpp" -#include "Core/Geometry/IndexedGeometry.hpp" -#include - -#include +#include #include #include #include +#include +#include +#include #include +#include #include #include - #include #include #include @@ -48,8 +47,6 @@ void SkinningComponent::initialize() { m_renderObjectReader = compMsg->getterCallback( getEntity(), m_meshName ); m_skeletonGetter = compMsg->getterCallback( getEntity(), m_skelName ); - // m_geomWriter = compMsg->rwCallback( getEntity(), m_meshName - // ); m_geomWriter = compMsg->rwCallback( getEntity(), m_meshName ); @@ -176,8 +173,7 @@ void SkinningComponent::skin() { break; } case COR: { - ///\todo centerOfRotationSkinning( m_refData, tangents, bitangents, - /// m_frameData ); + centerOfRotationSkinning( m_refData, tangents, bitangents, m_frameData ); break; } case LBS: diff --git a/src/Engine/Scene/SkinningComponent.hpp b/src/Engine/Scene/SkinningComponent.hpp index f5523e812ae..53a699d6877 100644 --- a/src/Engine/Scene/SkinningComponent.hpp +++ b/src/Engine/Scene/SkinningComponent.hpp @@ -199,8 +199,6 @@ class RA_ENGINE_API SkinningComponent : public Component Getter m_renderObjectReader; /// Getter/Setter to the skinned geom - // ReadWrite m_geomWriter; - // ReadWrite m_geomWriter; ReadWrite m_geomWriter; /// The per-bone skinning weights. From ca45fbc01a5587312c8fa81d112a59298c57f873 Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 8 May 2026 12:05:08 +0200 Subject: [PATCH 055/144] [core] Refactor indexed geometry (comments, inline). --- src/Core/Geometry/IndexedGeometry.hpp | 257 ++++++++++++++------------ 1 file changed, 143 insertions(+), 114 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 942905ee197..a8832fe9254 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -52,7 +52,9 @@ inline VectorArray triangulate( const VectorArray& in ) { return out; } -/// \brief Base class for index collections stored in MultiIndexedGeometry +/** + * \brief Base class for index collections stored in MultiIndexedGeometry. + */ class RA_CORE_API GeometryIndexLayerBase : public Utils::ObservableVoid, public Utils::ObjectWithSemantic, public Utils::ContainerIntrospectionInterface @@ -87,7 +89,9 @@ class RA_CORE_API GeometryIndexLayerBase : public Utils::ObservableVoid, inline GeometryIndexLayerBase( SemanticNames... names ) : ObjectWithSemantic( names... ) {} }; -/// \brief Typed index collection +/** + * \brief Typed index collection. + */ template struct GeometryIndexLayer : public GeometryIndexLayerBase { using IndexType = T; @@ -149,51 +153,53 @@ struct GeometryIndexLayer : public GeometryIndexLayerBase { DECLARE_INDEX_LAYER( InvalidIndexLayer, Vector1ui ); -/// \brief AbstractGeometry with per-vertex attributes and layers of indices. -/// Each layer represents a different topology or indexing logic, e.g. triangle/line/quad -/// meshes, point-clouds. -/// -/// Multiple layers are useful to share and maintain consistency of per-vertex attributes -/// between different meshes representing the same geometry, e.g., a quad and triangle mesh -/// layers connecting the same set of vertices. -/// -/// ## Data-structure -/// It is designed as follow: -/// - Per-vertex attributes are stored as AttribArrayGeometry, -/// - Each layer of indices is represented as a GeometryIndexLayer, which inherits -/// Utils::ObjectWithSemantic -/// to store its semantics (Utils::ObjectWithSemantic::SemanticNameCollection), e.g., -/// triangle/line/quad meshes, point-clouds. -/// - The collection of layers is stored as a map, indexed by #LayerKeyType, which is defined as -/// the union -/// of the layer name (set to "" by default) and semantics. -/// -/// \see GeometryIndexLayerBase for more details about layers, semantics, and custom layers -/// definition. \see PointCloudIndexLayer, TriangleIndexLayer for examples of layers -/// -/// ## Adding new layers -/// \see setLayer to add or update an existing layer. -/// -/// Example of adding a PointCloudIndexLayer to an existing MultiIndexedGeometry `geo`: -/// \snippet tests/unittest/Core/indexview.cpp Creating and adding pointcloud layer -/// -/// -/// ## Accessing layers -/// Each layer is also associated with a `lock` state, used to give read-only or to lock write -/// access. -/// -/// Layers can be accessed in different ways (see #containsLayer, #countLayers, -/// #getFirstLayerOccurrence, and #getLayer): -/// - query by name and semantics, by passing either #LayerKeyType or a pair of name/semantics -/// - query by semantics (Utils::ObjectWithSemantic::SemanticNameCollection), names are ignored. -/// Only the first occurrence found is returned when required. -/// - query by semantic name (Utils::ObjectWithSemantic::SemanticName): matches any layer including -/// the -/// given semantic name. Only the first occurrence found is returned when required. -/// -/// \note Layer ordering is arbitrary and might change each time a new layer is added. -/// -/// +/** + * \brief AbstractGeometry with per-vertex attributes and layers of indices. + * Each layer represents a different topology or indexing logic, e.g. triangle/line/quad + * meshes, point-clouds. + * + * Multiple layers are useful to share and maintain consistency of per-vertex attributes + * between different meshes representing the same geometry, e.g., a quad and triangle mesh + * layers connecting the same set of vertices. + * + * ## Data-structure + * It is designed as follow: + * - Per-vertex attributes are stored as AttribArrayGeometry, + * - Each layer of indices is represented as a GeometryIndexLayer, which inherits + * Utils::ObjectWithSemantic + * to store its semantics (Utils::ObjectWithSemantic::SemanticNameCollection), e.g., + * triangle/line/quad meshes, point-clouds. + * - The collection of layers is stored as a map, indexed by #LayerKeyType, which is defined as + * the union + * of the layer name (set to "" by default) and semantics. + * + * \see GeometryIndexLayerBase for more details about layers, semantics, and custom layers + * definition. \see PointCloudIndexLayer, TriangleIndexLayer for examples of layers + * + * ## Adding new layers + * \see setLayer to add or update an existing layer. + * + * Example of adding a PointCloudIndexLayer to an existing MultiIndexedGeometry `geo`: + * \snippet tests/unittest/Core/indexview.cpp Creating and adding pointcloud layer + * + * + * ## Accessing layers + * Each layer is also associated with a `lock` state, used to give read-only or to lock write + * access. + * + * Layers can be accessed in different ways (see #containsLayer, #countLayers, + * #getFirstLayerOccurrence, and #getLayer): + * - query by name and semantics, by passing either #LayerKeyType or a pair of name/semantics + * - query by semantics (Utils::ObjectWithSemantic::SemanticNameCollection), names are ignored. + * Only the first occurrence found is returned when required. + * - query by semantic name (Utils::ObjectWithSemantic::SemanticName): matches any layer including + * the + * given semantic name. Only the first occurrence found is returned when required. + * + * \note Layer ordering is arbitrary and might change each time a new layer is added. + * + */ + class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Utils::ObservableVoid { public: @@ -208,7 +214,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util using Vec3AttribHandle = AttribArrayGeometry::Vec3AttribHandle; using Vec4AttribHandle = AttribArrayGeometry::Vec4AttribHandle; - inline MultiIndexedGeometry() = default; + MultiIndexedGeometry() = default; explicit MultiIndexedGeometry( const MultiIndexedGeometry& other ); explicit MultiIndexedGeometry( MultiIndexedGeometry&& other ); explicit MultiIndexedGeometry( const AttribArrayGeometry& other ); @@ -216,7 +222,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util MultiIndexedGeometry& operator=( const MultiIndexedGeometry& other ); MultiIndexedGeometry& operator=( MultiIndexedGeometry&& other ); - virtual inline ~MultiIndexedGeometry(); + virtual ~MultiIndexedGeometry(); void clear() override; /// \brief Copy geometry and indices from \p others. @@ -238,7 +244,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \brief Check if at least one layer with such properties exists /// \param layerKey layer key /// \complexity \f$ O(n) \f$, with \f$ n \f$ the number of layers in the collection - inline bool containsLayer( const LayerKeyType& layerKey ) const; + bool containsLayer( const LayerKeyType& layerKey ) const; /// \copybrief containsLayer( const LayerKeyType& ) const /// @@ -246,8 +252,8 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \param semantics collection of semantics associated with the layer (they should all match) /// \param layerName layer name /// \complexity \f$ O(n) \f$, with \f$ n \f$ the number of layers in the collection - inline bool containsLayer( const LayerSemanticCollection& semantics, - const std::string& layerName ) const; + bool containsLayer( const LayerSemanticCollection& semantics, + const std::string& layerName ) const; /// \copybrief containsLayer( const LayerKeyType& ) const /// @@ -269,7 +275,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \brief Count the number of layer matching the input parameters /// \param layerKey layer key /// \complexity \f$ O(n) \f$, with \f$ n \f$ the number of layers in the collection - inline size_t countLayers( const LayerKeyType& layerKey ) const; + size_t countLayers( const LayerKeyType& layerKey ) const; /// \copybrief countLayers( const LayerKeyType& ) const /// @@ -277,8 +283,8 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \param semantics collection of semantics associated with the layer (they should all match) /// \param layerName layer name /// \complexity \f$ O(n) \f$, with \f$ n \f$ the number of layers in the collection - inline size_t countLayers( const LayerSemanticCollection& semantics, - const std::string& layerName ) const; + size_t countLayers( const LayerSemanticCollection& semantics, + const std::string& layerName ) const; /// \copybrief countLayers( const LayerKeyType& ) const /// @@ -301,7 +307,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \param layerKey layer key /// \complexity \f$ O(n) \f$, with \f$ n \f$ the number of layers in the collection /// \throws std::out_of_range - inline const GeometryIndexLayerBase& getLayer( const LayerKeyType& layerKey ) const; + const GeometryIndexLayerBase& getLayer( const LayerKeyType& layerKey ) const; /// \copybrief getLayer( const LayerKeyType& ) const /// @@ -310,8 +316,8 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \param layerName layer name /// \complexity \f$ O(n) \f$, with \f$ n \f$ the number of layers in the collection /// \throws std::out_of_range - inline const GeometryIndexLayerBase& getLayer( const LayerSemanticCollection& semantics, - const std::string& layerName ) const; + const GeometryIndexLayerBase& getLayer( const LayerSemanticCollection& semantics, + const std::string& layerName ) const; /// \copybrief getLayer( const LayerKeyType& ) const /// /// Convenience function. @@ -353,8 +359,8 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \param layerName layer name /// \complexity \f$ O(n) \f$, with \f$ n \f$ the number of layers in the collection /// \throws std::out_of_range - inline GeometryIndexLayerBase& getLayerWithLock( const LayerSemanticCollection& semantics, - const std::string& layerName ); + GeometryIndexLayerBase& getLayerWithLock( const LayerSemanticCollection& semantics, + const std::string& layerName ); /// \copybrief getLayerWithLock( const LayerKeyType& ) /// @@ -397,8 +403,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \param layerName layer name /// \complexity \f$ O(n) \f$, with \f$ n \f$ the number of layers in the collection /// \throws std::out_of_range - inline void unlockLayer( const LayerSemanticCollection& semantics, - const std::string& layerName ); + void unlockLayer( const LayerSemanticCollection& semantics, const std::string& layerName ); // The following methods are only mean to be used by PredifinedIndexGeometry and should not be // part of the final API @@ -444,7 +449,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// /// Usage: /// \snippet tests/unittest/Core/indexview.cpp Iterating over layer keys - [[nodiscard]] inline auto layerKeys() const; + [[nodiscard]] auto layerKeys() const; /// returs default layer key, initialized to InvalidLayerKey, const LayerKeyType& default_layer_key() const { return m_default_layer_key; } @@ -472,21 +477,26 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util }; 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 + /** + * 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; + + /// Default layer key, initialized as invalid, set to first added Layer Key. LayerKeyType m_default_layer_key = std::make_pair( { InvalidIndexLayer::staticSemanticName }, "invalid" ); }; -/// \name Predefined index layers -/// The use of these layers helps in generic management of geometries -/// \{ - +/** + * \name Predefined index layers + * The use of these layers helps in generic management of geometries + * \{ + */ /// \brief Index layer for a point cloud OPEN_DECLARATION_INDEX_LAYER( PointCloudIndexLayer, Vector1ui ) /// \brief Constructor of an index layer with linearly spaced indices ranging from \f$0\f$ to @@ -506,27 +516,41 @@ void linearIndices( const AttribArrayGeometry& attr ) { }; -/// \brief Index layer for triangle mesh. -/// \note, This layer ensures that all faces have exactly 3 vertices +/** + * \brief Index layer for triangle mesh. + * + * \note, This layer ensures that all faces have exactly 3 vertices. + */ DECLARE_INDEX_LAYER( TriangleIndexLayer, Vector3ui ) -/// \brief Index layer for quadrilateral mesh. -/// \note, This layer ensures that all faces have exactly 4 vertices +/** + * \brief Index layer for quadrilateral mesh. + * + * \note, This layer ensures that all faces have exactly 4 vertices + */ DECLARE_INDEX_LAYER( QuadIndexLayer, Vector4ui ) -/// \brief Index layer for polygonal mesh. -/// \note, Using this layer, all faces might have more than 4 vertices or have different number of -/// vertices. +/** + * \brief Index layer for polygonal mesh. + * + * \note, Using this layer, all faces might have more than 4 vertices or have different number of + * vertices. + */ DECLARE_INDEX_LAYER( PolyIndexLayer, VectorNui ) /** one Ni index -> one strip */ DECLARE_INDEX_LAYER( StripOrFanIndexLayer, VectorNui ) -/// \brief Index layer for line mesh. -/// \note, This layer ensures that all faces have exactly 2 vertices +/** + * \brief Index layer for line mesh. + * + * \note, This layer ensures that all faces have exactly 2 vertices + */ DECLARE_INDEX_LAYER( LineIndexLayer, Vector2ui ) -/// \} +/** + * \} + */ #undef INDEX_LAYER_CLONE_IMPLEMENTATION #undef OPEN_DECLARATION_INDEX_LAYER @@ -586,22 +610,22 @@ class IndexedGeometry : public MultiIndexedGeometry using DefaultLayerType = typename IndexLayerType::getType::Type; public: - inline IndexedGeometry(); + IndexedGeometry(); - inline const IndexContainerType& getIndices() const; + const IndexContainerType& getIndices() const; /// read write access to indices. /// Cause indices to be "lock" for the caller /// need to be unlock by the caller before any one can ask for write access. - inline IndexContainerType& getIndicesWithLock(); + IndexContainerType& getIndicesWithLock(); /// unlock previously read write acces, notify observers of the update. - inline void indicesUnlock(); + void indicesUnlock(); /// set indices. Indices must be unlock, i.e. no one should have write /// access to it. /// Notify observers of the update. - inline void setIndices( IndexContainerType&& indices ); - inline void setIndices( const IndexContainerType& indices ); - inline const LayerKeyType& getLayerKey() const; + void setIndices( IndexContainerType&& indices ); + void setIndices( const IndexContainerType& indices ); + const LayerKeyType& getLayerKey() const; }; class RA_CORE_API IndexedPointCloud : public IndexedGeometry @@ -612,7 +636,12 @@ using QuadMesh = IndexedGeometry; using PolyMesh = IndexedGeometry; using LineMesh = IndexedGeometry; -// GeometryIndexLayerBase +//----------------------------------------------------------------------------- +//- Implementation ------------------------------------------------------------ +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +//- GeometryIndexLayerBase ---------------------------------------------------- inline GeometryIndexLayerBase::GeometryIndexLayerBase( const GeometryIndexLayerBase& other ) : ObjectWithSemantic( other.semantics() ) {} @@ -637,10 +666,10 @@ inline bool GeometryIndexLayerBase::operator==( const GeometryIndexLayerBase& ) return false; } -// GeometryIndexLayer - +//----------------------------------------------------------------------------- +//- GeometryIndexLayer -------------------------------------------------------- template -inline typename GeometryIndexLayer::IndexContainerType& GeometryIndexLayer::collection() { +typename GeometryIndexLayer::IndexContainerType& GeometryIndexLayer::collection() { return m_collection; } @@ -651,7 +680,7 @@ GeometryIndexLayer::collection() const { } template -inline bool GeometryIndexLayer::append( const GeometryIndexLayerBase& other, int offset ) { +bool GeometryIndexLayer::append( const GeometryIndexLayerBase& other, int offset ) { if ( shareSemantic( other ) ) { const auto& othercasted = static_cast&>( other ); @@ -669,7 +698,7 @@ inline bool GeometryIndexLayer::append( const GeometryIndexLayerBase& other, } template -inline void GeometryIndexLayer::offset( int offset, uint start_index ) { +void GeometryIndexLayer::offset( int offset, uint start_index ) { std::transform( m_collection.cbegin() + start_index, m_collection.cend(), m_collection.begin() + start_index, @@ -677,7 +706,7 @@ inline void GeometryIndexLayer::offset( int offset, uint start_index ) { } template -inline bool GeometryIndexLayer::operator==( const GeometryIndexLayerBase& other ) const { +bool GeometryIndexLayer::operator==( const GeometryIndexLayerBase& other ) const { if ( shareSemantic( other ) ) { const auto& othercasted = static_cast&>( other ); return othercasted.collection() == m_collection; @@ -686,38 +715,39 @@ inline bool GeometryIndexLayer::operator==( const GeometryIndexLayerBase& oth } template -inline size_t GeometryIndexLayer::getSize() const { +size_t GeometryIndexLayer::getSize() const { return m_collection.size(); } template -inline size_t GeometryIndexLayer::getNumberOfComponents() const { +size_t GeometryIndexLayer::getNumberOfComponents() const { return IndexType::RowsAtCompileTime; } template -inline size_t GeometryIndexLayer::getBufferSize() const { +size_t GeometryIndexLayer::getBufferSize() const { return m_collection.size() * sizeof( IndexType ); } template -inline int GeometryIndexLayer::getStride() const { +int GeometryIndexLayer::getStride() const { return sizeof( IndexType ); } template -inline const void* GeometryIndexLayer::dataPtr() const { +const void* GeometryIndexLayer::dataPtr() const { return m_collection.data(); } template -inline std::unique_ptr GeometryIndexLayer::clone() { +std::unique_ptr GeometryIndexLayer::clone() { auto copy = std::make_unique>( *this ); copy->m_collection = m_collection; return copy; } -// MultiIndexedGeometry +//----------------------------------------------------------------------------- +//- MultiIndexedGeometry ------------------------------------------------------ inline MultiIndexedGeometry::~MultiIndexedGeometry() { detachAll(); clear(); @@ -762,38 +792,37 @@ MultiIndexedGeometry::unlockLayer( const MultiIndexedGeometry::LayerSemanticColl unlockLayer( { semantics, layerName } ); } -[[nodiscard]] inline auto MultiIndexedGeometry::layerKeys() const { +inline auto MultiIndexedGeometry::layerKeys() const { return Utils::map_keys( m_indices ); } -// PointCloudIndexLayer +//----------------------------------------------------------------------------- +//- IndexedGeometry ----------------------------------------------------------- template -inline IndexedGeometry::IndexedGeometry() { +IndexedGeometry::IndexedGeometry() { auto layer = std::make_unique(); auto added = addLayer( std::move( layer ) ); if ( added.first ) { set_default_layer_key( added.second ); } } template - -inline const typename IndexedGeometry::IndexContainerType& -IndexedGeometry::getIndices() const { +const typename IndexedGeometry::IndexContainerType& IndexedGeometry::getIndices() const { const auto& abstractLayer = getLayer( default_layer_key() ); return static_cast::DefaultLayerType&>( abstractLayer ).collection(); } template -inline typename IndexedGeometry::IndexContainerType& IndexedGeometry::getIndicesWithLock() { +typename IndexedGeometry::IndexContainerType& IndexedGeometry::getIndicesWithLock() { auto& abstractLayer = getLayerWithLock( default_layer_key() ); return static_cast::DefaultLayerType&>( abstractLayer ).collection(); } template -inline void IndexedGeometry::indicesUnlock() { +void IndexedGeometry::indicesUnlock() { unlockLayer( default_layer_key() ); } template -inline void IndexedGeometry::setIndices( IndexContainerType&& indices ) { +void IndexedGeometry::setIndices( IndexContainerType&& indices ) { auto& abstractLayer = getLayerWithLock( default_layer_key() ); static_cast::DefaultLayerType&>( abstractLayer ).collection() = std::move( indices ); @@ -802,7 +831,7 @@ inline void IndexedGeometry::setIndices( IndexContainerType&& indices ) { } template -inline void IndexedGeometry::setIndices( const IndexContainerType& indices ) { +void IndexedGeometry::setIndices( const IndexContainerType& indices ) { auto& abstractLayer = getLayerWithLock( default_layer_key() ); static_cast::DefaultLayerType&>( abstractLayer ).collection() = indices; indicesUnlock(); @@ -810,7 +839,7 @@ inline void IndexedGeometry::setIndices( const IndexContainerType& indices ) } template -inline const typename IndexedGeometry::LayerKeyType& IndexedGeometry::getLayerKey() const { +const typename IndexedGeometry::LayerKeyType& IndexedGeometry::getLayerKey() const { return default_layer_key(); } From 8aea033e5d437557dc718955d8cf3d26f90ec6bb Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 8 May 2026 13:25:22 +0200 Subject: [PATCH 056/144] [core] Simpler init of default key, reset when deep clear. --- src/Core/Geometry/IndexedGeometry.cpp | 1 + src/Core/Geometry/IndexedGeometry.hpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index 18a6e846619..e5974b21d7c 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -256,6 +256,7 @@ void MultiIndexedGeometry::deepCopy( const MultiIndexedGeometry& other ) { void MultiIndexedGeometry::deepClear() { m_indices.clear(); + m_default_layer_key = { { InvalidIndexLayer::staticSemanticName }, "invalid" }; } ////////////////////////////////////////////////////////////////////// diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index a8832fe9254..4c71d8c8590 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -487,9 +487,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util std::unordered_map m_indices; /// Default layer key, initialized as invalid, set to first added Layer Key. - LayerKeyType m_default_layer_key = std::make_pair( - { InvalidIndexLayer::staticSemanticName }, - "invalid" ); + LayerKeyType m_default_layer_key { { InvalidIndexLayer::staticSemanticName }, "invalid" }; }; /** @@ -499,6 +497,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util */ /// \brief Index layer for a point cloud OPEN_DECLARATION_INDEX_LAYER( PointCloudIndexLayer, Vector1ui ) + /// \brief Constructor of an index layer with linearly spaced indices ranging from \f$0\f$ to /// \f$n-1\f$ inline explicit PointCloudIndexLayer( size_t n ) : @@ -810,6 +809,7 @@ const typename IndexedGeometry::IndexContainerType& IndexedGeometry::getIn const auto& abstractLayer = getLayer( default_layer_key() ); return static_cast::DefaultLayerType&>( abstractLayer ).collection(); } + template typename IndexedGeometry::IndexContainerType& IndexedGeometry::getIndicesWithLock() { auto& abstractLayer = getLayerWithLock( default_layer_key() ); From 106a4bb0f00d71ded4707a50a65118dadeed05cb Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 8 May 2026 16:13:20 +0200 Subject: [PATCH 057/144] [core] Clean and refactor RayCastTriangleMesh. --- src/Core/Geometry/RayCast.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Core/Geometry/RayCast.cpp b/src/Core/Geometry/RayCast.cpp index 87815c40313..a56dc1cc5e5 100644 --- a/src/Core/Geometry/RayCast.cpp +++ b/src/Core/Geometry/RayCast.cpp @@ -322,12 +322,15 @@ bool RayCastTriangleMesh( const Ray& r, const TriangleMesh& mesh, std::vector& hitsOut, std::vector& trianglesIdxOut ) { - bool hit = false; - for ( size_t i = 0; i < mesh.getIndices().size(); ++i ) { - const auto& t = mesh.getIndices()[i]; - const Vector3& a = mesh.vertices()[t[0]]; - const Vector3& b = mesh.vertices()[t[1]]; - const Vector3& c = mesh.vertices()[t[2]]; + bool hit = false; + const auto& indices = mesh.getIndices(); + const auto& vertices = mesh.vertices(); + for ( size_t i = 0; i < indices.size(); ++i ) { + const auto& t = indices[i]; + CORE_ASSERT( indices.getNumberOfComponents() == 3, "Ray cast only on triangle" ); + const auto& a = vertices[t[0]]; + const auto& b = vertices[t[1]]; + const auto& c = vertices[t[2]]; if ( RayCastTriangle( r, a, b, c, hitsOut ) ) { trianglesIdxOut.push_back( t ); hit = true; From 29b361bb3d495a2755ca911392e0d0c9c94fb47d Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 8 May 2026 16:13:50 +0200 Subject: [PATCH 058/144] [tests] Add MultiIndexGeometry default_layer_key test. --- tests/unittest/Core/indexview.cpp | 41 +++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/unittest/Core/indexview.cpp b/tests/unittest/Core/indexview.cpp index 5d11344bfaa..bb5fca99d57 100644 --- a/tests/unittest/Core/indexview.cpp +++ b/tests/unittest/Core/indexview.cpp @@ -9,6 +9,47 @@ struct CustomTriangleIndexLayer : public Ra::Core::Geometry::TriangleIndexLayer static constexpr const char* staticSemanticName = "CustomSemantic"; }; +TEST_CASE( "Core/Geometry/MultiIndexedGeometry", + "[unittests][Core][Core/Geometry][MultiIndexedGeometry]" ) { + using namespace Ra::Core::Geometry; + + MultiIndexedGeometry geo; + REQUIRE( geo.default_layer_key().second == "invalid" ); + REQUIRE( geo.default_layer_key().first.contains( InvalidIndexLayer::staticSemanticName ) ); + geo.setVertices( { { 0, 0, 0 }, { 1, 0, 0 }, { 0, 1, 0 }, { 1, 1, 1 } } ); + geo.setNormals( { { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 } } ); + + { + std::unique_ptr layer = std::make_unique(); + + auto& indices = layer->collection(); + indices.push_back( { 0, 1, 2, 3 } ); + auto added = geo.addLayer( std::move( layer ) ); + + REQUIRE( added.first == true ); + REQUIRE( added.second.first.contains( QuadIndexLayer::staticSemanticName ) ); + REQUIRE( geo.default_layer_key().second == "" ); + REQUIRE( geo.default_layer_key().first.contains( QuadIndexLayer::staticSemanticName ) ); + } + { + std::unique_ptr layer = std::make_unique(); + + auto& indices = layer->collection(); + indices.push_back( { 0, 1, 2 } ); + indices.push_back( { 1, 2, 3 } ); + auto added = geo.addLayer( std::move( layer ) ); + + REQUIRE( added.first == true ); + REQUIRE( added.second.first.contains( TriangleIndexLayer::staticSemanticName ) ); + REQUIRE( geo.default_layer_key().second == "" ); + REQUIRE( geo.default_layer_key().first.contains( QuadIndexLayer::staticSemanticName ) ); + + geo.set_default_layer_key( added.second ); + + REQUIRE( geo.default_layer_key().first.contains( TriangleIndexLayer::staticSemanticName ) ); + } +} + TEST_CASE( "Core/Geometry/IndexedGeometry", "[unittests][Core][Core/Geometry][IndexedGeometry]" ) { using Ra::Core::Vector3; using namespace Ra::Core::Geometry; From 39e811122eeee838a12e802bb18c882736277fc0 Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 8 May 2026 16:59:40 +0200 Subject: [PATCH 059/144] [engine] Some autos and addAttrib for GeometryDisplayable. --- src/Engine/Data/EnvironmentTexture.cpp | 4 ++-- src/Engine/Data/Mesh.hpp | 13 +++++++++++++ src/Gui/Viewer/Gizmo/ScaleGizmo.cpp | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Engine/Data/EnvironmentTexture.cpp b/src/Engine/Data/EnvironmentTexture.cpp index 85cb3ba512f..89504d3dc0f 100644 --- a/src/Engine/Data/EnvironmentTexture.cpp +++ b/src/Engine/Data/EnvironmentTexture.cpp @@ -198,8 +198,8 @@ void EnvironmentTexture::initializeTexture() { if ( m_isSkyBox ) { // make the skybox geometry Aabb aabb( Vector3 { -1_ra, -1_ra, -1_ra }, Vector3 { 1_ra, 1_ra, 1_ra } ); - Geometry::TriangleMesh skyMesh = Geometry::makeSharpBox( aabb ); - m_displayMesh = std::make_unique( "skyBox" ); + auto skyMesh = Geometry::makeSharpBox( aabb ); + m_displayMesh = std::make_unique( "skyBox" ); m_displayMesh->loadGeometry( std::move( skyMesh ) ); } } diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 04e2c463554..bb9d5e1633e 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -411,6 +411,11 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable /// Update (i.e. send to GPU) the buffers marked as dirty void updateGL() override; + /// Helper function that calls Ra::Core::CoreGeometry::addAttrib() + template + inline Ra::Core::Utils::AttribHandle addAttrib( const std::string& name, + const typename Core::VectorArray& data ); + inline size_t getNumVertices() const override { return m_geom.vertices().size(); } void set_active_layer_key( LayerKeyType layer_key ) { @@ -803,6 +808,14 @@ void CoreGeometryDisplayable::setupCoreMeshObservers() { m_isDirty = true; } +/// Helper function that calls Ra::Core::CoreGeometry::addAttrib() +template +Ra::Core::Utils::AttribHandle +GeometryDisplayable::addAttrib( const std::string& name, + const typename Core::VectorArray& data ) { + return m_geom.addAttrib( name, data ); +} + /// Helper function that calls Ra::Core::CoreGeometry::addAttrib() template template diff --git a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp index b6599a943d2..dfc75604df4 100644 --- a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp @@ -40,7 +40,7 @@ ScaleGizmo::ScaleGizmo( Engine::Scene::Component* c, boxBounds.extend( Core::Vector3( -radius * 2_ra, -radius * 2_ra, -radius * 2_ra ) ); boxBounds.extend( Core::Vector3( radius * 2_ra, radius * 2_ra, radius * 2_ra ) ); boxBounds.translate( arrowScale * cylinderEnd ); - Core::Geometry::TriangleMesh box = Core::Geometry::makeSharpBox( boxBounds ); + auto box = Core::Geometry::makeSharpBox( boxBounds ); cylinder.append( box ); std::shared_ptr mesh( new Engine::Data::Mesh( "Scale Gizmo Arrow" ) ); From be4a37904760f846768b546cc645c5f98f6dae68 Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 8 May 2026 17:00:32 +0200 Subject: [PATCH 060/144] [tests] more multi index test. --- tests/unittest/Core/indexview.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/unittest/Core/indexview.cpp b/tests/unittest/Core/indexview.cpp index bb5fca99d57..a90904bfd59 100644 --- a/tests/unittest/Core/indexview.cpp +++ b/tests/unittest/Core/indexview.cpp @@ -48,6 +48,11 @@ TEST_CASE( "Core/Geometry/MultiIndexedGeometry", REQUIRE( geo.default_layer_key().first.contains( TriangleIndexLayer::staticSemanticName ) ); } + MultiIndexedGeometry geo2 { geo }; + REQUIRE( geo2.default_layer_key().second != "invalid" ); + REQUIRE( geo2.default_layer_key().first.contains( TriangleIndexLayer::staticSemanticName ) ); + REQUIRE( geo2.getLayer( geo2.default_layer_key() ) + .hasSemantic( TriangleIndexLayer::staticSemanticName ) ); } TEST_CASE( "Core/Geometry/IndexedGeometry", "[unittests][Core][Core/Geometry][IndexedGeometry]" ) { From 4c59ac7a6cd4b69247a40bca40c1c13e5a6f51c1 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 9 May 2026 10:15:36 +0200 Subject: [PATCH 061/144] [examples] Add strip to all primitives. --- .../DrawPrimitives/AllPrimitivesComponent.cpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index ae75dadd15f..7bf4eeca544 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -44,6 +44,7 @@ const bool ENABLE_LOGO = true; const bool ENABLE_COLLAPSE = true; const bool ENABLE_SPLIT = true; const bool ENABLE_TORUS = true; +const bool ENABLE_QUADSTRIP = true; using namespace Ra; using namespace Ra::Core; @@ -1082,4 +1083,28 @@ void AllPrimitivesComponent::initialize() { } } } + if ( ENABLE_QUADSTRIP ) { + updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); + updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); + + { + using Ra::Engine::Data::Mesh; + { + auto strip = RenderObject::createRenderObject( + "test_quadstrip", + this, + RenderObjectType::Geometry, + DrawPrimitives::QuadStrip( cellCorner + Vector3 { 0_ra, 2_ra * offset, 0_ra }, + { .1_ra, 0_ra, 0_ra }, + { 0_ra, .1_ra / 4, 0_ra }, + 8, + colorBoost * Color::Cyan() ), + {} ); + strip->setMaterial( blinnPhongMaterial ); + addRenderObject( strip ); + } + + {} + } + } } From e628e02d6adbded47c8abb303432fdd3429d024c Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 9 May 2026 10:16:07 +0200 Subject: [PATCH 062/144] [core] Add doc for makeGrid. --- src/Core/Geometry/MeshPrimitives.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index 5a77bc6bf74..d2416b96747 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -30,6 +30,8 @@ RA_CORE_API QuadMesh makePlaneGrid( const uint rows = 1, const Utils::optional& color = {}, bool generateTexCoord = false ); +/// Create a 2D grid, with only outer points, connected as lines, inner line intersctions are not +/// present in verstices. RA_CORE_API LineMesh makeGrid( const Core::Vector3& center, const Core::Vector3& x, const Core::Vector3& y, From c40a5d5a5efc3076cf8eb08ef4ff6257a3c7cc4f Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 9 May 2026 18:14:33 +0200 Subject: [PATCH 063/144] [examples] Add textured quad strip to DrawPrimitives. --- .../DrawPrimitives/AllPrimitivesComponent.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index 7bf4eeca544..ca05e02c03e 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -1094,7 +1094,7 @@ void AllPrimitivesComponent::initialize() { "test_quadstrip", this, RenderObjectType::Geometry, - DrawPrimitives::QuadStrip( cellCorner + Vector3 { 0_ra, 2_ra * offset, 0_ra }, + DrawPrimitives::QuadStrip( cellCorner + offsetVec, { .1_ra, 0_ra, 0_ra }, { 0_ra, .1_ra / 4, 0_ra }, 8, @@ -1104,7 +1104,20 @@ void AllPrimitivesComponent::initialize() { addRenderObject( strip ); } - {} + { + auto strip = RenderObject::createRenderObject( + "test_quadstrip", + this, + RenderObjectType::Geometry, + DrawPrimitives::QuadStrip( cellCorner + 2_ra * offsetVec, + { .1_ra, 0_ra, 0_ra }, + { 0_ra, .1_ra / 4, 0_ra }, + 8, + colorBoost * Color::Cyan() ), + {} ); + strip->setMaterial( blinnPhongTexturedMaterial ); + addRenderObject( strip ); + } } } } From 1839c8b3444a8c00f4ac67efef5ef8ffc36694f8 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 9 May 2026 18:15:15 +0200 Subject: [PATCH 064/144] [core] Refactor makePlaneGrid. --- src/Core/Geometry/MeshPrimitives.cpp | 39 +++++++++++++++++----------- src/Core/Geometry/MeshPrimitives.hpp | 4 +-- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index 2670aac471d..0c317a30158 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -910,7 +910,7 @@ LineMesh makeGrid( const Core::Vector3& center, QuadMesh makePlaneGrid( const uint rows, const uint cols, const Vector2& halfExts, - const Transform& T, + const Transform& transform, const Utils::optional& color, bool generateTexCoord ) { QuadMesh result; @@ -922,32 +922,41 @@ QuadMesh makePlaneGrid( const uint rows, const uint R = ( rows + 1 ); const uint C = ( cols + 1 ); const uint v_size = C * R; - const uint t_size = cols * rows; + const uint f_size = cols * rows; vertices.resize( v_size ); normals.resize( v_size ); - texCoords.reserve( v_size ); + texCoords.resize( v_size ); - const Vector3 X = T.linear().col( 0 ).normalized(); - const Vector3 Y = T.linear().col( 1 ).normalized(); - const Vector3 Z = T.linear().col( 2 ).normalized(); + const Vector3 X = transform.linear().col( 0 ).normalized(); + const Vector3 Y = transform.linear().col( 1 ).normalized(); + const Vector3 Z = transform.linear().col( 2 ).normalized(); - const Vector3 x = ( 2_ra * halfExts[0] * X ) / Scalar( cols ); - const Vector3 y = ( 2_ra * halfExts[1] * Y ) / Scalar( rows ); - const Vector3 o = T.translation() - ( halfExts[0] * X ) - ( halfExts[1] * Y ); + const Vector3 x = ( 2_ra * halfExts[0] * X ) / Scalar( cols ); + const Vector3 y = ( 2_ra * halfExts[1] * Y ) / Scalar( rows ); + const Vector3 origin = transform.translation() - ( halfExts[0] * X ) - ( halfExts[1] * Y ); - const Scalar du = 1_ra / rows; - const Scalar dv = 1_ra / cols; + const Scalar du = 1_ra / cols; + const Scalar dv = 1_ra / rows; Grid v( { R, C } ); + Scalar cv = 0; + Vector3 current_row = origin; + uint id = 0; for ( uint i = 0; i < R; ++i ) { + Scalar cu = 0; + Vector3 current_point = current_row; for ( uint j = 0; j < C; ++j ) { - const uint id = ( i * C ) + j; v.at( { i, j } ) = id; - vertices[id] = o + ( i * y ) + ( j * x ); + vertices[id] = current_point; normals[id] = Z; - texCoords.emplace_back( i * du, j * dv, 0_ra ); + texCoords[id] = Vector3( cu, cv, 0_ra ); + current_point += x; + cu += du; + ++id; } + cv += dv; + current_row += y; } result.setVertices( std::move( vertices ) ); @@ -957,7 +966,7 @@ QuadMesh makePlaneGrid( const uint rows, if ( bool( color ) ) result.colorize( *color ); auto& face_layer = result.getIndicesWithLock(); - face_layer.reserve( t_size ); + face_layer.reserve( f_size ); for ( uint i = 0; i < rows; ++i ) { for ( uint j = 0; j < cols; ++j ) { diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index d2416b96747..f00db63b3de 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -16,8 +16,8 @@ namespace Geometry { // /// Create a 2D grid mesh with given number of row and columns -/// \param rows: number of rows -/// \param cols: number of columns +/// \param rows: number of rows (y direction) +/// \param cols: number of columns (x direction) /// \param halfExts: from center of the grid to each corner, in 2D, before applying T /// \param T: apply T to the generated vertices /// \param color: if set, colorize vertices From 6da62e61c225be6e9915605d641d56535e9b061e Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 9 May 2026 18:15:35 +0200 Subject: [PATCH 065/144] [core] Add operator<< on std::set helper. --- src/Core/Utils/StdUtils.hpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Core/Utils/StdUtils.hpp b/src/Core/Utils/StdUtils.hpp index 849a35257a2..9c52cb0bda9 100644 --- a/src/Core/Utils/StdUtils.hpp +++ b/src/Core/Utils/StdUtils.hpp @@ -2,7 +2,9 @@ #include +#include #include +#include /// This file contains utilities and wrapper to the standard library /// that didn't fit into any other category (see Containers) @@ -26,6 +28,18 @@ inline std::size_t hash( const std::pair& p ) { hash_combine( result, p.second ); return result; } + +/// output content of std::set +template +std::ostream& operator<<( std::ostream& out, const std::set& set ) { + if ( set.empty() ) return out << "{}"; + out << "{ " << *set.begin(); + std::for_each( std::next( set.begin() ), set.end(), [&out]( const T& element ) { + out << ", " << element; + } ); + return out << " }"; +} + } // namespace Utils } // namespace Core } // namespace Ra From 1926ae8284ed9b834f78bc86237ec43a8bccc02a Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 9 May 2026 18:16:19 +0200 Subject: [PATCH 066/144] [engine] QuadStrip use makePlaneGrid. --- src/Engine/Data/DrawPrimitives.cpp | 63 ++++++++++++++++++------------ src/Engine/Data/DrawPrimitives.hpp | 12 +++--- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index 43f7a88c5ee..0f23ba102c9 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -151,34 +151,44 @@ GeometryDisplayablePtr Triangle( const Core::Vector3& a, return ret; } -/// \todo continue to convert mesh creation and remove call to deprecated Mesh::loadGeometry -MeshPtr QuadStrip( const Core::Vector3& a, - const Core::Vector3& x, - const Core::Vector3& y, - uint quads, - const Core::Utils::Color& color ) { - Core::Vector3Array vertices( quads * 2 + 2 ); - std::vector indices( quads * 2 + 2 ); - - Core::Vector3 B = a; - vertices[0] = B; - vertices[1] = B + x; - indices[0] = 0; - indices[1] = 1; - for ( uint i = 0; i < quads; ++i ) { - B += y; - vertices[2 * i + 2] = B; - vertices[2 * i + 3] = B + x; - indices[2 * i + 2] = 2 * i + 2; - indices[2 * i + 3] = 2 * i + 3; - } +GeometryDisplayablePtr QuadStrip( const Core::Vector3& a, + const Core::Vector3& x, + const Core::Vector3& y, + uint quads, + const Core::Utils::Color& color ) { - Core::Vector4Array colors( vertices.size(), color ); + const Core::Vector3 trans = a + .5_ra * ( x + quads * y ); + using namespace Ra::Core::Geometry; - MeshPtr mesh( new Mesh( "Quad Strip Primitive", Mesh::RM_TRIANGLE_STRIP ) ); - mesh->loadGeometry( vertices, indices ); - mesh->getCoreGeometry().addAttrib( - Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), colors ); + Core::Transform t = Core::Transform::Identity(); + t.linear().col( 0 ) = x.normalized(); + t.linear().col( 1 ) = y.normalized(); + t.linear().col( 2 ) = x.cross( y ).normalized(); + + t.pretranslate( trans ); + + Vector2 halfExts = Vector2( x.norm() / 2_ra, quads * y.norm() / 2_ra ); + auto geom = makePlaneGrid( quads, 1, halfExts, t, color, true ); + + auto vertHandle = geom.getAttribHandle( getAttribName( VERTEX_POSITION ) ); + auto& vertAttrib = geom.getAttrib( vertHandle ); + + Core::Vector4Array colors( vertAttrib.getSize(), color ); + geom.addAttrib( getAttribName( MeshAttrib::VERTEX_COLOR ), colors ); + + auto mesh = make_shared( "Quad Strip Primitive" ); + auto strip_layer = std::make_unique(); + strip_layer->collection().push_back( StripOrFanIndexLayer::IndexType::LinSpaced( + vertAttrib.getSize(), 0, vertAttrib.getSize() - 1 ) ); + auto [strip_check, strip_key] = geom.addLayer( std::move( strip_layer ) ); + + auto default_layer = geom.default_layer_key(); + geom.set_default_layer_key( strip_key ); + + mesh->loadGeometry( + std::move( geom ), + GeometryDisplayable::ArrayOfLayerKeys<2> { + { { strip_key, Mesh::RM_TRIANGLE_STRIP }, { default_layer, Mesh::RM_QUADS } } } ); return mesh; } @@ -430,6 +440,7 @@ GeometryDisplayablePtr Normal( const Core::Vector3& point, return make_shared( "Normal Primitive", std::move( geom ) ); } +/// \todo continue to convert mesh creation and remove call to deprecated Mesh::loadGeometry MeshPtr Frame( const Core::Transform& frameFromEntity, Scalar scale ) { // Frame is a bit different from the others // since there are 3 lines of different colors. diff --git a/src/Engine/Data/DrawPrimitives.hpp b/src/Engine/Data/DrawPrimitives.hpp index 9e22877c048..cf679e0f8e7 100644 --- a/src/Engine/Data/DrawPrimitives.hpp +++ b/src/Engine/Data/DrawPrimitives.hpp @@ -71,12 +71,12 @@ RA_ENGINE_API GeometryDisplayablePtr Triangle( const Core::Vector3& a, const Core::Utils::Color& color, bool fill = false ); -/// Displays a strip of n quads, starting at A and with directions X and Y. -RA_ENGINE_API MeshPtr QuadStrip( const Core::Vector3& a, - const Core::Vector3& x, - const Core::Vector3& y, - uint quads, - const Core::Utils::Color& color ); +/// Displays a strip of n quads (in Y), starting at A and with directions X and Y. +RA_ENGINE_API GeometryDisplayablePtr QuadStrip( const Core::Vector3& a, + const Core::Vector3& x, + const Core::Vector3& y, + uint quads, + const Core::Utils::Color& color ); /// Displays circle computed with given center and radius, /// in plane normal to given vector in wireframe From 139475c4e9aead56ef27124dff883d1d67b2a2da Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 9 May 2026 18:16:51 +0200 Subject: [PATCH 067/144] [engine] Mesh output error if layer not added. --- src/Engine/Data/Mesh.hpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index bb9d5e1633e..89a140f32f5 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -385,6 +386,7 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable /// \param r is a collection of keys and renderMode, e.g. { {key1, RM_TRIANGLES}, {key2, /// RM_LINES} } /// \todo c++20 switch to range concept + template inline void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, const RangeOfLayerKeys& r ) { @@ -392,9 +394,12 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable m_geom = std::move( mesh ); setupCoreMeshObservers(); - for ( const auto& k : r ) - addRenderLayer( k.first, k.second ); - + for ( const auto& k : r ) { + auto check = addRenderLayer( k.first, k.second ); + if ( !check ) { + LOG( logERROR ) << "failed to load " << k.first.first << " " << k.first.second; + } + } set_active_layer_key( r[0].first ); } inline void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, From c50500fac97b541a5f7e85b572011bac7c548cd7 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 9 May 2026 18:17:17 +0200 Subject: [PATCH 068/144] [engine] Handle wireframe when there isn't any triangle layer. --- src/Engine/Rendering/ForwardRenderer.cpp | 25 ++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Engine/Rendering/ForwardRenderer.cpp b/src/Engine/Rendering/ForwardRenderer.cpp index 3c697bb8bed..8f022948496 100644 --- a/src/Engine/Rendering/ForwardRenderer.cpp +++ b/src/Engine/Rendering/ForwardRenderer.cpp @@ -404,6 +404,7 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData 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; @@ -432,12 +433,10 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData else if ( hasQuadLayer && !coreGeom.containsLayer( lineKey2 ) ) { setupLineMesh( *td, "wireframe main" ); } + auto shader = m_shaderProgramManager->getShaderProgram( "Wireframe" ); + if ( ( hasQuadLayer || hasPolyLayer || hasTriangleLayer ) && shader && + ro->isVisible() ) { - const Data::ShaderProgram* shader = - m_shaderProgramManager->getShaderProgram( "Wireframe" ); - - if ( hasTriangleLayer && shader && ro->isVisible() ) { - GL_CHECK_ERROR; td->updateGL(); GL_CHECK_ERROR; shader->bind(); @@ -448,16 +447,18 @@ 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 } ); - if ( hasTriangleLayer && ( hasQuadLayer || hasPolyLayer ) ) - shader->setUniform( "pixelWidth", 1.5f ); - else - shader->setUniform( "pixelWidth", 1.8f ); - GL_CHECK_ERROR; - td->render( shader, lineKey ); + if ( hasTriangleLayer ) { + if ( hasQuadLayer || hasPolyLayer ) { + shader->setUniform( "pixelWidth", 1.2f ); + } + else { shader->setUniform( "pixelWidth", 2.4f ); } + GL_CHECK_ERROR; + td->render( shader, lineKey ); + } if ( ( hasQuadLayer || hasPolyLayer ) ) { - shader->setUniform( "pixelWidth", 2.1f ); + shader->setUniform( "pixelWidth", 2.4f ); GL_CHECK_ERROR; td->render( shader, lineKey2 ); } From f65931c13973015f4e4766e0844a855c967987b2 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 10 May 2026 10:33:19 +0200 Subject: [PATCH 069/144] [core][engine][example] Add aabb mesh primitive. --- .../DrawPrimitives/AllPrimitivesComponent.cpp | 11 ++++- src/Core/Geometry/MeshPrimitives.cpp | 35 ++++++++++----- src/Engine/Data/DrawPrimitives.cpp | 45 +++++++------------ src/Engine/Data/DrawPrimitives.hpp | 6 ++- 4 files changed, 55 insertions(+), 42 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index ca05e02c03e..0fd0a552a7d 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -590,7 +590,7 @@ void AllPrimitivesComponent::initialize() { DrawPrimitives::Grid( const Core::Vector3& center, const Core::Vector3& x, const Core::Vector3& y, - k const Core::Color& color, + const Core::Color& color, Scalar cellSize = 1.f, uint res = 10 ); @@ -740,6 +740,15 @@ void AllPrimitivesComponent::initialize() { renderObject->setMaterial( roMaterial ); addRenderObject( renderObject ); + + auto aabb = + DrawPrimitives::AABB( renderObject->computeAabb(), Utils::Color::Red() ); + + auto renderObject1 = RenderObject::createRenderObject( + "AABB", this, RenderObjectType::Geometry, aabb, {} ); + + renderObject1->setMaterial( plainMaterial ); + addRenderObject( renderObject1 ); } } } diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index 0c317a30158..2fba9cbe90e 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -198,19 +198,32 @@ MultiIndexedGeometry makeSharpBox2( const Aabb& aabb, 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 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 - }; + result.addLayer( std::move( layer ) ); + } + { + auto layer = std::make_unique(); + layer->collection() = { + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 0 }, // Floor + { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 4 }, // Ceil + { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 8 }, // Left + { 12, 13 }, { 13, 14 }, { 14, 15 }, { 15, 12 }, // Right + { 16, 17 }, { 17, 18 }, { 18, 19 }, { 19, 16 }, // Bottom + { 20, 21 }, { 21, 22 }, { 22, 23 }, { 23, 20 } // Top + }; + result.addLayer( std::move( layer ), false, "aabb" ); + } - result.addLayer( std::move( layer ) ); if ( bool( color ) ) result.colorize( *color ); result.checkConsistency(); return MultiIndexedGeometry { std::move( result ) }; diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index 0f23ba102c9..cb3b972e4cc 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -15,6 +15,7 @@ #include #include +#include #include namespace Ra { @@ -441,7 +442,7 @@ GeometryDisplayablePtr Normal( const Core::Vector3& point, } /// \todo continue to convert mesh creation and remove call to deprecated Mesh::loadGeometry -MeshPtr Frame( const Core::Transform& frameFromEntity, Scalar scale ) { +GeometryDisplayablePtr Frame( const Core::Transform& frameFromEntity, Scalar scale ) { // Frame is a bit different from the others // since there are 3 lines of different colors. Core::Vector3 pos = frameFromEntity.translation(); @@ -449,8 +450,10 @@ MeshPtr Frame( const Core::Transform& frameFromEntity, Scalar scale ) { Core::Vector3 y = frameFromEntity.linear() * Core::Vector3::UnitY(); Core::Vector3 z = frameFromEntity.linear() * Core::Vector3::UnitZ(); - Core::Vector3Array vertices = { - pos, pos + scale * x, pos, pos + scale * y, pos, pos + scale * z }; + Geometry::LineMesh geom; + geom.setVertices( { { pos, pos + scale * x, pos, pos + scale * y, pos, pos + scale * z } } ); + + geom.setIndices( { { 0, 1 }, { 2, 3 }, { 4, 5 } } ); Core::Vector4Array colors = { Core::Utils::Color::Red(), @@ -461,14 +464,10 @@ MeshPtr Frame( const Core::Transform& frameFromEntity, Scalar scale ) { Core::Utils::Color::Blue(), }; - std::vector indices = { 0, 1, 2, 3, 4, 5 }; - MeshPtr mesh( new Mesh( "Frame Primitive", Mesh::RM_LINES ) ); - - mesh->loadGeometry( vertices, indices ); - mesh->getCoreGeometry().addAttrib( + geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), colors ); - return mesh; + return make_shared( "Frame Primitive", std::move( geom ) ); } GeometryDisplayablePtr Grid( const Core::Vector3& center, @@ -482,27 +481,17 @@ GeometryDisplayablePtr Grid( const Core::Vector3& center, return mesh; } -MeshPtr AABB( const Core::Aabb& aabb, const Core::Utils::Color& color ) { - Core::Vector3Array vertices( 8 ); - - for ( uint i = 0; i < 8; ++i ) { - vertices[i] = aabb.corner( static_cast( i ) ); - } - - std::vector indices = { - 0, 1, 1, 3, 3, 2, 2, 0, // Floor - 0, 4, 1, 5, 2, 6, 3, 7, // Links - 4, 5, 5, 7, 7, 6, 6, 4, // Ceil - }; +GeometryDisplayablePtr AABB( const Core::Aabb& aabb, const Core::Utils::Color& color ) { + auto geom = makeSharpBox2( aabb, color ); + auto ret = make_shared( "AABB Primitive", std::move( geom ) ); + auto [key, layer] = ret->getCoreGeometry().getFirstLayerOccurrence( + Core::Geometry::LineIndexLayer::staticSemanticName ); - Core::Vector4Array colors( vertices.size(), color ); + std::cerr << "aabb check " << key.first << " " << key.second << "\n"; - MeshPtr mesh( new Mesh( "AABB Primitive", Mesh::RM_LINES ) ); - mesh->loadGeometry( vertices, indices ); - mesh->getCoreGeometry().addAttrib( - Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), colors ); - - return mesh; + ret->addRenderLayer( key, AttribArrayDisplayable::MeshRenderMode::RM_LINES ); + ret->set_active_layer_key( key ); + return ret; } MeshPtr OBB( const Obb& obb, const Core::Utils::Color& color ) { diff --git a/src/Engine/Data/DrawPrimitives.hpp b/src/Engine/Data/DrawPrimitives.hpp index cf679e0f8e7..9432f54be96 100644 --- a/src/Engine/Data/DrawPrimitives.hpp +++ b/src/Engine/Data/DrawPrimitives.hpp @@ -136,7 +136,8 @@ RA_ENGINE_API GeometryDisplayablePtr Normal( const Core::Vector3& point, /// (X,Y,Z = red, green blue) /// Remainder : the transform will be drawn relative /// to the component's entity transform. -RA_ENGINE_API MeshPtr Frame( const Core::Transform& frameFromEntity, Scalar scale = 0.1f ); +RA_ENGINE_API GeometryDisplayablePtr Frame( const Core::Transform& frameFromEntity, + Scalar scale = 0.1f ); /// Create a res*res square grid centered on center, /// in plane defined by the vectors x and y. @@ -148,7 +149,8 @@ RA_ENGINE_API GeometryDisplayablePtr Grid( const Core::Vector3& center, uint res = 10 ); /// Display a wireframe AABB -RA_ENGINE_API MeshPtr AABB( const Core::Aabb& aabb, const Core::Utils::Color& color ); +RA_ENGINE_API GeometryDisplayablePtr AABB( const Core::Aabb& aabb, + const Core::Utils::Color& color ); /// Display a wireframe OBB RA_ENGINE_API MeshPtr OBB( const Core::Geometry::Obb& obb, const Core::Utils::Color& color ); From da19105d186fbaf1f9a73bf81226734acf02e981 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 10 May 2026 17:09:42 +0200 Subject: [PATCH 070/144] [core] Obb is core Aabb instead of in class using. --- src/Core/Geometry/Obb.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Geometry/Obb.hpp b/src/Core/Geometry/Obb.hpp index e0b09b01c19..128165744c3 100644 --- a/src/Core/Geometry/Obb.hpp +++ b/src/Core/Geometry/Obb.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -12,7 +13,6 @@ class Obb { public: using Transform = Eigen::Transform; - using Aabb = Eigen::AlignedBox; /// Constructors and destructor. From f5fcf878e4430aa931c329f9e0b8cfb08914f2ba Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 10 May 2026 17:10:16 +0200 Subject: [PATCH 071/144] [Engine] Do not draw wireframe if RO is already in line mode. --- src/Engine/Rendering/ForwardRenderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Engine/Rendering/ForwardRenderer.cpp b/src/Engine/Rendering/ForwardRenderer.cpp index 8f022948496..cfd9dcb2edc 100644 --- a/src/Engine/Rendering/ForwardRenderer.cpp +++ b/src/Engine/Rendering/ForwardRenderer.cpp @@ -406,6 +406,7 @@ void ForwardRenderer::renderInternal( const Data::ViewingParameters& renderData auto td = std::dynamic_pointer_cast( displayable ); if ( td ) { + if ( td->active_layer_key().first.contains( "LineIndexLayer" ) ) return; using namespace Core::Geometry; using LayerKeyType = Core::Geometry::MultiIndexedGeometry::LayerKeyType; using LineIndexLayer = Core::Geometry::LineIndexLayer; From 2431b4b6e5e130e0a96a8c50cf49941c167edb41 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 10 May 2026 17:11:19 +0200 Subject: [PATCH 072/144] [gui] Set pivot on alt right clic. --- src/Gui/Configs/default.xml | 2 +- .../Viewer/RotateAroundCameraManipulator.cpp | 23 ++++++++++++++++++- .../Viewer/RotateAroundCameraManipulator.hpp | 5 ++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Gui/Configs/default.xml b/src/Gui/Configs/default.xml index f905a75958a..509bb255313 100644 --- a/src/Gui/Configs/default.xml +++ b/src/Gui/Configs/default.xml @@ -12,7 +12,7 @@ - + diff --git a/src/Gui/Viewer/RotateAroundCameraManipulator.cpp b/src/Gui/Viewer/RotateAroundCameraManipulator.cpp index 0df3e2d45a8..43d656375f6 100644 --- a/src/Gui/Viewer/RotateAroundCameraManipulator.cpp +++ b/src/Gui/Viewer/RotateAroundCameraManipulator.cpp @@ -77,7 +77,9 @@ void RotateAroundCameraManipulator::rotateCallback( QEvent* event ) { } } void RotateAroundCameraManipulator::setPivotCallback( QEvent* event ) { - if ( event->type() == QEvent::KeyPress ) { setPivotFromPixel( m_lastMouseX, m_lastMouseY ); } + // if ( event->type() == QEvent::KeyPress ) { + setPivotFromPixel( m_lastMouseX, m_lastMouseY ); + // } } void RotateAroundCameraManipulator::zoomCallback( QEvent* event ) { if ( event->type() == QEvent::MouseMove ) { @@ -141,6 +143,25 @@ bool RotateAroundCameraManipulator::handleMouseMoveEvent( return handled; } +bool RotateAroundCameraManipulator::handleMousePressEvent( + QMouseEvent* event, + const Qt::MouseButtons& /*buttons*/, + const Qt::KeyboardModifiers& /* modifiers*/, + int key ) { + + m_lastMouseX = event->pos().x(); + m_lastMouseY = event->pos().y(); + + bool handled = m_keyMappingCallbackManager.triggerEventCallback( event, key ); + + if ( m_light != nullptr ) { + m_light->setPosition( m_camera->getPosition() ); + m_light->setDirection( m_camera->getDirection() ); + } + + return handled; +} + bool RotateAroundCameraManipulator::handleKeyPressEvent( QKeyEvent* event, const Ra::Gui::KeyMappingManager::KeyMappingAction& action ) { diff --git a/src/Gui/Viewer/RotateAroundCameraManipulator.hpp b/src/Gui/Viewer/RotateAroundCameraManipulator.hpp index cb2de1b6987..3eee174dd7a 100644 --- a/src/Gui/Viewer/RotateAroundCameraManipulator.hpp +++ b/src/Gui/Viewer/RotateAroundCameraManipulator.hpp @@ -32,6 +32,11 @@ class RA_GUI_API RotateAroundCameraManipulator const Qt::MouseButtons& buttons, const Qt::KeyboardModifiers& modifiers, int key ) override; + bool handleMousePressEvent( QMouseEvent* event, + const Qt::MouseButtons& buttons, + const Qt::KeyboardModifiers& modifiers, + int key ) override; + /// \copydoc TrackballCameraManipulator::handleKeyPressEvent() bool handleKeyPressEvent( QKeyEvent* event, const Ra::Gui::KeyMappingManager::KeyMappingAction& action ) override; From 41d32fae6c53666da6c60a9e1034a7767d90738d Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 10 May 2026 17:11:55 +0200 Subject: [PATCH 073/144] [core] Add makeBox2, prepare transition. --- src/Core/Geometry/MeshPrimitives.cpp | 61 +++++++++++++++++++++++++++ src/Core/Geometry/MeshPrimitives.hpp | 14 ++++++ src/Core/Geometry/TopologicalMesh.hpp | 14 ++++++ 3 files changed, 89 insertions(+) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index 2fba9cbe90e..0a93ef153da 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -84,6 +84,67 @@ TriangleMesh makeBox( const Aabb& aabb, const Utils::optional& col return result; } +MultiIndexedGeometry makeBox2( const Vector3& halfExts, + const Utils::optional& color ) { + return makeBox2( -halfExts, + Vector3 { 2_ra * halfExts.x(), 0, 0 }, + Vector3 { 0, 2_ra * halfExts.y(), 0 }, + Vector3 { 0, 0, 2_ra * halfExts.z() }, + color ); +} + +MultiIndexedGeometry makeBox2( const Aabb& aabb, const Utils::optional& color ) { + + return makeBox2( aabb.corner( Aabb::BottomLeftFloor ), + aabb.corner( Aabb::BottomRightFloor ) - aabb.corner( Aabb::BottomLeftFloor ), + aabb.corner( Aabb::BottomLeftCeil ) - aabb.corner( Aabb::BottomLeftFloor ), + aabb.corner( Aabb::TopLeftFloor ) - aabb.corner( Aabb::BottomLeftFloor ), + color ); +} + +MultiIndexedGeometry makeBox2( const Vector3& corner, + const Vector3& x, + const Vector3& y, + const Vector3& z, + const Utils::optional& color ) { + MultiIndexedGeometry result; + result.setVertices( { corner, + corner + x, + corner + x + y, + corner + y, + corner + z, + corner + x + z, + corner + x + y + z, + corner + y + z } ); + const auto& v = result.vertices(); + + Vector3 center = corner + .5_ra * ( x + y + z ); + + result.setNormals( { + v[0] - center, + v[1] - center, + v[2] - center, + v[3] - center, + v[4] - center, + v[5] - center, + v[6] - center, + v[7] - center, + } ); + + auto layer = std::make_unique(); + layer->collection() = { Vector4ui( 0, 3, 2, 1 ), + Vector4ui( 4, 5, 6, 7 ), + Vector4ui( 0, 1, 5, 4 ), + Vector4ui( 0, 4, 7, 3 ), + Vector4ui( 1, 2, 6, 5 ), + Vector4ui( 2, 3, 7, 6 ) }; + if ( bool( color ) ) result.colorize( *color ); + + result.addLayer( std::move( layer ) ); + + return MultiIndexedGeometry { std::move( result ) }; +} + TriangleMesh makeSharpBox( const Vector3& halfExts, const Utils::optional& color, bool generateTexCoord ) { diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index f00db63b3de..15d91a2a546 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -65,6 +65,20 @@ RA_CORE_API TriangleMesh makeBox( const Vector3& halfExts = Vector3( .5_ra, .5_r RA_CORE_API TriangleMesh makeBox( const Aabb& aabb, const Utils::optional& color = {} ); +/// Create an axis-aligned cubic mesh with the given half extents, centered on the origin. +RA_CORE_API MultiIndexedGeometry makeBox2( const Vector3& halfExts = Vector3( .5_ra, .5_ra, .5_ra ), + const Utils::optional& color = {} ); + +/// Create an axis-aligned cubic mesh +RA_CORE_API MultiIndexedGeometry makeBox2( const Aabb& aabb, + const Utils::optional& color = {} ); + +RA_CORE_API MultiIndexedGeometry makeBox2( const Vector3& corner, + const Vector3& x, + const Vector3& y, + const Vector3& z, + const Utils::optional& color ); + /// Create an axis-aligned cubic mesh with the given half extents, centered on the origin. RA_CORE_API TriangleMesh makeSharpBox( const Vector3& halfExts = Vector3( .5_ra, .5_ra, .5_ra ), const Utils::optional& color = {}, diff --git a/src/Core/Geometry/TopologicalMesh.hpp b/src/Core/Geometry/TopologicalMesh.hpp index 5b754a056e7..e7bccc0e534 100644 --- a/src/Core/Geometry/TopologicalMesh.hpp +++ b/src/Core/Geometry/TopologicalMesh.hpp @@ -88,6 +88,7 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT + explicit TopologicalMesh( const Ra::Core::Geometry::MultiIndexedGeometry& mesh, + NonManifoldFaceCommand command ); inline void initWithWedge( const Ra::Core::Geometry::MultiIndexedGeometry& mesh, @@ -1062,6 +1066,16 @@ inline TopologicalMesh::TopologicalMesh( const Ra::Core::Geometry::MultiIndexedGeometry::LayerKeyType& layerKey ) : TopologicalMesh( mesh, layerKey, DefaultNonManifoldFaceCommand( "[default ctor]" ) ) {} +inline TopologicalMesh::TopologicalMesh( const Ra::Core::Geometry::MultiIndexedGeometry& mesh ) : + TopologicalMesh( mesh, + mesh.default_layer_key(), + DefaultNonManifoldFaceCommand( "[default ctor]" ) ) {} + +template +inline TopologicalMesh::TopologicalMesh( const Ra::Core::Geometry::MultiIndexedGeometry& mesh, + NonManifoldFaceCommand command ) : + TopologicalMesh( mesh, mesh.default_layer_key(), command ) {} + template TopologicalMesh::TopologicalMesh( const Ra::Core::Geometry::MultiIndexedGeometry& mesh, From 12d5c9b576df14a6da54b7c7ce7e4667238e0c5e Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 10 May 2026 17:12:21 +0200 Subject: [PATCH 074/144] [examples] DrawPrimitives add cube from makeBox2. Also move first wireframe triangle out of filled triangle. --- .../DrawPrimitives/AllPrimitivesComponent.cpp | 95 +++++++++++-------- 1 file changed, 57 insertions(+), 38 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index 0fd0a552a7d..3c5b663add0 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -136,43 +136,62 @@ void AllPrimitivesComponent::initialize() { if ( ENABLE_CUBES ) { std::shared_ptr cube1( new GeometryDisplayable( "Cube" ) ); auto coord = cellSize / 16_ra; - cube1->loadGeometry( - 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 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, {} ); - renderObjectTexCube->setLocalTransform( - Transform { Translation( cellCorner + Vector3 { 0_ra, coord * 3.5_ra, 0_ra } ) } ); - renderObjectTexCube->setMaterial( blinnPhongTexturedMaterial ); - - addRenderObject( renderObjectTexCube ); - - // another cube - std::shared_ptr cube2( new GeometryDisplayable( "Cube" ) ); - coord = cellSize / 4_ra; - cube2->loadGeometry( Geometry::makeSharpBox2( Vector3 { coord, coord, coord } ) ); - - const std::string myColourName { "colour" }; - cube2->getCoreGeometry().addAttrib( - myColourName, Vector4Array { cube2->getNumVertices(), Color::Red() } ); - - cube2->setAttribNameMatching( - myColourName, Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_COLOR ) ); - auto renderObject2 = RenderObject::createRenderObject( - "CubeRO_2", this, RenderObjectType::Geometry, cube2, {} ); - coord = cellSize / 2_ra; - renderObject2->setLocalTransform( - Transform { Translation( cellCorner + Vector3 { coord, coord, coord } ) } ); - renderObject2->setMaterial( lambertianMaterial ); - addRenderObject( renderObject2 ); + { + cube1->loadGeometry( + 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 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, {} ); + renderObjectTexCube->setLocalTransform( + Transform { Translation( cellCorner + Vector3 { 0_ra, coord * 3.5_ra, 0_ra } ) } ); + renderObjectTexCube->setMaterial( blinnPhongTexturedMaterial ); + + addRenderObject( renderObjectTexCube ); + } + { + // another cube + std::shared_ptr cube2( new GeometryDisplayable( "Cube" ) ); + coord = cellSize / 4_ra; + cube2->loadGeometry( Geometry::makeSharpBox2( Vector3 { coord, coord, coord } ) ); + + const std::string myColourName { "colour" }; + cube2->getCoreGeometry().addAttrib( + myColourName, Vector4Array { cube2->getNumVertices(), Color::Red() } ); + + cube2->setAttribNameMatching( + myColourName, + Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_COLOR ) ); + auto renderObject2 = RenderObject::createRenderObject( + "CubeRO_2", this, RenderObjectType::Geometry, cube2, {} ); + coord = cellSize / 2_ra; + renderObject2->setLocalTransform( + Transform { Translation( cellCorner + Vector3 { coord, coord, coord } ) } ); + renderObject2->setMaterial( lambertianMaterial ); + addRenderObject( renderObject2 ); + } + { + std::shared_ptr cube3( new GeometryDisplayable( "Cube" ) ); + auto c = cellCorner + Vector3 { coord, coord, coord } + Vector3 { coord, 0, 0 }; + auto x = Vector3 { coord, coord, 0 }; + auto y = Vector3 { -coord, coord, 0 }; + cube3->loadGeometry( + Geometry::makeBox2( c, x, y, x.cross( y ) / x.norm(), Color::Yellow() ) ); + auto renderObject3 = RenderObject::createRenderObject( + "Cube3", this, RenderObjectType::Geometry, cube3, {} ); + renderObject3->setMaterial( blinnPhongMaterial ); + addRenderObject( renderObject3 ); + } } //// POINTS //// if ( ENABLE_POINTS ) { @@ -318,7 +337,7 @@ void AllPrimitivesComponent::initialize() { triangle2->setMaterial( plainMaterial ); addRenderObject( triangle2 ); - for ( int i = 0; i < 10; ++i ) { + for ( int i = 1; i < 11; ++i ) { auto triwire = RenderObject::createRenderObject( "test_triangle_wire", this, From a74cc0374b490bd163452f009b9322a82906934e Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 10 May 2026 17:37:39 +0200 Subject: [PATCH 075/144] [core] Template indexed geometry with layer type instead of index. --- src/Core/Geometry/IndexedGeometry.hpp | 51 +++++---------------------- src/Core/Geometry/TopologicalMesh.hpp | 18 +++++----- 2 files changed, 17 insertions(+), 52 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 4c71d8c8590..920950a3101 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -555,39 +555,6 @@ DECLARE_INDEX_LAYER( LineIndexLayer, Vector2ui ) #undef OPEN_DECLARATION_INDEX_LAYER #undef DECLARE_INDEX_LAYER -/// Temporary class providing the old API for TriangleMesh, LineMesh and PolyMesh -/// This class will be marked as deprecated soon. -namespace IndexLayerType { -template -struct getType {}; - -template <> -struct getType { - using Type = Ra::Core::Geometry::LineIndexLayer; -}; - -template <> -struct getType { - using Type = Ra::Core::Geometry::TriangleIndexLayer; -}; - -template <> -struct getType { - using Type = Ra::Core::Geometry::QuadIndexLayer; -}; - -template <> -struct getType { - using Type = Ra::Core::Geometry::PolyIndexLayer; -}; - -template <> -struct getType { - using Type = Ra::Core::Geometry::PointCloudIndexLayer; -}; - -} // namespace IndexLayerType - /** * \brief A single layer MultiIndexedGeometry. * @@ -602,11 +569,9 @@ template class IndexedGeometry : public MultiIndexedGeometry { public: - using IndexType = T; - using IndexContainerType = VectorArray; - - private: - using DefaultLayerType = typename IndexLayerType::getType::Type; + using DefaultLayerType = T; + using IndexType = T::IndexType; + using IndexContainerType = T::IndexContainerType; public: IndexedGeometry(); @@ -627,13 +592,13 @@ class IndexedGeometry : public MultiIndexedGeometry const LayerKeyType& getLayerKey() const; }; -class RA_CORE_API IndexedPointCloud : public IndexedGeometry +class RA_CORE_API IndexedPointCloud : public IndexedGeometry {}; -using TriangleMesh = IndexedGeometry; -using QuadMesh = IndexedGeometry; -using PolyMesh = IndexedGeometry; -using LineMesh = IndexedGeometry; +using TriangleMesh = IndexedGeometry; +using QuadMesh = IndexedGeometry; +using PolyMesh = IndexedGeometry; +using LineMesh = IndexedGeometry; //----------------------------------------------------------------------------- //- Implementation ------------------------------------------------------------ diff --git a/src/Core/Geometry/TopologicalMesh.hpp b/src/Core/Geometry/TopologicalMesh.hpp index e7bccc0e534..537f8a41989 100644 --- a/src/Core/Geometry/TopologicalMesh.hpp +++ b/src/Core/Geometry/TopologicalMesh.hpp @@ -143,10 +143,10 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT IndexedGeometry toIndexedMesh(); - PolyMesh toPolyMesh() { return toIndexedMesh(); } - LineMesh toLineMesh() { return toIndexedMesh(); } - QuadMesh toQuadMesh() { return toIndexedMesh(); } - TriangleMesh toTriangleMesh() { return toIndexedMesh(); } + PolyMesh toPolyMesh() { return toIndexedMesh(); } + LineMesh toLineMesh() { return toIndexedMesh(); } + QuadMesh toQuadMesh() { return toIndexedMesh(); } + TriangleMesh toTriangleMesh() { return toIndexedMesh(); } /** * Update triangle mesh data, assuming the mesh and this topo mesh has the @@ -1483,14 +1483,14 @@ TopologicalMesh::getWedgeIndexPph() const { return m_wedgeIndexPph; } -template -IndexedGeometry TopologicalMesh::toIndexedMesh() { +template +IndexedGeometry TopologicalMesh::toIndexedMesh() { // first cleanup deleted element garbage_collection(); - IndexedGeometry out; - typename IndexedGeometry::IndexContainerType indices; + IndexedGeometry out; + typename IndexedGeometry::IndexContainerType indices; /// add attribs to out std::vector> wedgeFloatAttribHandles; @@ -1526,7 +1526,7 @@ IndexedGeometry TopologicalMesh::toIndexedMesh() { for ( TopologicalMesh::FaceIter f_it = faces_sbegin(); f_it != faces_end(); ++f_it ) { int i = 0; - IndexType faceIndices( valence( *f_it ) ); + typename LayerType::IndexType faceIndices( valence( *f_it ) ); CORE_ASSERT( faceIndices.size() == valence( *f_it ), "Invalid face size." ); // iterator over vertex (through halfedge to get access to halfedge normals) From 8cda9946365e0324902f9d6702e5373e09c0ba5b Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 10 May 2026 20:59:16 +0200 Subject: [PATCH 076/144] [core] Add indices/set_indices templated function. And use them in IndexedGeometry. Clean deprecated code. Move online to class definition. --- src/Core/Geometry/IndexedGeometry.cpp | 24 ----- src/Core/Geometry/IndexedGeometry.hpp | 123 +++++++++++++------------- 2 files changed, 63 insertions(+), 84 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index e5974b21d7c..7abe365ad7f 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -187,30 +187,6 @@ GeometryIndexLayerBase& MultiIndexedGeometry::getLayerWithLock( const LayerKeyTy ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// -void MultiIndexedGeometry::unlockFirstLayerOccurrence( const LayerSemantic& semanticName ) { - for ( auto& [key, value] : m_indices ) { - if ( key.first.find( semanticName ) != key.first.end() ) { - CORE_ASSERT( value.first, "try to release unlocked layer" ); - value.first = false; - notify(); - return; - } - } - throw std::out_of_range( "Layer entry not found" ); -} - -void MultiIndexedGeometry::unlockFirstLayerOccurrence( const LayerSemanticCollection& semantics ) { - for ( auto& [key, value] : m_indices ) { - if ( key.first == semantics ) { - CORE_ASSERT( value.first, "try to release unlocked layer" ); - value.first = false; - notify(); - return; - } - } - throw std::out_of_range( "Layer entry not found" ); -} - void MultiIndexedGeometry::unlockLayer( const LayerKeyType& layerKey ) { auto& p = m_indices.at( layerKey ); CORE_ASSERT( p.first, "try to release unlocked layer" ); diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 920950a3101..20b0415f623 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -69,7 +69,7 @@ class RA_CORE_API GeometryIndexLayerBase : public Utils::ObservableVoid, /// \brief Move assignment operator /// \copydetails GeometryIndexLayerBase(const GeometryIndexLayerBase&) inline GeometryIndexLayerBase& operator=( GeometryIndexLayerBase&& other ); - virtual ~GeometryIndexLayerBase(); + virtual ~GeometryIndexLayerBase() {} /// \brief Create new layer with duplicated content virtual std::unique_ptr clone() = 0; @@ -80,7 +80,7 @@ class RA_CORE_API GeometryIndexLayerBase : public Utils::ObservableVoid, virtual void offset( int offset, uint start_index = 0 ) = 0; /// \brief Compare if two layers have the same content - virtual inline bool operator==( const GeometryIndexLayerBase& other ) const; + virtual inline bool operator==( const GeometryIndexLayerBase& ) const { return false; } protected: /// \brief Hidden constructor that must be called by inheriting classes to define the object @@ -97,15 +97,15 @@ struct GeometryIndexLayer : public GeometryIndexLayerBase { using IndexType = T; using IndexContainerType = VectorArray; - inline IndexContainerType& collection(); - const IndexContainerType& collection() const; + inline IndexContainerType& collection() { return m_collection; } + const IndexContainerType& collection() const { return m_collection; } inline bool append( const GeometryIndexLayerBase& other, int offset = 0 ) final; inline void offset( int offset, uint start_index = 0 ) final; /// \warning Does not account for elements permutations inline bool operator==( const GeometryIndexLayerBase& other ) const final; - inline size_t getSize() const override final; + inline size_t getSize() const override final { return m_collection.size(); } inline std::unique_ptr clone() override; @@ -405,28 +405,62 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \throws std::out_of_range void unlockLayer( const LayerSemanticCollection& semantics, const std::string& layerName ); - // The following methods are only mean to be used by PredifinedIndexGeometry and should not be - // part of the final API - protected: - /// \copybrief unlockLayer( const LayerKeyType& ) - /// - /// Convenience function. - /// \see getLayerWithLock( const LayerKeyType& ) for details about locks - /// \param semantics collection of semantics associated with the layer (they should all match) - /// \complexity \f$ O(n) \f$, with \f$ n \f$ the number of layers in the collection - /// \throws std::out_of_range - void unlockFirstLayerOccurrence( const LayerSemanticCollection& semantics ); + template + void set_indices( const typename IndexLayer::IndexContainerType& indices ) { + auto own_indices = indices; + set_indices( std::move( own_indices ) ); + } - /// \copybrief unlockLayer( const LayerKeyType& ) - /// - /// Convenience function. - /// \see getLayerWithLock( const LayerKeyType& ) for details about locks - /// \param semanticName layer one semantic associated with the layer - /// \complexity \f$ O(n) \f$, with \f$ n \f$ the number of semantic names in the collection - /// \throws std::out_of_range - void unlockFirstLayerOccurrence( const LayerSemantic& semanticName ); + template + void set_indices( LayerKeyType layer_key, + const typename IndexLayer::IndexContainerType& indices ) { + auto own_indices = indices; + set_indices( layer_key, std::move( own_indices ) ); + } + template + void set_indices( typename IndexLayer::IndexContainerType&& indices ) { + auto result = getFirstLayerOccurrenceWithLock( IndexLayer::staticSemanticName ); + auto layer_key = result.first; + auto& locked_layer = result.second; + set_indices( layer_key, locked_layer, std::move( indices ) ); + } + + template + void set_indices( LayerKeyType layer_key, typename IndexLayer::IndexContainerType&& indices ) { + auto& locked_layer = getLayerWithLock( layer_key ); + set_indices( layer_key, locked_layer, std::move( indices ) ); + } + + template + const typename IndexLayer::IndexContainerType& indices() const { + auto result = getFirstLayerOccurrence( IndexLayer::staticSemanticName ); + return static_cast( result.second ).collection(); + } + + template + typename IndexLayer::IndexContainerType& indices_with_lock() { + auto result = getFirstLayerOccurrenceWithLock( IndexLayer::staticSemanticName ); + return static_cast( result.second ).collection(); + } + + template + void unlock_indices() { + auto result = getFirstLayerOccurrence( IndexLayer::staticSemanticName ); + unlockLayer( result.first ); + } + + protected: ////////////////////////////////////////////////////////////////////// + template + void set_indices( LayerKeyType layer_key, + GeometryIndexLayerBase& locked_layer, + IndexLayer::IndexContainerType&& indices ) { + static_cast( locked_layer ).collection() = std::move( indices ); + unlockLayer( layer_key ); + notify(); + } + ////////////////////////////////////////////////////////////////////// public: /// \brief Add layer @@ -624,25 +658,8 @@ inline GeometryIndexLayerBase& GeometryIndexLayerBase::operator=( GeometryIndexL return *this; } -inline GeometryIndexLayerBase::~GeometryIndexLayerBase() {} - -inline bool GeometryIndexLayerBase::operator==( const GeometryIndexLayerBase& ) const { - return false; -} - //----------------------------------------------------------------------------- //- GeometryIndexLayer -------------------------------------------------------- -template -typename GeometryIndexLayer::IndexContainerType& GeometryIndexLayer::collection() { - return m_collection; -} - -template -const typename GeometryIndexLayer::IndexContainerType& -GeometryIndexLayer::collection() const { - return m_collection; -} - template bool GeometryIndexLayer::append( const GeometryIndexLayerBase& other, int offset ) { if ( shareSemantic( other ) ) { @@ -678,11 +695,6 @@ bool GeometryIndexLayer::operator==( const GeometryIndexLayerBase& other ) co return false; } -template -size_t GeometryIndexLayer::getSize() const { - return m_collection.size(); -} - template size_t GeometryIndexLayer::getNumberOfComponents() const { return IndexType::RowsAtCompileTime; @@ -771,36 +783,27 @@ IndexedGeometry::IndexedGeometry() { template const typename IndexedGeometry::IndexContainerType& IndexedGeometry::getIndices() const { - const auto& abstractLayer = getLayer( default_layer_key() ); - return static_cast::DefaultLayerType&>( abstractLayer ).collection(); + return indices(); } template typename IndexedGeometry::IndexContainerType& IndexedGeometry::getIndicesWithLock() { - auto& abstractLayer = getLayerWithLock( default_layer_key() ); - return static_cast::DefaultLayerType&>( abstractLayer ).collection(); + return indices_with_lock(); } template void IndexedGeometry::indicesUnlock() { - unlockLayer( default_layer_key() ); + unlock_indices(); } template void IndexedGeometry::setIndices( IndexContainerType&& indices ) { - auto& abstractLayer = getLayerWithLock( default_layer_key() ); - static_cast::DefaultLayerType&>( abstractLayer ).collection() = - std::move( indices ); - indicesUnlock(); - notify(); + set_indices( default_layer_key(), std::move( indices ) ); } template void IndexedGeometry::setIndices( const IndexContainerType& indices ) { - auto& abstractLayer = getLayerWithLock( default_layer_key() ); - static_cast::DefaultLayerType&>( abstractLayer ).collection() = indices; - indicesUnlock(); - notify(); + set_indices( default_layer_key(), indices ); } template From ca8d7cc8b941ee5630b47071e4614616c1eda2ae Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 11 May 2026 12:19:32 +0200 Subject: [PATCH 077/144] [core] set_indices add layer if needed. Also add some semantic helper functions. --- src/Core/Geometry/IndexedGeometry.hpp | 51 ++++++++++++++++++--------- src/Core/Utils/ObjectWithSemantic.hpp | 13 ++++++- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 20b0415f623..52525df7335 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -207,6 +207,14 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util using LayerSemantic = Utils::ObjectWithSemantic::SemanticName; using LayerKeyType = std::pair; + /// Hash function for layer keys + struct RA_CORE_API LayerKeyHash { + std::size_t operator()( const LayerKeyType& k ) const; + }; + /// bool -> locked, ptr -> actual data + using LayerEntryType = std::pair>; + using IndexCollection = std::unordered_map; + using PointAttribHandle = AttribArrayGeometry::PointAttribHandle; using NormalAttribHandle = AttribArrayGeometry::NormalAttribHandle; using FloatAttribHandle = AttribArrayGeometry::FloatAttribHandle; @@ -383,6 +391,14 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util /// \throws std::out_of_range std::pair getFirstLayerOccurrenceWithLock( const LayerSemantic& semanticName ); + auto getFirstLayerIteratorWithLock( const LayerSemantic& semanticName ) + -> IndexCollection::iterator { + return std::find_if( m_indices.begin(), + m_indices.end(), + [&semanticName]( const IndexCollection::value_type& v ) { + return Utils::hasSemantic( v.first.first, semanticName ); + } ); + } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// @@ -406,9 +422,9 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util void unlockLayer( const LayerSemanticCollection& semantics, const std::string& layerName ); template - void set_indices( const typename IndexLayer::IndexContainerType& indices ) { + LayerKeyType set_indices( const typename IndexLayer::IndexContainerType& indices ) { auto own_indices = indices; - set_indices( std::move( own_indices ) ); + return set_indices( std::move( own_indices ) ); } template @@ -419,11 +435,21 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util } template - void set_indices( typename IndexLayer::IndexContainerType&& indices ) { - auto result = getFirstLayerOccurrenceWithLock( IndexLayer::staticSemanticName ); - auto layer_key = result.first; - auto& locked_layer = result.second; - set_indices( layer_key, locked_layer, std::move( indices ) ); + LayerKeyType set_indices( typename IndexLayer::IndexContainerType&& indices ) { + auto itr = getFirstLayerIteratorWithLock( IndexLayer::staticSemanticName ); + LayerKeyType layer_key; + GeometryIndexLayerBase* locked_layer = nullptr; + if ( itr == m_indices.end() ) { + auto added = addLayer( std::move( std::make_unique() ) ); + layer_key = added.second; + locked_layer = &getLayerWithLock( layer_key ); + } + else { + layer_key = itr->first; + locked_layer = itr->second.second.get(); + } + set_indices( layer_key, *locked_layer, std::move( indices ) ); + return layer_key; } template @@ -501,15 +527,6 @@ 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: - /// Hash function for layer keys - struct RA_CORE_API LayerKeyHash { - std::size_t operator()( const LayerKeyType& k ) const; - }; - private: /** * Collection of pairs @@ -518,7 +535,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util * 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; + IndexCollection m_indices; /// Default layer key, initialized as invalid, set to first added Layer Key. LayerKeyType m_default_layer_key { { InvalidIndexLayer::staticSemanticName }, "invalid" }; diff --git a/src/Core/Utils/ObjectWithSemantic.hpp b/src/Core/Utils/ObjectWithSemantic.hpp index 81897a5851a..afb031f4296 100644 --- a/src/Core/Utils/ObjectWithSemantic.hpp +++ b/src/Core/Utils/ObjectWithSemantic.hpp @@ -20,7 +20,8 @@ class RA_CORE_API ObjectWithSemantic public: using SemanticName = std::string; - /// Store in set to allow for logarithmic search + /// Store in set to allow for logarithmic search, + /// \todo move out of class ? extends set to add helper functions ? using SemanticNameCollection = std::set; inline explicit ObjectWithSemantic( const ObjectWithSemantic& other ) : @@ -66,6 +67,16 @@ class RA_CORE_API ObjectWithSemantic SemanticNameCollection m_names; }; +inline bool hasSemantic( const ObjectWithSemantic::SemanticNameCollection& a, + const ObjectWithSemantic::SemanticName& name ) { + return a.contains( name ); +} + +inline bool shareSemantic( const ObjectWithSemantic::SemanticNameCollection& a, + const ObjectWithSemantic::SemanticNameCollection& b ) { + return std::any_of( a.begin(), a.end(), [&b]( const auto& s ) { return hasSemantic( b, s ); } ); +} + } // namespace Utils } // namespace Core } // namespace Ra From d598b630b659aff33d624bc24aac73b015b2a6bd Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 11 May 2026 12:20:22 +0200 Subject: [PATCH 078/144] [engine] Use MultiIndexedGeometry instead of old Mesh or LineMesh. --- src/Engine/Data/DrawPrimitives.cpp | 129 ++++++++++++++--------------- src/Engine/Data/DrawPrimitives.hpp | 15 ++-- 2 files changed, 70 insertions(+), 74 deletions(-) diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index cb3b972e4cc..a900a2aa6e5 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -1,3 +1,4 @@ +#include "Core/Containers/VectorArray.hpp" #include #include @@ -55,14 +56,14 @@ Rendering::RenderObject* Primitive( Scene::Component* component, GeometryDisplayablePtr Point( const Core::Vector3& point, const Core::Utils::Color& color, Scalar scale ) { - Geometry::LineMesh geom; + Geometry::MultiIndexedGeometry geom; geom.setVertices( { ( point + ( scale * Core::Vector3::UnitX() ) ), ( point - ( scale * Core::Vector3::UnitX() ) ), ( point + ( scale * Core::Vector3::UnitY() ) ), ( point - ( scale * Core::Vector3::UnitY() ) ), ( point + ( scale * Core::Vector3::UnitZ() ) ), ( point - ( scale * Core::Vector3::UnitZ() ) ) } ); - geom.setIndices( { { 0, 1 }, { 2, 3 }, { 4, 5 } } ); + geom.set_indices( { { 0, 1 }, { 2, 3 }, { 4, 5 } } ); geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); @@ -72,9 +73,9 @@ Point( const Core::Vector3& point, const Core::Utils::Color& color, Scalar scale GeometryDisplayablePtr Line( const Core::Vector3& a, const Core::Vector3& b, const Core::Utils::Color& color ) { - Geometry::LineMesh geom; + Geometry::MultiIndexedGeometry geom; geom.setVertices( { a, b } ); - geom.setIndices( { { 0, 1 } } ); + geom.set_indices( { { 0, 1 } } ); geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); @@ -342,8 +343,6 @@ GeometryDisplayablePtr Disk( const Core::Vector3& center, uint segments, const Core::Utils::Color& color ) { CORE_ASSERT( segments > 2, "Cannot draw a circle with less than 3 points" ); - // MultiIndexedGeometry geom; - // GeometryIndexLayer fan_indices; uint seg = segments + 1; Core::Vector3Array vertices( seg ); @@ -410,7 +409,7 @@ GeometryDisplayablePtr Normal( const Core::Vector3& point, const Scalar arrowFract = 0.1f; - Geometry::LineMesh geom; + Geometry::MultiIndexedGeometry geom; Core::Vector3Array vertices = { point, @@ -425,15 +424,15 @@ GeometryDisplayablePtr Normal( const Core::Vector3& point, }; geom.setVertices( vertices ); - geom.setIndices( { { 0, 1 }, - { 1, 2 }, - { 1, 3 }, - { 4, 5 }, - { 5, 6 }, - { 6, 7 }, - { 7, 4 }, - { 4, 6 }, - { 5, 7 } } ); + geom.set_indices( { { 0, 1 }, + { 1, 2 }, + { 1, 3 }, + { 4, 5 }, + { 5, 6 }, + { 6, 7 }, + { 7, 4 }, + { 4, 6 }, + { 5, 7 } } ); geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); @@ -441,7 +440,6 @@ GeometryDisplayablePtr Normal( const Core::Vector3& point, return make_shared( "Normal Primitive", std::move( geom ) ); } -/// \todo continue to convert mesh creation and remove call to deprecated Mesh::loadGeometry GeometryDisplayablePtr Frame( const Core::Transform& frameFromEntity, Scalar scale ) { // Frame is a bit different from the others // since there are 3 lines of different colors. @@ -487,45 +485,37 @@ GeometryDisplayablePtr AABB( const Core::Aabb& aabb, const Core::Utils::Color& c auto [key, layer] = ret->getCoreGeometry().getFirstLayerOccurrence( Core::Geometry::LineIndexLayer::staticSemanticName ); - std::cerr << "aabb check " << key.first << " " << key.second << "\n"; - ret->addRenderLayer( key, AttribArrayDisplayable::MeshRenderMode::RM_LINES ); ret->set_active_layer_key( key ); return ret; } -MeshPtr OBB( const Obb& obb, const Core::Utils::Color& color ) { - Core::Vector3Array vertices( 8 ); +GeometryDisplayablePtr OBB( const Obb& obb, const Core::Utils::Color& color ) { - for ( uint i = 0; i < 8; ++i ) { - vertices[i] = obb.worldCorner( i ); - } - - std::vector indices = { - 0, 1, 1, 3, 3, 2, 2, 0, // Floor - 4, 5, 5, 7, 7, 6, 6, 4, // Ceil - 0, 4, 1, 5, 2, 6, 3, 7, // Links - }; - - Core::Vector4Array colors( vertices.size(), color ); - - MeshPtr mesh( new Mesh( "OBB Primitive", Mesh::RM_LINES ) ); - mesh->loadGeometry( vertices, indices ); - mesh->getCoreGeometry().addAttrib( - Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), colors ); + auto geom = + makeBox2( obb.corner( Aabb::BottomLeftFloor ), + obb.corner( Aabb::BottomRightFloor ) - obb.corner( Aabb::BottomLeftFloor ), + obb.corner( Aabb::BottomLeftCeil ) - obb.corner( Aabb::BottomLeftFloor ), + obb.corner( Aabb::TopLeftFloor ) - obb.corner( Aabb::BottomLeftFloor ), + color ); + auto ret = make_shared( "AABB Primitive", std::move( geom ) ); + auto [key, layer] = ret->getCoreGeometry().getFirstLayerOccurrence( + Core::Geometry::LineIndexLayer::staticSemanticName ); - return mesh; + ret->addRenderLayer( key, AttribArrayDisplayable::MeshRenderMode::RM_LINES ); + ret->set_active_layer_key( key ); + return ret; } -MeshPtr Spline( const Core::Geometry::Spline<3, 3>& spline, - uint pointCount, - const Core::Utils::Color& color, - Scalar /*scale*/ ) { +GeometryDisplayablePtr Spline( const Core::Geometry::Spline<3, 3>& spline, + uint pointCount, + const Core::Utils::Color& color, + Scalar /*scale*/ ) { Core::Vector3Array vertices; vertices.reserve( pointCount ); - std::vector indices; - indices.reserve( pointCount * 2 - 2 ); + Vector2uArray indices; + indices.reserve( pointCount - 1 ); Scalar dt = Scalar( 1 ) / Scalar( pointCount - 1 ); for ( uint i = 0; i < pointCount; ++i ) { @@ -534,38 +524,43 @@ MeshPtr Spline( const Core::Geometry::Spline<3, 3>& spline, } for ( uint i = 0; i < pointCount - 1; ++i ) { - indices.push_back( i ); - indices.push_back( i + 1 ); + indices.emplace_back( i, i + 1 ); } Core::Vector4Array colors( vertices.size(), color ); - MeshPtr mesh( new Mesh( "Spline Primitive", Mesh::RM_LINES ) ); - mesh->loadGeometry( vertices, indices ); - mesh->getCoreGeometry().addAttrib( - Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), colors ); + Geometry::MultiIndexedGeometry geom; - return mesh; + auto line_layer = geom.set_indices( std::move( indices ) ); + geom.setVertices( std::move( vertices ) ); + geom.addAttrib( + Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), + Core::Vector4Array { geom.vertices().size(), color } ); + + return make_shared( "Spline Primitive", std::move( geom ) ); } -MeshPtr LineStrip( const Core::Vector3Array& vertices, const Core::Vector4Array& colors ) { - std::vector indices( vertices.size() ); - std::iota( indices.begin(), indices.end(), 0 ); - auto r = ( vertices.size() % 3 ); - if ( r != 0 ) { - for ( ; r < 3; ++r ) { - indices.push_back( vertices.size() - 1 ); - } - } - MeshPtr mesh( new Mesh( "Line Strip Primitive", Mesh::RM_LINE_STRIP ) ); - mesh->loadGeometry( vertices, indices ); - if ( colors.size() > 0 ) { - mesh->getCoreGeometry().addAttrib( - Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), - colors ); - } +GeometryDisplayablePtr LineStrip( const Core::Vector3Array& vertices, + const Core::Vector4Array& colors ) { + VectorArray indices( 1 ); + + indices[0] = VectorNui::LinSpaced( vertices.size(), 0, vertices.size() - 1 ); + + Geometry::MultiIndexedGeometry geom; + geom.setVertices( vertices ); + + auto strip_key = geom.set_indices( std::move( indices ) ); + geom.addAttrib( + Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), colors ); + + auto mesh = make_shared( "Line Strip Primitive" ); + mesh->loadGeometry( + std::move( geom ), + GeometryDisplayable::ArrayOfLayerKeys<1> { { { strip_key, Mesh::RM_LINE_STRIP } } } ); + return mesh; } + } // namespace DrawPrimitives } // namespace Data } // namespace Engine diff --git a/src/Engine/Data/DrawPrimitives.hpp b/src/Engine/Data/DrawPrimitives.hpp index 9432f54be96..2143f5e5e8c 100644 --- a/src/Engine/Data/DrawPrimitives.hpp +++ b/src/Engine/Data/DrawPrimitives.hpp @@ -153,16 +153,17 @@ RA_ENGINE_API GeometryDisplayablePtr AABB( const Core::Aabb& aabb, const Core::Utils::Color& color ); /// Display a wireframe OBB -RA_ENGINE_API MeshPtr OBB( const Core::Geometry::Obb& obb, const Core::Utils::Color& color ); +RA_ENGINE_API GeometryDisplayablePtr OBB( const Core::Geometry::Obb& obb, + const Core::Utils::Color& color ); -RA_ENGINE_API MeshPtr Spline( const Core::Geometry::Spline<3, 3>& spline, - uint pointCount, - const Core::Utils::Color& color, - Scalar scale = 1.0f ); +RA_ENGINE_API GeometryDisplayablePtr Spline( const Core::Geometry::Spline<3, 3>& spline, + uint pointCount, + const Core::Utils::Color& color, + Scalar scale = 1.0f ); /// Display a line strip. -RA_ENGINE_API MeshPtr LineStrip( const Core::Vector3Array& vertices, - const Core::Vector4Array& colors ); +RA_ENGINE_API GeometryDisplayablePtr LineStrip( const Core::Vector3Array& vertices, + const Core::Vector4Array& colors ); } // namespace DrawPrimitives } // namespace Data From 7ec55161d6fc214bc6827f91c1bf7d9913a5544d Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 11 May 2026 12:21:13 +0200 Subject: [PATCH 079/144] [examples] DrawPrimitives, add spline and line strip. --- .../DrawPrimitives/AllPrimitivesComponent.cpp | 81 ++++++++++++++----- 1 file changed, 61 insertions(+), 20 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index 3c5b663add0..60f093a3ef0 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -1,4 +1,5 @@ +#include "Engine/Data/DrawPrimitives.hpp" #include #include @@ -26,25 +27,27 @@ #include -const bool ENABLE_GRID = true; -const bool ENABLE_CUBES = true; -const bool ENABLE_POINTS = true; -const bool ENABLE_LINES = true; -const bool ENABLE_VECTORS = true; -const bool ENABLE_RAYS = true; -const bool ENABLE_TRIANGLES = true; -const bool ENABLE_CIRCLES = true; -const bool ENABLE_ARCS = true; -const bool ENABLE_SPHERES = true; -const bool ENABLE_CAPSULES = true; -const bool ENABLE_DISKS = true; -const bool ENABLE_NORMALS = true; -const bool ENABLE_POLYS = true; -const bool ENABLE_LOGO = true; -const bool ENABLE_COLLAPSE = true; -const bool ENABLE_SPLIT = true; -const bool ENABLE_TORUS = true; -const bool ENABLE_QUADSTRIP = true; +const bool ENABLE_GRID = true; +const bool ENABLE_CUBES = true; +const bool ENABLE_POINTS = true; +const bool ENABLE_LINES = true; +const bool ENABLE_VECTORS = true; +const bool ENABLE_RAYS = true; +const bool ENABLE_TRIANGLES = true; +const bool ENABLE_CIRCLES = true; +const bool ENABLE_ARCS = true; +const bool ENABLE_SPHERES = true; +const bool ENABLE_CAPSULES = true; +const bool ENABLE_DISKS = true; +const bool ENABLE_NORMALS = true; +const bool ENABLE_POLYS = true; +const bool ENABLE_LOGO = true; +const bool ENABLE_COLLAPSE = true; +const bool ENABLE_SPLIT = true; +const bool ENABLE_TORUS = true; +const bool ENABLE_QUADSTRIPS = true; +const bool ENABLE_SPLINES = true; +const bool ENABLE_LINE_STRIPS = true; using namespace Ra; using namespace Ra::Core; @@ -594,6 +597,7 @@ void AllPrimitivesComponent::initialize() { normal->setMaterial( plainMaterial ); addRenderObject( normal ); } + /* addRenderObject( RenderObject::createRenderObject( "test_ray", @@ -1111,7 +1115,7 @@ void AllPrimitivesComponent::initialize() { } } } - if ( ENABLE_QUADSTRIP ) { + if ( ENABLE_QUADSTRIPS ) { updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); @@ -1148,4 +1152,41 @@ void AllPrimitivesComponent::initialize() { } } } + + if ( ENABLE_SPLINES ) { + updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); + updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); + Core::Geometry::Spline<3, 3> s; + auto c = cellCorner + 2_ra * offsetVec; + s.setCtrlPoints( { c + Vector3( 0, 0, 0 ), + c + Vector3( .15 * cellSize, .5 * cellSize, .4 * cellSize ), + c + Vector3( .35 * cellSize, -.5 * cellSize, .2 * cellSize ), + c + Vector3( .4 * cellSize, 0, 0 ) } ); + auto spline = RenderObject::createRenderObject( + "test_spline", + this, + RenderObjectType::Geometry, + DrawPrimitives::Spline( s, 32, colorBoost * Color::Cyan() ), + {} ); + spline->setMaterial( plainMaterial ); + addRenderObject( spline ); + } + if ( ENABLE_LINE_STRIPS ) { + // updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); + // updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); + auto c = cellCorner + 2_ra * offsetVec; + auto strip = RenderObject::createRenderObject( + "test_linestrip", + this, + RenderObjectType::Geometry, + DrawPrimitives::LineStrip( + { c + Vector3( 0, 0, 0 ), + c + Vector3( .15 * cellSize, .5 * cellSize, .4 * cellSize ), + c + Vector3( .35 * cellSize, -.5 * cellSize, .2 * cellSize ), + c + Vector3( .4 * cellSize, 0, 0 ) }, + { Color::Cyan(), Color::Red(), Color::Yellow(), Color::Magenta() } ), + {} ); + strip->setMaterial( plainMaterial ); + addRenderObject( strip ); + } } From 260f040ae9cf0aaa0aa81f3b43b4e27ce655a15e Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 11 May 2026 19:41:44 +0200 Subject: [PATCH 080/144] [engine] Remove deprecated MeshPtr, LineMesh->MultiIndexedGeometry. --- src/Engine/Data/DrawPrimitives.cpp | 24 ++++++++++-------------- src/Engine/Data/DrawPrimitives.hpp | 3 --- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index a900a2aa6e5..a106758818c 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -28,10 +28,6 @@ namespace Engine { namespace Data { namespace DrawPrimitives { -Rendering::RenderObject* Primitive( Scene::Component* component, const MeshPtr& mesh ) { - return Primitive( component, std::dynamic_pointer_cast( mesh ) ); -} - Rendering::RenderObject* Primitive( Scene::Component* component, const GeometryDisplayablePtr& mesh ) { return Primitive( component, std::dynamic_pointer_cast( mesh ) ); @@ -93,12 +89,12 @@ Vector( const Core::Vector3& start, const Core::Vector3& v, const Core::Utils::C const Scalar arrowFract = 0.1f; - Geometry::LineMesh geom; + Geometry::MultiIndexedGeometry geom; geom.setVertices( { start, end, start + ( ( 1.f - arrowFract ) * v ) + ( ( arrowFract * l ) * a ), start + ( ( 1.f - arrowFract ) * v ) - ( ( arrowFract * l ) * a ) } ); - geom.setIndices( { { 0, 1 }, { 1, 2 }, { 1, 3 } } ); + geom.set_indices( { { 0, 1 }, { 1, 2 }, { 1, 3 } } ); geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); @@ -107,10 +103,10 @@ Vector( const Core::Vector3& start, const Core::Vector3& v, const Core::Utils::C } GeometryDisplayablePtr Ray( const Core::Ray& ray, const Core::Utils::Color& color, Scalar len ) { - Geometry::LineMesh geom; + Geometry::MultiIndexedGeometry geom; Core::Vector3 end = ray.pointAt( len ); geom.setVertices( { ray.origin(), end } ); - geom.setIndices( { { 0, 1 } } ); + geom.set_indices( { { 0, 1 } } ); geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); @@ -201,7 +197,7 @@ GeometryDisplayablePtr Circle( const Core::Vector3& center, const Core::Utils::Color& color ) { CORE_ASSERT( segments >= 2, "Cannot draw a circle with less than 3 points" ); - Geometry::LineMesh geom; + Geometry::MultiIndexedGeometry geom; ///\todo refer to class typedef instaed of core types/ Core::Vector3Array vertices( segments + 1 ); Geometry::LineMesh::IndexContainerType indices; @@ -224,7 +220,7 @@ GeometryDisplayablePtr Circle( const Core::Vector3& center, } geom.setVertices( std::move( vertices ) ); - geom.setIndices( std::move( indices ) ); + geom.set_indices( std::move( indices ) ); geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); @@ -238,7 +234,7 @@ GeometryDisplayablePtr CircleArc( const Core::Vector3& center, Scalar angle, uint segments, const Core::Utils::Color& color ) { - Geometry::LineMesh geom; + Geometry::MultiIndexedGeometry geom; Core::Vector3Array vertices( segments + 1 ); Geometry::LineMesh::IndexContainerType indices; indices.resize( segments ); @@ -261,7 +257,7 @@ GeometryDisplayablePtr CircleArc( const Core::Vector3& center, } geom.setVertices( std::move( vertices ) ); - geom.setIndices( std::move( indices ) ); + geom.set_indices( std::move( indices ) ); geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Core::Vector4Array { geom.vertices().size(), color } ); @@ -448,10 +444,10 @@ GeometryDisplayablePtr Frame( const Core::Transform& frameFromEntity, Scalar sca Core::Vector3 y = frameFromEntity.linear() * Core::Vector3::UnitY(); Core::Vector3 z = frameFromEntity.linear() * Core::Vector3::UnitZ(); - Geometry::LineMesh geom; + Geometry::MultiIndexedGeometry geom; geom.setVertices( { { pos, pos + scale * x, pos, pos + scale * y, pos, pos + scale * z } } ); - geom.setIndices( { { 0, 1 }, { 2, 3 }, { 4, 5 } } ); + geom.set_indices( { { 0, 1 }, { 2, 3 }, { 4, 5 } } ); Core::Vector4Array colors = { Core::Utils::Color::Red(), diff --git a/src/Engine/Data/DrawPrimitives.hpp b/src/Engine/Data/DrawPrimitives.hpp index 2143f5e5e8c..5021945bceb 100644 --- a/src/Engine/Data/DrawPrimitives.hpp +++ b/src/Engine/Data/DrawPrimitives.hpp @@ -29,18 +29,15 @@ class GeometryDisplayable; /// note that objects will be drawn in their entity's local frame. /// For "instant" debug drawing, \see DebugDisplay. namespace DrawPrimitives { -using MeshPtr = std::shared_ptr; using AttribArrayDisplayablePtr = std::shared_ptr; using GeometryDisplayablePtr = std::shared_ptr; ///\{ /// Renturn a render object to display the given geometry -RA_ENGINE_API Rendering::RenderObject* Primitive( Scene::Component* comp, const MeshPtr& mesh ); RA_ENGINE_API Rendering::RenderObject* Primitive( Scene::Component* comp, const GeometryDisplayablePtr& mesh ); RA_ENGINE_API Rendering::RenderObject* Primitive( Scene::Component* comp, const AttribArrayDisplayablePtr& mesh ); - ///\} /// Displays given point shown as the crossing of 3 lines of length 'scale' From 2caa7b56fb4c58db99e13546ca2ffe18b79b2c4c Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 11 May 2026 21:39:40 +0200 Subject: [PATCH 081/144] [core] Remove explicit from MultiIndexedGeometry copy ctor. --- src/Core/Geometry/IndexedGeometry.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 52525df7335..6cf7b1571d8 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -223,10 +223,10 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util using Vec4AttribHandle = AttribArrayGeometry::Vec4AttribHandle; MultiIndexedGeometry() = default; - explicit MultiIndexedGeometry( const MultiIndexedGeometry& other ); - explicit MultiIndexedGeometry( MultiIndexedGeometry&& other ); - explicit MultiIndexedGeometry( const AttribArrayGeometry& other ); - explicit MultiIndexedGeometry( AttribArrayGeometry&& other ); + MultiIndexedGeometry( const MultiIndexedGeometry& other ); + MultiIndexedGeometry( MultiIndexedGeometry&& other ); + MultiIndexedGeometry( const AttribArrayGeometry& other ); + MultiIndexedGeometry( AttribArrayGeometry&& other ); MultiIndexedGeometry& operator=( const MultiIndexedGeometry& other ); MultiIndexedGeometry& operator=( MultiIndexedGeometry&& other ); From 4e048c4fc47210c7cb3ae1f8b1bf0dd0b5253555 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 11 May 2026 22:58:19 +0200 Subject: [PATCH 082/144] [core] Remove explicit call to copy ctor. --- src/Core/Geometry/MeshPrimitives.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index 0a93ef153da..85aa13e440b 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -142,7 +142,7 @@ MultiIndexedGeometry makeBox2( const Vector3& corner, result.addLayer( std::move( layer ) ); - return MultiIndexedGeometry { std::move( result ) }; + return result; } TriangleMesh makeSharpBox( const Vector3& halfExts, @@ -287,7 +287,7 @@ MultiIndexedGeometry makeSharpBox2( const Aabb& aabb, if ( bool( color ) ) result.colorize( *color ); result.checkConsistency(); - return MultiIndexedGeometry { std::move( result ) }; + return result; } MultiIndexedGeometry makeSharpBox2( const Vector3& halfExts, From c83d4fb8c8fef8b0621516a3529c88b7fc99c177 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 11 May 2026 23:01:58 +0200 Subject: [PATCH 083/144] [core] indices_with_lock return pair with layer_key to unlockLayer. --- src/Core/Geometry/IndexedGeometry.hpp | 28 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 6cf7b1571d8..b818125a3bd 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -465,15 +465,21 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util } template - typename IndexLayer::IndexContainerType& indices_with_lock() { - auto result = getFirstLayerOccurrenceWithLock( IndexLayer::staticSemanticName ); - return static_cast( result.second ).collection(); - } - - template - void unlock_indices() { - auto result = getFirstLayerOccurrence( IndexLayer::staticSemanticName ); - unlockLayer( result.first ); + auto indices_with_lock() { + auto itr = getFirstLayerIteratorWithLock( IndexLayer::staticSemanticName ); + LayerKeyType layer_key; + GeometryIndexLayerBase* locked_layer = nullptr; + if ( itr == m_indices.end() ) { + auto added = addLayer( std::move( std::make_unique() ) ); + layer_key = added.second; + locked_layer = &getLayerWithLock( layer_key ); + } + else { + layer_key = itr->first; + locked_layer = itr->second.second.get(); + } + return std::pair( + layer_key, static_cast( *locked_layer ).collection() ); } protected: @@ -805,12 +811,12 @@ const typename IndexedGeometry::IndexContainerType& IndexedGeometry::getIn template typename IndexedGeometry::IndexContainerType& IndexedGeometry::getIndicesWithLock() { - return indices_with_lock(); + return indices_with_lock().second; } template void IndexedGeometry::indicesUnlock() { - unlock_indices(); + unlockLayer( default_layer_key() ); } template From f2c9dbb0347c1435aa1a54049a6918770b5c85d9 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 11 May 2026 23:42:28 +0200 Subject: [PATCH 084/144] [core] Everything (?) is MultiIndexed. --- src/Core/Geometry/IndexedGeometry.cpp | 2 +- src/Core/Geometry/MeshPrimitives.cpp | 62 +++++++++++++-------------- src/Core/Geometry/MeshPrimitives.hpp | 50 ++++++++++----------- src/Core/Geometry/TopologicalMesh.hpp | 36 ++++++++-------- 4 files changed, 76 insertions(+), 74 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index 7abe365ad7f..16252545edf 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -72,7 +72,7 @@ bool MultiIndexedGeometry::append( const MultiIndexedGeometry& other ) { value.first, std::unique_ptr { value.second->clone() } ); dataHasBeenCopied = true; m_indices[key].second->offset( offset ); - ///\todo offest indices. + ///\todo offest indices. (done ?) } else { // try to append to an existing layer: should always work diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index 85aa13e440b..aa38b7a32e7 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -427,9 +427,9 @@ TriangleMesh makeSharpBox( const Aabb& aabb, return result; } -TriangleMesh +MultiIndexedGeometry makeGeodesicSphere( Scalar radius, uint numSubdiv, const Utils::optional& color ) { - TriangleMesh result; + MultiIndexedGeometry result; uint faceCount = uint( std::pow( 4, numSubdiv ) ) * 20; TriangleMesh::PointAttribHandle::Container vertices; @@ -507,24 +507,24 @@ makeGeodesicSphere( Scalar radius, uint numSubdiv, const Utils::optional( std::move( indices ) ); if ( bool( color ) ) result.colorize( *color ); result.checkConsistency(); return result; } -TriangleMesh makeCylinder( const Vector3& a, - const Vector3& b, - Scalar radius, - uint sideSegments, - uint fillSegments, - const Utils::optional& color ) { - TriangleMesh result; +MultiIndexedGeometry makeCylinder( const Vector3& a, + const Vector3& b, + Scalar radius, + uint sideSegments, + uint fillSegments, + const Utils::optional& color ) { + MultiIndexedGeometry result; - TriangleMesh::PointAttribHandle::Container vertices; - TriangleMesh::NormalAttribHandle::Container normals; - TriangleMesh::IndexContainerType indices; + MultiIndexedGeometry::PointAttribHandle::Container vertices; + MultiIndexedGeometry::NormalAttribHandle::Container normals; + TriangleIndexLayer::IndexContainerType indices; const Vector3 ab = b - a; const Vector3 dir = ab.normalized(); @@ -593,18 +593,18 @@ TriangleMesh makeCylinder( const Vector3& a, result.setVertices( std::move( vertices ) ); result.setNormals( std::move( normals ) ); - result.setIndices( std::move( indices ) ); + result.set_indices( std::move( indices ) ); if ( bool( color ) ) result.colorize( *color ); result.checkConsistency(); return result; } -TriangleMesh makeCapsule( Scalar length, - Scalar radius, - uint nFaces, - const Utils::optional& color ) { - TriangleMesh result; +MultiIndexedGeometry makeCapsule( Scalar length, + Scalar radius, + uint nFaces, + const Utils::optional& color ) { + MultiIndexedGeometry result; TriangleMesh::PointAttribHandle::Container vertices; TriangleMesh::NormalAttribHandle::Container normals; @@ -775,26 +775,26 @@ TriangleMesh makeCapsule( Scalar length, } result.setVertices( std::move( vertices ) ); result.setNormals( std::move( normals ) ); - result.setIndices( std::move( indices ) ); + result.set_indices( std::move( indices ) ); if ( bool( color ) ) result.colorize( *color ); result.checkConsistency(); return result; } -TriangleMesh makeTube( const Vector3& a, - const Vector3& b, - Scalar outerRadius, - Scalar innerRadius, - uint nFaces, - const Utils::optional& color ) { +MultiIndexedGeometry makeTube( const Vector3& a, + const Vector3& b, + Scalar outerRadius, + Scalar innerRadius, + uint nFaces, + const Utils::optional& color ) { CORE_ASSERT( outerRadius > innerRadius, "Outer radius must be bigger than inner." ); - TriangleMesh result; - TriangleMesh::PointAttribHandle::Container vertices; - TriangleMesh::NormalAttribHandle::Container normals; - TriangleMesh::IndexContainerType indices; + MultiIndexedGeometry result; + MultiIndexedGeometry::PointAttribHandle::Container vertices; + MultiIndexedGeometry::NormalAttribHandle::Container normals; + TriangleIndexLayer::IndexContainerType indices; vertices.reserve( 6 * nFaces ); normals.reserve( 6 * nFaces ); indices.reserve( 12 * nFaces ); @@ -876,7 +876,7 @@ TriangleMesh makeTube( const Vector3& a, } result.setVertices( std::move( vertices ) ); result.setNormals( std::move( normals ) ); - result.setIndices( std::move( indices ) ); + result.set_indices( std::move( indices ) ); if ( bool( color ) ) result.colorize( *color ); result.checkConsistency(); diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index 15d91a2a546..9dbdd5de47b 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -104,9 +104,9 @@ RA_CORE_API MultiIndexedGeometry makeSharpBox2( const Aabb& aabb, /// 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 -TriangleMesh makeParametricSphere( Scalar radius = 1_ra, - const Utils::optional& color = {}, - bool generateTexCoord = false ); +MultiIndexedGeometry makeParametricSphere( Scalar radius = 1_ra, + const Utils::optional& color = {}, + bool generateTexCoord = false ); /// Create a parametric torus mesh. The minor radius is the radius of the inside of the tube and /// the major radius is the radius of the whole torus. The torus will be centered at the origin @@ -125,36 +125,38 @@ QuadMesh makeParametricTorus( Scalar majorRadius, // const Utils::optional& color = {}, // bool generateTexCoord = false ); /// Create a spherical mesh by subdivision of an icosahedron. -RA_CORE_API TriangleMesh makeGeodesicSphere( Scalar radius = 1_ra, - uint numSubdiv = 3, - const Utils::optional& color = {} ); +RA_CORE_API MultiIndexedGeometry +makeGeodesicSphere( Scalar radius = 1_ra, + uint numSubdiv = 3, + const Utils::optional& color = {} ); /// Create a cylinder approximation (sideSegments-faced prism) with base faces centered on a and /// b with given radius. Fill (the tube part) is split into equally sapced fill segments. Side /// and fill make a sharp edge. -RA_CORE_API TriangleMesh makeCylinder( const Vector3& a, - const Vector3& b, - Scalar radius, - uint sideSegments = 32, - uint fillSegments = 2, - const Utils::optional& color = {} ); +RA_CORE_API +MultiIndexedGeometry makeCylinder( const Vector3& a, + const Vector3& b, + Scalar radius, + uint sideSegments = 32, + uint fillSegments = 2, + const Utils::optional& color = {} ); /// Create a capsule with given cylinder length and radius. /// Total length is length + 2*radius /// The capsule is along z axis -RA_CORE_API TriangleMesh makeCapsule( Scalar length, - Scalar radius, - uint nFaces = 32, - const Utils::optional& color = {} ); +RA_CORE_API MultiIndexedGeometry makeCapsule( Scalar length, + Scalar radius, + uint nFaces = 32, + const Utils::optional& color = {} ); /// Create a tube (empty cylinder) delimited by two radii, with bases centered on A and B. /// Outer radius must be larger than inner radius. -RA_CORE_API TriangleMesh makeTube( const Vector3& a, - const Vector3& b, - Scalar outerRadius, - Scalar InnerRadius, - uint nFaces = 32, - const Utils::optional& color = {} ); +RA_CORE_API MultiIndexedGeometry makeTube( const Vector3& a, + const Vector3& b, + Scalar outerRadius, + Scalar InnerRadius, + uint nFaces = 32, + const Utils::optional& color = {} ); /// Create a cone approximation (n-faced pyramid) with base face centered on base, pointing /// towards tip with given base radius. @@ -165,7 +167,7 @@ RA_CORE_API TriangleMesh makeCone( const Vector3& base, const Utils::optional& color = {} ); template -TriangleMesh +MultiIndexedGeometry makeParametricSphere( Scalar radius, const Utils::optional& color, bool gtc ) { const Scalar du = 1_ra / SLICES; @@ -301,7 +303,7 @@ makeParametricSphere( Scalar radius, const Utils::optional& color, topoMesh.mergeEqualWedges(); topoMesh.garbage_collection(); - TriangleMesh result = topoMesh.toTriangleMesh(); + auto result = topoMesh.toTriangleMesh(); result.checkConsistency(); return result; } diff --git a/src/Core/Geometry/TopologicalMesh.hpp b/src/Core/Geometry/TopologicalMesh.hpp index 537f8a41989..6089ce3e7b1 100644 --- a/src/Core/Geometry/TopologicalMesh.hpp +++ b/src/Core/Geometry/TopologicalMesh.hpp @@ -142,11 +142,11 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT - IndexedGeometry toIndexedMesh(); - PolyMesh toPolyMesh() { return toIndexedMesh(); } - LineMesh toLineMesh() { return toIndexedMesh(); } - QuadMesh toQuadMesh() { return toIndexedMesh(); } - TriangleMesh toTriangleMesh() { return toIndexedMesh(); } + MultiIndexedGeometry toIndexedMesh(); + MultiIndexedGeometry toPolyMesh() { return toIndexedMesh(); } + MultiIndexedGeometry toLineMesh() { return toIndexedMesh(); } + MultiIndexedGeometry toQuadMesh() { return toIndexedMesh(); } + MultiIndexedGeometry toTriangleMesh() { return toIndexedMesh(); } /** * Update triangle mesh data, assuming the mesh and this topo mesh has the @@ -1151,15 +1151,15 @@ void TopologicalMesh::initWithWedge( command.initialize( mesh ); auto processFaces = [&mesh, &vertexHandles, this, hasNormals, &command]( const auto& faces ) { - size_t num_triangles = faces.size(); - for ( unsigned int i = 0; i < num_triangles; i++ ) { - const auto& face = faces[i]; - const size_t num_vert = face.size(); - std::vector face_vhandles( num_vert ); - std::vector face_normals( num_vert ); - std::vector face_wedges( num_vert ); - - for ( size_t j = 0; j < num_vert; ++j ) { + size_t face_count = faces.size(); + for ( unsigned int i = 0; i < face_count; i++ ) { + const auto& face = faces[i]; + const size_t vertex_count = face.size(); + std::vector face_vhandles( vertex_count ); + std::vector face_normals( vertex_count ); + std::vector face_wedges( vertex_count ); + + for ( size_t j = 0; j < vertex_count; ++j ) { unsigned int inMeshVertexIndex = face[j]; const Vector3& p = mesh.vertices()[inMeshVertexIndex]; @@ -1484,13 +1484,13 @@ TopologicalMesh::getWedgeIndexPph() const { } template -IndexedGeometry TopologicalMesh::toIndexedMesh() { +MultiIndexedGeometry TopologicalMesh::toIndexedMesh() { // first cleanup deleted element garbage_collection(); - IndexedGeometry out; - typename IndexedGeometry::IndexContainerType indices; + MultiIndexedGeometry out; + typename LayerType::IndexContainerType indices; /// add attribs to out std::vector> wedgeFloatAttribHandles; @@ -1539,7 +1539,7 @@ IndexedGeometry TopologicalMesh::toIndexedMesh() { indices.push_back( faceIndices ); } - out.setIndices( std::move( indices ) ); + out.set_indices( std::move( indices ) ); return out; } From d594fab0e6e34fbdaf6ca758d8e037f8cd46f42b Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 11 May 2026 23:43:01 +0200 Subject: [PATCH 085/144] [engine] Draw primitive auto (for TriangleMesh->MultiIndexed). --- src/Engine/Data/DrawPrimitives.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index a106758818c..c5a433f5686 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -301,7 +301,7 @@ GeometryDisplayablePtr Capsule( const Core::Vector3& p1, const Core::Utils::Color& color ) { const Scalar l = ( p2 - p1 ).norm(); - TriangleMesh geom = makeCapsule( l, radius, 32, color ); + auto geom = makeCapsule( l, radius, 32, color ); // Compute the transform so that // (0,0,-l/2) maps to p1 and (0,0,l/2) maps to p2 From e1ee91e2dd25aea793406d4eefea9af878d30e80 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 11 May 2026 23:43:33 +0200 Subject: [PATCH 086/144] [gui] Guizmo geom use MultiIndexed. --- src/Gui/Viewer/Gizmo/ScaleGizmo.cpp | 9 +++++---- src/Gui/Viewer/Gizmo/TranslateGizmo.cpp | 15 +++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp index dfc75604df4..c43cfab3a4f 100644 --- a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp @@ -32,9 +32,9 @@ ScaleGizmo::ScaleGizmo( Engine::Scene::Component* c, constexpr Scalar radius = arrowScale * axisWidth / 2_ra; for ( uint i = 0; i < 3; ++i ) { - Core::Vector3 cylinderEnd = Core::Vector3::Zero(); - cylinderEnd[i] = ( 1_ra - arrowFrac ); - Core::Geometry::TriangleMesh cylinder = Core::Geometry::makeCylinder( + Core::Vector3 cylinderEnd = Core::Vector3::Zero(); + cylinderEnd[i] = ( 1_ra - arrowFrac ); + auto cylinder = Core::Geometry::makeCylinder( Core::Vector3::Zero(), arrowScale * cylinderEnd, radius, 32 ); Core::Aabb boxBounds; boxBounds.extend( Core::Vector3( -radius * 2_ra, -radius * 2_ra, -radius * 2_ra ) ); @@ -43,7 +43,8 @@ ScaleGizmo::ScaleGizmo( Engine::Scene::Component* c, auto box = Core::Geometry::makeSharpBox( boxBounds ); cylinder.append( box ); - std::shared_ptr mesh( new Engine::Data::Mesh( "Scale Gizmo Arrow" ) ); + std::shared_ptr mesh( + new Engine::Data::GeometryDisplayable( "Scale Gizmo Arrow" ) ); mesh->loadGeometry( std::move( cylinder ) ); Engine::Rendering::RenderObject* arrowDrawable = new Engine::Rendering::RenderObject( diff --git a/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp b/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp index 13ddcfa7920..ac9a09c06db 100644 --- a/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp @@ -28,18 +28,17 @@ TranslateGizmo::TranslateGizmo( Engine::Scene::Component* c, constexpr Scalar arrowFrac = .15_ra; for ( uint i = 0; i < 3; ++i ) { - Core::Vector3 cylinderEnd = Core::Vector3::Zero(); - cylinderEnd[i] = ( 1_ra - arrowFrac ); - Core::Vector3 arrowEnd = Core::Vector3::Zero(); - arrowEnd[i] = 1_ra; - Core::Geometry::TriangleMesh cylinder = Core::Geometry::makeCylinder( + Core::Vector3 cylinderEnd = Core::Vector3::Zero(); + cylinderEnd[i] = ( 1_ra - arrowFrac ); + Core::Vector3 arrowEnd = Core::Vector3::Zero(); + arrowEnd[i] = 1_ra; + auto cylinder = Core::Geometry::makeCylinder( Core::Vector3::Zero(), arrowScale * cylinderEnd, arrowScale * axisWidth / 2_ra, 32 ); - Core::Geometry::TriangleMesh cone = Core::Geometry::makeCone( + auto cone = Core::Geometry::makeCone( arrowScale * cylinderEnd, arrowScale * arrowEnd, arrowScale * arrowFrac / 2_ra, 32 ); cylinder.append( cone ); - std::shared_ptr mesh( - new Engine::Data::Mesh( "Translate Gizmo Arrow" ) ); + auto mesh = std::make_shared( "Translate Gizmo Arrow" ); mesh->loadGeometry( std::move( cylinder ) ); Engine::Rendering::RenderObject* arrowDrawable = new Engine::Rendering::RenderObject( From 78946ec9fbaa7d2737971cfdd11bbac94f58d341 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 11 May 2026 23:43:53 +0200 Subject: [PATCH 087/144] [tests] Update tests according to Indexed->MultiIndexed. --- tests/unittest/Core/topomesh.cpp | 102 +++++++++++++++++-------------- 1 file changed, 55 insertions(+), 47 deletions(-) diff --git a/tests/unittest/Core/topomesh.cpp b/tests/unittest/Core/topomesh.cpp index 70f111e497a..75831c30d18 100644 --- a/tests/unittest/Core/topomesh.cpp +++ b/tests/unittest/Core/topomesh.cpp @@ -1,3 +1,4 @@ +#include "Core/Geometry/IndexedGeometry.hpp" #include #include #include @@ -116,9 +117,8 @@ class WedgeDataAndIdx } \ } -template void copyToWedgesVector( size_t size, - const IndexedGeometry& meshOne, + const MultiIndexedGeometry& meshOne, AlignedStdVector& wedgesMeshOne, AttribBase* attr ) { @@ -142,9 +142,9 @@ void copyToWedgesVector( size_t size, } #undef COPY_TO_WEDGES_VECTOR_HELPER -template -bool isSameMeshWedge( const Ra::Core::Geometry::IndexedGeometry& meshOne, - const Ra::Core::Geometry::IndexedGeometry& meshTwo ) { +template +bool isSameMeshWedge( const Ra::Core::Geometry::MultiIndexedGeometry& meshOne, + const Ra::Core::Geometry::MultiIndexedGeometry& meshTwo ) { using namespace Ra::Core; using namespace Ra::Core::Geometry; @@ -156,7 +156,8 @@ bool isSameMeshWedge( const Ra::Core::Geometry::IndexedGeometry& meshOne, if ( meshOne.vertices().size() != meshTwo.vertices().size() ) return false; if ( meshOne.normals().size() != meshTwo.normals().size() ) return false; - if ( meshOne.getIndices().size() != meshTwo.getIndices().size() ) return false; + if ( meshOne.indices().size() != meshTwo.indices().size() ) + return false; AlignedStdVector wedgesMeshOne; AlignedStdVector wedgesMeshTwo; @@ -169,12 +170,12 @@ bool isSameMeshWedge( const Ra::Core::Geometry::IndexedGeometry& meshOne, wedgesMeshTwo.push_back( wd ); } using namespace std::placeholders; - auto f1 = std::bind( - copyToWedgesVector, size, std::cref( meshOne ), std::ref( wedgesMeshOne ), _1 ); + auto f1 = + std::bind( copyToWedgesVector, size, std::cref( meshOne ), std::ref( wedgesMeshOne ), _1 ); meshOne.vertexAttribs().for_each_attrib( f1 ); - auto f2 = std::bind( - copyToWedgesVector, size, std::cref( meshTwo ), std::ref( wedgesMeshTwo ), _1 ); + auto f2 = + std::bind( copyToWedgesVector, size, std::cref( meshTwo ), std::ref( wedgesMeshTwo ), _1 ); meshTwo.vertexAttribs().for_each_attrib( f2 ); std::sort( wedgesMeshOne.begin(), wedgesMeshOne.end() ); @@ -206,10 +207,8 @@ bool isSameMeshWedge( const Ra::Core::Geometry::IndexedGeometry& meshOne, // std::cout << wedgesMeshTwo[i].m_idx << " : " << curIdx << "\n"; } - typename Ra::Core::Geometry::IndexedGeometry::IndexContainerType indices1 = - meshOne.getIndices(); - typename Ra::Core::Geometry::IndexedGeometry::IndexContainerType indices2 = - meshTwo.getIndices(); + typename IndexLayer::IndexContainerType indices1 = meshOne.indices(); + typename IndexLayer::IndexContainerType indices2 = meshTwo.indices(); for ( auto& face : indices1 ) { // std::cout << "face "; @@ -237,10 +236,11 @@ bool isSameMeshWedge( const Ra::Core::Geometry::IndexedGeometry& meshOne, } template -void testConverter1( const Ra::Core::Geometry::IndexedGeometry& mesh ) { +void testConverter1( const MultiIndexedGeometry& mesh ) { auto topologicalMesh = TopologicalMesh( mesh ); auto newMesh = topologicalMesh.toIndexedMesh(); - REQUIRE( ( isSameMesh( mesh, mesh.getIndices(), newMesh, newMesh.getIndices(), false ) ) ); + REQUIRE( ( isSameMesh( + mesh, mesh.template indices(), newMesh, newMesh.template indices(), false ) ) ); REQUIRE( topologicalMesh.checkIntegrity() ); }; @@ -264,12 +264,12 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To } SECTION( "Closed mesh" ) { - testConverter1( Ra::Core::Geometry::makeBox() ); - testConverter1( Ra::Core::Geometry::makeSharpBox() ); + testConverter1( Ra::Core::Geometry::makeBox2() ); + testConverter1( Ra::Core::Geometry::makeSharpBox2() ); } SECTION( "Mesh with boundaries" ) { - testConverter1( Ra::Core::Geometry::makePlaneGrid( 2, 2 ) ); + testConverter1( Ra::Core::Geometry::makePlaneGrid( 2, 2 ) ); } SECTION( "With user def attribs" ) { @@ -322,7 +322,10 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To auto topologicalMesh = TopologicalMesh( mesh ); auto newMesh = topologicalMesh.toTriangleMesh(); - REQUIRE( isSameMesh( mesh, mesh.getIndices(), newMesh, newMesh.getIndices() ) ); + REQUIRE( isSameMesh( mesh, + mesh.indices(), + newMesh, + newMesh.indices() ) ); REQUIRE( topologicalMesh.checkIntegrity() ); // oversize attrib not suported @@ -347,9 +350,12 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To TopologicalMesh::WedgeIndex { 0 }, getAttribName( VERTEX_NORMAL ), Vector3( 0, 0, 0 ) ); auto newMeshModified = topologicalMesh.toTriangleMesh(); - REQUIRE( isSameMesh( mesh, mesh.getIndices(), newMesh, newMesh.getIndices() ) ); - REQUIRE( isSameMeshWedge( mesh, newMesh ) ); - REQUIRE( !isSameMeshWedge( mesh, newMeshModified ) ); + REQUIRE( isSameMesh( mesh, + mesh.indices(), + newMesh, + newMesh.indices() ) ); + REQUIRE( isSameMeshWedge( mesh, newMesh ) ); + REQUIRE( !isSameMeshWedge( mesh, newMeshModified ) ); REQUIRE( topologicalMesh.checkIntegrity() ); } @@ -410,7 +416,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To mesh.setIndices( std::move( indices ) ); TopologicalMesh topo1 { mesh }; REQUIRE( topo1.checkIntegrity() ); - TriangleMesh mesh1 = topo1.toTriangleMesh(); + auto mesh1 = topo1.toTriangleMesh(); // there is no normals at all. REQUIRE( !topo1.has_halfedge_normals() ); @@ -427,7 +433,10 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To OpenMesh::FPropHandleT fProp; REQUIRE( mesh.vertexAttribs().hasSameAttribs( mesh1.vertexAttribs() ) ); - REQUIRE( isSameMesh( mesh, mesh.getIndices(), mesh1, mesh1.getIndices() ) ); + REQUIRE( isSameMesh( mesh, + mesh.indices(), + mesh1, + mesh1.indices() ) ); REQUIRE( mesh1.normals().size() == 0 ); } @@ -473,7 +482,7 @@ void test_split( TopologicalMesh& topo, TopologicalMesh::EdgeHandle eh, Scalar f } void test_poly() { - Ra::Core::Geometry::PolyMesh polyMesh; + MultiIndexedGeometry polyMesh; polyMesh.setVertices( { // quad { -1.1_ra, -0_ra, 0_ra }, @@ -518,12 +527,12 @@ void test_poly() { degen << 1, 0, 9, 10, 11, 12, 13, 14, 15, 16; auto degen2 = VectorNui( 10 ); degen2 << 14, 13, 12, 11, 10, 9, 17, 18, 16, 15; - polyMesh.setIndices( { quad, hepta, degen, degen2 } ); + polyMesh.set_indices( { quad, hepta, degen, degen2 } ); TopologicalMesh topologicalMesh; - topologicalMesh.initWithWedge( polyMesh, polyMesh.getLayerKey() ); + topologicalMesh.initWithWedge( polyMesh, polyMesh.default_layer_key() ); auto newMesh = topologicalMesh.toPolyMesh(); - REQUIRE( isSameMeshWedge( newMesh, polyMesh ) ); + REQUIRE( isSameMeshWedge( newMesh, polyMesh ) ); } TEST_CASE( "Core/Geometry/TopologicalMesh/PolyMesh", @@ -600,39 +609,39 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Manifold", auto buildMesh = []( const VectorArray& v, const VectorArray& n, const VectorArray& i ) { - TriangleMesh m; + MultiIndexedGeometry m; m.setVertices( v ); m.setNormals( n ); - auto& idx = m.getIndicesWithLock(); + auto [layer_key, idx] = m.indices_with_lock(); std::copy( i.begin(), i.end(), std::back_inserter( idx ) ); - m.indicesUnlock(); + m.unlockLayer( layer_key ); LOG( logINFO ) << " Built a mesh with " << m.vertices().size() << " vertices, " - << m.normals().size() << " normals and " << m.getIndices().size() - << " indices."; + << m.normals().size() << " normals and " + << m.indices().size() << " indices."; return m; }; // test if candidateMesh -> TopologicalMesh -> TriangleMesh isSameMesh than // referenceMesh, with and without the command. - auto testConverter = []( const TriangleMesh& referenceMesh, - const TriangleMesh& candidateMesh, + auto testConverter = []( const MultiIndexedGeometry& referenceMesh, + const MultiIndexedGeometry& candidateMesh, NonManifoldCommand1 command ) { // test with functor TopologicalMesh topoWithCommand { candidateMesh, command }; auto convertedMeshWithCommand = topoWithCommand.toTriangleMesh(); REQUIRE( isSameMesh( referenceMesh, - referenceMesh.getIndices(), + referenceMesh.indices(), convertedMeshWithCommand, - convertedMeshWithCommand.getIndices() ) ); + convertedMeshWithCommand.indices() ) ); // test without functor TopologicalMesh topoWithoutCommand { candidateMesh }; auto convertedMeshWithoutCommand = topoWithoutCommand.toTriangleMesh(); REQUIRE( isSameMesh( referenceMesh, - referenceMesh.getIndices(), + referenceMesh.indices(), convertedMeshWithoutCommand, - convertedMeshWithoutCommand.getIndices() ) ); + convertedMeshWithoutCommand.indices() ) ); return convertedMeshWithoutCommand; }; @@ -862,8 +871,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/MergeWedges", REQUIRE( topo.checkIntegrity() ); } -template -void testAttrib( const IndexedGeometry& mesh, const std::string& name, Scalar value ) { +void testAttrib( const MultiIndexedGeometry& mesh, const std::string& name, Scalar value ) { auto attribHandle = mesh.template getAttribHandle( name ); REQUIRE( attribHandle.idx().isValid() ); @@ -944,8 +952,8 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Triangulate", auto poly = topo.toPolyMesh(); REQUIRE( poly.vertices().size() == 4 ); - REQUIRE( poly.getIndices().size() == 1 ); - REQUIRE( poly.getIndices()[0].size() == 4 ); + REQUIRE( poly.indices().size() == 1 ); + REQUIRE( poly.indices()[0].size() == 4 ); testAttrib( poly, "test1", 0_ra ); testAttrib( poly, "test2", 3_ra ); testAttrib( poly, "test3", 3_ra ); @@ -954,9 +962,9 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Triangulate", topo.checkIntegrity(); auto tri = topo.toTriangleMesh(); REQUIRE( tri.vertices().size() == 4 ); - REQUIRE( tri.getIndices().size() == 2 ); - REQUIRE( tri.getIndices()[0].size() == 3 ); - REQUIRE( tri.getIndices()[1].size() == 3 ); + REQUIRE( tri.indices().size() == 2 ); + REQUIRE( tri.indices()[0].size() == 3 ); + REQUIRE( tri.indices()[1].size() == 3 ); testAttrib( tri, "test1", 0_ra ); testAttrib( tri, "test2", 3_ra ); testAttrib( tri, "test3", 3_ra ); From 513cf1be3738319688486a749b5986a3cb5a3cc2 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 08:00:14 +0200 Subject: [PATCH 088/144] [gui] Move gizmo todo to viewer (where it's instancied). --- src/Gui/Viewer/Gizmo/GizmoManager.cpp | 8 -------- src/Gui/Viewer/Viewer.cpp | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Gui/Viewer/Gizmo/GizmoManager.cpp b/src/Gui/Viewer/Gizmo/GizmoManager.cpp index 54af767f2c6..7b813ab5770 100644 --- a/src/Gui/Viewer/Gizmo/GizmoManager.cpp +++ b/src/Gui/Viewer/Gizmo/GizmoManager.cpp @@ -45,14 +45,6 @@ bool GizmoManager::isValidAction( const Gui::KeyMappingManager::KeyMappingAction return res; } -/* - * FIXME : Mathias -- Creating gizmos by default is not a good idea. - * implies that all applications developped on top of the engine will have them. - * This is not a good idea. Applications must be able to define and - * create their own gizmos - * - * \see issue #194 - */ GizmoManager::GizmoManager( QObject* parent ) : QObject( parent ), m_currentGizmoType( NONE ), m_mode( Gizmo::GLOBAL ) { m_gizmos[0].reset( new TranslateGizmo( Engine::Scene::SystemEntity::uiCmp(), diff --git a/src/Gui/Viewer/Viewer.cpp b/src/Gui/Viewer/Viewer.cpp index 2f032478a24..db267e2974e 100644 --- a/src/Gui/Viewer/Viewer.cpp +++ b/src/Gui/Viewer/Viewer.cpp @@ -506,6 +506,14 @@ bool Viewer::initializeGL() { } m_pendingRenderers.clear(); + /* + * \todo FIXME : Mathias -- Creating gizmos by default is not a good idea. + * implies that all applications developped on top of the engine will have them. + * This is not a good idea. Applications must be able to define and + * create their own gizmos + * + * \see issue #194 + */ // create the gizmo manager (Ui) createGizmoManager(); From 58e9d31eee254b90ecf9fe36c75111b3e0fe426c Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 08:01:09 +0200 Subject: [PATCH 089/144] [gui] Add todo to todo comment. --- src/Gui/Viewer/Gizmo/ScaleGizmo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp index c43cfab3a4f..7a726a954d2 100644 --- a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp @@ -66,7 +66,7 @@ ScaleGizmo::ScaleGizmo( Engine::Scene::Component* c, auto plane = Core::Geometry::makePlaneGrid( 1, 1, Core::Vector2( arrowFrac * arrowScale, arrowFrac * arrowScale ), T ); - // \FIXME this hack is here to be sure the plane will be selected (see shader) + ///\todo \FIXME this hack is here to be sure the plane will be selected (see shader) auto& normals = plane.normalsWithLock(); normals.getMap().fill( 0_ra ); plane.normalsUnlock(); From 7090cc0a17c742e037ea853f78be150e6d677090 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 08:17:25 +0200 Subject: [PATCH 090/144] [core] Fix MultiIndexGeometry append bad offset. --- src/Core/Geometry/IndexedGeometry.cpp | 5 ++--- src/Core/Geometry/IndexedGeometry.hpp | 4 ---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index 16252545edf..1a95f0c0f6b 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -58,7 +58,7 @@ void MultiIndexedGeometry::checkConsistency() const {} bool MultiIndexedGeometry::append( const MultiIndexedGeometry& other ) { - int offset = other.vertices().size(); + int offset = vertices().size(); // first append attribs AttribArrayGeometry::append( other ); @@ -72,7 +72,6 @@ bool MultiIndexedGeometry::append( const MultiIndexedGeometry& other ) { value.first, std::unique_ptr { value.second->clone() } ); dataHasBeenCopied = true; m_indices[key].second->offset( offset ); - ///\todo offest indices. (done ?) } else { // try to append to an existing layer: should always work @@ -91,7 +90,7 @@ bool MultiIndexedGeometry::append( const MultiIndexedGeometry& other ) { invalidateAabb(); notify(); } - return true; + return dataHasBeenCopied; } ////////////////////////////////////////////////////////////////////// diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index b818125a3bd..a32299627b1 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -688,10 +688,6 @@ bool GeometryIndexLayer::append( const GeometryIndexLayerBase& other, int off if ( shareSemantic( other ) ) { const auto& othercasted = static_cast&>( other ); - // m_collection.insert( - // m_collection.end(), othercasted.collection().begin(), othercasted.collection().end() - // ); - std::transform( othercasted.collection().cbegin(), othercasted.collection().cend(), std::back_inserter( m_collection ), From 11b450ffef6fe7c7710d8f76ccbb446246378f7d Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 08:17:58 +0200 Subject: [PATCH 091/144] [gizmo] Add empty line for readability. --- src/Gui/Viewer/Gizmo/ScaleGizmo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp index 7a726a954d2..344f2abbc35 100644 --- a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp @@ -41,6 +41,7 @@ ScaleGizmo::ScaleGizmo( Engine::Scene::Component* c, boxBounds.extend( Core::Vector3( radius * 2_ra, radius * 2_ra, radius * 2_ra ) ); boxBounds.translate( arrowScale * cylinderEnd ); auto box = Core::Geometry::makeSharpBox( boxBounds ); + cylinder.append( box ); std::shared_ptr mesh( From c01ae5cf19b74ed48c31ade33cf6e79cc7d58914 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 09:27:37 +0200 Subject: [PATCH 092/144] [engine] Remove Mesh component alias, everything is SurfaceMesh. --- src/Engine/Scene/GeometryComponent.cpp | 4 +- src/Engine/Scene/GeometryComponent.hpp | 84 +++++++++++++------------- src/Engine/Scene/GeometrySystem.cpp | 2 +- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/Engine/Scene/GeometryComponent.cpp b/src/Engine/Scene/GeometryComponent.cpp index 0193504f2b9..4f91ae13831 100644 --- a/src/Engine/Scene/GeometryComponent.cpp +++ b/src/Engine/Scene/GeometryComponent.cpp @@ -30,7 +30,7 @@ namespace Engine { namespace Scene { template <> -SurfaceMeshComponent::SurfaceMeshComponent( +SurfaceMeshComponentBase::SurfaceMeshComponentBase( const std::string& name, Entity* entity, Ra::Core::Geometry::MultiIndexedGeometry&& mesh, @@ -52,7 +52,7 @@ const Index* GeometryComponent::roIndexRead() const { } template <> -void SurfaceMeshComponent::generateMesh( +void SurfaceMeshComponentBase::generateMesh( const Ra::Core::Asset::GeometryData* data ) { m_contentName = data->getName(); m_displayMesh = Ra::Core::make_shared( m_contentName ); diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index 637b025380e..e3a9d06ebed 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -62,33 +62,33 @@ class RA_ENGINE_API GeometryComponent : public Component * - triangles: rw (if deformable) */ template -class SurfaceMeshComponent : public GeometryComponent +class SurfaceMeshComponentBase : public GeometryComponent { using base = GeometryComponent; public: using RenderMeshType = typename Data::RenderMeshType::getType::Type; - inline SurfaceMeshComponent( const std::string& name, - Entity* entity, - const Ra::Core::Asset::GeometryData* data ); - inline SurfaceMeshComponent( const std::string& name, - Entity* entity, - std::shared_ptr data ); + inline SurfaceMeshComponentBase( const std::string& name, + Entity* entity, + const Ra::Core::Asset::GeometryData* data ); + inline SurfaceMeshComponentBase( const std::string& name, + Entity* entity, + std::shared_ptr data ); /*! * Constructor from an existing mesh * \warning Moves the mesh and takes its ownership */ - inline SurfaceMeshComponent( const std::string& name, - Entity* entity, - CoreMeshType&& mesh, - Core::Asset::MaterialData* mat = nullptr ); - inline SurfaceMeshComponent( const std::string& name, - Entity* entity, - CoreMeshType&& mesh, - std::shared_ptr mat ); - ~SurfaceMeshComponent() override = default; + inline SurfaceMeshComponentBase( const std::string& name, + Entity* entity, + CoreMeshType&& mesh, + Core::Asset::MaterialData* mat = nullptr ); + inline SurfaceMeshComponentBase( const std::string& name, + Entity* entity, + CoreMeshType&& mesh, + std::shared_ptr mat ); + ~SurfaceMeshComponentBase() override = default; /// Returns the current display geometry. inline const CoreMeshType& getCoreGeometry() const; @@ -116,10 +116,7 @@ class SurfaceMeshComponent : public GeometryComponent std::shared_ptr m_displayMesh { nullptr }; }; -using TriangleMeshComponent = SurfaceMeshComponent; -using GeometryDisplayableComponent = SurfaceMeshComponent; -using QuadMeshComponent = SurfaceMeshComponent; -using PolyMeshComponent = SurfaceMeshComponent; +using SurfaceMeshComponent = SurfaceMeshComponentBase; /// \warning, WIP /// \todo doc. @@ -218,7 +215,7 @@ class RA_ENGINE_API VolumeComponent : public Component }; template -SurfaceMeshComponent::SurfaceMeshComponent( +SurfaceMeshComponentBase::SurfaceMeshComponentBase( const std::string& name, Entity* entity, const Ra::Core::Asset::GeometryData* data ) : @@ -227,25 +224,27 @@ SurfaceMeshComponent::SurfaceMeshComponent( } template <> -RA_ENGINE_API SurfaceMeshComponent::SurfaceMeshComponent( +RA_ENGINE_API +SurfaceMeshComponentBase::SurfaceMeshComponentBase( const std::string& name, Entity* entity, Ra::Core::Geometry::MultiIndexedGeometry&& mesh, Core::Asset::MaterialData* mat ); template -SurfaceMeshComponent::SurfaceMeshComponent( const std::string& name, - Entity* entity, - std::shared_ptr data ) : +SurfaceMeshComponentBase::SurfaceMeshComponentBase( + const std::string& name, + Entity* entity, + std::shared_ptr data ) : GeometryComponent( name, entity ), m_displayMesh( data ) { finalizeROFromGeometry( convertMatdataToMaterial( nullptr ), Core::Transform::Identity() ); } template -SurfaceMeshComponent::SurfaceMeshComponent( const std::string& name, - Entity* entity, - CoreMeshType&& mesh, - Core::Asset::MaterialData* mat ) : +SurfaceMeshComponentBase::SurfaceMeshComponentBase( const std::string& name, + Entity* entity, + CoreMeshType&& mesh, + Core::Asset::MaterialData* mat ) : GeometryComponent( name, entity ), m_displayMesh( new RenderMeshType( name, std::move( mesh ) ) ) { setContentName( name ); @@ -253,7 +252,7 @@ SurfaceMeshComponent::SurfaceMeshComponent( const std::string& nam } template -SurfaceMeshComponent::SurfaceMeshComponent( +SurfaceMeshComponentBase::SurfaceMeshComponentBase( const std::string& name, Entity* entity, CoreMeshType&& mesh, @@ -264,7 +263,8 @@ SurfaceMeshComponent::SurfaceMeshComponent( finalizeROFromGeometry( mat, Core::Transform::Identity() ); } template -void SurfaceMeshComponent::generateMesh( const Ra::Core::Asset::GeometryData* data ) { +void SurfaceMeshComponentBase::generateMesh( + const Ra::Core::Asset::GeometryData* data ) { m_contentName = data->getName(); m_displayMesh = Ra::Core::make_shared( m_contentName ); CoreMeshType mesh = Data::createCoreMeshFromGeometryData( data ); @@ -277,11 +277,11 @@ void SurfaceMeshComponent::generateMesh( const Ra::Core::Asset::Ge } template <> -RA_ENGINE_API void SurfaceMeshComponent::generateMesh( +RA_ENGINE_API void SurfaceMeshComponentBase::generateMesh( const Ra::Core::Asset::GeometryData* data ); template -std::shared_ptr SurfaceMeshComponent::convertMatdataToMaterial( +std::shared_ptr SurfaceMeshComponentBase::convertMatdataToMaterial( const Core::Asset::MaterialData* data ) { // The technique for rendering this component std::shared_ptr roMaterial; @@ -302,7 +302,7 @@ std::shared_ptr SurfaceMeshComponent::convertMatda } template -void SurfaceMeshComponent::finalizeROFromGeometry( +void SurfaceMeshComponentBase::finalizeROFromGeometry( std::shared_ptr roMaterial, Core::Transform transform ) { @@ -329,25 +329,25 @@ void SurfaceMeshComponent::finalizeROFromGeometry( #endif template -const CoreMeshType& SurfaceMeshComponent::getCoreGeometry() const { +const CoreMeshType& SurfaceMeshComponentBase::getCoreGeometry() const { CHECK_MESH_NOT_NULL; return m_displayMesh->getCoreGeometry(); } template -typename SurfaceMeshComponent::RenderMeshType* -SurfaceMeshComponent::getDisplayable() { +typename SurfaceMeshComponentBase::RenderMeshType* +SurfaceMeshComponentBase::getDisplayable() { CHECK_MESH_NOT_NULL; return m_displayMesh.get(); } template -void SurfaceMeshComponent::setupIO( const std::string& id ) { +void SurfaceMeshComponentBase::setupIO( const std::string& id ) { CHECK_MESH_NOT_NULL; const auto& cm = ComponentMessenger::getInstance(); - auto cbOut = std::bind( &SurfaceMeshComponent::getMeshOutput, this ); - auto cbRw = std::bind( &SurfaceMeshComponent::getMeshRw, this ); + auto cbOut = std::bind( &SurfaceMeshComponentBase::getMeshOutput, this ); + auto cbRw = std::bind( &SurfaceMeshComponentBase::getMeshRw, this ); cm->registerOutput( getEntity(), this, id, cbOut ); cm->registerReadWrite( getEntity(), this, id, cbRw ); @@ -362,13 +362,13 @@ void SurfaceMeshComponent::setupIO( const std::string& id ) { } template -const CoreMeshType* SurfaceMeshComponent::getMeshOutput() const { +const CoreMeshType* SurfaceMeshComponentBase::getMeshOutput() const { CHECK_MESH_NOT_NULL; return &m_displayMesh->getCoreGeometry(); } template -CoreMeshType* SurfaceMeshComponent::getMeshRw() { +CoreMeshType* SurfaceMeshComponentBase::getMeshRw() { CHECK_MESH_NOT_NULL; return &( m_displayMesh->getCoreGeometry() ); } diff --git a/src/Engine/Scene/GeometrySystem.cpp b/src/Engine/Scene/GeometrySystem.cpp index 0d757e39406..23fac9a7a42 100644 --- a/src/Engine/Scene/GeometrySystem.cpp +++ b/src/Engine/Scene/GeometrySystem.cpp @@ -33,7 +33,7 @@ void GeometrySystem::handleAssetLoading( Entity* entity, case Ra::Core::Asset::GeometryData::QUAD_MESH: case Ra::Core::Asset::GeometryData::TRI_MESH: case Ra::Core::Asset::GeometryData::POLY_MESH: - comp = new GeometryDisplayableComponent( componentName, entity, data ); + comp = new SurfaceMeshComponent( componentName, entity, data ); break; case Ra::Core::Asset::GeometryData::TETRA_MESH: case Ra::Core::Asset::GeometryData::HEX_MESH: From 6cacd420a41f1bd95965be6eb86835896e966d52 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 09:28:39 +0200 Subject: [PATCH 093/144] [examples] Update according to SurfaceMeshComponent. --- examples/CustomCameraManipulator/main.cpp | 2 +- .../DrawPrimitives/AllPrimitivesComponent.cpp | 39 +++++++++++++++++++ examples/EntityAnimation/main.cpp | 4 +- examples/EnvMap/main.cpp | 2 +- examples/HelloRadium/main.cpp | 4 +- examples/KeyEvent/main.cpp | 8 ++-- examples/Picking/main.cpp | 2 +- examples/RawShaderMaterial/main.cpp | 3 +- examples/SimpleAnimation/main.cpp | 10 ++--- examples/SimpleSkinning/main.cpp | 2 +- examples/TexturedQuad/main.cpp | 2 +- examples/TexturedQuadDynamic/main.cpp | 2 +- examples/Volume/main.cpp | 4 +- 13 files changed, 61 insertions(+), 23 deletions(-) diff --git a/examples/CustomCameraManipulator/main.cpp b/examples/CustomCameraManipulator/main.cpp index 5f73388884d..daca836a68e 100644 --- a/examples/CustomCameraManipulator/main.cpp +++ b/examples/CustomCameraManipulator/main.cpp @@ -52,7 +52,7 @@ int main( int argc, char* argv[] ) { //! [Create a geometry component with the cube] auto c = - new Ra::Engine::Scene::TriangleMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); + new Ra::Engine::Scene::SurfaceMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); //! [Create a geometry component with the cube] //! [Register the entity/component association to the geometry system ] diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index 60f093a3ef0..3d6afc5d0ce 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -1102,6 +1102,7 @@ void AllPrimitivesComponent::initialize() { { auto geom = makeParametricTorus<32, 12>( .1_ra, .05_ra, Color::White(), true ); + auto texTorusMesh = make_shared( "Textured Torus", std::move( geom ) ); auto texTorus = RenderObject::createRenderObject( @@ -1189,4 +1190,42 @@ void AllPrimitivesComponent::initialize() { strip->setMaterial( plainMaterial ); addRenderObject( strip ); } + { + updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); + updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); + + constexpr Scalar arrowScale = .1_ra; + constexpr Scalar axisWidth = .05_ra; + constexpr Scalar arrowFrac = .125_ra; + constexpr Scalar radius = arrowScale * axisWidth / 2_ra; + + Core::Vector3 cylinderEnd = Core::Vector3::Zero(); + cylinderEnd[1] = ( 1_ra - arrowFrac ); + + auto startPoint = cellCorner + offsetVec; + + auto cylinder = Core::Geometry::makeCylinder( Core::Vector3::Zero() + startPoint, + arrowScale * cylinderEnd + startPoint, + radius, + 4, + 4, + Color::Magenta() ); + + Core::Aabb boxBounds; + boxBounds.extend( Core::Vector3( -radius * 2_ra, -radius * 2_ra, -radius * 2_ra ) ); + boxBounds.extend( Core::Vector3( radius * 2_ra, radius * 2_ra, radius * 2_ra ) ); + boxBounds.translate( arrowScale * cylinderEnd + startPoint ); + auto box = Core::Geometry::makeSharpBox( boxBounds, Color::Yellow() ); + + cylinder.append( box ); + + std::shared_ptr mesh( + new Engine::Data::GeometryDisplayable( "Scale Gizmo Arrow" ) ); + mesh->loadGeometry( std::move( cylinder ) ); + + auto arrowDrawable = RenderObject::createRenderObject( + "Scale Gizmo Arrow", this, Engine::Rendering::RenderObjectType::Geometry, mesh, {} ); + arrowDrawable->setMaterial( plainMaterial ); + addRenderObject( arrowDrawable ); + } } diff --git a/examples/EntityAnimation/main.cpp b/examples/EntityAnimation/main.cpp index ba7a1cbc1fb..8911e5ed02b 100644 --- a/examples/EntityAnimation/main.cpp +++ b/examples/EntityAnimation/main.cpp @@ -119,7 +119,7 @@ int main( int argc, char* argv[] ) { //! [Create a geometry component with the cube] // component ownership is transfered to entity in component ctor - new Scene::TriangleMeshComponent( "Fixed cube geometry", e, std::move( cube ), nullptr ); + new Scene::SurfaceMeshComponent( "Fixed cube geometry", e, std::move( cube ), nullptr ); //! [Create a geometry component with the cube] } //! [Create the demo fixed entity/component] @@ -141,7 +141,7 @@ int main( int argc, char* argv[] ) { // an animated yellow cube auto cube = Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f }, Ra::Core::Utils::Color::Yellow() ); - new Scene::TriangleMeshComponent( "Fixed cube geometry", e, std::move( cube ), nullptr ); + new Scene::SurfaceMeshComponent( "Fixed cube geometry", e, std::move( cube ), nullptr ); // an animated camera, thay is not the one active at startup. Use key '0' to activate auto camera = new Scene::CameraComponent( e, "Animated Camera" ); diff --git a/examples/EnvMap/main.cpp b/examples/EnvMap/main.cpp index 5f8579a58b1..d2621738ba3 100644 --- a/examples/EnvMap/main.cpp +++ b/examples/EnvMap/main.cpp @@ -87,7 +87,7 @@ int main( int argc, char* argv[] ) { //! [Create the engine entity for the cube] //! [Create a geometry component with the cube] - new Ra::Engine::Scene::TriangleMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); + new Ra::Engine::Scene::SurfaceMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); //! [Create a geometry component with the cube] //! [Place the camera away from the cube] diff --git a/examples/HelloRadium/main.cpp b/examples/HelloRadium/main.cpp index c7461ae86df..818bf6072c2 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::GeometryDisplayableComponent( - "Cube Mesh", e, std::move( cube ), nullptr ); + auto c = + new Ra::Engine::Scene::SurfaceMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); //! [Create a geometry component with the cube] //! [Register the entity/component association to the geometry system ] diff --git a/examples/KeyEvent/main.cpp b/examples/KeyEvent/main.cpp index db8c29a4533..97781d5a181 100644 --- a/examples/KeyEvent/main.cpp +++ b/examples/KeyEvent/main.cpp @@ -74,19 +74,19 @@ class DemoWindow : public Ra::Gui::SimpleWindow //! [Manage KeyEvent reaching the window] /// Custom Key event management method void colorup() { - auto& mesh = dynamic_cast( + auto& mesh = dynamic_cast( m_obj->getMesh()->getAbstractGeometry() ); m_colIdx = ( m_colIdx + 1 ) % 10; mesh.colorize( m_colors[m_colIdx] ); } void colordown() { - auto& mesh = dynamic_cast( + auto& mesh = dynamic_cast( m_obj->getMesh()->getAbstractGeometry() ); m_colIdx = ( m_colIdx + 9 ) % 10; mesh.colorize( m_colors[m_colIdx] ); } void colorreset() { - auto& mesh = dynamic_cast( + auto& mesh = dynamic_cast( m_obj->getMesh()->getAbstractGeometry() ); m_colIdx = 0; mesh.colorize( m_colors[m_colIdx] ); @@ -150,7 +150,7 @@ int main( int argc, char* argv[] ) { //! [Create a geometry component with the cube] auto c = - new Ra::Engine::Scene::TriangleMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); + new Ra::Engine::Scene::SurfaceMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); //! [Create a geometry component with the cube] //! [Register the entity/component association to the geometry system ] diff --git a/examples/Picking/main.cpp b/examples/Picking/main.cpp index 76182636392..b06fac48523 100644 --- a/examples/Picking/main.cpp +++ b/examples/Picking/main.cpp @@ -122,7 +122,7 @@ void addDummyScene( Ra::Gui::BaseApplication& app ) { auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); auto e = app.m_engine->getEntityManager()->createEntity( "Cube" ); auto c = - new Ra::Engine::Scene::TriangleMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); + new Ra::Engine::Scene::SurfaceMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); auto geometrySystem = app.m_engine->getSystem( "GeometrySystem" ); geometrySystem->addComponent( e, c ); diff --git a/examples/RawShaderMaterial/main.cpp b/examples/RawShaderMaterial/main.cpp index 3bb42665a64..49b8f91f00c 100644 --- a/examples/RawShaderMaterial/main.cpp +++ b/examples/RawShaderMaterial/main.cpp @@ -105,8 +105,7 @@ std::shared_ptr initQuad( Ra::Gui::BaseAppl Ra::Core::Asset::RawShaderMaterialData mat { "Quad Material", _config1, paramProvider }; //! [Create a geometry component using the custom material] - auto c = - new Ra::Engine::Scene::TriangleMeshComponent( "Quad Mesh", e, std::move( quad ), &mat ); + auto c = new Ra::Engine::Scene::SurfaceMeshComponent( "Quad Mesh", e, std::move( quad ), &mat ); //! [Register the entity/component association to the geometry system ] auto system = app.m_engine->getSystem( "GeometrySystem" ); diff --git a/examples/SimpleAnimation/main.cpp b/examples/SimpleAnimation/main.cpp index 19b8b8a74de..502764183fe 100644 --- a/examples/SimpleAnimation/main.cpp +++ b/examples/SimpleAnimation/main.cpp @@ -39,7 +39,7 @@ * - Add the animation component to the animation system * */ -class KeyFramedGeometryComponent : public Ra::Engine::Scene::TriangleMeshComponent +class KeyFramedGeometryComponent : public Ra::Engine::Scene::SurfaceMeshComponent { public: /*! @@ -49,10 +49,10 @@ class KeyFramedGeometryComponent : public Ra::Engine::Scene::TriangleMeshCompone inline KeyFramedGeometryComponent( const std::string& name, Ra::Engine::Scene::Entity* entity, Ra::Core::Geometry::TriangleMesh&& mesh ) : - Ra::Engine::Scene::TriangleMeshComponent( name, - entity, - std::move( mesh ), - new Ra::Core::Asset::BlinnPhongMaterialData {} ), + Ra::Engine::Scene::SurfaceMeshComponent( name, + entity, + std::move( mesh ), + new Ra::Core::Asset::BlinnPhongMaterialData {} ), m_transform( 0_ra, Ra::Core::Transform::Identity() ) { //! [Creating the transform KeyFrames] Ra::Core::Transform T = Ra::Core::Transform::Identity(); diff --git a/examples/SimpleSkinning/main.cpp b/examples/SimpleSkinning/main.cpp index ef0da15ac66..6d38af287c6 100644 --- a/examples/SimpleSkinning/main.cpp +++ b/examples/SimpleSkinning/main.cpp @@ -91,7 +91,7 @@ void setupScene( Ra::Engine::RadiumEngine* engine ) { // component ownership is transfered to entity in component ctor auto meshComponent = - new TriangleMeshComponent( "Cylinder", entity, std::move( cylinder ), nullptr ); + new SurfaceMeshComponent( "Cylinder", entity, std::move( cylinder ), nullptr ); // create a squeleton with three bones. std::map boneMatrices; diff --git a/examples/TexturedQuad/main.cpp b/examples/TexturedQuad/main.cpp index c64e87c7910..40d32c7402d 100644 --- a/examples/TexturedQuad/main.cpp +++ b/examples/TexturedQuad/main.cpp @@ -53,7 +53,7 @@ int main( int argc, char* argv[] ) { textureHandle ); // the entity get's this new component ownership. A bit wired since hidden in ctor. - new Ra::Engine::Scene::TriangleMeshComponent( "Quad Mesh", e, std::move( quad ), material ); + new Ra::Engine::Scene::SurfaceMeshComponent( "Quad Mesh", e, std::move( quad ), material ); //! [Create an entity and component to draw or data] app.m_mainWindow->prepareDisplay(); diff --git a/examples/TexturedQuadDynamic/main.cpp b/examples/TexturedQuadDynamic/main.cpp index f16e3f24772..00d9d5dc2b7 100644 --- a/examples/TexturedQuadDynamic/main.cpp +++ b/examples/TexturedQuadDynamic/main.cpp @@ -58,7 +58,7 @@ int main( int argc, char* argv[] ) { material->setSpecularColor( Ra::Core::Utils::Color::Black() ); // the entity get's this new component ownership. a bit wired since hidden in ctor. - new Ra::Engine::Scene::TriangleMeshComponent( "Quad Mesh", e, std::move( quad ), material ); + new Ra::Engine::Scene::SurfaceMeshComponent( "Quad Mesh", e, std::move( quad ), material ); //! [Create an entity and component to draw or data] //! [Tell the window that something is to be displayed] diff --git a/examples/Volume/main.cpp b/examples/Volume/main.cpp index 1c276836271..37083eb6830 100644 --- a/examples/Volume/main.cpp +++ b/examples/Volume/main.cpp @@ -86,7 +86,7 @@ int main( int argc, char* argv[] ) { //! [Create a geometry component with the cube] auto cc = - new Ra::Engine::Scene::TriangleMeshComponent( "Cube Mesh", ce, std::move( cube ), nullptr ); + new Ra::Engine::Scene::SurfaceMeshComponent( "Cube Mesh", ce, std::move( cube ), nullptr ); //! [Create a geometry component with the cube] //! [Register the entity/component association to the geometry system ] @@ -125,7 +125,7 @@ int main( int argc, char* argv[] ) { //! [Create a geometry component with the cube] auto cc = - new Ra::Engine::Scene::TriangleMeshComponent( "Cube Mesh", ce, std::move( cube ), nullptr ); + new Ra::Engine::Scene::SurfaceMeshComponent( "Cube Mesh", ce, std::move( cube ), nullptr ); //! [Create a geometry component with the cube] //! [Register the entity/component association to the geometry system ] From e19aac590c9177d182283d6586e5b04de5ee19c6 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 09:29:05 +0200 Subject: [PATCH 094/144] [doc] Wip update mesh documentation. --- doc/concepts/mesh.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/concepts/mesh.md b/doc/concepts/mesh.md index 9f7b3a22da3..da9c16b5ca9 100644 --- a/doc/concepts/mesh.md +++ b/doc/concepts/mesh.md @@ -3,6 +3,7 @@ # Geometry types +(todo update according to MultiIndexedGeometry) There is three kind of geometry representation included in radium source : 1. Ra::Core::Geometry::*, which handles geometry data and connectivity as a indexed vertex array. @@ -10,6 +11,7 @@ Each vertex is a unique set of position, normal, and other attributes. If indexed, faces are defined with VectorXui, where X is 1 for point, 2 for lines, 3 for triangles, and N for polygons. See inheritance diagram of Ra::Core::Geometry::AbstractGeometry : - Ra::Core::Geometry::AttribArrayGeometry + - Ra::Core::Geometry::MultiIndexedGeometry* - Ra::Core::Geometry::IndexedGeometry - Ra::Core::Geometry::LineStrip * - Ra::Core::Geometry::PointCloud * @@ -20,14 +22,12 @@ See inheritance diagram of Ra::Core::Geometry::AbstractGeometry : 2. Ra::Core::Geometry::TopologicalMesh, which is an half-edge data structure. A converter allows to go back and forth to `TriangleMesh` without loss of data, but during the conversion, vertices with the same position represents the same topological point (and are hence merged). -**Soon deprecated:** The other vertex attributes are stored on half-edges (to manage multiple normals per 3D positions -for instance). -**New:** The other vertex attributes are stored on wedges. Each half-edge has one wedge index. If multiple half-edge have the same set of attributes (including vertex position) they have the same wedge index at construction. See section [wedges](#wedges) below. +The other vertex attributes are stored on wedges. Each half-edge has one wedge index. If multiple half-edge have the same set of attributes (including vertex position) they have the same wedge index at construction. See section [wedges](#wedges) below. 3. Ra::Engine::Data::*, which stores a Core Geometry to handle 3D data, and manages the rendering aspect of it (VAO, VBO, draw call). See inheritance diagram of Ra::Engine::Data::AttribArrayDisplayable - Ra::Engine::Data::Displayable - Ra::Engine::Data::AttribArrayDisplayable - - Ra::Engine::Data::CoreGeometryDisplayable + - Ra::Engine::Data::GeometryDisplayable * - Ra::Engine::Data::PointCloud * - Ra::Engine::Data::IndexedGeometry - Ra::Engine::Data::IndexedAttribArrayDisplayable From 61bfde5c51ffc6fa5d42e1e4350ae938e7c4fb7d Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 21:37:53 +0200 Subject: [PATCH 095/144] [core][engine] Move triangulate function in Helper namespace. --- src/Core/Geometry/IndexedGeometry.hpp | 4 ++-- src/Engine/Data/Mesh.cpp | 4 ++-- src/Engine/Data/Mesh.hpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index a32299627b1..265f0d1c301 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -13,7 +13,7 @@ namespace Ra { namespace Core { namespace Geometry { - +namespace Helper { template VectorArray triangulate( const VectorArray& in ) { VectorArray out; @@ -51,7 +51,7 @@ inline VectorArray triangulate( const VectorArray& in ) { } return out; } - +} /** * \brief Base class for index collections stored in MultiIndexedGeometry. */ diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index f314e5eccb1..8fc4add4474 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -194,7 +194,7 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m const auto& quadLayer = dynamic_cast( layer ); auto triangleLayer = std::make_unique(); - triangleLayer->collection() = Core::Geometry::triangulate( quadLayer.collection() ); + triangleLayer->collection() = Core::Geometry::Helper::triangulate( quadLayer.collection() ); LayerKeyType triangleKey = { triangleLayer->semantics(), "triangulation" }; auto layerAdded = m_geom.addLayer( std::move( triangleLayer ), false, "triangulation" ); @@ -213,7 +213,7 @@ void GeometryDisplayable::loadGeometry( Core::Geometry::MultiIndexedGeometry&& m dynamic_cast( m_geom.getLayer( key ) ); auto triangleLayer = std::make_unique(); - triangleLayer->collection() = Core::Geometry::triangulate( polyLayer.collection() ); + triangleLayer->collection() = Core::Geometry::Helper::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"; } diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 89a140f32f5..49d062c2b14 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -1002,7 +1002,7 @@ void GeneralMesh::updateGL_specific_impl() { this->m_indicesDirty = true; } if ( this->m_indicesDirty ) { - m_triangleIndices = Core::Geometry::triangulate( this->m_mesh.getIndices() ); + m_triangleIndices = Core::Geometry::Helper::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 ); From 92967e3d82e4d88b360837ce11aaa19b174784aa Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 21:38:56 +0200 Subject: [PATCH 096/144] [core] Add a triangulate method that create a triangle layer. --- src/Core/Geometry/IndexedGeometry.hpp | 143 ++++++++++++++------------ 1 file changed, 78 insertions(+), 65 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 265f0d1c301..af258525199 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -153,6 +153,71 @@ struct GeometryIndexLayer : public GeometryIndexLayerBase { DECLARE_INDEX_LAYER( InvalidIndexLayer, Vector1ui ); +/** + * \name Predefined index layers + * The use of these layers helps in generic management of geometries + * \{ + */ +/// \brief Index layer for a point cloud +OPEN_DECLARATION_INDEX_LAYER( PointCloudIndexLayer, Vector1ui ) + +/// \brief Constructor of an index layer with linearly spaced indices ranging from \f$0\f$ to +/// \f$n-1\f$ +inline explicit PointCloudIndexLayer( size_t n ) : + GeometryIndexLayer( PointCloudIndexLayer::staticSemanticName ) { + collection().resize( n ); + collection().getMap() = IndexContainerType::Matrix::LinSpaced( n, 0, n - 1 ); +} + +/// \brief Generate linearly spaced indices with same size as \p attr vertex buffer +void linearIndices( const AttribArrayGeometry& attr ) { + auto nbVert = attr.vertices().size(); + collection().resize( nbVert ); + collection().getMap() = IndexContainerType::Matrix::LinSpaced( nbVert, 0, nbVert - 1 ); +} + +}; + +/** + * \brief Index layer for triangle mesh. + * + * \note, This layer ensures that all faces have exactly 3 vertices. + */ +DECLARE_INDEX_LAYER( TriangleIndexLayer, Vector3ui ) + +/** + * \brief Index layer for quadrilateral mesh. + * + * \note, This layer ensures that all faces have exactly 4 vertices + */ +DECLARE_INDEX_LAYER( QuadIndexLayer, Vector4ui ) + +/** + * \brief Index layer for polygonal mesh. + * + * \note, Using this layer, all faces might have more than 4 vertices or have different number of + * vertices. + */ +DECLARE_INDEX_LAYER( PolyIndexLayer, VectorNui ) + +/** one Ni index -> one strip */ +DECLARE_INDEX_LAYER( StripOrFanIndexLayer, VectorNui ) + +/** + * \brief Index layer for line mesh. + * + * \note, This layer ensures that all faces have exactly 2 vertices + */ +DECLARE_INDEX_LAYER( LineIndexLayer, Vector2ui ) + +/** + * \} + */ + +#undef INDEX_LAYER_CLONE_IMPLEMENTATION +#undef OPEN_DECLARATION_INDEX_LAYER +#undef DECLARE_INDEX_LAYER + /** * \brief AbstractGeometry with per-vertex attributes and layers of indices. * Each layer represents a different topology or indexing logic, e.g. triangle/line/quad @@ -464,6 +529,19 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util return static_cast( result.second ).collection(); } + template + LayerKeyType triangulate() { + if ( !containsLayer( TriangleIndexLayer::staticSemanticName ) ) { + auto result = getFirstLayerOccurrence( IndexLayer::staticSemanticName ); + auto& layer = static_cast( result.second ).collection(); + + auto triangle_layer = std::make_unique(); + triangle_layer->collection() = Helper::triangulate( layer ); + return addLayer( std::move( triangle_layer ) ).second; + } + return getFirstLayerOccurrence( TriangleIndexLayer::staticSemanticName ).first; + } + template auto indices_with_lock() { auto itr = getFirstLayerIteratorWithLock( IndexLayer::staticSemanticName ); @@ -547,71 +625,6 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util LayerKeyType m_default_layer_key { { InvalidIndexLayer::staticSemanticName }, "invalid" }; }; -/** - * \name Predefined index layers - * The use of these layers helps in generic management of geometries - * \{ - */ -/// \brief Index layer for a point cloud -OPEN_DECLARATION_INDEX_LAYER( PointCloudIndexLayer, Vector1ui ) - -/// \brief Constructor of an index layer with linearly spaced indices ranging from \f$0\f$ to -/// \f$n-1\f$ -inline explicit PointCloudIndexLayer( size_t n ) : - GeometryIndexLayer( PointCloudIndexLayer::staticSemanticName ) { - collection().resize( n ); - collection().getMap() = IndexContainerType::Matrix::LinSpaced( n, 0, n - 1 ); -} - -/// \brief Generate linearly spaced indices with same size as \p attr vertex buffer -void linearIndices( const AttribArrayGeometry& attr ) { - auto nbVert = attr.vertices().size(); - collection().resize( nbVert ); - collection().getMap() = IndexContainerType::Matrix::LinSpaced( nbVert, 0, nbVert - 1 ); -} - -}; - -/** - * \brief Index layer for triangle mesh. - * - * \note, This layer ensures that all faces have exactly 3 vertices. - */ -DECLARE_INDEX_LAYER( TriangleIndexLayer, Vector3ui ) - -/** - * \brief Index layer for quadrilateral mesh. - * - * \note, This layer ensures that all faces have exactly 4 vertices - */ -DECLARE_INDEX_LAYER( QuadIndexLayer, Vector4ui ) - -/** - * \brief Index layer for polygonal mesh. - * - * \note, Using this layer, all faces might have more than 4 vertices or have different number of - * vertices. - */ -DECLARE_INDEX_LAYER( PolyIndexLayer, VectorNui ) - -/** one Ni index -> one strip */ -DECLARE_INDEX_LAYER( StripOrFanIndexLayer, VectorNui ) - -/** - * \brief Index layer for line mesh. - * - * \note, This layer ensures that all faces have exactly 2 vertices - */ -DECLARE_INDEX_LAYER( LineIndexLayer, Vector2ui ) - -/** - * \} - */ - -#undef INDEX_LAYER_CLONE_IMPLEMENTATION -#undef OPEN_DECLARATION_INDEX_LAYER -#undef DECLARE_INDEX_LAYER - /** * \brief A single layer MultiIndexedGeometry. * From a27b9abfdd3654888cdda149feee0b90f64b3db0 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 21:39:46 +0200 Subject: [PATCH 097/144] [core] Add some constness (and const overload) to topomesh. --- src/Core/Geometry/TopologicalMesh.cpp | 7 +++--- src/Core/Geometry/TopologicalMesh.hpp | 32 +++++++++++++++++++++------ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/Core/Geometry/TopologicalMesh.cpp b/src/Core/Geometry/TopologicalMesh.cpp index 41c907837c3..419e9c8db8d 100644 --- a/src/Core/Geometry/TopologicalMesh.cpp +++ b/src/Core/Geometry/TopologicalMesh.cpp @@ -186,7 +186,7 @@ TopologicalMesh::TopologicalMesh() { add_property( m_wedgeIndexPph ); } -void TopologicalMesh::updateTriangleMesh( Ra::Core::Geometry::MultiIndexedGeometry& out ) { +void TopologicalMesh::updateTriangleMesh( Ra::Core::Geometry::MultiIndexedGeometry& out ) const { TriangleMesh::PointAttribHandle::Container wedgePosition; AlignedStdVector::Container> wedgeFloatAttribData( m_wedges.m_floatAttribNames.size() ); @@ -215,7 +215,7 @@ void TopologicalMesh::updateTriangleMesh( Ra::Core::Geometry::MultiIndexedGeomet } void TopologicalMesh::updateTriangleMeshNormals( - AttribArrayGeometry::NormalAttribHandle::Container& normals ) { + AttribArrayGeometry::NormalAttribHandle::Container& normals ) const { if ( !has_halfedge_normals() ) { LOG( logERROR ) << "TopologicalMesh has no normals, nothing set"; return; @@ -226,7 +226,8 @@ void TopologicalMesh::updateTriangleMeshNormals( } } -void TopologicalMesh::updateTriangleMeshNormals( Ra::Core::Geometry::MultiIndexedGeometry& out ) { +void TopologicalMesh::updateTriangleMeshNormals( + Ra::Core::Geometry::MultiIndexedGeometry& out ) const { auto& normals = out.normalsWithLock(); updateTriangleMeshNormals( normals ); out.normalsUnlock(); diff --git a/src/Core/Geometry/TopologicalMesh.hpp b/src/Core/Geometry/TopologicalMesh.hpp index 6089ce3e7b1..69d8e29a850 100644 --- a/src/Core/Geometry/TopologicalMesh.hpp +++ b/src/Core/Geometry/TopologicalMesh.hpp @@ -152,9 +152,10 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT void copyWedgeDataToAttribContainer( AlignedStdVector::Container>& c, - const VectorArray& wd ) { + const VectorArray& wd ) const { for ( size_t i = 0; i < wd.size(); ++i ) { c[i].push_back( wd[i] ); } } template - void moveContainerToMesh( Ra::Core::Geometry::MultiIndexedGeometry& out, - const std::vector& names, - AlignedStdVector::Container>& wedgeAttribData ) { + void + moveContainerToMesh( Ra::Core::Geometry::MultiIndexedGeometry& out, + const std::vector& names, + AlignedStdVector::Container>& wedgeAttribData ) const { for ( size_t i = 0; i < wedgeAttribData.size(); ++i ) { auto attrHandle = out.template addAttrib( names[i] ); out.getAttrib( attrHandle ).setData( std::move( wedgeAttribData[i] ) ); @@ -496,9 +498,13 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT inline T& getWedgeData( const WedgeIndex& idx, int attribIndex ); template + inline const T& getWedgeData( const WedgeIndex& idx, int attribIndex ) const; + template inline const T& getWedgeAttrib( const WedgeIndex& idx, const std::string& name ) const; template inline T& getWedgeAttrib( const WedgeIndex& idx, int attribIndex ); + template + inline const T& getWedgeAttrib( const WedgeIndex& idx, int attribIndex ) const; unsigned int getWedgeRefCount( const WedgeIndex& idx ) const; @@ -809,12 +815,24 @@ inline T& TopologicalMesh::WedgeCollection::getWedgeData( const TopologicalMesh: int attribIndex ) { return getWedgeAttrib( idx, attribIndex ); } +template +inline const T& +TopologicalMesh::WedgeCollection::getWedgeData( const TopologicalMesh::WedgeIndex& idx, + int attribIndex ) const { + return getWedgeAttrib( idx, attribIndex ); +} template inline T& TopologicalMesh::WedgeCollection::getWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, int attribIndex ) { return m_data[idx].getWedgeData().getAttribArray()[attribIndex]; } +template +inline const T& +TopologicalMesh::WedgeCollection::getWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, + int attribIndex ) const { + return m_data[idx].getWedgeData().getAttribArray()[attribIndex]; +} inline unsigned int TopologicalMesh::WedgeCollection::getWedgeRefCount( const WedgeIndex& idx ) const { From 4c3651f1061fe01f18e66775700a4be32647029f Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 21:40:48 +0200 Subject: [PATCH 098/144] [tests] topomesh use makeBox2 (e.g. with MultiIndexed, with Quad). --- tests/unittest/Core/topomesh.cpp | 39 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/tests/unittest/Core/topomesh.cpp b/tests/unittest/Core/topomesh.cpp index 75831c30d18..45247e7ed4c 100644 --- a/tests/unittest/Core/topomesh.cpp +++ b/tests/unittest/Core/topomesh.cpp @@ -299,13 +299,14 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To { 0_ra, 1_ra }, { 0_ra, 0_ra } }; - auto mesh = Ra::Core::Geometry::makeBox(); - auto handle2 = mesh.addAttrib( "vector2_attrib" ); - auto handle4 = mesh.addAttrib( "vector4_attrib" ); - auto handle5 = mesh.addAttrib( "vector5_attrib" ); - auto ehandle2 = mesh.addAttrib( "evector2_attrib" ); - auto ehandle4 = mesh.addAttrib( "evector4_attrib" ); - auto ehandle5 = mesh.addAttrib( "evector5_attrib" ); + auto mesh = Ra::Core::Geometry::makeBox2(); + auto layer_key = mesh.triangulate(); + auto handle2 = mesh.addAttrib( "vector2_attrib" ); + auto handle4 = mesh.addAttrib( "vector4_attrib" ); + auto handle5 = mesh.addAttrib( "vector5_attrib" ); + auto ehandle2 = mesh.addAttrib( "evector2_attrib" ); + auto ehandle4 = mesh.addAttrib( "evector4_attrib" ); + auto ehandle5 = mesh.addAttrib( "evector5_attrib" ); auto& attrib2 = mesh.getAttrib( handle2 ); auto& attrib4 = mesh.getAttrib( handle4 ); @@ -320,7 +321,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To attrib4.unlock(); attrib5.unlock(); - auto topologicalMesh = TopologicalMesh( mesh ); + auto topologicalMesh = TopologicalMesh( mesh, layer_key ); auto newMesh = topologicalMesh.toTriangleMesh(); REQUIRE( isSameMesh( mesh, mesh.indices(), @@ -369,7 +370,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To } SECTION( "Test normals" ) { - auto mesh = Ra::Core::Geometry::makeBox(); + auto mesh = Ra::Core::Geometry::makeBox2(); auto topologicalMesh = TopologicalMesh( mesh ); for ( TopologicalMesh::ConstVertexIter v_it = topologicalMesh.vertices_begin(); @@ -385,7 +386,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To topologicalMesh.propagate_normal_to_wedges( *v_it ); } - auto newMesh = topologicalMesh.toTriangleMesh(); + auto newMesh = topologicalMesh.toQuadMesh(); bool check1 = true; bool check2 = true; for ( auto n : newMesh.normals() ) { @@ -1300,12 +1301,12 @@ TEST_CASE( "Core/TopologicalMesh/CollapseWedge", "[unittests]" ) { addSplitScene( points2, colors2, indices4, points1[5], points1[2] ); } } -template -void testConverter( IndexedGeometry&& mesh ) { + +void testConverter( MultiIndexedGeometry&& mesh ) { auto topologicalMesh = TopologicalMesh { mesh }; auto& vertices = mesh.verticesWithLock(); for ( auto& v : vertices ) { - v = TriangleMesh::Point( 0_ra, 1_ra, 2_ra ); + v = MultiIndexedGeometry::Point( 0_ra, 1_ra, 2_ra ); } mesh.verticesUnlock(); @@ -1314,8 +1315,8 @@ void testConverter( IndexedGeometry&& mesh ) { for ( auto itr = topologicalMesh.vertices_begin(); itr != topologicalMesh.vertices_end(); ++itr ) { - REQUIRE( - topologicalMesh.point( *itr ).isApprox( TriangleMesh::Point( 0_ra, 1_ra, 2_ra ) ) ); + REQUIRE( topologicalMesh.point( *itr ).isApprox( + MultiIndexedGeometry::Point( 0_ra, 1_ra, 2_ra ) ) ); // modify for next test. topologicalMesh.point( *itr ) = TopologicalMesh::Point( 3_ra, 4_ra, 5_ra ); } @@ -1325,7 +1326,7 @@ void testConverter( IndexedGeometry&& mesh ) { // not update since wedges are not updated yet for ( auto itr = mesh.vertices().begin(); itr != mesh.vertices().end(); ++itr ) { - REQUIRE( itr->isApprox( TriangleMesh::Point( 0_ra, 1_ra, 2_ra ) ) ); + REQUIRE( itr->isApprox( MultiIndexedGeometry::Point( 0_ra, 1_ra, 2_ra ) ) ); } topologicalMesh.copyPointsPositionToWedges(); @@ -1333,7 +1334,7 @@ void testConverter( IndexedGeometry&& mesh ) { // not update since wedges are not updated yet for ( auto itr = mesh.vertices().begin(); itr != mesh.vertices().end(); ++itr ) { - REQUIRE( itr->isApprox( TriangleMesh::Point( 3_ra, 4_ra, 5_ra ) ) ); + REQUIRE( itr->isApprox( MultiIndexedGeometry::Point( 3_ra, 4_ra, 5_ra ) ) ); } }; @@ -1344,8 +1345,8 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Updates", using Ra::Core::Geometry::TriangleMesh; SECTION( "Closed mesh" ) { - testConverter( Ra::Core::Geometry::makeBox() ); - testConverter( Ra::Core::Geometry::makeSharpBox() ); + testConverter( Ra::Core::Geometry::makeBox2() ); + testConverter( Ra::Core::Geometry::makeSharpBox2() ); } SECTION( "Mesh with boundaries" ) { From 9dcee9308f74919c3da2e3b4006d829bf9bdee26 Mon Sep 17 00:00:00 2001 From: dlyr Date: Tue, 12 May 2026 21:53:52 +0200 Subject: [PATCH 099/144] [core] Remove unneeded inline keyword in topomesh. --- src/Core/Geometry/TopologicalMesh.hpp | 244 +++++++++++++------------- 1 file changed, 118 insertions(+), 126 deletions(-) diff --git a/src/Core/Geometry/TopologicalMesh.hpp b/src/Core/Geometry/TopologicalMesh.hpp index 69d8e29a850..a2e149cd137 100644 --- a/src/Core/Geometry/TopologicalMesh.hpp +++ b/src/Core/Geometry/TopologicalMesh.hpp @@ -128,9 +128,8 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT void initWithWedge( const Ra::Core::Geometry::MultiIndexedGeometry& mesh, @@ -168,7 +167,7 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT& getInputTriangleMeshIndexPropHandle() const; + const OpenMesh::HPropHandleT& getInputTriangleMeshIndexPropHandle() const; /** * Return a handle to the halfedge property storing vertices indices within * the TriangleMesh returned by toTriangleMesh(). * \note This property is valid only after toTriangleMesh() has been called. */ - inline const OpenMesh::HPropHandleT& getOutputTriangleMeshIndexPropHandle() const; + const OpenMesh::HPropHandleT& getOutputTriangleMeshIndexPropHandle() const; /** * \name Dealing with normals @@ -244,18 +243,18 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT getVertexWedges( OpenMesh::VertexHandle vh ) const; + std::set getVertexWedges( OpenMesh::VertexHandle vh ) const; /** * get the wedge index associated with an halfedge */ - inline WedgeIndex getWedgeIndex( OpenMesh::HalfedgeHandle heh ) const; + WedgeIndex getWedgeIndex( OpenMesh::HalfedgeHandle heh ) const; /** * Access to wedge data. * \param idx must be valid and correspond to a non delete wedge index. */ - inline const WedgeData& getWedgeData( const WedgeIndex& idx ) const; + const WedgeData& getWedgeData( const WedgeIndex& idx ) const; template [[deprecated( "use getWedgeAttrib() instead." )]] const T& getWedgeData( const WedgeIndex& idx, const std::string& name ) const; @@ -265,14 +264,14 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT - [[deprecated( "use setWedgeAttrib() instead." )]] inline bool + [[deprecated( "use setWedgeAttrib() instead." )]] bool setWedgeData( const WedgeIndex& idx, const std::string& name, const T& value ); template - inline bool setWedgeAttrib( const WedgeIndex& idx, const std::string& name, const T& value ); + bool setWedgeAttrib( const WedgeIndex& idx, const std::string& name, const T& value ); /** return a WedgeData with all attrib initialized to default values */ - inline WedgeData newWedgeData() const { return m_wedges.newWedgeData(); } + WedgeData newWedgeData() const { return m_wedges.newWedgeData(); } /** return a WedgeData with position (and vertex handle) initialized from the value of he's to * vertex. */ - inline WedgeData newWedgeData( HalfedgeHandle he ) const { + WedgeData newWedgeData( HalfedgeHandle he ) const { return m_wedges.newWedgeData( to_vertex_handle( he ), point( to_vertex_handle( he ) ) ); } @@ -300,10 +299,10 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT - inline WedgeAttribIndex addWedgeAttrib( const std::string& name, T value = {} ) { + WedgeAttribIndex addWedgeAttrib( const std::string& name, T value = {} ) { return m_wedges.addAttrib( name, value ); } @@ -311,41 +310,41 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT& getVec4AttribNames() const; - inline const std::vector& getVec3AttribNames() const; - inline const std::vector& getVec2AttribNames() const; - inline const std::vector& getFloatAttribNames() const; + const std::vector& getVec4AttribNames() const; + const std::vector& getVec3AttribNames() const; + const std::vector& getVec2AttribNames() const; + const std::vector& getFloatAttribNames() const; /// true if more than one wedge arount vertex \a vh, false if only one wedge - inline bool isFeatureVertex( const VertexHandle& vh ) const; + bool isFeatureVertex( const VertexHandle& vh ) const; /// true if at least one of edge's vertex as two different wedge arount the /// edge. /// false if the two vertices have the same wedge for both face aside the edge. - inline bool isFeatureEdge( const EdgeHandle& eh ) const; + bool isFeatureEdge( const EdgeHandle& eh ) const; - inline const OpenMesh::HPropHandleT& getWedgeIndexPph() const; + const OpenMesh::HPropHandleT& getWedgeIndexPph() const; void delete_face( FaceHandle _fh, bool _delete_isolated_vertices = true ); @@ -372,14 +371,14 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT - inline VectorArray& getAttribArray(); + VectorArray& getAttribArray(); template - inline const VectorArray& getAttribArray() const; + const VectorArray& getAttribArray() const; friend Wedge; // Index m_inputTriangleMeshIndex; @@ -481,7 +480,7 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT - inline const T& getWedgeData( const WedgeIndex& idx, const std::string& name ) const; + const T& getWedgeData( const WedgeIndex& idx, const std::string& name ) const; template - inline T& getWedgeData( const WedgeIndex& idx, int attribIndex ); + T& getWedgeData( const WedgeIndex& idx, int attribIndex ); template - inline const T& getWedgeData( const WedgeIndex& idx, int attribIndex ) const; + const T& getWedgeData( const WedgeIndex& idx, int attribIndex ) const; template - inline const T& getWedgeAttrib( const WedgeIndex& idx, const std::string& name ) const; + const T& getWedgeAttrib( const WedgeIndex& idx, const std::string& name ) const; template - inline T& getWedgeAttrib( const WedgeIndex& idx, int attribIndex ); + T& getWedgeAttrib( const WedgeIndex& idx, int attribIndex ); template - inline const T& getWedgeAttrib( const WedgeIndex& idx, int attribIndex ) const; + const T& getWedgeAttrib( const WedgeIndex& idx, int attribIndex ) const; unsigned int getWedgeRefCount( const WedgeIndex& idx ) const; /// \see TopologicalMesh::setWedgeData - inline void setWedgeData( const WedgeIndex& idx, const WedgeData& wd ); + void setWedgeData( const WedgeIndex& idx, const WedgeData& wd ); /// change WedgeData member name to value. /// wd is moidified accordingly. /// \return false if name is not of type T /// \retrun true on sucess template - inline bool + bool setWedgeAttrib( TopologicalMesh::WedgeData& wd, const std::string& name, const T& value ); template - inline bool - setWedgeAttrib( const WedgeIndex& idx, const std::string& name, const T& value ); + bool setWedgeAttrib( const WedgeIndex& idx, const std::string& name, const T& value ); template - inline void setWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, - const int& attribIndex, - const T& value ); + void setWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, + const int& attribIndex, + const T& value ); template - inline WedgeAttribIndex getWedgeAttribIndex( const std::string& name ); + WedgeAttribIndex getWedgeAttribIndex( const std::string& name ); - inline bool setWedgePosition( const WedgeIndex& idx, const Vector3& value ); + bool setWedgePosition( const WedgeIndex& idx, const Vector3& value ); /// management template - inline const std::vector& getNameArray() const; + const std::vector& getNameArray() const; // name is supposed to be unique within all attribs // not checks are performed @@ -552,19 +550,18 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelTnew index correspondance to update wedgeIndexPph - /// inline void removeDuplicateWedge + /// void removeDuplicateWedge - inline size_t size() const { return m_data.size(); } + size_t size() const { return m_data.size(); } /// remove unreferenced wedge, halfedges need to be reindexed. - inline void garbageCollection(); + void garbageCollection(); - inline void clean(); + void clean(); // return a new wedgeData with uninit values. - inline WedgeData newWedgeData() const; - inline WedgeData newWedgeData( TopologicalMesh::VertexHandle vh, - TopologicalMesh::Point p ) const; + WedgeData newWedgeData() const; + WedgeData newWedgeData( TopologicalMesh::VertexHandle vh, TopologicalMesh::Point p ) const; ///\ todo private: /// attrib names associated to vertex/wedges, getted from CoreMesh, if any, @@ -581,7 +578,7 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT> m_wedgeVector4AttribHandles; template - inline std::vector& getNameArray(); + std::vector& getNameArray(); AlignedStdVector m_data; }; @@ -606,13 +603,13 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT& /*face_vhandles*/ ) { + void process( const std::vector& /*face_vhandles*/ ) { LOG( logWARNING ) << "Invalid face handle returned : face not added " + m_details; } /// \brief If needed, apply post-processing on the Ra::Core::Geometry::TopologicalMesh - inline void postProcess( TopologicalMesh& ) {} + void postProcess( TopologicalMesh& ) {} private: std::string m_details; @@ -623,19 +620,19 @@ class RA_CORE_API TopologicalMesh : public OpenMesh::PolyMesh_ArrayKernelT version above template - inline void copyAttribToWedgeData( const Ra::Core::Geometry::MultiIndexedGeometry& mesh, - unsigned int vindex, - const std::vector>& attrHandleVec, - VectorArray* to ); + void copyAttribToWedgeData( const Ra::Core::Geometry::MultiIndexedGeometry& mesh, + unsigned int vindex, + const std::vector>& attrHandleVec, + VectorArray* to ); /// \todo when MultiIndexView will be operational, remove the IndexedGeometry version above - inline void copyMeshToWedgeData( const Ra::Core::Geometry::MultiIndexedGeometry& mesh, - unsigned int vindex, - const std::vector>& wprop_float, - const std::vector>& wprop_vec2, - const std::vector>& wprop_vec3, - const std::vector>& wprop_vec4, - TopologicalMesh::WedgeData* wd ); + void copyMeshToWedgeData( const Ra::Core::Geometry::MultiIndexedGeometry& mesh, + unsigned int vindex, + const std::vector>& wprop_float, + const std::vector>& wprop_vec2, + const std::vector>& wprop_vec3, + const std::vector>& wprop_vec4, + TopologicalMesh::WedgeData* wd ); template using HandleAndValueVector = @@ -676,7 +673,7 @@ inline bool TopologicalMesh::WedgeData::operator==( const TopologicalMesh::Wedge m_vector4Attrib == lhs.m_vector4Attrib; } -bool TopologicalMesh::WedgeData::operator!=( const TopologicalMesh::WedgeData& lhs ) const { +inline bool TopologicalMesh::WedgeData::operator!=( const TopologicalMesh::WedgeData& lhs ) const { return !( *this == lhs ); } @@ -735,7 +732,7 @@ GET_ATTRIB_ARRAY_HELPER( Vector4, vector4 ) #undef GET_ATTRIB_ARRAY_HELPER template -inline VectorArray& TopologicalMesh::WedgeData::getAttribArray() { +VectorArray& TopologicalMesh::WedgeData::getAttribArray() { static_assert( sizeof( T ) == -1, "this type is not supported" ); } @@ -784,16 +781,14 @@ TopologicalMesh::WedgeCollection::getWedgeData( const WedgeIndex& idx ) const { } template -inline const T& -TopologicalMesh::WedgeCollection::getWedgeData( const TopologicalMesh::WedgeIndex& idx, - const std::string& name ) const { +const T& TopologicalMesh::WedgeCollection::getWedgeData( const TopologicalMesh::WedgeIndex& idx, + const std::string& name ) const { return getWedgeAttrib( idx, name ); } template -inline const T& -TopologicalMesh::WedgeCollection::getWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, - const std::string& name ) const { +const T& TopologicalMesh::WedgeCollection::getWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, + const std::string& name ) const { if ( idx.isValid() ) { auto nameArray = getNameArray(); auto itr = std::find( nameArray.begin(), nameArray.end(), name ); @@ -811,26 +806,24 @@ TopologicalMesh::WedgeCollection::getWedgeAttrib( const TopologicalMesh::WedgeIn } template -inline T& TopologicalMesh::WedgeCollection::getWedgeData( const TopologicalMesh::WedgeIndex& idx, - int attribIndex ) { +T& TopologicalMesh::WedgeCollection::getWedgeData( const TopologicalMesh::WedgeIndex& idx, + int attribIndex ) { return getWedgeAttrib( idx, attribIndex ); } template -inline const T& -TopologicalMesh::WedgeCollection::getWedgeData( const TopologicalMesh::WedgeIndex& idx, - int attribIndex ) const { +const T& TopologicalMesh::WedgeCollection::getWedgeData( const TopologicalMesh::WedgeIndex& idx, + int attribIndex ) const { return getWedgeAttrib( idx, attribIndex ); } template -inline T& TopologicalMesh::WedgeCollection::getWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, - int attribIndex ) { +T& TopologicalMesh::WedgeCollection::getWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, + int attribIndex ) { return m_data[idx].getWedgeData().getAttribArray()[attribIndex]; } template -inline const T& -TopologicalMesh::WedgeCollection::getWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, - int attribIndex ) const { +const T& TopologicalMesh::WedgeCollection::getWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, + int attribIndex ) const { return m_data[idx].getWedgeData().getAttribArray()[attribIndex]; } @@ -852,9 +845,9 @@ inline void TopologicalMesh::WedgeCollection::setWedgeData( const TopologicalMes } template -inline bool TopologicalMesh::WedgeCollection::setWedgeAttrib( TopologicalMesh::WedgeData& wd, - const std::string& name, - const T& value ) { +bool TopologicalMesh::WedgeCollection::setWedgeAttrib( TopologicalMesh::WedgeData& wd, + const std::string& name, + const T& value ) { auto nameArray = getNameArray(); auto itr = std::find( nameArray.begin(), nameArray.end(), name ); if ( itr != nameArray.end() ) { @@ -870,10 +863,9 @@ inline bool TopologicalMesh::WedgeCollection::setWedgeAttrib( TopologicalMesh::W } template -inline bool -TopologicalMesh::WedgeCollection::setWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, - const std::string& name, - const T& value ) { +bool TopologicalMesh::WedgeCollection::setWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, + const std::string& name, + const T& value ) { if ( idx.isValid() ) { auto nameArray = getNameArray(); auto itr = std::find( nameArray.begin(), nameArray.end(), name ); @@ -891,15 +883,14 @@ TopologicalMesh::WedgeCollection::setWedgeAttrib( const TopologicalMesh::WedgeIn } template -inline void -TopologicalMesh::WedgeCollection::setWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, - const int& attrIndex, - const T& value ) { +void TopologicalMesh::WedgeCollection::setWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, + const int& attrIndex, + const T& value ) { m_data[idx].getWedgeData().getAttribArray()[attrIndex] = value; } template -inline TopologicalMesh::WedgeAttribIndex +TopologicalMesh::WedgeAttribIndex TopologicalMesh::WedgeCollection::getWedgeAttribIndex( const std::string& name ) { auto nameArray = getNameArray(); auto itr = std::find( nameArray.begin(), nameArray.end(), name ); @@ -937,7 +928,7 @@ GET_NAME_ARRAY_HELPER( Vector4, vector4 ) // These template functions are defined above for supported types. // For unsupported types they simply generate a compile error. template -inline const std::vector& TopologicalMesh::WedgeCollection::getNameArray() const { +const std::vector& TopologicalMesh::WedgeCollection::getNameArray() const { LOG( logWARNING ) << "Warning, mesh attribute " << typeid( T ).name() << " is not supported (only float, vec2, vec3 nor vec4 are supported)"; @@ -946,7 +937,7 @@ inline const std::vector& TopologicalMesh::WedgeCollection::getName } template -inline std::vector& TopologicalMesh::WedgeCollection::getNameArray() { +std::vector& TopologicalMesh::WedgeCollection::getNameArray() { LOG( logWARNING ) << "Warning, mesh attribute " << typeid( T ).name() << " is not supported (only float, vec2, vec3 nor vec4 are supported)"; @@ -1090,8 +1081,8 @@ inline TopologicalMesh::TopologicalMesh( const Ra::Core::Geometry::MultiIndexedG DefaultNonManifoldFaceCommand( "[default ctor]" ) ) {} template -inline TopologicalMesh::TopologicalMesh( const Ra::Core::Geometry::MultiIndexedGeometry& mesh, - NonManifoldFaceCommand command ) : +TopologicalMesh::TopologicalMesh( const Ra::Core::Geometry::MultiIndexedGeometry& mesh, + NonManifoldFaceCommand command ) : TopologicalMesh( mesh, mesh.default_layer_key(), command ) {} template @@ -1337,13 +1328,14 @@ void TopologicalMesh::copyAttribToWedgeData( const MultiIndexedGeometry& mesh, } } -void TopologicalMesh::copyMeshToWedgeData( const MultiIndexedGeometry& mesh, - unsigned int vindex, - const std::vector>& wprop_float, - const std::vector>& wprop_vec2, - const std::vector>& wprop_vec3, - const std::vector>& wprop_vec4, - TopologicalMesh::WedgeData* wd ) { +inline void +TopologicalMesh::copyMeshToWedgeData( const MultiIndexedGeometry& mesh, + unsigned int vindex, + const std::vector>& wprop_float, + const std::vector>& wprop_vec2, + const std::vector>& wprop_vec3, + const std::vector>& wprop_vec4, + TopologicalMesh::WedgeData* wd ) { copyAttribToWedgeData( mesh, vindex, wprop_float, &wd->m_floatAttrib ); copyAttribToWedgeData( mesh, vindex, wprop_vec2, &wd->m_vector2Attrib ); copyAttribToWedgeData( mesh, vindex, wprop_vec3, &wd->m_vector3Attrib ); @@ -1404,16 +1396,16 @@ inline unsigned int TopologicalMesh::getWedgeRefCount( const WedgeIndex& idx ) c } template -inline bool TopologicalMesh::setWedgeData( const TopologicalMesh::WedgeIndex& idx, - const std::string& name, - const T& value ) { +bool TopologicalMesh::setWedgeData( const TopologicalMesh::WedgeIndex& idx, + const std::string& name, + const T& value ) { return setWedgeAttrib( idx, name, value ); } template -inline bool TopologicalMesh::setWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, - const std::string& name, - const T& value ) { +bool TopologicalMesh::setWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, + const std::string& name, + const T& value ) { return m_wedges.setWedgeAttrib( idx, name, value ); } @@ -1428,14 +1420,14 @@ TopologicalMesh::getWedgeData( const WedgeIndex& idx ) const { } template -inline const T& TopologicalMesh::getWedgeData( const TopologicalMesh::WedgeIndex& idx, - const std::string& name ) const { +const T& TopologicalMesh::getWedgeData( const TopologicalMesh::WedgeIndex& idx, + const std::string& name ) const { return getWedgeAttrib( idx, name ); } template -inline const T& TopologicalMesh::getWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, - const std::string& name ) const { +const T& TopologicalMesh::getWedgeAttrib( const TopologicalMesh::WedgeIndex& idx, + const std::string& name ) const { return m_wedges.getWedgeData( idx, name ); } From 8639a1a9768eea512a4ea9acd344a2f98f37ed1c Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 13 May 2026 21:56:22 +0200 Subject: [PATCH 100/144] [examples] Use makeSharpBox2 when appropriate. --- examples/CoreExample/main.cpp | 2 +- examples/CustomCameraManipulator/main.cpp | 2 +- examples/DrawPrimitives/AllPrimitivesComponent.cpp | 8 +++++--- examples/EntityAnimation/main.cpp | 4 ++-- examples/KeyEvent/main.cpp | 4 +++- examples/SimpleAnimation/main.cpp | 9 +++++---- examples/Volume/main.cpp | 4 ++-- 7 files changed, 19 insertions(+), 14 deletions(-) diff --git a/examples/CoreExample/main.cpp b/examples/CoreExample/main.cpp index 3039fc250ab..708960d26b5 100644 --- a/examples/CoreExample/main.cpp +++ b/examples/CoreExample/main.cpp @@ -10,7 +10,7 @@ int main( int /*argc*/, char** /*argv*/ ) { using namespace Ra::Core; - auto box = Geometry::makeSharpBox( { 1., 1., 1. } ); + auto box = Geometry::makeSharpBox2( { 1., 1., 1. } ); auto topo = Geometry::TopologicalMesh( box ); auto resourcesPaths { Resources::getBasePath() }; diff --git a/examples/CustomCameraManipulator/main.cpp b/examples/CustomCameraManipulator/main.cpp index daca836a68e..c77a6b173c0 100644 --- a/examples/CustomCameraManipulator/main.cpp +++ b/examples/CustomCameraManipulator/main.cpp @@ -37,7 +37,7 @@ int main( int argc, char* argv[] ) { //! [Creating the application] //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); + auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); //! [Creating the cube] //! [Colorize the Cube] diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index 3d6afc5d0ce..85eddecdc14 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -1194,8 +1194,8 @@ void AllPrimitivesComponent::initialize() { updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); - constexpr Scalar arrowScale = .1_ra; - constexpr Scalar axisWidth = .05_ra; + constexpr Scalar arrowScale = .3_ra; + constexpr Scalar axisWidth = .2_ra; constexpr Scalar arrowFrac = .125_ra; constexpr Scalar radius = arrowScale * axisWidth / 2_ra; @@ -1215,7 +1215,9 @@ void AllPrimitivesComponent::initialize() { boxBounds.extend( Core::Vector3( -radius * 2_ra, -radius * 2_ra, -radius * 2_ra ) ); boxBounds.extend( Core::Vector3( radius * 2_ra, radius * 2_ra, radius * 2_ra ) ); boxBounds.translate( arrowScale * cylinderEnd + startPoint ); - auto box = Core::Geometry::makeSharpBox( boxBounds, Color::Yellow() ); + auto box = Core::Geometry::makeSharpBox2( boxBounds, Color::Yellow() ); + // box is quads, need triangulate before append + box.triangulate(); cylinder.append( box ); diff --git a/examples/EntityAnimation/main.cpp b/examples/EntityAnimation/main.cpp index 8911e5ed02b..3d9241c17e5 100644 --- a/examples/EntityAnimation/main.cpp +++ b/examples/EntityAnimation/main.cpp @@ -114,7 +114,7 @@ int main( int argc, char* argv[] ) { //! [Create the engine entity for the fixed component] //! [Creating the cube] - auto cube = Geometry::makeSharpBox( { 0.5f, 0.5f, 0.5f }, Utils::Color::Green() ); + auto cube = Geometry::makeSharpBox2( { 0.5f, 0.5f, 0.5f }, Utils::Color::Green() ); //! [Creating the Cube] //! [Create a geometry component with the cube] @@ -140,7 +140,7 @@ int main( int argc, char* argv[] ) { //! [attach components to the animated entity ] // an animated yellow cube auto cube = - Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f }, Ra::Core::Utils::Color::Yellow() ); + Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f }, Ra::Core::Utils::Color::Yellow() ); new Scene::SurfaceMeshComponent( "Fixed cube geometry", e, std::move( cube ), nullptr ); // an animated camera, thay is not the one active at startup. Use key '0' to activate diff --git a/examples/KeyEvent/main.cpp b/examples/KeyEvent/main.cpp index 97781d5a181..89cdf13cd2b 100644 --- a/examples/KeyEvent/main.cpp +++ b/examples/KeyEvent/main.cpp @@ -24,6 +24,8 @@ /** * Simple custom windows for custom KeyEvent demonstration */ +using Ra::Core::Geometry::makeSharpBox2; + class DemoWindow : public Ra::Gui::SimpleWindow { Q_OBJECT @@ -135,7 +137,7 @@ int main( int argc, char* argv[] ) { //! [Creating the application] //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); + auto cube = makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); //! [Creating the cube] //! [Colorize the Cube] diff --git a/examples/SimpleAnimation/main.cpp b/examples/SimpleAnimation/main.cpp index 502764183fe..6b84071a5cf 100644 --- a/examples/SimpleAnimation/main.cpp +++ b/examples/SimpleAnimation/main.cpp @@ -46,9 +46,10 @@ class KeyFramedGeometryComponent : public Ra::Engine::Scene::SurfaceMeshComponen * Constructor from an existing core mesh * \warning Moves the mesh and takes its ownership */ - inline KeyFramedGeometryComponent( const std::string& name, - Ra::Engine::Scene::Entity* entity, - Ra::Core::Geometry::TriangleMesh&& mesh ) : + inline KeyFramedGeometryComponent( + const std::string& name, + Ra::Engine::Scene::Entity* entity, + Ra::Engine::Scene::SurfaceMeshComponent::CoreMeshType&& mesh ) : Ra::Engine::Scene::SurfaceMeshComponent( name, entity, std::move( mesh ), @@ -139,7 +140,7 @@ int main( int argc, char* argv[] ) { //! [Create the demo animated component] //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); + auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); //! [Creating the cube] //! [Create the engine entity for the cube] diff --git a/examples/Volume/main.cpp b/examples/Volume/main.cpp index 37083eb6830..b033ce28497 100644 --- a/examples/Volume/main.cpp +++ b/examples/Volume/main.cpp @@ -71,7 +71,7 @@ int main( int argc, char* argv[] ) { geometrySystem->addComponent( e, c ); //! [Register the entity/component association to the geometry system ] //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox( { 0.5f, 0.5f, 1.f } ); + auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.5f, 0.5f, 1.f } ); //! [Creating the cube] //! [Colorize the Cube] @@ -110,7 +110,7 @@ int main( int argc, char* argv[] ) { auto geometrySystem = app.m_engine->getSystem( "GeometrySystem" ); //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox( { 0.5_ra, 0.05_ra, 0.5_ra } ); + auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.5_ra, 0.05_ra, 0.5_ra } ); //! [Creating the cube] //! [Colorize the Cube] From 5cf4229359a0be27322545d99060fa99af2128a1 Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 13 May 2026 21:59:05 +0200 Subject: [PATCH 101/144] [engine] Some mesh type update, and sharpBox2. --- src/Engine/Data/EnvironmentTexture.cpp | 6 +++--- src/Engine/Data/EnvironmentTexture.hpp | 2 +- src/Engine/Scene/GeometryComponent.cpp | 5 ++--- src/Engine/Scene/GeometryComponent.hpp | 3 ++- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Engine/Data/EnvironmentTexture.cpp b/src/Engine/Data/EnvironmentTexture.cpp index 89504d3dc0f..a59637b7533 100644 --- a/src/Engine/Data/EnvironmentTexture.cpp +++ b/src/Engine/Data/EnvironmentTexture.cpp @@ -198,9 +198,9 @@ void EnvironmentTexture::initializeTexture() { if ( m_isSkyBox ) { // make the skybox geometry Aabb aabb( Vector3 { -1_ra, -1_ra, -1_ra }, Vector3 { 1_ra, 1_ra, 1_ra } ); - auto skyMesh = Geometry::makeSharpBox( aabb ); - m_displayMesh = std::make_unique( "skyBox" ); - m_displayMesh->loadGeometry( std::move( skyMesh ) ); + auto skyMesh = Geometry::makeSharpBox2( aabb ); + m_displayMesh = std::make_unique( + "skyBox", std::move( skyMesh ) ); } } diff --git a/src/Engine/Data/EnvironmentTexture.hpp b/src/Engine/Data/EnvironmentTexture.hpp index 8f6e3b1c985..ad858598505 100644 --- a/src/Engine/Data/EnvironmentTexture.hpp +++ b/src/Engine/Data/EnvironmentTexture.hpp @@ -184,7 +184,7 @@ class RA_ENGINE_API EnvironmentTexture /// Is the envmap a Skybox ? bool m_isSkyBox { false }; /// The mesh of the skybox - std::unique_ptr m_displayMesh { nullptr }; + std::unique_ptr m_displayMesh { nullptr }; /// The texture of the skybox std::unique_ptr m_skyTexture { nullptr }; /// The Lod to use for the skybox diff --git a/src/Engine/Scene/GeometryComponent.cpp b/src/Engine/Scene/GeometryComponent.cpp index 4f91ae13831..af9275847c1 100644 --- a/src/Engine/Scene/GeometryComponent.cpp +++ b/src/Engine/Scene/GeometryComponent.cpp @@ -54,9 +54,8 @@ const Index* GeometryComponent::roIndexRead() const { template <> void SurfaceMeshComponentBase::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; + m_contentName = data->getName(); + m_displayMesh = Ra::Core::make_shared( m_contentName ); CoreMeshType mesh { data->getGeometry() }; m_displayMesh->loadGeometry( std::move( mesh ) ); diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index e3a9d06ebed..7e6904e76c4 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -61,12 +61,13 @@ class RA_ENGINE_API GeometryComponent : public Component * - normals: rw (if deformable) * - triangles: rw (if deformable) */ -template +template class SurfaceMeshComponentBase : public GeometryComponent { using base = GeometryComponent; public: + using CoreMeshType = T; using RenderMeshType = typename Data::RenderMeshType::getType::Type; inline SurfaceMeshComponentBase( const std::string& name, From 84b8eae3379810be2c6554152a71bffe44d8d076 Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 13 May 2026 21:59:47 +0200 Subject: [PATCH 102/144] [core] Append new layer always unlocked (since a copy). --- src/Core/Geometry/IndexedGeometry.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index 1a95f0c0f6b..eae59f36185 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -68,8 +68,9 @@ bool MultiIndexedGeometry::append( const MultiIndexedGeometry& other ) { auto it = m_indices.find( key ); if ( it == m_indices.end() ) // copy entire layer { + // lock status of copied data is false. m_indices[key] = std::make_pair( - value.first, std::unique_ptr { value.second->clone() } ); + false, std::unique_ptr { value.second->clone() } ); dataHasBeenCopied = true; m_indices[key].second->offset( offset ); } From 5db8a9f9e78f67a65466fc677383a43f9dbb7c1d Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 13 May 2026 22:01:32 +0200 Subject: [PATCH 103/144] [gui] Gizmo triangulate before append. --- src/Gui/Viewer/Gizmo/ScaleGizmo.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp index 344f2abbc35..23457b03a07 100644 --- a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp @@ -40,7 +40,9 @@ ScaleGizmo::ScaleGizmo( Engine::Scene::Component* c, boxBounds.extend( Core::Vector3( -radius * 2_ra, -radius * 2_ra, -radius * 2_ra ) ); boxBounds.extend( Core::Vector3( radius * 2_ra, radius * 2_ra, radius * 2_ra ) ); boxBounds.translate( arrowScale * cylinderEnd ); - auto box = Core::Geometry::makeSharpBox( boxBounds ); + auto box = Core::Geometry::makeSharpBox2( boxBounds ); + // box is quads, need triangulate before append + box.triangulate(); cylinder.append( box ); From baf43f58368de64e9d7e190a8426c1ef0e9732b8 Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 13 May 2026 22:05:23 +0200 Subject: [PATCH 104/144] [gui] SimpleWindow, add quit action and connect to shortcut. --- src/Gui/RadiumWindow/SimpleWindow.cpp | 6 ++++++ src/Gui/RadiumWindow/SimpleWindow.hpp | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/Gui/RadiumWindow/SimpleWindow.cpp b/src/Gui/RadiumWindow/SimpleWindow.cpp index 1ff2e84e7a7..0a8c3547181 100644 --- a/src/Gui/RadiumWindow/SimpleWindow.cpp +++ b/src/Gui/RadiumWindow/SimpleWindow.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace Ra { using namespace Gui; @@ -32,6 +33,11 @@ SimpleWindow::SimpleWindow( uint w, uint h, QWidget* parent ) : MainWindowInterf setCentralWidget( viewerWidget ); setWindowTitle( QString( "Radium player" ) ); + quit_action = new QAction( this ); + quit_action->setShortcuts( { QKeySequence::Close, QKeySequence::Quit } ); + connect( quit_action, &QAction::triggered, this, &QApplication::quit ); + addAction( quit_action ); + createConnections(); } diff --git a/src/Gui/RadiumWindow/SimpleWindow.hpp b/src/Gui/RadiumWindow/SimpleWindow.hpp index 7739e46be35..0b954c97584 100644 --- a/src/Gui/RadiumWindow/SimpleWindow.hpp +++ b/src/Gui/RadiumWindow/SimpleWindow.hpp @@ -65,6 +65,10 @@ class RA_GUI_API SimpleWindow : public Ra::Gui::MainWindowInterface /// Emitted when frame must be updated void frameUpdate(); + protected: + /// to add quit shortcut, might be added as a menu. + QAction* quit_action { nullptr }; + private: /// create the UI connections void createConnections(); From c8a064c8f2ae0e4b5822da7c3c5d22f807ba91ef Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 13 May 2026 22:06:14 +0200 Subject: [PATCH 105/144] [examples] Add quit action to minimalapp. --- examples/DrawPrimitives/minimalapp.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/DrawPrimitives/minimalapp.cpp b/examples/DrawPrimitives/minimalapp.cpp index 216a166483a..628a708578e 100644 --- a/examples/DrawPrimitives/minimalapp.cpp +++ b/examples/DrawPrimitives/minimalapp.cpp @@ -88,6 +88,12 @@ void MinimalApp::initialize( const glbinding::Version& version ) { m_viewer_widget->setAutoFillBackground( false ); m_viewer_widget->resize( 500, 500 ); m_viewer_widget->show(); + + auto quit_action = new QAction( this ); + quit_action->setShortcuts( { QKeySequence::Close, QKeySequence::Quit } ); + connect( quit_action, &QAction::triggered, this, &QApplication::quit ); + m_viewer_widget->addAction( quit_action ); + return; } From 70cd8a91e4fedb3008139c64598f3ab409d21682 Mon Sep 17 00:00:00 2001 From: dlyr Date: Wed, 13 May 2026 22:06:45 +0200 Subject: [PATCH 106/144] [tests] topo mesh sharpBox2. --- tests/unittest/Core/topomesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unittest/Core/topomesh.cpp b/tests/unittest/Core/topomesh.cpp index 45247e7ed4c..c8ecbb5df6c 100644 --- a/tests/unittest/Core/topomesh.cpp +++ b/tests/unittest/Core/topomesh.cpp @@ -836,7 +836,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Initialization", TEST_CASE( "Core/Geometry/TopologicalMesh/MergeWedges", "[unittests][Core][Core/Geometry][TopologicalMesh]" ) { - auto mesh = Ra::Core::Geometry::makeSharpBox(); + auto mesh = Ra::Core::Geometry::makeSharpBox2(); auto topo = TopologicalMesh { mesh }; std::set wedgesIndices; From 05d1ce1e234d298038e2f4d6e0624fcc6d30866f Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 14 May 2026 11:32:28 +0200 Subject: [PATCH 107/144] [core] Indexed geom triangulate_any and comments. --- src/Core/Geometry/IndexedGeometry.cpp | 7 ++++--- src/Core/Geometry/IndexedGeometry.hpp | 17 ++++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index eae59f36185..59c8c4034b9 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -68,9 +68,10 @@ bool MultiIndexedGeometry::append( const MultiIndexedGeometry& other ) { auto it = m_indices.find( key ); if ( it == m_indices.end() ) // copy entire layer { - // lock status of copied data is false. - m_indices[key] = std::make_pair( - false, std::unique_ptr { value.second->clone() } ); + + m_indices[key] = + std::make_pair( false, // copied data are unlocked (since its a clone). + std::unique_ptr { value.second->clone() } ); dataHasBeenCopied = true; m_indices[key].second->offset( offset ); } diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index af258525199..41bb4bd8230 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -307,7 +307,7 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util void checkConsistency() const; /// Append another MultiIndexedGeometry to this one. Layers with same - /// name/semantics are concatenated, and other layers are ignored + /// name/semantics are concatenated, and other layers are merged. /// \return true if all fields have been copied bool append( const MultiIndexedGeometry& other ); @@ -529,6 +529,21 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util return static_cast( result.second ).collection(); } + /// Call triangulate, if there isn't any triangle index, on the first found index between quad + /// and poly. + /// \return the layer key of the triangle layer (old or new) + LayerKeyType triangulate_any() { + if ( !containsLayer( TriangleIndexLayer::staticSemanticName ) ) { + if ( containsLayer( QuadIndexLayer::staticSemanticName ) ) + return triangulate(); + if ( containsLayer( PolyIndexLayer::staticSemanticName ) ) + return triangulate(); + } + return getFirstLayerOccurrence( TriangleIndexLayer::staticSemanticName ).first; + } + + /// triangulate IndexLayer if there isn't any triangle index yet. + /// \return the layer key of the triangle layer (old or new) template LayerKeyType triangulate() { if ( !containsLayer( TriangleIndexLayer::staticSemanticName ) ) { From 4c50a78168d1be09139ae1a209a2f18e6279642c Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 14 May 2026 11:32:47 +0200 Subject: [PATCH 108/144] [engine] use bracket include. --- src/Engine/Scene/SkinningComponent.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engine/Scene/SkinningComponent.hpp b/src/Engine/Scene/SkinningComponent.hpp index 53a699d6877..de94906d34f 100644 --- a/src/Engine/Scene/SkinningComponent.hpp +++ b/src/Engine/Scene/SkinningComponent.hpp @@ -1,11 +1,11 @@ #pragma once -#include "Core/Geometry/IndexedGeometry.hpp" #include #include #include #include #include +#include #include #include #include From 7d016f50226e5ca6b2d861b895a8880b0438063d Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 14 May 2026 11:33:48 +0200 Subject: [PATCH 109/144] [gui] Gizmo use triangulate_any. --- src/Gui/Viewer/Gizmo/ScaleGizmo.cpp | 3 ++- src/Gui/Viewer/Gizmo/TranslateGizmo.cpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp index 23457b03a07..7083900dae4 100644 --- a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp @@ -36,13 +36,14 @@ ScaleGizmo::ScaleGizmo( Engine::Scene::Component* c, cylinderEnd[i] = ( 1_ra - arrowFrac ); auto cylinder = Core::Geometry::makeCylinder( Core::Vector3::Zero(), arrowScale * cylinderEnd, radius, 32 ); + cylinder.triangulate_any(); Core::Aabb boxBounds; boxBounds.extend( Core::Vector3( -radius * 2_ra, -radius * 2_ra, -radius * 2_ra ) ); boxBounds.extend( Core::Vector3( radius * 2_ra, radius * 2_ra, radius * 2_ra ) ); boxBounds.translate( arrowScale * cylinderEnd ); auto box = Core::Geometry::makeSharpBox2( boxBounds ); // box is quads, need triangulate before append - box.triangulate(); + box.triangulate_any(); cylinder.append( box ); diff --git a/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp b/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp index ac9a09c06db..99fde2dbd3a 100644 --- a/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/TranslateGizmo.cpp @@ -34,8 +34,10 @@ TranslateGizmo::TranslateGizmo( Engine::Scene::Component* c, arrowEnd[i] = 1_ra; auto cylinder = Core::Geometry::makeCylinder( Core::Vector3::Zero(), arrowScale * cylinderEnd, arrowScale * axisWidth / 2_ra, 32 ); + cylinder.triangulate_any(); auto cone = Core::Geometry::makeCone( arrowScale * cylinderEnd, arrowScale * arrowEnd, arrowScale * arrowFrac / 2_ra, 32 ); + cone.triangulate_any(); cylinder.append( cone ); auto mesh = std::make_shared( "Translate Gizmo Arrow" ); From 902774c70c9e572fa6b90af6c579bf5f4ac5a277 Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 15 May 2026 11:44:42 +0200 Subject: [PATCH 110/144] [examples] Switch to makeSharpBox2 --- examples/EnvMap/main.cpp | 2 +- examples/HelloRadium/main.cpp | 2 +- examples/Picking/main.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/EnvMap/main.cpp b/examples/EnvMap/main.cpp index d2621738ba3..ebf3d1b94f4 100644 --- a/examples/EnvMap/main.cpp +++ b/examples/EnvMap/main.cpp @@ -73,7 +73,7 @@ int main( int argc, char* argv[] ) { //! [Setting the envmap on the renderer] //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); + auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); //! [Creating the cube] //! [Colorize the Cube] diff --git a/examples/HelloRadium/main.cpp b/examples/HelloRadium/main.cpp index 818bf6072c2..6132e526dcb 100644 --- a/examples/HelloRadium/main.cpp +++ b/examples/HelloRadium/main.cpp @@ -27,7 +27,7 @@ int main( int argc, char* argv[] ) { //! [Verifying the OpenGL version available to the engine] //! [Creating the cube] - auto cube { std::move( Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ) ) }; + auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); //! [Creating the cube] //! [Colorize the Cube] diff --git a/examples/Picking/main.cpp b/examples/Picking/main.cpp index b06fac48523..72bec06a473 100644 --- a/examples/Picking/main.cpp +++ b/examples/Picking/main.cpp @@ -119,7 +119,7 @@ class DemoWindowFactory : public Ra::Gui::BaseApplication::WindowFactory }; void addDummyScene( Ra::Gui::BaseApplication& app ) { - auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); + auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); auto e = app.m_engine->getEntityManager()->createEntity( "Cube" ); auto c = new Ra::Engine::Scene::SurfaceMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); From e56ee79bcdabc71839dc98fff05e430b2ffb505b Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 15 May 2026 11:45:12 +0200 Subject: [PATCH 111/144] [engine] VolumeObject Mesh -> GeometryDisplayable. --- src/Engine/Data/VolumeObject.cpp | 31 +------------------------------ src/Engine/Data/VolumeObject.hpp | 2 +- 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/src/Engine/Data/VolumeObject.cpp b/src/Engine/Data/VolumeObject.cpp index 87ce9d40a4c..f40b1b927f3 100644 --- a/src/Engine/Data/VolumeObject.cpp +++ b/src/Engine/Data/VolumeObject.cpp @@ -18,36 +18,7 @@ VolumeObject::~VolumeObject() {} void VolumeObject::loadGeometry( Core::Geometry::AbstractVolume* volume, const Core::Aabb& aabb ) { if ( volume != nullptr && volume->isDense() ) { - m_mesh.loadGeometry( Core::Geometry::makeSharpBox( aabb ) ); - - Core::Vector3Array tex_coords; - tex_coords.resize( 24 ); - tex_coords.getMap() << - // R - Scalar( 1 ), - Scalar( 1 ), Scalar( 0 ), Scalar( 0 ), // Bottom - Scalar( 1 ), Scalar( 0 ), Scalar( 0 ), Scalar( 1 ), // Top - Scalar( 1 ), Scalar( 1 ), Scalar( 1 ), Scalar( 1 ), // Right - Scalar( 0 ), Scalar( 0 ), Scalar( 0 ), Scalar( 0 ), // Left - Scalar( 1 ), Scalar( 0 ), Scalar( 0 ), Scalar( 1 ), // Floor - Scalar( 1 ), Scalar( 1 ), Scalar( 0 ), Scalar( 0 ), // Ceil - // G - Scalar( 0 ), Scalar( 1 ), Scalar( 1 ), Scalar( 0 ), // Bottom - Scalar( 0 ), Scalar( 0 ), Scalar( 1 ), Scalar( 1 ), // Top - Scalar( 1 ), Scalar( 0 ), Scalar( 0 ), Scalar( 1 ), // Right - Scalar( 0 ), Scalar( 1 ), Scalar( 1 ), Scalar( 0 ), // Left - Scalar( 0 ), Scalar( 0 ), Scalar( 0 ), Scalar( 0 ), // Floor - Scalar( 1 ), Scalar( 1 ), Scalar( 1 ), Scalar( 1 ), // Ceil - // B - Scalar( 0 ), Scalar( 0 ), Scalar( 0 ), Scalar( 0 ), // Bottom - Scalar( 1 ), Scalar( 1 ), Scalar( 1 ), Scalar( 1 ), // Top - Scalar( 0 ), Scalar( 0 ), Scalar( 1 ), Scalar( 1 ), // Right - Scalar( 0 ), Scalar( 0 ), Scalar( 1 ), Scalar( 1 ), // Left - Scalar( 0 ), Scalar( 0 ), Scalar( 1 ), Scalar( 1 ), // Floor - Scalar( 0 ), Scalar( 1 ), Scalar( 1 ), Scalar( 0 ); // Ceil - m_mesh.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_TEXCOORD ), - tex_coords ); - + m_mesh.loadGeometry( Core::Geometry::makeSharpBox2( aabb ) ); Core::Geometry::VolumeGrid* grid = static_cast( volume ); m_volume = std::unique_ptr( volume ); diff --git a/src/Engine/Data/VolumeObject.hpp b/src/Engine/Data/VolumeObject.hpp index 111758b477d..37b7f6e1abb 100644 --- a/src/Engine/Data/VolumeObject.hpp +++ b/src/Engine/Data/VolumeObject.hpp @@ -81,7 +81,7 @@ class RA_ENGINE_API VolumeObject : public Displayable std::unique_ptr m_volume; Texture m_tex { {} }; /// Mesh used to display the bounding box of the grid for the ray marching - Mesh m_mesh; + GeometryDisplayable m_mesh; /// General dirty bit of the mesh. An empty volume is not dirty bool m_isDirty { false }; From 1870c72286a3bad5154403ceb7726a33930c152a Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 15 May 2026 11:45:50 +0200 Subject: [PATCH 112/144] [core] Include StdUtils to cout set if needed. --- src/Core/Geometry/IndexedGeometry.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 41bb4bd8230..296c91ca5f2 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include From 6d6633f13ef83c675d3c7e36feae09c5a2630841 Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 15 May 2026 11:46:48 +0200 Subject: [PATCH 113/144] [tests] Update index view using MultiIndexedGeometry. --- tests/unittest/Core/indexview.cpp | 160 ++++++++++++++---------------- 1 file changed, 74 insertions(+), 86 deletions(-) diff --git a/tests/unittest/Core/indexview.cpp b/tests/unittest/Core/indexview.cpp index a90904bfd59..0b6010eb822 100644 --- a/tests/unittest/Core/indexview.cpp +++ b/tests/unittest/Core/indexview.cpp @@ -20,7 +20,7 @@ TEST_CASE( "Core/Geometry/MultiIndexedGeometry", geo.setNormals( { { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 } } ); { - std::unique_ptr layer = std::make_unique(); + auto layer = std::make_unique(); auto& indices = layer->collection(); indices.push_back( { 0, 1, 2, 3 } ); @@ -32,7 +32,7 @@ TEST_CASE( "Core/Geometry/MultiIndexedGeometry", REQUIRE( geo.default_layer_key().first.contains( QuadIndexLayer::staticSemanticName ) ); } { - std::unique_ptr layer = std::make_unique(); + auto layer = std::make_unique(); auto& indices = layer->collection(); indices.push_back( { 0, 1, 2 } ); @@ -63,77 +63,70 @@ TEST_CASE( "Core/Geometry/IndexedGeometry", "[unittests][Core][Core/Geometry][In // Store keys of the layers that should be in the geometry std::set keys; - TriangleMesh mesh = Ra::Core::Geometry::makeBox(); - // copy AttribArrayGeometry; - MultiIndexedGeometry geo( mesh ); - - // Create triangle Layer - ObjectWithSemantic::SemanticNameCollection tilSemantics; - { - // TriangleMesh is a MultiIndexedGeometry, so the layer has already - // been added - REQUIRE( geo.containsLayer( TriangleIndexLayer::staticSemanticName ) ); - auto [key, layer] = geo.getFirstLayerOccurrence( TriangleIndexLayer::staticSemanticName ); - keys.insert( key ); - tilSemantics = layer.semantics(); - } - - ObjectWithSemantic::SemanticNameCollection pilSemantics; - { - //! [Creating and adding pointcloud layer] - auto pil = std::make_unique(); - // fill indices as linspace - pil->linearIndices( geo ); - // optional: save semantics for later - pilSemantics = pil->semantics(); - // insert with default name - bool layerAdded = geo.addLayer( std::move( pil ) ).first; - //! [Creating and adding pointcloud layer] - REQUIRE( layerAdded ); - - keys.insert( { pilSemantics, "" } ); - } - - REQUIRE( geo.containsLayer( tilSemantics ) ); - REQUIRE( geo.containsLayer( pilSemantics ) ); - REQUIRE( geo.containsLayer( TriangleIndexLayer::staticSemanticName ) ); - REQUIRE( geo.containsLayer( PointCloudIndexLayer::staticSemanticName ) ); - - REQUIRE( geo.countLayers( tilSemantics ) == 1 ); - REQUIRE( geo.countLayers( pilSemantics ) == 1 ); - REQUIRE( geo.countLayers( TriangleIndexLayer::staticSemanticName ) == 1 ); - REQUIRE( geo.countLayers( PointCloudIndexLayer::staticSemanticName ) == 1 ); - - ObjectWithSemantic::SemanticNameCollection cilSemantics; - auto cil = std::make_unique(); - cil->collection() = mesh.getIndices(); - cilSemantics = cil->semantics(); - - REQUIRE( !geo.containsLayer( cilSemantics ) ); - REQUIRE( geo.countLayers( cilSemantics ) == 0 ); - - REQUIRE( geo.addLayer( std::move( cil ) ).first ); - keys.insert( { cilSemantics, "" } ); - - REQUIRE( geo.containsLayer( cilSemantics ) ); - REQUIRE( geo.containsLayer( TriangleIndexLayer::staticSemanticName ) ); - REQUIRE( geo.containsLayer( PointCloudIndexLayer::staticSemanticName ) ); - REQUIRE( geo.containsLayer( CustomTriangleIndexLayer::staticSemanticName ) ); - - REQUIRE( geo.countLayers( tilSemantics ) == 1 ); - REQUIRE( geo.countLayers( pilSemantics ) == 1 ); - REQUIRE( geo.countLayers( cilSemantics ) == 1 ); - REQUIRE( geo.countLayers( TriangleIndexLayer::staticSemanticName ) == 2 ); - REQUIRE( geo.countLayers( PointCloudIndexLayer::staticSemanticName ) == 1 ); - REQUIRE( geo.countLayers( CustomTriangleIndexLayer::staticSemanticName ) == 1 ); + MultiIndexedGeometry geom { Ra::Core::Geometry::makeBox2() }; + // makeBox create quads, now get triangles + geom.triangulate_any(); + + REQUIRE( geom.containsLayer( QuadIndexLayer::staticSemanticName ) ); + keys.insert( geom.getFirstLayerOccurrence( QuadIndexLayer::staticSemanticName ).first ); + + REQUIRE( geom.containsLayer( TriangleIndexLayer::staticSemanticName ) ); + auto [triangle_key, triangle_layer] = + geom.getFirstLayerOccurrence( TriangleIndexLayer::staticSemanticName ); + keys.insert( triangle_key ); + auto triangle_semantics = triangle_layer.semantics(); + + //! [Creating and adding pointcloud layer] + auto point_layer = std::make_unique(); + // fill indices as linspace + point_layer->linearIndices( geom ); + // optional: save semantics for later + auto point_semantics = point_layer->semantics(); + // insert with default name + auto [point_index_added, point_index_key] = geom.addLayer( std::move( point_layer ) ); + //! [Creating and adding pointcloud layer] + REQUIRE( point_index_added ); + keys.insert( point_index_key ); + + REQUIRE( geom.containsLayer( triangle_semantics ) ); + REQUIRE( geom.containsLayer( point_semantics ) ); + REQUIRE( geom.containsLayer( TriangleIndexLayer::staticSemanticName ) ); + REQUIRE( geom.containsLayer( PointCloudIndexLayer::staticSemanticName ) ); + + REQUIRE( geom.countLayers( triangle_semantics ) == 1 ); + REQUIRE( geom.countLayers( point_semantics ) == 1 ); + REQUIRE( geom.countLayers( TriangleIndexLayer::staticSemanticName ) == 1 ); + REQUIRE( geom.countLayers( PointCloudIndexLayer::staticSemanticName ) == 1 ); + + auto custom_layer = std::make_unique(); + custom_layer->collection() = geom.indices(); + auto custom_semantics = custom_layer->semantics(); + + REQUIRE( !geom.containsLayer( custom_semantics ) ); + REQUIRE( geom.countLayers( custom_semantics ) == 0 ); + + REQUIRE( geom.addLayer( std::move( custom_layer ) ).first ); + keys.insert( { custom_semantics, "" } ); + + REQUIRE( geom.containsLayer( custom_semantics ) ); + REQUIRE( geom.containsLayer( TriangleIndexLayer::staticSemanticName ) ); + REQUIRE( geom.containsLayer( PointCloudIndexLayer::staticSemanticName ) ); + REQUIRE( geom.containsLayer( CustomTriangleIndexLayer::staticSemanticName ) ); + + REQUIRE( geom.countLayers( triangle_semantics ) == 1 ); + REQUIRE( geom.countLayers( point_semantics ) == 1 ); + REQUIRE( geom.countLayers( custom_semantics ) == 1 ); + REQUIRE( geom.countLayers( TriangleIndexLayer::staticSemanticName ) == 2 ); + REQUIRE( geom.countLayers( PointCloudIndexLayer::staticSemanticName ) == 1 ); + REQUIRE( geom.countLayers( CustomTriangleIndexLayer::staticSemanticName ) == 1 ); // Check layer keys iterator: we should traverse all keys REQUIRE( keys.size() != 0 ); //! [Iterating over layer keys] - for ( const auto& k : geo.layerKeys() ) { + for ( const auto& k : geom.layerKeys() ) { REQUIRE( keys.erase( k ) == 1 ); - REQUIRE( geo.countLayers( k ) == 1 ); + REQUIRE( geom.countLayers( k ) == 1 ); } //! [Iterating over layer keys] REQUIRE( keys.size() == 0 ); @@ -146,7 +139,7 @@ TEST_CASE( "Core/Geometry/IndexedGeometry/Attributes", using Ra::Core::Utils::ObjectWithSemantic; using Vec3AttribHandle = AttribArrayGeometry::Vec3AttribHandle; - MultiIndexedGeometry mesh( Ra::Core::Geometry::makeBox() ); + MultiIndexedGeometry mesh( Ra::Core::Geometry::makeBox2() ); // base attributes are automatically added auto h_pos = mesh.getAttribHandle( getAttribName( VERTEX_POSITION ) ); @@ -197,20 +190,17 @@ TEST_CASE( "Core/Geometry/IndexedGeometry/Attributes", // Test attribute copy const auto v0 = mesh.vertices()[0]; - TriangleMesh meshCopy; + MultiIndexedGeometry meshCopy; meshCopy.copy( mesh ); REQUIRE( mesh.vertices()[0].isApprox( v0 ) ); meshCopy.verticesWithLock()[0] += Ra::Core::Vector3( 0.5, 0.5, 0.5 ); meshCopy.verticesUnlock(); REQUIRE( !meshCopy.vertices()[0].isApprox( v0 ) ); - // For the documentation in doc/developer/mesh.md - //! [create TriangleMesh] - using Ra::Core::Geometry::TriangleMesh; - TriangleMesh m; - TriangleMesh::PointAttribHandle::Container vertices; - TriangleMesh::NormalAttribHandle::Container normals; - TriangleMesh::IndexContainerType indices; + MultiIndexedGeometry m; + MultiIndexedGeometry::PointAttribHandle::Container vertices; + MultiIndexedGeometry::NormalAttribHandle::Container normals; + TriangleIndexLayer::IndexContainerType indices; vertices.push_back( { 0, 0, 0 } ); vertices.push_back( { 1, 0, 0 } ); @@ -222,7 +212,7 @@ TEST_CASE( "Core/Geometry/IndexedGeometry/Attributes", m.setVertices( std::move( vertices ) ); m.setNormals( std::move( normals ) ); - m.setIndices( { { 0, 1, 2 } } ); + m.set_indices( { { 0, 1, 2 } } ); auto handle1 = m.addAttrib( "vector3_attrib" ); auto& attrib1 = m.getAttrib( handle1 ); @@ -238,11 +228,9 @@ TEST_CASE( "Core/Geometry/IndexedGeometry/Attributes", auto& attrib2 = m.getAttrib( handle2 ); attrib2.setData( { 1.f, 2.f, 3.f } ); - TriangleMesh m2; + MultiIndexedGeometry m2; m2.copyBaseGeometry( m ); m2.copyAttributes( m, handle1 ); - //! [create TriangleMesh] - m2.copyAttributes( m, handle2 ); auto& attribM2_1 = m2.getAttrib( handle1 ); @@ -296,10 +284,10 @@ TEST_CASE( "Core/Geometry/IndexedGeometry/CopyAllAttributes", using namespace Ra::Core::Geometry; using Ra::Core::Geometry::TriangleMesh; - TriangleMesh m; - TriangleMesh::PointAttribHandle::Container vertices; - TriangleMesh::NormalAttribHandle::Container normals; - TriangleMesh::IndexContainerType indices; + MultiIndexedGeometry m; + MultiIndexedGeometry::PointAttribHandle::Container vertices; + MultiIndexedGeometry::NormalAttribHandle::Container normals; + TriangleIndexLayer::IndexContainerType indices; vertices.push_back( { 0, 0, 0 } ); vertices.push_back( { 1, 0, 0 } ); @@ -311,7 +299,7 @@ TEST_CASE( "Core/Geometry/IndexedGeometry/CopyAllAttributes", m.setVertices( std::move( vertices ) ); m.setNormals( std::move( normals ) ); - m.setIndices( { { 0, 1, 2 } } ); + m.set_indices( { { 0, 1, 2 } } ); auto handle1 = m.addAttrib( "vector2_attrib" ); auto& attrib1 = m.getAttrib( handle1 ); @@ -340,7 +328,7 @@ TEST_CASE( "Core/Geometry/IndexedGeometry/CopyAllAttributes", } attrib3.unlock(); - TriangleMesh m3; + MultiIndexedGeometry m3; m3.copyBaseGeometry( m ); From 7517a50ab1e7d6445bc0f19ed6a5440dc7584b56 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 10:22:37 +0200 Subject: [PATCH 114/144] [core][engine][...] Remove template from param sphere and torus. --- .../DrawPrimitives/AllPrimitivesComponent.cpp | 4 +- src/Core/Geometry/MeshPrimitives.cpp | 20 ++-- src/Core/Geometry/MeshPrimitives.hpp | 113 +++++++++--------- src/Engine/Data/DrawPrimitives.cpp | 2 +- src/Gui/Viewer/Gizmo/RotateGizmo.cpp | 4 +- 5 files changed, 73 insertions(+), 70 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index 85eddecdc14..f9826985e07 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -1089,7 +1089,7 @@ void AllPrimitivesComponent::initialize() { { using Ra::Engine::Data::Mesh; { - auto geom = makeParametricTorus<16, 8>( .04_ra, .01_ra, Color::White() ); + auto geom = makeParametricTorus( .04_ra, .01_ra, Color::White(), 16, 8 ); auto torusMesh = make_shared( "Torus", std::move( geom ) ); auto torus = RenderObject::createRenderObject( "test_torus", this, RenderObjectType::Geometry, torusMesh, {} ); @@ -1101,7 +1101,7 @@ void AllPrimitivesComponent::initialize() { } { - auto geom = makeParametricTorus<32, 12>( .1_ra, .05_ra, Color::White(), true ); + auto geom = makeParametricTorus( .1_ra, .05_ra, Color::White(), true, 32, 12 ); auto texTorusMesh = make_shared( "Textured Torus", std::move( geom ) ); diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index aa38b7a32e7..097a5853637 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -883,15 +883,15 @@ MultiIndexedGeometry makeTube( const Vector3& a, return result; } -TriangleMesh makeCone( const Vector3& base, - const Vector3& tip, - Scalar radius, - uint nFaces, - const Utils::optional& color ) { - TriangleMesh result; - TriangleMesh::PointAttribHandle::Container vertices; - TriangleMesh::NormalAttribHandle::Container normals; - TriangleMesh::IndexContainerType indices; +MultiIndexedGeometry makeCone( const Vector3& base, + const Vector3& tip, + Scalar radius, + uint nFaces, + const Utils::optional& color ) { + MultiIndexedGeometry result; + MultiIndexedGeometry::PointAttribHandle::Container vertices; + MultiIndexedGeometry::NormalAttribHandle::Container normals; + TriangleIndexLayer::IndexContainerType indices; vertices.reserve( 2 + nFaces ); normals.reserve( 2 + nFaces ); indices.reserve( 2 * nFaces ); @@ -928,7 +928,7 @@ TriangleMesh makeCone( const Vector3& base, } result.setVertices( std::move( vertices ) ); result.setNormals( std::move( normals ) ); - result.setIndices( std::move( indices ) ); + result.set_indices( std::move( indices ) ); if ( bool( color ) ) result.colorize( *color ); result.checkConsistency(); diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index 9dbdd5de47b..4c02ed8c342 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -103,27 +103,25 @@ RA_CORE_API MultiIndexedGeometry makeSharpBox2( const Aabb& aabb, /// 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 -MultiIndexedGeometry makeParametricSphere( Scalar radius = 1_ra, - const Utils::optional& color = {}, - bool generateTexCoord = false ); +RA_CORE_API MultiIndexedGeometry +makeParametricSphere( Scalar radius = 1_ra, + const Utils::optional& color = {}, + bool generateTexCoord = false, + const uint SLICES = 16, + const uint STACK = 16 ); /// Create a parametric torus mesh. The minor radius is the radius of the inside of the tube and /// the major radius is the radius of the whole torus. The torus will be centered at the origin /// and have Z as rotation axis. Template parameters set the resolution of the mesh. \param /// generateTexCoord: maps parametric (u,v) to texture corrdinates [0,1]^2 -template -QuadMesh makeParametricTorus( Scalar majorRadius, - Scalar minorRadius, - const Utils::optional& color = {}, - bool generateTexCoord = false ); - -// QuadMesh makeParametricTorus( Scalar majorRadius, -// Scalar minorRadius, -// int U = 16, -// int V = 16, -// const Utils::optional& color = {}, -// bool generateTexCoord = false ); +RA_CORE_API MultiIndexedGeometry +makeParametricTorus( Scalar majorRadius, + Scalar minorRadius, + const Utils::optional& color = {}, + bool generateTexCoord = false, + const uint U = 16, + const uint V = 16 ); + /// Create a spherical mesh by subdivision of an icosahedron. RA_CORE_API MultiIndexedGeometry makeGeodesicSphere( Scalar radius = 1_ra, @@ -160,15 +158,17 @@ RA_CORE_API MultiIndexedGeometry makeTube( const Vector3& a, /// Create a cone approximation (n-faced pyramid) with base face centered on base, pointing /// towards tip with given base radius. -RA_CORE_API TriangleMesh makeCone( const Vector3& base, - const Vector3& tip, - Scalar radius, - uint nFaces = 32, - const Utils::optional& color = {} ); +RA_CORE_API MultiIndexedGeometry makeCone( const Vector3& base, + const Vector3& tip, + Scalar radius, + uint nFaces = 32, + const Utils::optional& color = {} ); -template -MultiIndexedGeometry -makeParametricSphere( Scalar radius, const Utils::optional& color, bool gtc ) { +inline MultiIndexedGeometry makeParametricSphere( Scalar radius, + const Utils::optional& color, + bool gtc, + const uint SLICES, + const uint STACKS ) { const Scalar du = 1_ra / SLICES; const Scalar dv = 1_ra / STACKS; @@ -183,7 +183,8 @@ makeParametricSphere( Scalar radius, const Utils::optional& color, gtc ? topoMesh.addWedgeAttrib( getAttribName( MeshAttrib::VERTEX_TEXCOORD ) ) : WAI::Invalid(); - TopologicalMesh::VertexHandle vhandles[( STACKS - 1 ) * SLICES + 2]; + std::vector vhandles; + vhandles.resize( ( STACKS - 1 ) * SLICES + 2 ); Vector3Array topoTexCoords; topoTexCoords.reserve( ( STACKS - 1 ) * SLICES + 2 + 2 * SLICES ); Vector3Array topoNormals; @@ -193,7 +194,7 @@ makeParametricSphere( Scalar radius, const Utils::optional& color, // check https://en.wikipedia.org/wiki/Spherical_coordinate_system // theta \in [0, pi] // phi \in [0, 2pi] - const Scalar uFactor = 2_ra / Scalar { SLICES } * Core::Math::Pi; + const Scalar uFactor = 2_ra / static_cast( SLICES ) * Core::Math::Pi; const Scalar vFactor = Core::Math::Pi / STACKS; for ( uint u = 0; u < SLICES; ++u ) { const Scalar phi = u * uFactor; @@ -233,27 +234,28 @@ makeParametricSphere( Scalar radius, const Utils::optional& color, }; // take seams into account when u =1 - auto wedgeSetterSeam = [wedgeSetter, &topoTexCoords, &topoNormals, whNormal, whTexCoord]( - int u, int vhIndex, TopologicalMesh::FaceHandle fh ) { - Vector3 t = topoTexCoords[vhIndex]; - if ( u == SLICES - 1 ) t[0] = 0_ra; - wedgeSetter( vhIndex, fh, topoNormals[vhIndex], t ); - }; + auto wedgeSetterSeam = + [wedgeSetter, &topoTexCoords, &topoNormals, whNormal, whTexCoord, SLICES]( + uint u, int vhIndex, TopologicalMesh::FaceHandle fh ) { + Vector3 t = topoTexCoords[vhIndex]; + if ( u == SLICES - 1 ) t[0] = 0_ra; + wedgeSetter( vhIndex, fh, topoNormals[vhIndex], t ); + }; // special for poles - auto wedgeSetterPole = - [wedgeSetter, &topoTexCoords, whNormal, whTexCoord]( bool north, - int id, - int baseSlice, - int nextSlice, - int u, - TopologicalMesh::FaceHandle fh ) { - // pole vertex use "midpoint" texCoord - Scalar bu = topoTexCoords[baseSlice][0]; - Scalar nu = ( u == SLICES - 1 ) ? 0_ra : topoTexCoords[nextSlice][0]; - Scalar tu = ( bu + nu ) * .5_ra; - wedgeSetter( id, fh, Vector3( 0, 0, north ? 1 : -1 ), Vector3( tu, north ? 0 : 1, 0 ) ); - }; + auto wedgeSetterPole = [wedgeSetter, &topoTexCoords, whNormal, whTexCoord, SLICES]( + bool north, + int id, + int baseSlice, + int nextSlice, + uint u, + TopologicalMesh::FaceHandle fh ) { + // pole vertex use "midpoint" texCoord + Scalar bu = topoTexCoords[baseSlice][0]; + Scalar nu = ( u == SLICES - 1 ) ? 0_ra : topoTexCoords[nextSlice][0]; + Scalar tu = ( bu + nu ) * .5_ra; + wedgeSetter( id, fh, Vector3( 0, 0, north ? 1 : -1 ), Vector3( tu, north ? 0 : 1, 0 ) ); + }; for ( uint u = 0; u < SLICES; ++u ) { for ( uint v = 2; v < STACKS; ++v ) { @@ -308,15 +310,16 @@ makeParametricSphere( Scalar radius, const Utils::optional& color, return result; } -template -QuadMesh makeParametricTorus( Scalar majorRadius, - Scalar minorRadius, - const Utils::optional& color, - bool generateTexCoord ) { - QuadMesh result; - QuadMesh::PointAttribHandle::Container vertices; - QuadMesh::NormalAttribHandle::Container normals; - QuadMesh::IndexContainerType indices; +inline MultiIndexedGeometry makeParametricTorus( Scalar majorRadius, + Scalar minorRadius, + const Utils::optional& color, + bool generateTexCoord, + const uint U, + const uint V ) { + MultiIndexedGeometry result; + MultiIndexedGeometry::PointAttribHandle::Container vertices; + MultiIndexedGeometry::NormalAttribHandle::Container normals; + QuadIndexLayer::IndexContainerType indices; Ra::Core::Vector3Array texCoords; vertices.reserve( ( U + 1 ) * ( V + 1 ) ); @@ -353,7 +356,7 @@ QuadMesh makeParametricTorus( Scalar majorRadius, result.setVertices( std::move( vertices ) ); result.setNormals( std::move( normals ) ); - result.setIndices( std::move( indices ) ); + result.set_indices( std::move( indices ) ); if ( generateTexCoord ) result.addAttrib( getAttribName( MeshAttrib::VERTEX_TEXCOORD ), std::move( texCoords ) ); if ( color ) result.colorize( *color ); diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index c5a433f5686..351f400ded7 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -283,7 +283,7 @@ GeometryDisplayablePtr ParametricSphere( const Core::Vector3& center, Scalar radius, const Core::Utils::Color& color, bool generateTexCoord ) { - auto geom = makeParametricSphere<32, 32>( radius, color, generateTexCoord ); + auto geom = makeParametricSphere( radius, color, generateTexCoord, 32, 32 ); auto handle = geom.getAttribHandle( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_POSITION ) ); auto& vertices = geom.getAttrib( handle ); diff --git a/src/Gui/Viewer/Gizmo/RotateGizmo.cpp b/src/Gui/Viewer/Gizmo/RotateGizmo.cpp index 35ad710300a..7f36bc5abd4 100644 --- a/src/Gui/Viewer/Gizmo/RotateGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/RotateGizmo.cpp @@ -24,8 +24,8 @@ RotateGizmo::RotateGizmo( Engine::Scene::Component* c, constexpr Scalar torusAspectRatio = .08_ra; // For x,y,z for ( uint i = 0; i < 3; ++i ) { - auto torus = Core::Geometry::makeParametricTorus<32>( torusOutRadius, - torusAspectRatio * torusOutRadius ); + auto torus = Core::Geometry::makeParametricTorus( + torusOutRadius, torusAspectRatio * torusOutRadius, {}, false, 32, 32 ); // Transform the torus from z-axis to axis i. auto& data = torus.verticesWithLock(); for ( auto& v : data ) { From 8231958137771cfd752e3965874c8727af360081 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 10:30:07 +0200 Subject: [PATCH 115/144] [core] Move makeParametricShpere (and Torus) implem to .cpp. --- src/Core/Geometry/MeshPrimitives.cpp | 204 +++++++++++++++++++++++++++ src/Core/Geometry/MeshPrimitives.hpp | 202 -------------------------- 2 files changed, 204 insertions(+), 202 deletions(-) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index 097a5853637..e2e1ee4aa88 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include // areApproxEqual #include @@ -1056,6 +1058,208 @@ QuadMesh makePlaneGrid( const uint rows, return result; } + +MultiIndexedGeometry makeParametricSphere( Scalar radius, + const Utils::optional& color, + bool gtc, + const uint SLICES, + const uint STACKS ) { + + const Scalar du = 1_ra / SLICES; + const Scalar dv = 1_ra / STACKS; + using WAI = TopologicalMesh::WedgeAttribIndex; + TopologicalMesh topoMesh; + auto whNormal = topoMesh.addWedgeAttrib( getAttribName( MeshAttrib::VERTEX_NORMAL ) ); + + WAI whColor = + color ? topoMesh.addWedgeAttrib( getAttribName( MeshAttrib::VERTEX_COLOR ) ) + : WAI::Invalid(); + WAI whTexCoord = + gtc ? topoMesh.addWedgeAttrib( getAttribName( MeshAttrib::VERTEX_TEXCOORD ) ) + : WAI::Invalid(); + + std::vector vhandles; + vhandles.resize( ( STACKS - 1 ) * SLICES + 2 ); + Vector3Array topoTexCoords; + topoTexCoords.reserve( ( STACKS - 1 ) * SLICES + 2 + 2 * SLICES ); + Vector3Array topoNormals; + topoNormals.reserve( ( STACKS - 1 ) * SLICES + 2 ); + + uint index = 0; + // check https://en.wikipedia.org/wiki/Spherical_coordinate_system + // theta \in [0, pi] + // phi \in [0, 2pi] + const Scalar uFactor = 2_ra / static_cast( SLICES ) * Core::Math::Pi; + const Scalar vFactor = Core::Math::Pi / STACKS; + for ( uint u = 0; u < SLICES; ++u ) { + const Scalar phi = u * uFactor; + for ( uint v = 1; v < STACKS; ++v ) { + // Regular vertices on the sphere. + const Scalar theta = v * vFactor; + Vector3 p = Vector3( radius * std::cos( phi ) * std::sin( theta ), + radius * std::sin( phi ) * std::sin( theta ), + radius * std::cos( theta ) ); + vhandles[index++] = topoMesh.add_vertex( p ); + topoNormals.push_back( p.normalized() ); + topoTexCoords.emplace_back( 1_ra - u * du, v * dv, 0_ra ); + } + } + + // Add the pole vertices. + auto topoNorthPoleIdx = ( STACKS - 1 ) * SLICES; + auto topoSouthPoleIdx = topoNorthPoleIdx + 1; + vhandles[topoNorthPoleIdx] = topoMesh.add_vertex( Vector3( 0, 0, radius ) ); + vhandles[topoSouthPoleIdx] = topoMesh.add_vertex( Vector3( 0, 0, -radius ) ); + + // Set wedge for fh, vhIndex to n and t. + auto wedgeSetter = [&topoMesh, &vhandles, color, whNormal, whTexCoord, whColor, gtc]( + int vhIndex, TopologicalMesh::FaceHandle fh, Vector3 n, Vector3 t ) { + auto heh = topoMesh.halfedge_handle( vhandles[vhIndex], fh ); + auto wd = topoMesh.newWedgeData( heh ); + wd.m_vector3Attrib[whNormal] = n; + if ( gtc ) wd.m_vector3Attrib[whTexCoord] = t; + if ( color ) wd.m_vector4Attrib[whColor] = *color; + topoMesh.replaceWedge( heh, wd ); + }; + + // For general vertices retrieve normals and texCoords from vhIndex + auto wedgeSetterGeneric = [wedgeSetter, &topoNormals, &topoTexCoords, whNormal, whTexCoord]( + int vhIndex, TopologicalMesh::FaceHandle fh ) { + wedgeSetter( vhIndex, fh, topoNormals[vhIndex], topoTexCoords[vhIndex] ); + }; + + // take seams into account when u =1 + auto wedgeSetterSeam = + [wedgeSetter, &topoTexCoords, &topoNormals, whNormal, whTexCoord, SLICES]( + uint u, int vhIndex, TopologicalMesh::FaceHandle fh ) { + Vector3 t = topoTexCoords[vhIndex]; + if ( u == SLICES - 1 ) t[0] = 0_ra; + wedgeSetter( vhIndex, fh, topoNormals[vhIndex], t ); + }; + + // special for poles + auto wedgeSetterPole = [wedgeSetter, &topoTexCoords, whNormal, whTexCoord, SLICES]( + bool north, + int id, + int baseSlice, + int nextSlice, + uint u, + TopologicalMesh::FaceHandle fh ) { + // pole vertex use "midpoint" texCoord + Scalar bu = topoTexCoords[baseSlice][0]; + Scalar nu = ( u == SLICES - 1 ) ? 0_ra : topoTexCoords[nextSlice][0]; + Scalar tu = ( bu + nu ) * .5_ra; + wedgeSetter( id, fh, Vector3( 0, 0, north ? 1 : -1 ), Vector3( tu, north ? 0 : 1, 0 ) ); + }; + + for ( uint u = 0; u < SLICES; ++u ) { + for ( uint v = 2; v < STACKS; ++v ) { + const uint nextSlice = ( ( u + 1 ) % SLICES ) * ( STACKS - 1 ); + const uint baseSlice = u * ( STACKS - 1 ); + std::vector vindices = { baseSlice + v - 2, + baseSlice + v - 1, + nextSlice + v - 1, + baseSlice + v - 2, + nextSlice + v - 1, + nextSlice + v - 2 }; + + auto fh1 = topoMesh.add_face( + { vhandles[vindices[0]], vhandles[vindices[1]], vhandles[vindices[2]] } ); + auto fh2 = topoMesh.add_face( + { vhandles[vindices[3]], vhandles[vindices[4]], vhandles[vindices[5]] } ); + + wedgeSetterGeneric( baseSlice + v - 2, fh1 ); + wedgeSetterGeneric( baseSlice + v - 1, fh1 ); + wedgeSetterGeneric( baseSlice + v - 2, fh2 ); + + wedgeSetterSeam( u, nextSlice + v - 1, fh1 ); + wedgeSetterSeam( u, nextSlice + v - 1, fh2 ); + wedgeSetterSeam( u, nextSlice + v - 2, fh2 ); + } + } + // caps faces + for ( uint u = 0; u < SLICES; ++u ) { + const uint nextSlice = ( ( u + 1 ) % SLICES ) * ( STACKS - 1 ); + const uint baseSlice = u * ( STACKS - 1 ); + + auto fh1 = topoMesh.add_face( + { vhandles[topoNorthPoleIdx], vhandles[baseSlice], vhandles[nextSlice] } ); + auto fh2 = topoMesh.add_face( { vhandles[topoSouthPoleIdx], + vhandles[nextSlice + STACKS - 2], + vhandles[baseSlice + STACKS - 2] } ); + + wedgeSetterGeneric( baseSlice, fh1 ); + wedgeSetterGeneric( baseSlice + STACKS - 2, fh2 ); + wedgeSetterSeam( u, nextSlice, fh1 ); + wedgeSetterSeam( u, nextSlice + STACKS - 2, fh2 ); + + // pole vertex use "midpoint" texCoord + wedgeSetterPole( true, topoNorthPoleIdx, baseSlice, nextSlice, u, fh1 ); + wedgeSetterPole( false, topoSouthPoleIdx, baseSlice, nextSlice, u, fh2 ); + } + + topoMesh.mergeEqualWedges(); + topoMesh.garbage_collection(); + auto result = topoMesh.toTriangleMesh(); + result.checkConsistency(); + return result; +} + +MultiIndexedGeometry makeParametricTorus( Scalar majorRadius, + Scalar minorRadius, + const Utils::optional& color, + bool generateTexCoord, + const uint U, + const uint V ) { + MultiIndexedGeometry result; + MultiIndexedGeometry::PointAttribHandle::Container vertices; + MultiIndexedGeometry::NormalAttribHandle::Container normals; + QuadIndexLayer::IndexContainerType indices; + Ra::Core::Vector3Array texCoords; + + vertices.reserve( ( U + 1 ) * ( V + 1 ) ); + normals.reserve( ( U + 1 ) * ( V + 1 ) ); + indices.reserve( 2 * U * V ); + texCoords.reserve( ( U + 1 ) * ( V + 1 ) ); + + const Scalar du = 1_ra / U; + const Scalar dv = 1_ra / V; + + for ( uint iu = 0; iu <= U; ++iu ) { + Scalar u = Scalar( iu ) * Core::Math::PiMul2 / Scalar( U ); + Core::Vector3 circleCenter( majorRadius * std::cos( u ), majorRadius * std::sin( u ), 0.f ); + + for ( uint iv = 0; iv <= V; ++iv ) { + Scalar v = Scalar( iv ) * Core::Math::PiMul2 / Scalar( V ); + + Core::Vector3 vertex( ( majorRadius + minorRadius * std::cos( v ) ) * std::cos( u ), + ( majorRadius + minorRadius * std::cos( v ) ) * std::sin( u ), + minorRadius * std::sin( v ) ); + + vertices.push_back( vertex ); + normals.push_back( ( vertex - circleCenter ).normalized() ); + texCoords.emplace_back( iu * du, iv * dv, 0_ra ); + + if ( iu != U && iv != V ) { + indices.emplace_back( iu * ( V + 1 ) + iv, + ( iu + 1 ) * ( V + 1 ) + iv, + ( iu + 1 ) * ( V + 1 ) + ( iv + 1 ), + iu * ( V + 1 ) + ( iv + 1 ) ); + } + } + } + + result.setVertices( std::move( vertices ) ); + result.setNormals( std::move( normals ) ); + result.set_indices( std::move( indices ) ); + if ( generateTexCoord ) + result.addAttrib( getAttribName( MeshAttrib::VERTEX_TEXCOORD ), std::move( texCoords ) ); + if ( color ) result.colorize( *color ); + result.checkConsistency(); + + return result; +} + } // namespace Geometry } // namespace Core } // namespace Ra diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index 4c02ed8c342..9473ae2e9ec 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -2,8 +2,6 @@ #include #include -#include -#include #include #include #include @@ -164,206 +162,6 @@ RA_CORE_API MultiIndexedGeometry makeCone( const Vector3& base, uint nFaces = 32, const Utils::optional& color = {} ); -inline MultiIndexedGeometry makeParametricSphere( Scalar radius, - const Utils::optional& color, - bool gtc, - const uint SLICES, - const uint STACKS ) { - - const Scalar du = 1_ra / SLICES; - const Scalar dv = 1_ra / STACKS; - using WAI = TopologicalMesh::WedgeAttribIndex; - TopologicalMesh topoMesh; - auto whNormal = topoMesh.addWedgeAttrib( getAttribName( MeshAttrib::VERTEX_NORMAL ) ); - - WAI whColor = - color ? topoMesh.addWedgeAttrib( getAttribName( MeshAttrib::VERTEX_COLOR ) ) - : WAI::Invalid(); - WAI whTexCoord = - gtc ? topoMesh.addWedgeAttrib( getAttribName( MeshAttrib::VERTEX_TEXCOORD ) ) - : WAI::Invalid(); - - std::vector vhandles; - vhandles.resize( ( STACKS - 1 ) * SLICES + 2 ); - Vector3Array topoTexCoords; - topoTexCoords.reserve( ( STACKS - 1 ) * SLICES + 2 + 2 * SLICES ); - Vector3Array topoNormals; - topoNormals.reserve( ( STACKS - 1 ) * SLICES + 2 ); - - uint index = 0; - // check https://en.wikipedia.org/wiki/Spherical_coordinate_system - // theta \in [0, pi] - // phi \in [0, 2pi] - const Scalar uFactor = 2_ra / static_cast( SLICES ) * Core::Math::Pi; - const Scalar vFactor = Core::Math::Pi / STACKS; - for ( uint u = 0; u < SLICES; ++u ) { - const Scalar phi = u * uFactor; - for ( uint v = 1; v < STACKS; ++v ) { - // Regular vertices on the sphere. - const Scalar theta = v * vFactor; - Vector3 p = Vector3( radius * std::cos( phi ) * std::sin( theta ), - radius * std::sin( phi ) * std::sin( theta ), - radius * std::cos( theta ) ); - vhandles[index++] = topoMesh.add_vertex( p ); - topoNormals.push_back( p.normalized() ); - topoTexCoords.emplace_back( 1_ra - u * du, v * dv, 0_ra ); - } - } - - // Add the pole vertices. - auto topoNorthPoleIdx = ( STACKS - 1 ) * SLICES; - auto topoSouthPoleIdx = topoNorthPoleIdx + 1; - vhandles[topoNorthPoleIdx] = topoMesh.add_vertex( Vector3( 0, 0, radius ) ); - vhandles[topoSouthPoleIdx] = topoMesh.add_vertex( Vector3( 0, 0, -radius ) ); - - // Set wedge for fh, vhIndex to n and t. - auto wedgeSetter = [&topoMesh, &vhandles, color, whNormal, whTexCoord, whColor, gtc]( - int vhIndex, TopologicalMesh::FaceHandle fh, Vector3 n, Vector3 t ) { - auto heh = topoMesh.halfedge_handle( vhandles[vhIndex], fh ); - auto wd = topoMesh.newWedgeData( heh ); - wd.m_vector3Attrib[whNormal] = n; - if ( gtc ) wd.m_vector3Attrib[whTexCoord] = t; - if ( color ) wd.m_vector4Attrib[whColor] = *color; - topoMesh.replaceWedge( heh, wd ); - }; - - // For general vertices retrieve normals and texCoords from vhIndex - auto wedgeSetterGeneric = [wedgeSetter, &topoNormals, &topoTexCoords, whNormal, whTexCoord]( - int vhIndex, TopologicalMesh::FaceHandle fh ) { - wedgeSetter( vhIndex, fh, topoNormals[vhIndex], topoTexCoords[vhIndex] ); - }; - - // take seams into account when u =1 - auto wedgeSetterSeam = - [wedgeSetter, &topoTexCoords, &topoNormals, whNormal, whTexCoord, SLICES]( - uint u, int vhIndex, TopologicalMesh::FaceHandle fh ) { - Vector3 t = topoTexCoords[vhIndex]; - if ( u == SLICES - 1 ) t[0] = 0_ra; - wedgeSetter( vhIndex, fh, topoNormals[vhIndex], t ); - }; - - // special for poles - auto wedgeSetterPole = [wedgeSetter, &topoTexCoords, whNormal, whTexCoord, SLICES]( - bool north, - int id, - int baseSlice, - int nextSlice, - uint u, - TopologicalMesh::FaceHandle fh ) { - // pole vertex use "midpoint" texCoord - Scalar bu = topoTexCoords[baseSlice][0]; - Scalar nu = ( u == SLICES - 1 ) ? 0_ra : topoTexCoords[nextSlice][0]; - Scalar tu = ( bu + nu ) * .5_ra; - wedgeSetter( id, fh, Vector3( 0, 0, north ? 1 : -1 ), Vector3( tu, north ? 0 : 1, 0 ) ); - }; - - for ( uint u = 0; u < SLICES; ++u ) { - for ( uint v = 2; v < STACKS; ++v ) { - const uint nextSlice = ( ( u + 1 ) % SLICES ) * ( STACKS - 1 ); - const uint baseSlice = u * ( STACKS - 1 ); - std::vector vindices = { baseSlice + v - 2, - baseSlice + v - 1, - nextSlice + v - 1, - baseSlice + v - 2, - nextSlice + v - 1, - nextSlice + v - 2 }; - - auto fh1 = topoMesh.add_face( - { vhandles[vindices[0]], vhandles[vindices[1]], vhandles[vindices[2]] } ); - auto fh2 = topoMesh.add_face( - { vhandles[vindices[3]], vhandles[vindices[4]], vhandles[vindices[5]] } ); - - wedgeSetterGeneric( baseSlice + v - 2, fh1 ); - wedgeSetterGeneric( baseSlice + v - 1, fh1 ); - wedgeSetterGeneric( baseSlice + v - 2, fh2 ); - - wedgeSetterSeam( u, nextSlice + v - 1, fh1 ); - wedgeSetterSeam( u, nextSlice + v - 1, fh2 ); - wedgeSetterSeam( u, nextSlice + v - 2, fh2 ); - } - } - // caps faces - for ( uint u = 0; u < SLICES; ++u ) { - const uint nextSlice = ( ( u + 1 ) % SLICES ) * ( STACKS - 1 ); - const uint baseSlice = u * ( STACKS - 1 ); - - auto fh1 = topoMesh.add_face( - { vhandles[topoNorthPoleIdx], vhandles[baseSlice], vhandles[nextSlice] } ); - auto fh2 = topoMesh.add_face( { vhandles[topoSouthPoleIdx], - vhandles[nextSlice + STACKS - 2], - vhandles[baseSlice + STACKS - 2] } ); - - wedgeSetterGeneric( baseSlice, fh1 ); - wedgeSetterGeneric( baseSlice + STACKS - 2, fh2 ); - wedgeSetterSeam( u, nextSlice, fh1 ); - wedgeSetterSeam( u, nextSlice + STACKS - 2, fh2 ); - - // pole vertex use "midpoint" texCoord - wedgeSetterPole( true, topoNorthPoleIdx, baseSlice, nextSlice, u, fh1 ); - wedgeSetterPole( false, topoSouthPoleIdx, baseSlice, nextSlice, u, fh2 ); - } - - topoMesh.mergeEqualWedges(); - topoMesh.garbage_collection(); - auto result = topoMesh.toTriangleMesh(); - result.checkConsistency(); - return result; -} - -inline MultiIndexedGeometry makeParametricTorus( Scalar majorRadius, - Scalar minorRadius, - const Utils::optional& color, - bool generateTexCoord, - const uint U, - const uint V ) { - MultiIndexedGeometry result; - MultiIndexedGeometry::PointAttribHandle::Container vertices; - MultiIndexedGeometry::NormalAttribHandle::Container normals; - QuadIndexLayer::IndexContainerType indices; - Ra::Core::Vector3Array texCoords; - - vertices.reserve( ( U + 1 ) * ( V + 1 ) ); - normals.reserve( ( U + 1 ) * ( V + 1 ) ); - indices.reserve( 2 * U * V ); - texCoords.reserve( ( U + 1 ) * ( V + 1 ) ); - - const Scalar du = 1_ra / U; - const Scalar dv = 1_ra / V; - - for ( uint iu = 0; iu <= U; ++iu ) { - Scalar u = Scalar( iu ) * Core::Math::PiMul2 / Scalar( U ); - Core::Vector3 circleCenter( majorRadius * std::cos( u ), majorRadius * std::sin( u ), 0.f ); - - for ( uint iv = 0; iv <= V; ++iv ) { - Scalar v = Scalar( iv ) * Core::Math::PiMul2 / Scalar( V ); - - Core::Vector3 vertex( ( majorRadius + minorRadius * std::cos( v ) ) * std::cos( u ), - ( majorRadius + minorRadius * std::cos( v ) ) * std::sin( u ), - minorRadius * std::sin( v ) ); - - vertices.push_back( vertex ); - normals.push_back( ( vertex - circleCenter ).normalized() ); - texCoords.emplace_back( iu * du, iv * dv, 0_ra ); - - if ( iu != U && iv != V ) { - indices.emplace_back( iu * ( V + 1 ) + iv, - ( iu + 1 ) * ( V + 1 ) + iv, - ( iu + 1 ) * ( V + 1 ) + ( iv + 1 ), - iu * ( V + 1 ) + ( iv + 1 ) ); - } - } - } - - result.setVertices( std::move( vertices ) ); - result.setNormals( std::move( normals ) ); - result.set_indices( std::move( indices ) ); - if ( generateTexCoord ) - result.addAttrib( getAttribName( MeshAttrib::VERTEX_TEXCOORD ), std::move( texCoords ) ); - if ( color ) result.colorize( *color ); - result.checkConsistency(); - - return result; -} } // namespace Geometry } // namespace Core } // namespace Ra From 47b73a99f2341e0a4a15c20793836d7e6f392246 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 10:30:38 +0200 Subject: [PATCH 116/144] [engine] iwyu (since core implem move to .cpp). --- src/Engine/Data/DrawPrimitives.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index 351f400ded7..b2203bb96f1 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -1,11 +1,12 @@ -#include "Core/Containers/VectorArray.hpp" #include #include +#include #include #include #include #include +#include #include #include From 0bc4cf1f0aec051474c29e337d8f18e63e5b3191 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 10:39:10 +0200 Subject: [PATCH 117/144] [core] use MultiIndexGeometry for makeGrid. --- src/Core/Geometry/MeshPrimitives.cpp | 20 ++++++++++---------- src/Core/Geometry/MeshPrimitives.hpp | 12 ++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index e2e1ee4aa88..ed3d39e96ca 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -937,18 +937,18 @@ MultiIndexedGeometry makeCone( const Vector3& base, return result; } -LineMesh makeGrid( const Core::Vector3& center, - const Core::Vector3& x, - const Core::Vector3& y, - const Core::Utils::Color& color, - Scalar cell_size, - uint res ) { +MultiIndexedGeometry makeGrid( const Core::Vector3& center, + const Core::Vector3& x, + const Core::Vector3& y, + const Core::Utils::Color& color, + Scalar cell_size, + uint res ) { CORE_ASSERT( res > 1, "Grid has to be at least a 2x2 grid." ); - LineMesh result; - TriangleMesh::PointAttribHandle::Container vertices; - auto indices = LineMesh::IndexContainerType {}; + MultiIndexedGeometry result; + MultiIndexedGeometry::PointAttribHandle::Container vertices; + auto indices = LineIndexLayer::IndexContainerType {}; vertices.reserve( 4 * ( res + 1 ) ); indices.reserve( 2 * ( res + 1 ) ); @@ -977,7 +977,7 @@ LineMesh makeGrid( const Core::Vector3& center, } result.setVertices( std::move( vertices ) ); - result.setIndices( std::move( indices ) ); + result.set_indices( std::move( indices ) ); result.colorize( color ); return result; diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index 9473ae2e9ec..0a260e368c1 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -30,12 +30,12 @@ RA_CORE_API QuadMesh makePlaneGrid( const uint rows = 1, /// Create a 2D grid, with only outer points, connected as lines, inner line intersctions are not /// present in verstices. -RA_CORE_API LineMesh makeGrid( const Core::Vector3& center, - const Core::Vector3& x, - const Core::Vector3& y, - const Core::Utils::Color& color, - Scalar cell_size, - uint res ); +RA_CORE_API MultiIndexedGeometry makeGrid( const Core::Vector3& center, + const Core::Vector3& x, + const Core::Vector3& y, + const Core::Utils::Color& color, + Scalar cell_size, + uint res ); /// Create a 2D quad mesh given half extents, centered on the origin with x axis as normal /// \see makePlaneGrid From 545f4267a7775980279c45ce4fe944cd43f2b1a0 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 10:43:08 +0200 Subject: [PATCH 118/144] [core] Remove old make*Box. --- src/Core/Geometry/MeshPrimitives.cpp | 185 --------------------------- src/Core/Geometry/MeshPrimitives.hpp | 34 ++--- 2 files changed, 8 insertions(+), 211 deletions(-) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index ed3d39e96ca..94785badff2 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -38,54 +38,6 @@ QuadMesh makeZNormalQuad( const Vector2& halfExts, return makePlaneGrid( 1, 1, halfExts, Transform::Identity(), color, generateTexCoord ); } -TriangleMesh makeBox( const Vector3& halfExts, const Utils::optional& color ) { - Aabb aabb( -halfExts, halfExts ); - return makeBox( aabb, color ); -} - -TriangleMesh makeBox( const Aabb& aabb, const Utils::optional& color ) { - TriangleMesh result; - result.setVertices( { aabb.corner( Aabb::BottomLeftFloor ), - aabb.corner( Aabb::BottomRightFloor ), - aabb.corner( Aabb::TopLeftFloor ), - aabb.corner( Aabb::TopRightFloor ), - aabb.corner( Aabb::BottomLeftCeil ), - aabb.corner( Aabb::BottomRightCeil ), - aabb.corner( Aabb::TopLeftCeil ), - aabb.corner( Aabb::TopRightCeil ) } ); - - static const Scalar a = 1_ra / std::sqrt( 3_ra ); - - result.setNormals( { Vector3( -a, -a, -a ), - Vector3( +a, -a, -a ), - Vector3( -a, +a, -a ), - Vector3( +a, +a, -a ), - Vector3( -a, -a, +a ), - Vector3( +a, -a, +a ), - Vector3( -a, +a, +a ), - Vector3( +a, +a, +a ) } ); - - result.setIndices( { - Vector3ui( 0, 2, 1 ), - Vector3ui( 1, 2, 3 ), // Floor - Vector3ui( 0, 1, 4 ), - Vector3ui( 4, 1, 5 ), // Front - Vector3ui( 3, 2, 6 ), - Vector3ui( 3, 6, 7 ), // Back - Vector3ui( 5, 1, 3 ), - Vector3ui( 5, 3, 7 ), // Right - Vector3ui( 2, 0, 4 ), - Vector3ui( 2, 4, 6 ), // Left - Vector3ui( 4, 5, 6 ), - Vector3ui( 6, 5, 7 ) // Top - } ); - - if ( bool( color ) ) result.colorize( *color ); - result.checkConsistency(); - - return result; -} - MultiIndexedGeometry makeBox2( const Vector3& halfExts, const Utils::optional& color ) { return makeBox2( -halfExts, @@ -147,13 +99,6 @@ MultiIndexedGeometry makeBox2( const Vector3& corner, return result; } -TriangleMesh makeSharpBox( const Vector3& halfExts, - const Utils::optional& color, - bool generateTexCoord ) { - Aabb aabb( -halfExts, halfExts ); - return makeSharpBox( aabb, color, generateTexCoord ); -} - MultiIndexedGeometry makeSharpBox2( const Aabb& aabb, const Utils::optional& color, bool generateTexCoord ) { @@ -299,136 +244,6 @@ MultiIndexedGeometry makeSharpBox2( const Vector3& halfExts, return makeSharpBox2( aabb, color, generateTexCoord ); } -TriangleMesh makeSharpBox( const Aabb& aabb, - const Utils::optional& color, - bool generateTexCoord ) { - TriangleMesh 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 ) ); - } - - result.setIndices( { - - Vector3ui( 0, 1, 2 ), - Vector3ui( 0, 2, 3 ), // Floor - Vector3ui( 4, 5, 6 ), - Vector3ui( 4, 6, 7 ), // Ceil - Vector3ui( 8, 9, 10 ), - Vector3ui( 8, 10, 11 ), // Left - Vector3ui( 12, 13, 14 ), - Vector3ui( 12, 14, 15 ), // Right - Vector3ui( 16, 17, 18 ), - Vector3ui( 16, 18, 19 ), // Bottom - Vector3ui( 20, 21, 22 ), - Vector3ui( 20, 22, 23 ) // Top - } ); - - if ( bool( color ) ) result.colorize( *color ); - result.checkConsistency(); - - return result; -} - MultiIndexedGeometry makeGeodesicSphere( Scalar radius, uint numSubdiv, const Utils::optional& color ) { MultiIndexedGeometry result; diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index 0a260e368c1..fe34f059763 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -28,15 +28,6 @@ RA_CORE_API QuadMesh makePlaneGrid( const uint rows = 1, const Utils::optional& color = {}, bool generateTexCoord = false ); -/// Create a 2D grid, with only outer points, connected as lines, inner line intersctions are not -/// present in verstices. -RA_CORE_API MultiIndexedGeometry makeGrid( const Core::Vector3& center, - const Core::Vector3& x, - const Core::Vector3& y, - const Core::Utils::Color& color, - Scalar cell_size, - uint res ); - /// Create a 2D quad mesh given half extents, centered on the origin with x axis as normal /// \see makePlaneGrid RA_CORE_API QuadMesh makeXNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), @@ -55,13 +46,14 @@ RA_CORE_API QuadMesh makeZNormalQuad( const Vector2& halfExts = Vector2( .5_ra, 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 TriangleMesh makeBox( const Vector3& halfExts = Vector3( .5_ra, .5_ra, .5_ra ), - const Utils::optional& color = {} ); - -/// Create an axis-aligned cubic mesh -RA_CORE_API TriangleMesh makeBox( const Aabb& aabb, - const Utils::optional& color = {} ); +/// Create a 2D grid, with only outer points, connected as lines, inner line intersctions are not +/// present in verstices. +RA_CORE_API MultiIndexedGeometry makeGrid( const Core::Vector3& center, + const Core::Vector3& x, + const Core::Vector3& y, + const Core::Utils::Color& color, + Scalar cell_size, + uint res ); /// Create an axis-aligned cubic mesh with the given half extents, centered on the origin. RA_CORE_API MultiIndexedGeometry makeBox2( const Vector3& halfExts = Vector3( .5_ra, .5_ra, .5_ra ), @@ -77,16 +69,6 @@ RA_CORE_API MultiIndexedGeometry makeBox2( const Vector3& corner, const Vector3& z, const Utils::optional& color ); -/// Create an axis-aligned cubic mesh with the given half extents, centered on the origin. -RA_CORE_API TriangleMesh makeSharpBox( 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 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, From 606ed17151f1006025e51261644b84935b385854 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 10:45:31 +0200 Subject: [PATCH 119/144] [core] Rename Box2 -> Box. --- src/Core/Geometry/MeshPrimitives.cpp | 50 ++++++++++++++-------------- src/Core/Geometry/MeshPrimitives.hpp | 34 +++++++++---------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index 94785badff2..f2ca4636c4c 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -38,29 +38,29 @@ QuadMesh makeZNormalQuad( const Vector2& halfExts, return makePlaneGrid( 1, 1, halfExts, Transform::Identity(), color, generateTexCoord ); } -MultiIndexedGeometry makeBox2( const Vector3& halfExts, - const Utils::optional& color ) { - return makeBox2( -halfExts, - Vector3 { 2_ra * halfExts.x(), 0, 0 }, - Vector3 { 0, 2_ra * halfExts.y(), 0 }, - Vector3 { 0, 0, 2_ra * halfExts.z() }, - color ); +MultiIndexedGeometry makeBox( const Vector3& halfExts, + const Utils::optional& color ) { + return makeBox( -halfExts, + Vector3 { 2_ra * halfExts.x(), 0, 0 }, + Vector3 { 0, 2_ra * halfExts.y(), 0 }, + Vector3 { 0, 0, 2_ra * halfExts.z() }, + color ); } -MultiIndexedGeometry makeBox2( const Aabb& aabb, const Utils::optional& color ) { +MultiIndexedGeometry makeBox( const Aabb& aabb, const Utils::optional& color ) { - return makeBox2( aabb.corner( Aabb::BottomLeftFloor ), - aabb.corner( Aabb::BottomRightFloor ) - aabb.corner( Aabb::BottomLeftFloor ), - aabb.corner( Aabb::BottomLeftCeil ) - aabb.corner( Aabb::BottomLeftFloor ), - aabb.corner( Aabb::TopLeftFloor ) - aabb.corner( Aabb::BottomLeftFloor ), - color ); + return makeBox( aabb.corner( Aabb::BottomLeftFloor ), + aabb.corner( Aabb::BottomRightFloor ) - aabb.corner( Aabb::BottomLeftFloor ), + aabb.corner( Aabb::BottomLeftCeil ) - aabb.corner( Aabb::BottomLeftFloor ), + aabb.corner( Aabb::TopLeftFloor ) - aabb.corner( Aabb::BottomLeftFloor ), + color ); } -MultiIndexedGeometry makeBox2( const Vector3& corner, - const Vector3& x, - const Vector3& y, - const Vector3& z, - const Utils::optional& color ) { +MultiIndexedGeometry makeBox( const Vector3& corner, + const Vector3& x, + const Vector3& y, + const Vector3& z, + const Utils::optional& color ) { MultiIndexedGeometry result; result.setVertices( { corner, corner + x, @@ -99,9 +99,9 @@ MultiIndexedGeometry makeBox2( const Vector3& corner, return result; } -MultiIndexedGeometry makeSharpBox2( const Aabb& aabb, - const Utils::optional& color, - bool generateTexCoord ) { +MultiIndexedGeometry makeSharpBox( const Aabb& aabb, + const Utils::optional& color, + bool generateTexCoord ) { MultiIndexedGeometry result; result.setVertices( { // Floor Face aabb.corner( Aabb::BottomLeftFloor ), @@ -237,11 +237,11 @@ MultiIndexedGeometry makeSharpBox2( const Aabb& aabb, return result; } -MultiIndexedGeometry makeSharpBox2( const Vector3& halfExts, - const Utils::optional& color, - bool generateTexCoord ) { +MultiIndexedGeometry makeSharpBox( const Vector3& halfExts, + const Utils::optional& color, + bool generateTexCoord ) { Aabb aabb( -halfExts, halfExts ); - return makeSharpBox2( aabb, color, generateTexCoord ); + return makeSharpBox( aabb, color, generateTexCoord ); } MultiIndexedGeometry diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index fe34f059763..3f9747a918c 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -56,30 +56,30 @@ RA_CORE_API MultiIndexedGeometry makeGrid( const Core::Vector3& center, uint res ); /// Create an axis-aligned cubic mesh with the given half extents, centered on the origin. -RA_CORE_API MultiIndexedGeometry makeBox2( const Vector3& halfExts = Vector3( .5_ra, .5_ra, .5_ra ), - const Utils::optional& color = {} ); +RA_CORE_API MultiIndexedGeometry makeBox( const Vector3& halfExts = Vector3( .5_ra, .5_ra, .5_ra ), + const Utils::optional& color = {} ); /// Create an axis-aligned cubic mesh -RA_CORE_API MultiIndexedGeometry makeBox2( const Aabb& aabb, - const Utils::optional& color = {} ); +RA_CORE_API MultiIndexedGeometry makeBox( const Aabb& aabb, + const Utils::optional& color = {} ); -RA_CORE_API MultiIndexedGeometry makeBox2( const Vector3& corner, - const Vector3& x, - const Vector3& y, - const Vector3& z, - const Utils::optional& color ); +RA_CORE_API MultiIndexedGeometry makeBox( const Vector3& corner, + const Vector3& x, + const Vector3& y, + const Vector3& z, + const Utils::optional& color ); /// 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 ); +RA_CORE_API MultiIndexedGeometry makeSharpBox( 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 ); +RA_CORE_API MultiIndexedGeometry makeSharpBox( 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 From a82d7c5f3bc95c5dff8089244943fd3c96dc0055 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 10:46:07 +0200 Subject: [PATCH 120/144] [engine][gui][...] Rename Box2 -> Box. --- examples/CoreExample/main.cpp | 2 +- examples/CustomCameraManipulator/main.cpp | 2 +- .../DrawPrimitives/AllPrimitivesComponent.cpp | 14 +++++++------- examples/EntityAnimation/main.cpp | 4 ++-- examples/EnvMap/main.cpp | 2 +- examples/HelloRadium/main.cpp | 2 +- examples/KeyEvent/main.cpp | 4 ++-- examples/Picking/main.cpp | 2 +- examples/SimpleAnimation/main.cpp | 2 +- examples/Volume/main.cpp | 4 ++-- src/Engine/Data/DrawPrimitives.cpp | 15 +++++++-------- src/Engine/Data/EnvironmentTexture.cpp | 2 +- src/Engine/Data/VolumeObject.cpp | 2 +- src/Gui/Viewer/Gizmo/ScaleGizmo.cpp | 2 +- tests/unittest/Core/indexview.cpp | 4 ++-- tests/unittest/Core/topomesh.cpp | 14 +++++++------- 16 files changed, 38 insertions(+), 39 deletions(-) diff --git a/examples/CoreExample/main.cpp b/examples/CoreExample/main.cpp index 708960d26b5..3039fc250ab 100644 --- a/examples/CoreExample/main.cpp +++ b/examples/CoreExample/main.cpp @@ -10,7 +10,7 @@ int main( int /*argc*/, char** /*argv*/ ) { using namespace Ra::Core; - auto box = Geometry::makeSharpBox2( { 1., 1., 1. } ); + auto box = Geometry::makeSharpBox( { 1., 1., 1. } ); auto topo = Geometry::TopologicalMesh( box ); auto resourcesPaths { Resources::getBasePath() }; diff --git a/examples/CustomCameraManipulator/main.cpp b/examples/CustomCameraManipulator/main.cpp index c77a6b173c0..daca836a68e 100644 --- a/examples/CustomCameraManipulator/main.cpp +++ b/examples/CustomCameraManipulator/main.cpp @@ -37,7 +37,7 @@ int main( int argc, char* argv[] ) { //! [Creating the application] //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); + auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); //! [Creating the cube] //! [Colorize the Cube] diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index f9826985e07..c60b8914fd5 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -141,7 +141,7 @@ void AllPrimitivesComponent::initialize() { auto coord = cellSize / 16_ra; { cube1->loadGeometry( - Geometry::makeSharpBox2( Vector3 { coord, coord, coord }, Color::Green() ) ); + Geometry::makeSharpBox( Vector3 { coord, coord, coord }, Color::Green() ) ); auto renderObject1 = RenderObject::createRenderObject( "Cube1", this, RenderObjectType::Geometry, cube1, {} ); renderObject1->setLocalTransform( Transform { Translation( cellCorner ) } ); @@ -151,9 +151,9 @@ void AllPrimitivesComponent::initialize() { { 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 ) ); + Geometry::makeSharpBox( 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, {} ); renderObjectTexCube->setLocalTransform( @@ -166,7 +166,7 @@ void AllPrimitivesComponent::initialize() { // another cube std::shared_ptr cube2( new GeometryDisplayable( "Cube" ) ); coord = cellSize / 4_ra; - cube2->loadGeometry( Geometry::makeSharpBox2( Vector3 { coord, coord, coord } ) ); + cube2->loadGeometry( Geometry::makeSharpBox( Vector3 { coord, coord, coord } ) ); const std::string myColourName { "colour" }; cube2->getCoreGeometry().addAttrib( @@ -189,7 +189,7 @@ void AllPrimitivesComponent::initialize() { auto x = Vector3 { coord, coord, 0 }; auto y = Vector3 { -coord, coord, 0 }; cube3->loadGeometry( - Geometry::makeBox2( c, x, y, x.cross( y ) / x.norm(), Color::Yellow() ) ); + Geometry::makeBox( c, x, y, x.cross( y ) / x.norm(), Color::Yellow() ) ); auto renderObject3 = RenderObject::createRenderObject( "Cube3", this, RenderObjectType::Geometry, cube3, {} ); renderObject3->setMaterial( blinnPhongMaterial ); @@ -1215,7 +1215,7 @@ void AllPrimitivesComponent::initialize() { boxBounds.extend( Core::Vector3( -radius * 2_ra, -radius * 2_ra, -radius * 2_ra ) ); boxBounds.extend( Core::Vector3( radius * 2_ra, radius * 2_ra, radius * 2_ra ) ); boxBounds.translate( arrowScale * cylinderEnd + startPoint ); - auto box = Core::Geometry::makeSharpBox2( boxBounds, Color::Yellow() ); + auto box = Core::Geometry::makeSharpBox( boxBounds, Color::Yellow() ); // box is quads, need triangulate before append box.triangulate(); diff --git a/examples/EntityAnimation/main.cpp b/examples/EntityAnimation/main.cpp index 3d9241c17e5..8911e5ed02b 100644 --- a/examples/EntityAnimation/main.cpp +++ b/examples/EntityAnimation/main.cpp @@ -114,7 +114,7 @@ int main( int argc, char* argv[] ) { //! [Create the engine entity for the fixed component] //! [Creating the cube] - auto cube = Geometry::makeSharpBox2( { 0.5f, 0.5f, 0.5f }, Utils::Color::Green() ); + auto cube = Geometry::makeSharpBox( { 0.5f, 0.5f, 0.5f }, Utils::Color::Green() ); //! [Creating the Cube] //! [Create a geometry component with the cube] @@ -140,7 +140,7 @@ int main( int argc, char* argv[] ) { //! [attach components to the animated entity ] // an animated yellow cube auto cube = - Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f }, Ra::Core::Utils::Color::Yellow() ); + Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f }, Ra::Core::Utils::Color::Yellow() ); new Scene::SurfaceMeshComponent( "Fixed cube geometry", e, std::move( cube ), nullptr ); // an animated camera, thay is not the one active at startup. Use key '0' to activate diff --git a/examples/EnvMap/main.cpp b/examples/EnvMap/main.cpp index ebf3d1b94f4..d2621738ba3 100644 --- a/examples/EnvMap/main.cpp +++ b/examples/EnvMap/main.cpp @@ -73,7 +73,7 @@ int main( int argc, char* argv[] ) { //! [Setting the envmap on the renderer] //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); + auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); //! [Creating the cube] //! [Colorize the Cube] diff --git a/examples/HelloRadium/main.cpp b/examples/HelloRadium/main.cpp index 6132e526dcb..da072516e52 100644 --- a/examples/HelloRadium/main.cpp +++ b/examples/HelloRadium/main.cpp @@ -27,7 +27,7 @@ int main( int argc, char* argv[] ) { //! [Verifying the OpenGL version available to the engine] //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); + auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); //! [Creating the cube] //! [Colorize the Cube] diff --git a/examples/KeyEvent/main.cpp b/examples/KeyEvent/main.cpp index 89cdf13cd2b..f8bdd131eff 100644 --- a/examples/KeyEvent/main.cpp +++ b/examples/KeyEvent/main.cpp @@ -24,7 +24,7 @@ /** * Simple custom windows for custom KeyEvent demonstration */ -using Ra::Core::Geometry::makeSharpBox2; +using Ra::Core::Geometry::makeSharpBox; class DemoWindow : public Ra::Gui::SimpleWindow { @@ -137,7 +137,7 @@ int main( int argc, char* argv[] ) { //! [Creating the application] //! [Creating the cube] - auto cube = makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); + auto cube = makeSharpBox( { 0.1f, 0.1f, 0.1f } ); //! [Creating the cube] //! [Colorize the Cube] diff --git a/examples/Picking/main.cpp b/examples/Picking/main.cpp index 72bec06a473..b06fac48523 100644 --- a/examples/Picking/main.cpp +++ b/examples/Picking/main.cpp @@ -119,7 +119,7 @@ class DemoWindowFactory : public Ra::Gui::BaseApplication::WindowFactory }; void addDummyScene( Ra::Gui::BaseApplication& app ) { - auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); + auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); auto e = app.m_engine->getEntityManager()->createEntity( "Cube" ); auto c = new Ra::Engine::Scene::SurfaceMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr ); diff --git a/examples/SimpleAnimation/main.cpp b/examples/SimpleAnimation/main.cpp index 6b84071a5cf..a260e788d93 100644 --- a/examples/SimpleAnimation/main.cpp +++ b/examples/SimpleAnimation/main.cpp @@ -140,7 +140,7 @@ int main( int argc, char* argv[] ) { //! [Create the demo animated component] //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.1f, 0.1f, 0.1f } ); + auto cube = Ra::Core::Geometry::makeSharpBox( { 0.1f, 0.1f, 0.1f } ); //! [Creating the cube] //! [Create the engine entity for the cube] diff --git a/examples/Volume/main.cpp b/examples/Volume/main.cpp index b033ce28497..37083eb6830 100644 --- a/examples/Volume/main.cpp +++ b/examples/Volume/main.cpp @@ -71,7 +71,7 @@ int main( int argc, char* argv[] ) { geometrySystem->addComponent( e, c ); //! [Register the entity/component association to the geometry system ] //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.5f, 0.5f, 1.f } ); + auto cube = Ra::Core::Geometry::makeSharpBox( { 0.5f, 0.5f, 1.f } ); //! [Creating the cube] //! [Colorize the Cube] @@ -110,7 +110,7 @@ int main( int argc, char* argv[] ) { auto geometrySystem = app.m_engine->getSystem( "GeometrySystem" ); //! [Creating the cube] - auto cube = Ra::Core::Geometry::makeSharpBox2( { 0.5_ra, 0.05_ra, 0.5_ra } ); + auto cube = Ra::Core::Geometry::makeSharpBox( { 0.5_ra, 0.05_ra, 0.5_ra } ); //! [Creating the cube] //! [Colorize the Cube] diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index b2203bb96f1..e064a8370fc 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -477,7 +477,7 @@ GeometryDisplayablePtr Grid( const Core::Vector3& center, } GeometryDisplayablePtr AABB( const Core::Aabb& aabb, const Core::Utils::Color& color ) { - auto geom = makeSharpBox2( aabb, color ); + auto geom = makeSharpBox( aabb, color ); auto ret = make_shared( "AABB Primitive", std::move( geom ) ); auto [key, layer] = ret->getCoreGeometry().getFirstLayerOccurrence( Core::Geometry::LineIndexLayer::staticSemanticName ); @@ -489,13 +489,12 @@ GeometryDisplayablePtr AABB( const Core::Aabb& aabb, const Core::Utils::Color& c GeometryDisplayablePtr OBB( const Obb& obb, const Core::Utils::Color& color ) { - auto geom = - makeBox2( obb.corner( Aabb::BottomLeftFloor ), - obb.corner( Aabb::BottomRightFloor ) - obb.corner( Aabb::BottomLeftFloor ), - obb.corner( Aabb::BottomLeftCeil ) - obb.corner( Aabb::BottomLeftFloor ), - obb.corner( Aabb::TopLeftFloor ) - obb.corner( Aabb::BottomLeftFloor ), - color ); - auto ret = make_shared( "AABB Primitive", std::move( geom ) ); + auto geom = makeBox( obb.corner( Aabb::BottomLeftFloor ), + obb.corner( Aabb::BottomRightFloor ) - obb.corner( Aabb::BottomLeftFloor ), + obb.corner( Aabb::BottomLeftCeil ) - obb.corner( Aabb::BottomLeftFloor ), + obb.corner( Aabb::TopLeftFloor ) - obb.corner( Aabb::BottomLeftFloor ), + color ); + auto ret = make_shared( "AABB Primitive", std::move( geom ) ); auto [key, layer] = ret->getCoreGeometry().getFirstLayerOccurrence( Core::Geometry::LineIndexLayer::staticSemanticName ); diff --git a/src/Engine/Data/EnvironmentTexture.cpp b/src/Engine/Data/EnvironmentTexture.cpp index a59637b7533..90a7f48fe7a 100644 --- a/src/Engine/Data/EnvironmentTexture.cpp +++ b/src/Engine/Data/EnvironmentTexture.cpp @@ -198,7 +198,7 @@ void EnvironmentTexture::initializeTexture() { if ( m_isSkyBox ) { // make the skybox geometry Aabb aabb( Vector3 { -1_ra, -1_ra, -1_ra }, Vector3 { 1_ra, 1_ra, 1_ra } ); - auto skyMesh = Geometry::makeSharpBox2( aabb ); + auto skyMesh = Geometry::makeSharpBox( aabb ); m_displayMesh = std::make_unique( "skyBox", std::move( skyMesh ) ); } diff --git a/src/Engine/Data/VolumeObject.cpp b/src/Engine/Data/VolumeObject.cpp index f40b1b927f3..d9db7219958 100644 --- a/src/Engine/Data/VolumeObject.cpp +++ b/src/Engine/Data/VolumeObject.cpp @@ -18,7 +18,7 @@ VolumeObject::~VolumeObject() {} void VolumeObject::loadGeometry( Core::Geometry::AbstractVolume* volume, const Core::Aabb& aabb ) { if ( volume != nullptr && volume->isDense() ) { - m_mesh.loadGeometry( Core::Geometry::makeSharpBox2( aabb ) ); + m_mesh.loadGeometry( Core::Geometry::makeSharpBox( aabb ) ); Core::Geometry::VolumeGrid* grid = static_cast( volume ); m_volume = std::unique_ptr( volume ); diff --git a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp index 7083900dae4..e128dc01f40 100644 --- a/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp +++ b/src/Gui/Viewer/Gizmo/ScaleGizmo.cpp @@ -41,7 +41,7 @@ ScaleGizmo::ScaleGizmo( Engine::Scene::Component* c, boxBounds.extend( Core::Vector3( -radius * 2_ra, -radius * 2_ra, -radius * 2_ra ) ); boxBounds.extend( Core::Vector3( radius * 2_ra, radius * 2_ra, radius * 2_ra ) ); boxBounds.translate( arrowScale * cylinderEnd ); - auto box = Core::Geometry::makeSharpBox2( boxBounds ); + auto box = Core::Geometry::makeSharpBox( boxBounds ); // box is quads, need triangulate before append box.triangulate_any(); diff --git a/tests/unittest/Core/indexview.cpp b/tests/unittest/Core/indexview.cpp index 0b6010eb822..8d7933ae61c 100644 --- a/tests/unittest/Core/indexview.cpp +++ b/tests/unittest/Core/indexview.cpp @@ -64,7 +64,7 @@ TEST_CASE( "Core/Geometry/IndexedGeometry", "[unittests][Core][Core/Geometry][In std::set keys; // copy AttribArrayGeometry; - MultiIndexedGeometry geom { Ra::Core::Geometry::makeBox2() }; + MultiIndexedGeometry geom { Ra::Core::Geometry::makeBox() }; // makeBox create quads, now get triangles geom.triangulate_any(); @@ -139,7 +139,7 @@ TEST_CASE( "Core/Geometry/IndexedGeometry/Attributes", using Ra::Core::Utils::ObjectWithSemantic; using Vec3AttribHandle = AttribArrayGeometry::Vec3AttribHandle; - MultiIndexedGeometry mesh( Ra::Core::Geometry::makeBox2() ); + MultiIndexedGeometry mesh( Ra::Core::Geometry::makeBox() ); // base attributes are automatically added auto h_pos = mesh.getAttribHandle( getAttribName( VERTEX_POSITION ) ); diff --git a/tests/unittest/Core/topomesh.cpp b/tests/unittest/Core/topomesh.cpp index c8ecbb5df6c..b94e5b72fe7 100644 --- a/tests/unittest/Core/topomesh.cpp +++ b/tests/unittest/Core/topomesh.cpp @@ -264,8 +264,8 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To } SECTION( "Closed mesh" ) { - testConverter1( Ra::Core::Geometry::makeBox2() ); - testConverter1( Ra::Core::Geometry::makeSharpBox2() ); + testConverter1( Ra::Core::Geometry::makeBox() ); + testConverter1( Ra::Core::Geometry::makeSharpBox() ); } SECTION( "Mesh with boundaries" ) { @@ -299,7 +299,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To { 0_ra, 1_ra }, { 0_ra, 0_ra } }; - auto mesh = Ra::Core::Geometry::makeBox2(); + auto mesh = Ra::Core::Geometry::makeBox(); auto layer_key = mesh.triangulate(); auto handle2 = mesh.addAttrib( "vector2_attrib" ); auto handle4 = mesh.addAttrib( "vector4_attrib" ); @@ -370,7 +370,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To } SECTION( "Test normals" ) { - auto mesh = Ra::Core::Geometry::makeBox2(); + auto mesh = Ra::Core::Geometry::makeBox(); auto topologicalMesh = TopologicalMesh( mesh ); for ( TopologicalMesh::ConstVertexIter v_it = topologicalMesh.vertices_begin(); @@ -836,7 +836,7 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Initialization", TEST_CASE( "Core/Geometry/TopologicalMesh/MergeWedges", "[unittests][Core][Core/Geometry][TopologicalMesh]" ) { - auto mesh = Ra::Core::Geometry::makeSharpBox2(); + auto mesh = Ra::Core::Geometry::makeSharpBox(); auto topo = TopologicalMesh { mesh }; std::set wedgesIndices; @@ -1345,8 +1345,8 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Updates", using Ra::Core::Geometry::TriangleMesh; SECTION( "Closed mesh" ) { - testConverter( Ra::Core::Geometry::makeBox2() ); - testConverter( Ra::Core::Geometry::makeSharpBox2() ); + testConverter( Ra::Core::Geometry::makeBox() ); + testConverter( Ra::Core::Geometry::makeSharpBox() ); } SECTION( "Mesh with boundaries" ) { From 38e16306dcbb23dde66d0004920d8ed2c77b4906 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 10:57:12 +0200 Subject: [PATCH 121/144] [core] makePlaneGrid returns MultiIndexGeometry. --- src/Core/Geometry/MeshPrimitives.cpp | 54 +++++++++++++++------------- src/Core/Geometry/MeshPrimitives.hpp | 30 ++++++++-------- 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index f2ca4636c4c..f69b2350e20 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -14,27 +14,27 @@ namespace Ra { namespace Core { namespace Geometry { -QuadMesh makeXNormalQuad( const Vector2& halfExts, - const Utils::optional& color, - bool generateTexCoord ) { +MultiIndexedGeometry makeXNormalQuad( const Vector2& halfExts, + const Utils::optional& color, + bool generateTexCoord ) { Transform T = Transform::Identity(); T.linear().col( 0 ).swap( T.linear().col( 1 ) ); T.linear().col( 1 ).swap( T.linear().col( 2 ) ); return makePlaneGrid( 1, 1, halfExts, T, color, generateTexCoord ); } -QuadMesh makeYNormalQuad( const Vector2& halfExts, - const Utils::optional& color, - bool generateTexCoord ) { +MultiIndexedGeometry makeYNormalQuad( const Vector2& halfExts, + const Utils::optional& color, + bool generateTexCoord ) { Transform T = Transform::Identity(); T.linear().col( 1 ).swap( T.linear().col( 2 ) ); T.linear().col( 0 ).swap( T.linear().col( 1 ) ); return makePlaneGrid( 1, 1, halfExts, T, color, generateTexCoord ); } -QuadMesh makeZNormalQuad( const Vector2& halfExts, - const Utils::optional& color, - bool generateTexCoord ) { +MultiIndexedGeometry makeZNormalQuad( const Vector2& halfExts, + const Utils::optional& color, + bool generateTexCoord ) { return makePlaneGrid( 1, 1, halfExts, Transform::Identity(), color, generateTexCoord ); } @@ -798,16 +798,16 @@ MultiIndexedGeometry makeGrid( const Core::Vector3& center, return result; } -QuadMesh makePlaneGrid( const uint rows, - const uint cols, - const Vector2& halfExts, - const Transform& transform, - const Utils::optional& color, - bool generateTexCoord ) { - QuadMesh result; +MultiIndexedGeometry makePlaneGrid( const uint rows, + const uint cols, + const Vector2& halfExts, + const Transform& transform, + const Utils::optional& color, + bool generateTexCoord ) { + MultiIndexedGeometry result; - QuadMesh::PointAttribHandle::Container vertices; - QuadMesh::NormalAttribHandle::Container normals; + MultiIndexedGeometry::PointAttribHandle::Container vertices; + MultiIndexedGeometry::NormalAttribHandle::Container normals; Ra::Core::Vector3Array texCoords; const uint R = ( rows + 1 ); @@ -852,23 +852,27 @@ QuadMesh makePlaneGrid( const uint rows, result.setVertices( std::move( vertices ) ); result.setNormals( std::move( normals ) ); + if ( generateTexCoord ) result.addAttrib( getAttribName( MeshAttrib::VERTEX_TEXCOORD ), std::move( texCoords ) ); + if ( bool( color ) ) result.colorize( *color ); - auto& face_layer = result.getIndicesWithLock(); - face_layer.reserve( f_size ); + auto face_layer = std::make_unique(); + + auto& indices = face_layer->collection(); + indices.reserve( f_size ); for ( uint i = 0; i < rows; ++i ) { for ( uint j = 0; j < cols; ++j ) { - face_layer.emplace_back( v.at( { i, j } ), - v.at( { i, j + 1 } ), - v.at( { i + 1, j + 1 } ), - v.at( { i + 1, j } ) ); + indices.emplace_back( v.at( { i, j } ), + v.at( { i, j + 1 } ), + v.at( { i + 1, j + 1 } ), + v.at( { i + 1, j } ) ); } } - result.indicesUnlock(); + result.addLayer( std::move( face_layer ) ); result.checkConsistency(); return result; diff --git a/src/Core/Geometry/MeshPrimitives.hpp b/src/Core/Geometry/MeshPrimitives.hpp index 3f9747a918c..9041bcf4007 100644 --- a/src/Core/Geometry/MeshPrimitives.hpp +++ b/src/Core/Geometry/MeshPrimitives.hpp @@ -21,30 +21,30 @@ namespace Geometry { /// \param color: if set, colorize vertices /// \param generateTexCoord: create uv tex coordinates on the grid, -halfExts have uv = (0,0), /// +halfExts have uv=(1,1) -RA_CORE_API QuadMesh makePlaneGrid( const uint rows = 1, - const uint cols = 1, - const Vector2& halfExts = Vector2( .5_ra, .5_ra ), - const Transform& T = Transform::Identity(), - const Utils::optional& color = {}, - bool generateTexCoord = false ); +RA_CORE_API MultiIndexedGeometry makePlaneGrid( const uint rows = 1, + const uint cols = 1, + const Vector2& halfExts = Vector2( .5_ra, .5_ra ), + const Transform& T = Transform::Identity(), + const Utils::optional& color = {}, + bool generateTexCoord = false ); /// Create a 2D quad mesh given half extents, centered on the origin with x axis as normal /// \see makePlaneGrid -RA_CORE_API QuadMesh makeXNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), - const Utils::optional& color = {}, - bool generateTexCoord = false ); +RA_CORE_API MultiIndexedGeometry makeXNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), + const Utils::optional& color = {}, + bool generateTexCoord = false ); /// Create a 2D quad mesh given half extents, centered on the origin with y axis as normal /// \see makePlaneGrid -RA_CORE_API QuadMesh makeYNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), - const Utils::optional& color = {}, - bool generateTexCoord = false ); +RA_CORE_API MultiIndexedGeometry makeYNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), + const Utils::optional& color = {}, + bool generateTexCoord = false ); /// Create a 2D quad mesh given half extents, centered on the origin with z axis as normal /// \see makePlaneGrid -RA_CORE_API QuadMesh makeZNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), - const Utils::optional& color = {}, - bool generateTexCoord = false ); +RA_CORE_API MultiIndexedGeometry makeZNormalQuad( const Vector2& halfExts = Vector2( .5_ra, .5_ra ), + const Utils::optional& color = {}, + bool generateTexCoord = false ); /// Create a 2D grid, with only outer points, connected as lines, inner line intersctions are not /// present in verstices. From 5e4110ab9f265298a072524b632f0ce9d64dabf1 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 19:18:33 +0200 Subject: [PATCH 122/144] [examples] TriMesh -> MultiIndexedGeometry. --- examples/DrawPrimitives/AllPrimitivesComponent.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index c60b8914fd5..47b26cdaf0f 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -1,4 +1,5 @@ +#include "Core/Geometry/IndexedGeometry.hpp" #include "Engine/Data/DrawPrimitives.hpp" #include @@ -922,7 +923,7 @@ void AllPrimitivesComponent::initialize() { const Vector3uArray& indices, Vector3 from, Vector3 to ) { - TriangleMesh mesh; + MultiIndexedGeometry mesh; TopologicalMesh topo; optional optHe; Vector3 up { 0_ra, .05_ra, 0_ra }; @@ -931,7 +932,7 @@ void AllPrimitivesComponent::initialize() { mesh.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Vector4Array { colors.begin(), colors.begin() + points.size() } ); - mesh.setIndices( indices ); + mesh.set_indices( indices ); topo = TopologicalMesh { mesh }; topo.mergeEqualWedges(); topo.garbage_collection(); @@ -1016,7 +1017,7 @@ void AllPrimitivesComponent::initialize() { const Vector3uArray& indices, Vector3 from, Vector3 to ) { - TriangleMesh mesh; + MultiIndexedGeometry mesh; TopologicalMesh topo; optional optHe; Vector3 up { 0_ra, .05_ra, 0_ra }; @@ -1025,7 +1026,7 @@ void AllPrimitivesComponent::initialize() { mesh.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), Vector4Array { colors.begin(), colors.begin() + points.size() } ); - mesh.setIndices( indices ); + mesh.set_indices( indices ); topo = TopologicalMesh { mesh }; topo.mergeEqualWedges(); From 4880829d7f658ff1470c70df9bc064870105f008 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 21:18:27 +0200 Subject: [PATCH 123/144] [engine] Continue update, remove some LineMesh. --- src/Engine/Data/Mesh.cpp | 37 ------------------- src/Engine/Data/Mesh.hpp | 18 ++++------ src/Engine/Rendering/ForwardRenderer.cpp | 4 +-- src/Engine/Scene/CameraComponent.cpp | 45 ++++++++++++------------ src/Engine/Scene/GeometryComponent.hpp | 6 +--- 5 files changed, 31 insertions(+), 79 deletions(-) diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index 8fc4add4474..ba523be4d23 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -47,43 +47,6 @@ size_t Mesh::getNumFaces() const { } } -void Mesh::loadGeometry( const Core::Vector3Array& vertices, const std::vector& indices ) { - // Do not remove this function to force everyone to use TriangleMesh. - // ... because we have some line meshes as well... - /// \todo find an alternative - Core::Geometry::TriangleMesh mesh; - - auto nIdx = indices.size(); - - if ( indices.empty() ) { - m_numElements = vertices.size(); - setRenderMode( RM_POINTS ); - } - else - m_numElements = nIdx; - mesh.setVertices( vertices ); - - // Check that when loading a TriangleMesh we actually have triangles or lines. - CORE_ASSERT( m_renderMode != GL_TRIANGLES || nIdx % 3 == 0, - "There should be 3 indices per triangle " ); - CORE_ASSERT( m_renderMode != GL_LINES || nIdx % 2 == 0, "There should be 2 indices per line" ); - CORE_ASSERT( m_renderMode != GL_LINES_ADJACENCY || nIdx % 4 == 0, - "There should be 4 indices per line adjacency" ); - Core::Geometry::TriangleMesh::IndexContainerType mindices; - for ( uint i = 0; i < indices.size(); i = i + 3 ) { - // We store all indices in order. This means that for lines we have - // (L00, L01, L10), (L11, L20, L21) etc. We fill the missing by wrapping around indices. - mindices.push_back( { indices[i], indices[( i + 1 ) % nIdx], indices[( i + 2 ) % nIdx] } ); - } - - mesh.setIndices( std::move( mindices ) ); - m_dataDirty.clear(); - m_vbos.clear(); - - ///\todo check line vs triangle here is a bug - loadGeometry( std::move( mesh ) ); -} - void AttribArrayDisplayable::updatePickingRenderMode() { switch ( getRenderMode() ) { case AttribArrayDisplayable::RM_POINTS: { diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 49d062c2b14..7230662ff51 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -495,17 +495,6 @@ class RA_ENGINE_API Mesh : public IndexedGeometry using base::IndexedGeometry; size_t getNumFaces() const override; - /** - * Use the given vertices and indices to build a display mesh according to - * the MeshRenderMode. - * \note This has to be used for non RM_TRIANGLES meshes only. - * \note Also removes all vertex attributes. - * \warning This will disappear as soon as old code will be removed. - */ - using base::loadGeometry; - [[deprecated]] void loadGeometry( const Core::Vector3Array& vertices, - const std::vector& indices ); - protected: private: }; @@ -623,7 +612,12 @@ createMeshFromGeometryData2( const std::string& name, const Ra::Core::Asset::Geo return ret; } -//////////////// AttribArrayDisplayable /////////////////////////////// +//----------------------------------------------------------------------------- +//- Implementation ------------------------------------------------------------ +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +//- AttribArrayDisplayable ---------------------------------------------------- void AttribArrayDisplayable::setRenderMode( MeshRenderMode mode ) { m_renderMode = mode; diff --git a/src/Engine/Rendering/ForwardRenderer.cpp b/src/Engine/Rendering/ForwardRenderer.cpp index cfd9dcb2edc..6fa5086a8d0 100644 --- a/src/Engine/Rendering/ForwardRenderer.cpp +++ b/src/Engine/Rendering/ForwardRenderer.cpp @@ -184,8 +184,8 @@ void computeIndices2( Core::Geometry::LineIndexLayer::IndexContainerType& indice std::sort( indices.begin(), indices.end(), - []( const Core::Geometry::LineMesh::IndexType& a, - const Core::Geometry::LineMesh::IndexType& b ) { + []( const Core::Geometry::LineIndexLayer::IndexType& a, + const Core::Geometry::LineIndexLayer::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() ); diff --git a/src/Engine/Scene/CameraComponent.cpp b/src/Engine/Scene/CameraComponent.cpp index 6bba8fa0121..3a245de8ab1 100644 --- a/src/Engine/Scene/CameraComponent.cpp +++ b/src/Engine/Scene/CameraComponent.cpp @@ -1,7 +1,8 @@ -#include #include +#include #include +#include #include #include #include @@ -28,34 +29,32 @@ CameraComponent::CameraComponent( Entity* entity, CameraComponent::~CameraComponent() = default; void CameraComponent::initialize() { - using Data::Material; - using Data::Mesh; using Data::PlainMaterial; if ( !m_renderObjects.empty() ) return; // Create the render mesh for the camera - Ra::Core::Geometry::LineMesh triMesh; - triMesh.setVertices( { { 0_ra, 0_ra, 0_ra }, - { -.5_ra, -.5_ra, -1_ra }, - { -.5_ra, .5_ra, -1_ra }, - { .5_ra, .5_ra, -1_ra }, - { .5_ra, -.5_ra, -1_ra }, - { -.3_ra, .5_ra, -1_ra }, - { 0_ra, .7_ra, -1_ra }, - { .3_ra, .5_ra, -1_ra } } ); - triMesh.setIndices( { { 0, 1 }, - { 0, 2 }, - { 0, 3 }, - { 0, 4 }, - { 1, 2 }, - { 1, 4 }, - { 2, 3 }, - { 3, 4 }, - { 5, 6 }, - { 6, 7 } } ); + Ra::Core::Geometry::MultiIndexedGeometry geom; + geom.setVertices( { { 0_ra, 0_ra, 0_ra }, + { -.5_ra, -.5_ra, -1_ra }, + { -.5_ra, .5_ra, -1_ra }, + { .5_ra, .5_ra, -1_ra }, + { .5_ra, -.5_ra, -1_ra }, + { -.3_ra, .5_ra, -1_ra }, + { 0_ra, .7_ra, -1_ra }, + { .3_ra, .5_ra, -1_ra } } ); + geom.set_indices( { { 0, 1 }, + { 0, 2 }, + { 0, 3 }, + { 0, 4 }, + { 1, 2 }, + { 1, 4 }, + { 2, 3 }, + { 3, 4 }, + { 5, 6 }, + { 6, 7 } } ); auto m = std::make_shared( m_name + "_mesh" ); - m->loadGeometry( std::move( triMesh ) ); + m->loadGeometry( std::move( geom ) ); // Create the RO auto mat = Core::make_shared( m_name + "_Material" ); diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index 7e6904e76c4..58e5c88efbb 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -24,7 +24,7 @@ class VolumeObject; namespace Scene { -/// Abstract interface of a geometric compoennet in the Engine. +/// Abstract interface of a geometric component in the Engine. class RA_ENGINE_API GeometryComponent : public Component { public: @@ -34,14 +34,10 @@ class RA_ENGINE_API GeometryComponent : public Component void initialize() override {} - // public: // Component communication management virtual void setupIO( const std::string& id ); void setContentName( const std::string& name ) { m_contentName = name; } - // void setDeformable( bool b ); - /// Returns the index of the associated RO (the display mesh) - // Ra::Core::Utils::Index getRenderObjectIndex() const; protected: private: const Ra::Core::Utils::Index* roIndexRead() const; From a63b14379fe1727971d3d7a89ec48661c02dc537 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 23:29:03 +0200 Subject: [PATCH 124/144] [examples] PolyMesh -> MultiIndexed. --- examples/DrawPrimitives/AllPrimitivesComponent.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index 47b26cdaf0f..49465bfa22e 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -646,7 +646,7 @@ void AllPrimitivesComponent::initialize() { updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); - Geometry::PolyMesh polyMesh; + MultiIndexedGeometry polyMesh; polyMesh.setVertices( { // quad { -1.1_ra, -0_ra, 0_ra }, @@ -674,7 +674,7 @@ void AllPrimitivesComponent::initialize() { quad << 0, 1, 2, 3; auto hepta = VectorNui( 7 ); hepta << 3, 2, 4, 5, 6, 7, 8; - polyMesh.setIndices( { quad, hepta } ); + polyMesh.set_indices( { quad, hepta } ); auto poly1 = make_shared( "Poly", std::move( polyMesh ) ); poly1->getCoreGeometry().addAttrib( @@ -1088,7 +1088,6 @@ void AllPrimitivesComponent::initialize() { updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); { - using Ra::Engine::Data::Mesh; { auto geom = makeParametricTorus( .04_ra, .01_ra, Color::White(), 16, 8 ); auto torusMesh = make_shared( "Torus", std::move( geom ) ); @@ -1122,7 +1121,6 @@ void AllPrimitivesComponent::initialize() { updateCellCorner( cellCorner, cellSize, nCellX, nCellY ); { - using Ra::Engine::Data::Mesh; { auto strip = RenderObject::createRenderObject( "test_quadstrip", From 3adda4784f8678480a640c545a08e73a0f6e1822 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 23:29:43 +0200 Subject: [PATCH 125/144] [engine] LineMesh -> MultiIndexed. --- src/Engine/Rendering/DebugRender.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Engine/Rendering/DebugRender.cpp b/src/Engine/Rendering/DebugRender.cpp index 5e373fd542c..685796d98f6 100644 --- a/src/Engine/Rendering/DebugRender.cpp +++ b/src/Engine/Rendering/DebugRender.cpp @@ -1,3 +1,4 @@ +#include "Core/Geometry/IndexedGeometry.hpp" #include #include @@ -140,7 +141,7 @@ void DebugRender::renderLines( const Core::Matrix4f& viewMatrix, const Core::Matrix4f& projMatrix ) { Core::Vector3Array vertices; Core::Vector4Array colors; - Core::Geometry::LineMesh::IndexContainerType indices; + Core::Geometry::LineIndexLayer::IndexContainerType indices; unsigned int indexI = 0; for ( const auto& l : m_lines ) { vertices.push_back( l.a ); @@ -161,9 +162,9 @@ void DebugRender::renderLines( const Core::Matrix4f& viewMatrix, m_lineProg->setUniform( "view", viewMatrix ); m_lineProg->setUniform( "proj", projMatrix ); - Core::Geometry::LineMesh geom; + Core::Geometry::MultiIndexedGeometry geom; geom.setVertices( vertices ); - geom.setIndices( std::move( indices ) ); + geom.set_indices( std::move( indices ) ); geom.addAttrib( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_COLOR ), colors ); From df22c6f3c4a7aed15c8e7f57c4703d7d24e18e56 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sat, 16 May 2026 23:30:16 +0200 Subject: [PATCH 126/144] [engine] DrawPrimitives, remove ref to TriangleMesh and LineMesh. --- src/Engine/Data/DrawPrimitives.cpp | 47 +++++++++++++++--------------- src/Engine/Data/DrawPrimitives.hpp | 1 - 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Engine/Data/DrawPrimitives.cpp b/src/Engine/Data/DrawPrimitives.cpp index e064a8370fc..424c075e7ce 100644 --- a/src/Engine/Data/DrawPrimitives.cpp +++ b/src/Engine/Data/DrawPrimitives.cpp @@ -169,8 +169,9 @@ GeometryDisplayablePtr QuadStrip( const Core::Vector3& a, Vector2 halfExts = Vector2( x.norm() / 2_ra, quads * y.norm() / 2_ra ); auto geom = makePlaneGrid( quads, 1, halfExts, t, color, true ); - auto vertHandle = geom.getAttribHandle( getAttribName( VERTEX_POSITION ) ); - auto& vertAttrib = geom.getAttrib( vertHandle ); + auto vertHandle = + geom.getAttribHandle( getAttribName( VERTEX_POSITION ) ); + auto& vertAttrib = geom.getAttrib( vertHandle ); Core::Vector4Array colors( vertAttrib.getSize(), color ); geom.addAttrib( getAttribName( MeshAttrib::VERTEX_COLOR ), colors ); @@ -184,10 +185,10 @@ GeometryDisplayablePtr QuadStrip( const Core::Vector3& a, auto default_layer = geom.default_layer_key(); geom.set_default_layer_key( strip_key ); - mesh->loadGeometry( - std::move( geom ), - GeometryDisplayable::ArrayOfLayerKeys<2> { - { { strip_key, Mesh::RM_TRIANGLE_STRIP }, { default_layer, Mesh::RM_QUADS } } } ); + mesh->loadGeometry( std::move( geom ), + GeometryDisplayable::ArrayOfLayerKeys<2> { + { { strip_key, AttribArrayDisplayable::RM_TRIANGLE_STRIP }, + { default_layer, AttribArrayDisplayable::RM_QUADS } } } ); return mesh; } @@ -201,7 +202,7 @@ GeometryDisplayablePtr Circle( const Core::Vector3& center, Geometry::MultiIndexedGeometry geom; ///\todo refer to class typedef instaed of core types/ Core::Vector3Array vertices( segments + 1 ); - Geometry::LineMesh::IndexContainerType indices; + Geometry::LineIndexLayer::IndexContainerType indices; indices.resize( segments ); Core::Vector3 xPlane, yPlane; @@ -237,7 +238,7 @@ GeometryDisplayablePtr CircleArc( const Core::Vector3& center, const Core::Utils::Color& color ) { Geometry::MultiIndexedGeometry geom; Core::Vector3Array vertices( segments + 1 ); - Geometry::LineMesh::IndexContainerType indices; + Geometry::LineIndexLayer::IndexContainerType indices; indices.resize( segments ); Core::Vector3 xPlane, yPlane; @@ -269,9 +270,9 @@ GeometryDisplayablePtr CircleArc( const Core::Vector3& center, GeometryDisplayablePtr Sphere( const Core::Vector3& center, Scalar radius, const Core::Utils::Color& color ) { auto geom = makeGeodesicSphere( radius, 2, color ); - auto handle = geom.getAttribHandle( + auto handle = geom.getAttribHandle( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_POSITION ) ); - auto& vertices = geom.getAttrib( handle ); + auto& vertices = geom.getAttrib( handle ); auto& data = vertices.getDataWithLock(); std::for_each( data.begin(), data.end(), [center]( Core::Vector3& v ) { v += center; } ); @@ -285,9 +286,9 @@ GeometryDisplayablePtr ParametricSphere( const Core::Vector3& center, const Core::Utils::Color& color, bool generateTexCoord ) { auto geom = makeParametricSphere( radius, color, generateTexCoord, 32, 32 ); - auto handle = geom.getAttribHandle( + auto handle = geom.getAttribHandle( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_POSITION ) ); - auto& vertices = geom.getAttrib( handle ); + auto& vertices = geom.getAttrib( handle ); auto& data = vertices.getDataWithLock(); std::for_each( data.begin(), data.end(), [center]( Core::Vector3& v ) { v += center; } ); @@ -315,16 +316,16 @@ GeometryDisplayablePtr Capsule( const Core::Vector3& p1, t.pretranslate( trans ); Matrix3 normalMatrix = t.linear().inverse().transpose(); - auto vertHandle = geom.getAttribHandle( + auto vertHandle = geom.getAttribHandle( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_POSITION ) ); - auto& vertAttrib = geom.getAttrib( vertHandle ); + auto& vertAttrib = geom.getAttrib( vertHandle ); auto& vertData = vertAttrib.getDataWithLock(); std::for_each( vertData.begin(), vertData.end(), [t]( Core::Vector3& v ) { v = t * v; } ); vertAttrib.unlock(); - auto normalHandle = geom.getAttribHandle( + auto normalHandle = geom.getAttribHandle( Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::VERTEX_NORMAL ) ); - auto& normalAttrib = geom.getAttrib( normalHandle ); + auto& normalAttrib = geom.getAttrib( normalHandle ); auto& normalData = normalAttrib.getDataWithLock(); std::for_each( normalData.begin(), normalData.end(), [normalMatrix]( Core::Vector3& n ) { n = normalMatrix * n; @@ -381,10 +382,10 @@ GeometryDisplayablePtr Disk( const Core::Vector3& center, Core::Vector4Array { geom.vertices().size(), color } ); auto mesh = make_shared( "Disk Primitive" ); - mesh->loadGeometry( - std::move( geom ), - GeometryDisplayable::ArrayOfLayerKeys<2> { - { { fan_key, Mesh::RM_TRIANGLE_FAN }, { face_key, Mesh::RM_TRIANGLES } } } ); + mesh->loadGeometry( std::move( geom ), + GeometryDisplayable::ArrayOfLayerKeys<2> { + { { fan_key, AttribArrayDisplayable::RM_TRIANGLE_FAN }, + { face_key, AttribArrayDisplayable::RM_TRIANGLES } } } ); mesh->set_active_layer_key( fan_key ); return mesh; } @@ -550,9 +551,9 @@ GeometryDisplayablePtr LineStrip( const Core::Vector3Array& vertices, Ra::Core::Geometry::getAttribName( Ra::Core::Geometry::MeshAttrib::VERTEX_COLOR ), colors ); auto mesh = make_shared( "Line Strip Primitive" ); - mesh->loadGeometry( - std::move( geom ), - GeometryDisplayable::ArrayOfLayerKeys<1> { { { strip_key, Mesh::RM_LINE_STRIP } } } ); + mesh->loadGeometry( std::move( geom ), + GeometryDisplayable::ArrayOfLayerKeys<1> { + { { strip_key, AttribArrayDisplayable::RM_LINE_STRIP } } } ); return mesh; } diff --git a/src/Engine/Data/DrawPrimitives.hpp b/src/Engine/Data/DrawPrimitives.hpp index 5021945bceb..33b89ced545 100644 --- a/src/Engine/Data/DrawPrimitives.hpp +++ b/src/Engine/Data/DrawPrimitives.hpp @@ -21,7 +21,6 @@ class Component; } namespace Data { -class Mesh; class AttribArrayDisplayable; class GeometryDisplayable; From e2149d398fb803fcd72a063cfc571dfd6d9798a4 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 17 May 2026 16:34:45 +0200 Subject: [PATCH 127/144] [engine] Use MultiIndexed for bone shape. --- src/Engine/Scene/SkeletonComponent.cpp | 25 +++++++++++++------------ src/Engine/Scene/SkeletonComponent.hpp | 4 ++-- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/Engine/Scene/SkeletonComponent.cpp b/src/Engine/Scene/SkeletonComponent.cpp index 5a6729adec3..39e8b8d9e3b 100644 --- a/src/Engine/Scene/SkeletonComponent.cpp +++ b/src/Engine/Scene/SkeletonComponent.cpp @@ -1,3 +1,4 @@ +#include "Core/Geometry/IndexedGeometry.hpp" #include #include @@ -34,7 +35,7 @@ namespace Ra { namespace Engine { namespace Scene { -std::shared_ptr SkeletonComponent::s_boneMesh { nullptr }; +std::shared_ptr SkeletonComponent::s_boneMesh { nullptr }; std::shared_ptr SkeletonComponent::s_boneMaterial { nullptr }; std::shared_ptr SkeletonComponent::s_boneRenderTechnique { nullptr }; @@ -262,9 +263,9 @@ bool SkeletonComponent::isShowingSkeleton() const { return m_boneDrawables.front()->isVisible(); } -Core::Geometry::TriangleMesh makeBoneShape() { +Core::Geometry::MultiIndexedGeometry makeBoneShape() { // Bone along Z axis. - Core::Geometry::TriangleMesh mesh; + Core::Geometry::MultiIndexedGeometry mesh; const Scalar l = 0.1_ra; const Scalar w = 0.1_ra; mesh.setVertices( { Core::Vector3( 0, 0, 0 ), @@ -281,14 +282,14 @@ Core::Geometry::TriangleMesh makeBoneShape() { Core::Vector3( 0, -1, 0 ), Core::Vector3( -1, 0, 0 ) } ); - mesh.setIndices( { Core::Vector3ui( 0, 2, 3 ), - Core::Vector3ui( 0, 5, 2 ), - Core::Vector3ui( 0, 3, 4 ), - Core::Vector3ui( 0, 4, 5 ), - Core::Vector3ui( 1, 3, 2 ), - Core::Vector3ui( 1, 2, 5 ), - Core::Vector3ui( 1, 4, 3 ), - Core::Vector3ui( 1, 5, 4 ) } ); + mesh.set_indices( { Core::Vector3ui( 0, 2, 3 ), + Core::Vector3ui( 0, 5, 2 ), + Core::Vector3ui( 0, 3, 4 ), + Core::Vector3ui( 0, 4, 5 ), + Core::Vector3ui( 1, 3, 2 ), + Core::Vector3ui( 1, 2, 5 ), + Core::Vector3ui( 1, 4, 3 ), + Core::Vector3ui( 1, 5, 4 ) } ); return mesh; } @@ -296,7 +297,7 @@ void SkeletonComponent::setupSkeletonDisplay() { m_renderObjects.clear(); m_boneDrawables.clear(); if ( !s_boneMesh ) { - s_boneMesh = std::make_shared( "Bone Mesh" ); + s_boneMesh = std::make_shared( "Bone Mesh" ); s_boneMesh->loadGeometry( makeBoneShape() ); s_boneMaterial.reset( new Data::BlinnPhongMaterial( "Bone Material" ) ); s_boneMaterial->setDiffuseColor( Color::Grey( 0.4_ra ) ); diff --git a/src/Engine/Scene/SkeletonComponent.hpp b/src/Engine/Scene/SkeletonComponent.hpp index 9ec28d62a85..6add21da809 100644 --- a/src/Engine/Scene/SkeletonComponent.hpp +++ b/src/Engine/Scene/SkeletonComponent.hpp @@ -1,5 +1,6 @@ #pragma once +#include "Engine/Data/Mesh.hpp" #include #include #include @@ -12,7 +13,6 @@ namespace Ra { namespace Engine { namespace Data { class BlinnPhongMaterial; -class Mesh; } // namespace Data namespace Rendering { class RenderObject; @@ -236,7 +236,7 @@ class RA_ENGINE_API SkeletonComponent : public Component std::map m_boneMap; /// Mesh for bone display. - static std::shared_ptr s_boneMesh; + static std::shared_ptr s_boneMesh; /// Material for bone display. static std::shared_ptr s_boneMaterial; From b8c8588914307b019a935860838074f8080dc8a4 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 17 May 2026 17:06:13 +0200 Subject: [PATCH 128/144] [examples] Load directly geom from geomData. --- .../DrawPrimitives/AllPrimitivesComponent.cpp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/examples/DrawPrimitives/AllPrimitivesComponent.cpp b/examples/DrawPrimitives/AllPrimitivesComponent.cpp index 49465bfa22e..3a3d1676ad5 100644 --- a/examples/DrawPrimitives/AllPrimitivesComponent.cpp +++ b/examples/DrawPrimitives/AllPrimitivesComponent.cpp @@ -724,20 +724,9 @@ void AllPrimitivesComponent::initialize() { auto geomData = data->getGeometryData(); for ( const auto& gd : geomData ) { - std::shared_ptr mesh { nullptr }; - switch ( gd->getType() ) { - case Ra::Core::Asset::GeometryData::TRI_MESH: - mesh = createMeshFromGeometryData2( "logo", gd ); - break; - case Ra::Core::Asset::GeometryData::QUAD_MESH: - mesh = createMeshFromGeometryData2( "logo", gd ); - break; - case Ra::Core::Asset::GeometryData::POLY_MESH: - mesh = createMeshFromGeometryData2( "logo", gd ); - break; - default: - break; - } + + auto geom { gd->getGeometry() }; + auto mesh = std::make_shared( "logo", std::move( geom ) ); std::shared_ptr roMaterial; const Core::Asset::MaterialData* md = From c7c73ba534fe8e5415939ad048474161307c8ab9 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 17 May 2026 17:06:35 +0200 Subject: [PATCH 129/144] [engine] Remove templated SurfaceMeshComponentBase. --- src/Engine/Scene/GeometryComponent.cpp | 18 ++- src/Engine/Scene/GeometryComponent.hpp | 165 +++++++++---------------- 2 files changed, 66 insertions(+), 117 deletions(-) diff --git a/src/Engine/Scene/GeometryComponent.cpp b/src/Engine/Scene/GeometryComponent.cpp index af9275847c1..ccde5ec64b1 100644 --- a/src/Engine/Scene/GeometryComponent.cpp +++ b/src/Engine/Scene/GeometryComponent.cpp @@ -29,16 +29,14 @@ namespace Ra { namespace Engine { namespace Scene { -template <> -SurfaceMeshComponentBase::SurfaceMeshComponentBase( - const std::string& name, - Entity* entity, - Ra::Core::Geometry::MultiIndexedGeometry&& mesh, - Core::Asset::MaterialData* mat ) : +SurfaceMeshComponent::SurfaceMeshComponent( const std::string& name, + Entity* entity, + CoreMeshType&& mesh, + std::shared_ptr mat ) : GeometryComponent( name, entity ), - m_displayMesh( new Data::GeometryDisplayable( name, std::move( mesh ) ) ) { + m_displayMesh( new RenderMeshType( name, std::move( mesh ) ) ) { setContentName( name ); - finalizeROFromGeometry( convertMatdataToMaterial( mat ), Core::Transform::Identity() ); + finalizeROFromGeometry( mat, Core::Transform::Identity() ); } void GeometryComponent::setupIO( const std::string& id ) { @@ -51,9 +49,7 @@ const Index* GeometryComponent::roIndexRead() const { return &m_roIndex; } -template <> -void SurfaceMeshComponentBase::generateMesh( - const Ra::Core::Asset::GeometryData* data ) { +void SurfaceMeshComponent::generateMesh( const Ra::Core::Asset::GeometryData* data ) { m_contentName = data->getName(); m_displayMesh = Ra::Core::make_shared( m_contentName ); CoreMeshType mesh { data->getGeometry() }; diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index 58e5c88efbb..edf5eef2450 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -57,64 +57,61 @@ class RA_ENGINE_API GeometryComponent : public Component * - normals: rw (if deformable) * - triangles: rw (if deformable) */ -template -class SurfaceMeshComponentBase : public GeometryComponent +class SurfaceMeshComponent : public GeometryComponent { using base = GeometryComponent; public: - using CoreMeshType = T; - using RenderMeshType = typename Data::RenderMeshType::getType::Type; + using CoreMeshType = Ra::Core::Geometry::MultiIndexedGeometry; + using RenderMeshType = Data::GeometryDisplayable; - inline SurfaceMeshComponentBase( const std::string& name, - Entity* entity, - const Ra::Core::Asset::GeometryData* data ); - inline SurfaceMeshComponentBase( const std::string& name, - Entity* entity, - std::shared_ptr data ); + SurfaceMeshComponent( const std::string& name, + Entity* entity, + const Ra::Core::Asset::GeometryData* data ); + SurfaceMeshComponent( const std::string& name, + Entity* entity, + std::shared_ptr data ); /*! * Constructor from an existing mesh * \warning Moves the mesh and takes its ownership */ - inline SurfaceMeshComponentBase( const std::string& name, - Entity* entity, - CoreMeshType&& mesh, - Core::Asset::MaterialData* mat = nullptr ); - inline SurfaceMeshComponentBase( const std::string& name, - Entity* entity, - CoreMeshType&& mesh, - std::shared_ptr mat ); - ~SurfaceMeshComponentBase() override = default; + SurfaceMeshComponent( const std::string& name, + Entity* entity, + CoreMeshType&& mesh, + Core::Asset::MaterialData* mat = nullptr ); + SurfaceMeshComponent( const std::string& name, + Entity* entity, + CoreMeshType&& mesh, + std::shared_ptr mat ); + ~SurfaceMeshComponent() override = default; /// Returns the current display geometry. - inline const CoreMeshType& getCoreGeometry() const; - inline RenderMeshType* getDisplayable(); + const CoreMeshType& getCoreGeometry() const; + RenderMeshType* getDisplayable(); // Component communication management - inline void setupIO( const std::string& id ) override; - inline void setDeformable( bool b ); + void setupIO( const std::string& id ) override; + void setDeformable( bool b ); private: - inline void generateMesh( const Ra::Core::Asset::GeometryData* data ); + void generateMesh( const Ra::Core::Asset::GeometryData* data ); - inline std::shared_ptr + std::shared_ptr convertMatdataToMaterial( const Core::Asset::MaterialData* data ); - inline void finalizeROFromGeometry( std::shared_ptr roMaterial, - Core::Transform transform ); + void finalizeROFromGeometry( std::shared_ptr roMaterial, + Core::Transform transform ); // Give access to the mesh and (if deformable) to update it - inline const CoreMeshType* getMeshOutput() const; - inline CoreMeshType* getMeshRw(); + const CoreMeshType* getMeshOutput() const; + CoreMeshType* getMeshRw(); private: // directly hold a reference to the displayMesh to simplify accesses in handlers std::shared_ptr m_displayMesh { nullptr }; }; -using SurfaceMeshComponent = SurfaceMeshComponentBase; - /// \warning, WIP /// \todo doc. class RA_ENGINE_API PointCloudComponent : public GeometryComponent @@ -144,10 +141,10 @@ class RA_ENGINE_API PointCloudComponent : public GeometryComponent Data::PointCloud* getGeometry(); /// set the splat size for rendering - inline void setSplatSize( float s ) { m_splatSize = s; } + void setSplatSize( float s ) { m_splatSize = s; } /// get the splat size for rendering - inline float getSplatSize() const { return m_splatSize; } + float getSplatSize() const { return m_splatSize; } public: // Component communication management @@ -170,7 +167,7 @@ class RA_ENGINE_API PointCloudComponent : public GeometryComponent float m_splatSize { 0.0025f }; }; -/*-----------------------------------------------------------------------------------------------*/ +//------------------------------------------------------------------------------------------------- /*! * \brief Main class to convert Ra::Core::Asset::VolumeData to Ra::Engine::VolumeObject @@ -211,75 +208,38 @@ class RA_ENGINE_API VolumeComponent : public Component std::shared_ptr m_displayVolume { nullptr }; }; -template -SurfaceMeshComponentBase::SurfaceMeshComponentBase( - const std::string& name, - Entity* entity, - const Ra::Core::Asset::GeometryData* data ) : +//------------------------------------------------------------------------------------------------- +//- Implementation -------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------------- + +//------------------------------------------------------------------------------------------------- +//- SurfaceMesheComponent ------------------------------------------------------------------------- +inline SurfaceMeshComponent::SurfaceMeshComponent( const std::string& name, + Entity* entity, + const Ra::Core::Asset::GeometryData* data ) : GeometryComponent( name, entity ), m_displayMesh( nullptr ) { generateMesh( data ); } -template <> -RA_ENGINE_API -SurfaceMeshComponentBase::SurfaceMeshComponentBase( - const std::string& name, - Entity* entity, - Ra::Core::Geometry::MultiIndexedGeometry&& mesh, - Core::Asset::MaterialData* mat ); - -template -SurfaceMeshComponentBase::SurfaceMeshComponentBase( - const std::string& name, - Entity* entity, - std::shared_ptr data ) : +inline SurfaceMeshComponent::SurfaceMeshComponent( const std::string& name, + Entity* entity, + std::shared_ptr data ) : GeometryComponent( name, entity ), m_displayMesh( data ) { finalizeROFromGeometry( convertMatdataToMaterial( nullptr ), Core::Transform::Identity() ); } -template -SurfaceMeshComponentBase::SurfaceMeshComponentBase( const std::string& name, - Entity* entity, - CoreMeshType&& mesh, - Core::Asset::MaterialData* mat ) : +inline SurfaceMeshComponent::SurfaceMeshComponent( const std::string& name, + Entity* entity, + CoreMeshType&& mesh, + Core::Asset::MaterialData* mat ) : GeometryComponent( name, entity ), m_displayMesh( new RenderMeshType( name, std::move( mesh ) ) ) { setContentName( name ); finalizeROFromGeometry( convertMatdataToMaterial( mat ), Core::Transform::Identity() ); } -template -SurfaceMeshComponentBase::SurfaceMeshComponentBase( - const std::string& name, - Entity* entity, - CoreMeshType&& mesh, - std::shared_ptr mat ) : - GeometryComponent( name, entity ), - m_displayMesh( new RenderMeshType( name, std::move( mesh ) ) ) { - setContentName( name ); - finalizeROFromGeometry( mat, Core::Transform::Identity() ); -} -template -void SurfaceMeshComponentBase::generateMesh( - const Ra::Core::Asset::GeometryData* data ) { - m_contentName = data->getName(); - m_displayMesh = Ra::Core::make_shared( m_contentName ); - CoreMeshType mesh = Data::createCoreMeshFromGeometryData( data ); - - m_displayMesh->loadGeometry( std::move( mesh ) ); - - finalizeROFromGeometry( - convertMatdataToMaterial( data->hasMaterial() ? &( data->getMaterial() ) : nullptr ), - data->getFrame() ); -} - -template <> -RA_ENGINE_API void SurfaceMeshComponentBase::generateMesh( - const Ra::Core::Asset::GeometryData* data ); - -template -std::shared_ptr SurfaceMeshComponentBase::convertMatdataToMaterial( - const Core::Asset::MaterialData* data ) { +inline std::shared_ptr +SurfaceMeshComponent::convertMatdataToMaterial( const Core::Asset::MaterialData* data ) { // The technique for rendering this component std::shared_ptr roMaterial; // First extract the material from asset or create a default one @@ -298,10 +258,9 @@ std::shared_ptr SurfaceMeshComponentBase::convertM return roMaterial; } -template -void SurfaceMeshComponentBase::finalizeROFromGeometry( - std::shared_ptr roMaterial, - Core::Transform transform ) { +inline void +SurfaceMeshComponent::finalizeROFromGeometry( std::shared_ptr roMaterial, + Core::Transform transform ) { // initialize with a default rendertechique that draws nothing std::string roName( m_name + "_" + m_contentName + "_RO" ); @@ -325,26 +284,22 @@ void SurfaceMeshComponentBase::finalizeROFromGeometry( # define CHECK_MESH_NOT_NULL_UNDEF #endif -template -const CoreMeshType& SurfaceMeshComponentBase::getCoreGeometry() const { +inline auto SurfaceMeshComponent::getCoreGeometry() const -> const CoreMeshType& { CHECK_MESH_NOT_NULL; return m_displayMesh->getCoreGeometry(); } -template -typename SurfaceMeshComponentBase::RenderMeshType* -SurfaceMeshComponentBase::getDisplayable() { +inline auto SurfaceMeshComponent::getDisplayable() -> RenderMeshType* { CHECK_MESH_NOT_NULL; return m_displayMesh.get(); } -template -void SurfaceMeshComponentBase::setupIO( const std::string& id ) { +inline void SurfaceMeshComponent::setupIO( const std::string& id ) { CHECK_MESH_NOT_NULL; const auto& cm = ComponentMessenger::getInstance(); - auto cbOut = std::bind( &SurfaceMeshComponentBase::getMeshOutput, this ); - auto cbRw = std::bind( &SurfaceMeshComponentBase::getMeshRw, this ); + auto cbOut = std::bind( &SurfaceMeshComponent::getMeshOutput, this ); + auto cbRw = std::bind( &SurfaceMeshComponent::getMeshRw, this ); cm->registerOutput( getEntity(), this, id, cbOut ); cm->registerReadWrite( getEntity(), this, id, cbRw ); @@ -358,14 +313,12 @@ void SurfaceMeshComponentBase::setupIO( const std::string& id ) { base::setupIO( id ); } -template -const CoreMeshType* SurfaceMeshComponentBase::getMeshOutput() const { +inline auto SurfaceMeshComponent::getMeshOutput() const -> const CoreMeshType* { CHECK_MESH_NOT_NULL; return &m_displayMesh->getCoreGeometry(); } -template -CoreMeshType* SurfaceMeshComponentBase::getMeshRw() { +inline auto SurfaceMeshComponent::getMeshRw() -> CoreMeshType* { CHECK_MESH_NOT_NULL; return &( m_displayMesh->getCoreGeometry() ); } From 19ce21fcfe87ac16f8e9e8fa8fc0ad3a748c0591 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 17 May 2026 17:07:12 +0200 Subject: [PATCH 130/144] [engine] Mesh remove deprecated General,Poly,Triangle,Quad -Mesh. --- src/Engine/Data/Mesh.hpp | 103 ++++----------------------------------- 1 file changed, 9 insertions(+), 94 deletions(-) diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 7230662ff51..39be024d5f1 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -427,7 +427,13 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable m_activeLayerKey = layer_key; setRenderMode( m_geomLayers[layer_key].renderMode ); } - LayerKeyType active_layer_key() { return m_activeLayerKey; } + const LayerKeyType& active_layer_key() const { return m_activeLayerKey; } + + size_t getNumFaces() const override { + ///\todo for strips and fan. + m_geom.getLayer( active_layer_key() ).getSize(); + return 0; + } protected: void setupCoreMeshObservers(); @@ -499,30 +505,6 @@ class RA_ENGINE_API Mesh : public IndexedGeometry private: }; -/// GeneralMesh, own a Mesh of type T ( e.g. Core::Geometry::PolyMesh or Core::Geometry::QuadMesh) -/// This class handle the GPU representation of a polyhedron mesh. -/// 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 GeneralMesh : public IndexedGeometry -{ - using base = IndexedGeometry; - using IndexType = Core::Vector3ui; - - public: - using base::IndexedGeometry; - inline size_t getNumFaces() const override; - - protected: - inline void updateGL_specific_impl() override; - - private: - Core::VectorArray m_triangleIndices; -}; - -using PolyMesh = GeneralMesh; -using QuadMesh = GeneralMesh; - /// create a TriangleMesh, PolyMesh or other Core::*Mesh from GeometryData /// \todo replace the copy of all geometry data by reference to original data. template @@ -566,21 +548,8 @@ CoreMeshType createCoreMeshFromGeometryData( const Ra::Core::Asset::GeometryData /// Helpers to get RenderMesh type from CoreMesh Type namespace RenderMeshType { template -struct getType {}; - -template <> -struct getType { - using Type = Ra::Engine::Data::Mesh; -}; - -template <> -struct getType { - using Type = Ra::Engine::Data::QuadMesh; -}; - -template <> -struct getType { - using Type = Ra::Engine::Data::PolyMesh; +struct getType { + static_assert( false ); }; template <> @@ -590,28 +559,6 @@ struct getType { } // namespace RenderMeshType -/// create Mesh, PolyMesh Engine::Data::*Mesh * from GeometryData -template -typename RenderMeshType::getType::Type* -createMeshFromGeometryData( const std::string& name, const Ra::Core::Asset::GeometryData* data ) { - using MeshType = typename RenderMeshType::getType::Type; - - auto mesh = createCoreMeshFromGeometryData( data ); - - MeshType* ret = new MeshType { name }; - ret->loadGeometry( std::move( mesh ) ); - - return ret; -} - -template -std::shared_ptr -createMeshFromGeometryData2( const std::string& name, const Ra::Core::Asset::GeometryData* data ) { - auto mesh = createCoreMeshFromGeometryData( data ); - auto ret = std::make_shared( name, std::move( mesh ) ); - return ret; -} - //----------------------------------------------------------------------------- //- Implementation ------------------------------------------------------------ //----------------------------------------------------------------------------- @@ -982,38 +929,6 @@ PointCloud::PointCloud( const std::string& name, PointCloud::PointCloud( const std::string& name, typename base::MeshRenderMode renderMode ) : base( name, renderMode ) {} -///////// PolyMesh /////////// - -template -size_t GeneralMesh::getNumFaces() const { - return this->getCoreGeometry().getIndices().size(); -} - -template -void GeneralMesh::updateGL_specific_impl() { - if ( !this->m_indices ) { - this->m_indices = globjects::Buffer::create(); - this->m_indicesDirty = true; - } - if ( this->m_indicesDirty ) { - m_triangleIndices = Core::Geometry::Helper::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; - - this->m_indices->setData( static_cast( m_triangleIndices.size() * - sizeof( GeneralMesh::IndexType ) ), - m_triangleIndices.data(), - GL_STATIC_DRAW ); - this->m_indicesDirty = false; - } - if ( !base::m_vao ) { base::m_vao = globjects::VertexArray::create(); } - base::m_vao->bind(); - base::m_vao->bindElementBuffer( this->m_indices.get() ); - base::m_vao->unbind(); -} - } // namespace Data } // namespace Engine } // namespace Ra From 9e2893fd60cb0cadddce71010323614c194e1deb Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 17 May 2026 17:26:52 +0200 Subject: [PATCH 131/144] [engine] Remove deprecated, refactor inline ... --- src/Engine/Data/DisplayableObject.hpp | 3 +- src/Engine/Data/Mesh.hpp | 206 ++++++------------------- src/Engine/Scene/GeometryComponent.hpp | 3 +- 3 files changed, 52 insertions(+), 160 deletions(-) diff --git a/src/Engine/Data/DisplayableObject.hpp b/src/Engine/Data/DisplayableObject.hpp index eb17bb65447..156ca49892e 100644 --- a/src/Engine/Data/DisplayableObject.hpp +++ b/src/Engine/Data/DisplayableObject.hpp @@ -41,8 +41,7 @@ class RA_ENGINE_API Displayable /// Returns the name of the mesh. inline const std::string& getName() const { return m_name; } - /// Returns the underlying AbstractGeometry, which is in fact a TriangleMesh - /// \see getTriangleMesh + /// Returns the underlying AbstractGeometry /// \todo not sure the displayable must have an abstract geometry ... virtual const Core::Geometry::AbstractGeometry& getAbstractGeometry() const = 0; virtual Core::Geometry::AbstractGeometry& getAbstractGeometry() = 0; diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 39be024d5f1..04f5c58a97d 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -88,9 +88,9 @@ class RA_ENGINE_API AttribArrayDisplayable : public Displayable using Displayable::getName; /// Set the render mode. - inline void setRenderMode( MeshRenderMode mode ); + void setRenderMode( MeshRenderMode mode ); /// Get the render mode. - inline MeshRenderMode getRenderMode() const; + MeshRenderMode getRenderMode() const { return m_renderMode; } /// \name /// Mark attrib data as dirty, forcing an update of the OpenGL buffer. @@ -179,7 +179,7 @@ class RA_ENGINE_API VaoIndices { public: /// Tag the indices as dirty, asking for a update to gpu. - inline void setIndicesDirty(); + void setIndicesDirty() { m_indicesDirty = true; } ///\todo Add test for Indices observer class IndicesObserver @@ -220,21 +220,23 @@ class CoreGeometryDisplayable : public AttribArrayDisplayable /// \name /// Core::Geometry getters ///\{ - inline const Core::Geometry::AbstractGeometry& getAbstractGeometry() const override; - inline Core::Geometry::AbstractGeometry& getAbstractGeometry() override; + const Core::Geometry::AbstractGeometry& getAbstractGeometry() const override { return m_mesh; } + Core::Geometry::AbstractGeometry& getAbstractGeometry() override { return m_mesh; } - inline const Core::Geometry::AttribArrayGeometry& getAttribArrayGeometry() const override; - inline Core::Geometry::AttribArrayGeometry& getAttribArrayGeometry() override; + const Core::Geometry::AttribArrayGeometry& getAttribArrayGeometry() const override { + return m_mesh; + } + Core::Geometry::AttribArrayGeometry& getAttribArrayGeometry() override { return m_mesh; } - inline const CoreGeometry& getCoreGeometry() const; - inline CoreGeometry& getCoreGeometry(); + const CoreGeometry& getCoreGeometry() const { return m_mesh; } + CoreGeometry& getCoreGeometry() { return m_mesh; } ///\} /// Helper function that calls Ra::Core::CoreGeometry::addAttrib() template - inline Ra::Core::Utils::AttribHandle addAttrib( const std::string& name, - const typename Core::VectorArray& data ); - inline size_t getNumVertices() const override; + Ra::Core::Utils::AttribHandle addAttrib( const std::string& name, + const typename Core::VectorArray& data ); + size_t getNumVertices() const override { return m_mesh.vertices().size(); } /// Use the given geometry as base for a display mesh. /// This will move \p mesh and *this will take the ownership @@ -279,7 +281,9 @@ class CoreGeometryDisplayable : public AttribArrayDisplayable /// it adds an observer to the new attrib. void addAttribObserver( const std::string& name ); - void addToTranslationTable( const std::string& name ); + void addToTranslationTable( const std::string& name ) { + m_translationTable.insert( name, name ); + } /// Core::Mesh attrib name to Render::Mesh attrib name /// key: core mesh name, value: shader name @@ -295,12 +299,12 @@ class RA_ENGINE_API PointCloud : public CoreGeometryDisplayable - inline void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, - const RangeOfLayerKeys& r ) { + void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, const RangeOfLayerKeys& r ) { m_geomLayers.clear(); m_geom = std::move( mesh ); setupCoreMeshObservers(); @@ -402,9 +403,9 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable } set_active_layer_key( r[0].first ); } - inline void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, - LayerKeyType key, - base::MeshRenderMode renderMode ) { + void loadGeometry( Core::Geometry::MultiIndexedGeometry&& mesh, + LayerKeyType key, + base::MeshRenderMode renderMode ) { loadGeometry( std::move( mesh ), ArrayOfLayerKeys<1> { { { key, renderMode } } } ); } @@ -418,10 +419,10 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable /// Helper function that calls Ra::Core::CoreGeometry::addAttrib() template - inline Ra::Core::Utils::AttribHandle addAttrib( const std::string& name, - const typename Core::VectorArray& data ); + Ra::Core::Utils::AttribHandle addAttrib( const std::string& name, + const typename Core::VectorArray& data ); - inline size_t getNumVertices() const override { return m_geom.vertices().size(); } + size_t getNumVertices() const override { return m_geom.vertices().size(); } void set_active_layer_key( LayerKeyType layer_key ) { m_activeLayerKey = layer_key; @@ -473,7 +474,7 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable static const uint no_restart = 0; uint restart { 0 }; - inline LayerEntryType() = default; + LayerEntryType() = default; }; /// The collection of indices layer we can use for rendering @@ -505,84 +506,19 @@ class RA_ENGINE_API Mesh : public IndexedGeometry private: }; -/// create a TriangleMesh, PolyMesh or other Core::*Mesh from GeometryData -/// \todo replace the copy of all geometry data by reference to original data. -template -CoreMeshType createCoreMeshFromGeometryData( const Ra::Core::Asset::GeometryData* data ) { - CoreMeshType mesh; - typename CoreMeshType::IndexContainerType indices; - - if ( !data->isLineMesh() ) { - auto& geo = data->getGeometry(); - const auto& [layerKeyType, layerBase] = - geo.getFirstLayerOccurrence( mesh.getLayerKey().first ); - const auto& layer = static_cast< - const Core::Geometry::GeometryIndexLayer&>( - layerBase ); - const auto& faces = layer.collection(); - indices.reserve( faces.size() ); - std::copy( faces.begin(), faces.end(), std::back_inserter( indices ) ); - } -#if 0 - // TODO manage line meshes in a "usual" way, i.e. as an indexed geometry with specific - // rendering properties (i.e. shader, as it is the case for point clouds) - // Create a degenerated triangle to handle edges case. - else { - const auto& edges = ... access the LineIndexLayer - indices.reserve( edges.size() ); - std::transform( - edges.begin(), edges.end(), std::back_inserter( indices ), []( Ra::Core::Vector2ui v ) { - return ( Ra::Core::Vector3ui { v( 0 ), v( 1 ), v( 1 ) } ); - } ); - } -#endif - - mesh.setIndices( std::move( indices ) ); - - // This copy only "usual" attributes. See Core::Geometry::AttribManager::copyAllAttributes - mesh.vertexAttribs().copyAllAttributes( data->getGeometry().vertexAttribs() ); - - return mesh; -} - -/// Helpers to get RenderMesh type from CoreMesh Type -namespace RenderMeshType { -template -struct getType { - static_assert( false ); -}; - -template <> -struct getType { - using Type = Ra::Engine::Data::GeometryDisplayable; -}; - -} // namespace RenderMeshType +//------------------------------------------------------------------------------------------------- +//- Implementation -------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//- Implementation ------------------------------------------------------------ -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -//- AttribArrayDisplayable ---------------------------------------------------- - -void AttribArrayDisplayable::setRenderMode( MeshRenderMode mode ) { +//------------------------------------------------------------------------------------------------- +//- AttribArrayDisplayable ------------------------------------------------------------------------ +inline void AttribArrayDisplayable::setRenderMode( MeshRenderMode mode ) { m_renderMode = mode; updatePickingRenderMode(); } -AttribArrayDisplayable::MeshRenderMode AttribArrayDisplayable::getRenderMode() const { - return m_renderMode; -} - -///////////////// VaoIndices /////////////////////// - -void VaoIndices::setIndicesDirty() { - m_indicesDirty = true; -} - -//////////////// CoreGeometryDisplayable /////////////////////////////// - +//------------------------------------------------------------------------------------------------- +//- CoreGeometryDisplayable ----------------------------------------------------------------------- template CoreGeometryDisplayable::CoreGeometryDisplayable( const std::string& name, MeshRenderMode renderMode ) : @@ -590,44 +526,6 @@ CoreGeometryDisplayable::CoreGeometryDisplayable( const std::strin setupCoreMeshObservers(); } -template -const Ra::Core::Geometry::AbstractGeometry& -CoreGeometryDisplayable::getAbstractGeometry() const { - return m_mesh; -} - -template -Ra::Core::Geometry::AbstractGeometry& CoreGeometryDisplayable::getAbstractGeometry() { - return m_mesh; -} - -template -const Ra::Core::Geometry::AttribArrayGeometry& -CoreGeometryDisplayable::getAttribArrayGeometry() const { - return m_mesh; -} - -template -Ra::Core::Geometry::AttribArrayGeometry& -CoreGeometryDisplayable::getAttribArrayGeometry() { - return m_mesh; -} - -template -const CoreGeometry& CoreGeometryDisplayable::getCoreGeometry() const { - return m_mesh; -} - -template -CoreGeometry& CoreGeometryDisplayable::getCoreGeometry() { - return m_mesh; -} - -template -void CoreGeometryDisplayable::addToTranslationTable( const std::string& name ) { - m_translationTable.insert( name, name ); -} - template void CoreGeometryDisplayable::addAttribObserver( const std::string& name ) { // this observer is called each time an attrib is added or removed from m_mesh @@ -730,7 +628,6 @@ void CoreGeometryDisplayable::loadGeometry_common( T&& mesh ) { } template - void CoreGeometryDisplayable::setupCoreMeshObservers() { int idx = 0; m_dataDirty.resize( m_mesh.vertexAttribs().getNumAttribs() ); @@ -771,11 +668,6 @@ CoreGeometryDisplayable::addAttrib( const std::string& name, return m_mesh.addAttrib( name, data ); } -template -size_t CoreGeometryDisplayable::getNumVertices() const { - return m_mesh.vertices().size(); -} - template void CoreGeometryDisplayable::loadGeometry( CoreGeometry&& /*mesh*/ ) { CORE_ASSERT( false, "must be specialized" ); @@ -856,8 +748,8 @@ void CoreGeometryDisplayable::setAttribNameMatching( m_translationTable.replace( meshAttribName, shaderAttribName ); } -//////////////// IndexedGeometry /////////////////////////////// - +//------------------------------------------------------------------------------------------------- +//- IndexedGeometry ------------------------------------------------------------------------------- template IndexedGeometry::IndexedGeometry( const std::string& name, typename base::CoreGeometry&& geom, @@ -917,16 +809,16 @@ void IndexedGeometry::render( const ShaderProgram* prog ) { } } -///////// PointCloud ////////// - -PointCloud::PointCloud( const std::string& name, - typename base::CoreGeometry&& geom, - typename base::MeshRenderMode renderMode ) : +//------------------------------------------------------------------------------------------------- +//- PointCloud ------------------------------------------------------------------------------------ +inline PointCloud::PointCloud( const std::string& name, + typename base::CoreGeometry&& geom, + typename base::MeshRenderMode renderMode ) : base( name, renderMode ) { loadGeometry( std::move( geom ) ); } -PointCloud::PointCloud( const std::string& name, typename base::MeshRenderMode renderMode ) : +inline PointCloud::PointCloud( const std::string& name, typename base::MeshRenderMode renderMode ) : base( name, renderMode ) {} } // namespace Data diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index edf5eef2450..3277020a167 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -49,7 +49,8 @@ class RA_ENGINE_API GeometryComponent : public Component }; /*! - * \brief Main class to convert Ra::Core::Asset::GeometryData to Ra::Engine::Mesh + * \brief Component class for surface mesh ( Engine::Data::GeometryDisplayable / + * Core::Geometry::MultiIndexedGeometry ) * * Exports access to the mesh geometry: * - SurfaceMeshComponent: get, rw (set vertices, normals and triangles dirty) From 0350d6d9dff4fbbfa3b17eeecda4ede816d21fe6 Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 17 May 2026 20:33:10 +0200 Subject: [PATCH 132/144] [engine] Remove deprecated Mesh. --- src/Engine/Data/Mesh.cpp | 14 -------------- src/Engine/Data/Mesh.hpp | 13 ------------- 2 files changed, 27 deletions(-) diff --git a/src/Engine/Data/Mesh.cpp b/src/Engine/Data/Mesh.cpp index ba523be4d23..4882c1d2f9a 100644 --- a/src/Engine/Data/Mesh.cpp +++ b/src/Engine/Data/Mesh.cpp @@ -33,20 +33,6 @@ AttribArrayDisplayable::AttribArrayDisplayable( const std::string& name, updatePickingRenderMode(); } -size_t Mesh::getNumFaces() const { - ///\todo fix this once we have explicit triangle fan and strip management. - switch ( getRenderMode() ) { - case MeshRenderMode::RM_TRIANGLE_STRIP: - [[fallthrough]]; - case MeshRenderMode::RM_TRIANGLE_FAN: - return ( getCoreGeometry().getIndices().size() - 1 ) * 3 + 1; - case MeshRenderMode::RM_TRIANGLES: - return getCoreGeometry().getIndices().size(); - default: - return size_t( 0 ); - } -} - void AttribArrayDisplayable::updatePickingRenderMode() { switch ( getRenderMode() ) { case AttribArrayDisplayable::RM_POINTS: { diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 04f5c58a97d..209c04cfac8 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -493,19 +493,6 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable BijectiveAssociation m_translationTable {}; }; -/// Mesh, own a Core::Geometry::TriangleMesh -class RA_ENGINE_API Mesh : public IndexedGeometry -{ - using base = IndexedGeometry; - - public: - using base::IndexedGeometry; - size_t getNumFaces() const override; - - protected: - private: -}; - //------------------------------------------------------------------------------------------------- //- Implementation -------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------- From fa66dffef4127a7a5c82189ddd774851e6d80fec Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 17 May 2026 20:33:44 +0200 Subject: [PATCH 133/144] [core] Change ref to TriangleMesh:: by MultiIndexedGeometry or Index --- src/Core/Geometry/MeshPrimitives.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Core/Geometry/MeshPrimitives.cpp b/src/Core/Geometry/MeshPrimitives.cpp index f69b2350e20..bf75ddbff38 100644 --- a/src/Core/Geometry/MeshPrimitives.cpp +++ b/src/Core/Geometry/MeshPrimitives.cpp @@ -249,9 +249,9 @@ makeGeodesicSphere( Scalar radius, uint numSubdiv, const Utils::optional& color ) { MultiIndexedGeometry result; - TriangleMesh::PointAttribHandle::Container vertices; - TriangleMesh::NormalAttribHandle::Container normals; - TriangleMesh::IndexContainerType indices; + MultiIndexedGeometry::PointAttribHandle::Container vertices; + MultiIndexedGeometry::NormalAttribHandle::Container normals; + TriangleIndexLayer::IndexContainerType indices; vertices.reserve( nFaces * nFaces + nFaces + 2 ); normals.reserve( nFaces * nFaces + nFaces + 2 ); From dbeff531ea1f2c060d8fcc3f19d0f55131ff50eb Mon Sep 17 00:00:00 2001 From: dlyr Date: Sun, 17 May 2026 20:44:32 +0200 Subject: [PATCH 134/144] [core] Remove ref to deprecated. --- src/Core/Geometry/IndexedGeometry.hpp | 3 --- src/Core/Geometry/TopologicalMesh.cpp | 2 +- src/Core/Geometry/TopologicalMesh.hpp | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 296c91ca5f2..f2cb78c06cb 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -682,9 +682,6 @@ class RA_CORE_API IndexedPointCloud : public IndexedGeometry; -using QuadMesh = IndexedGeometry; -using PolyMesh = IndexedGeometry; -using LineMesh = IndexedGeometry; //----------------------------------------------------------------------------- //- Implementation ------------------------------------------------------------ diff --git a/src/Core/Geometry/TopologicalMesh.cpp b/src/Core/Geometry/TopologicalMesh.cpp index 419e9c8db8d..a2a5332321a 100644 --- a/src/Core/Geometry/TopologicalMesh.cpp +++ b/src/Core/Geometry/TopologicalMesh.cpp @@ -187,7 +187,7 @@ TopologicalMesh::TopologicalMesh() { } void TopologicalMesh::updateTriangleMesh( Ra::Core::Geometry::MultiIndexedGeometry& out ) const { - TriangleMesh::PointAttribHandle::Container wedgePosition; + MultiIndexedGeometry::PointAttribHandle::Container wedgePosition; AlignedStdVector::Container> wedgeFloatAttribData( m_wedges.m_floatAttribNames.size() ); AlignedStdVector::Container> wedgeVector2AttribData( diff --git a/src/Core/Geometry/TopologicalMesh.hpp b/src/Core/Geometry/TopologicalMesh.hpp index a2e149cd137..38275fa5457 100644 --- a/src/Core/Geometry/TopologicalMesh.hpp +++ b/src/Core/Geometry/TopologicalMesh.hpp @@ -1508,7 +1508,7 @@ MultiIndexedGeometry TopologicalMesh::toIndexedMesh() { std::vector> wedgeVector3AttribHandles; std::vector> wedgeVector4AttribHandles; - TriangleMesh::PointAttribHandle::Container wedgePosition; + MultiIndexedGeometry::PointAttribHandle::Container wedgePosition; AlignedStdVector::Container> wedgeFloatAttribData( m_wedges.m_floatAttribNames.size() ); AlignedStdVector::Container> wedgeVector2AttribData( From 90c9c4af52ff59a6e429ad78cd26578e619720c8 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 18 May 2026 09:34:15 +0200 Subject: [PATCH 135/144] [tests] Get rid of lasts TriangleMesh in tests. --- tests/unittest/Core/indexview.cpp | 1 - tests/unittest/Core/topomesh.cpp | 29 ++++++++++++----------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/tests/unittest/Core/indexview.cpp b/tests/unittest/Core/indexview.cpp index 8d7933ae61c..7fc56a56109 100644 --- a/tests/unittest/Core/indexview.cpp +++ b/tests/unittest/Core/indexview.cpp @@ -282,7 +282,6 @@ TEST_CASE( "Core/Geometry/IndexedGeometry/CopyAllAttributes", using Ra::Core::Vector2; using Ra::Core::Vector3; using namespace Ra::Core::Geometry; - using Ra::Core::Geometry::TriangleMesh; MultiIndexedGeometry m; MultiIndexedGeometry::PointAttribHandle::Container vertices; diff --git a/tests/unittest/Core/topomesh.cpp b/tests/unittest/Core/topomesh.cpp index b94e5b72fe7..cb72811d082 100644 --- a/tests/unittest/Core/topomesh.cpp +++ b/tests/unittest/Core/topomesh.cpp @@ -247,7 +247,6 @@ void testConverter1( const MultiIndexedGeometry& mesh ) { TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][TopologicalMesh]" ) { using Ra::Core::Vector3; using Ra::Core::Geometry::TopologicalMesh; - using Ra::Core::Geometry::TriangleMesh; SECTION( "Test OpenMesh specialization" ) { Vector3 v1 { 1_ra, 0_ra, 0_ra }; @@ -412,9 +411,9 @@ TEST_CASE( "Core/Geometry/TopologicalMesh", "[unittests][Core][Core/Geometry][To VectorArray indices { { 0, 2, 1 }, { 0, 3, 2 } }; // well formed mesh - TriangleMesh mesh; + MultiIndexedGeometry mesh; mesh.setVertices( std::move( vertices ) ); - mesh.setIndices( std::move( indices ) ); + mesh.set_indices( std::move( indices ) ); TopologicalMesh topo1 { mesh }; REQUIRE( topo1.checkIntegrity() ); auto mesh1 = topo1.toTriangleMesh(); @@ -556,13 +555,12 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/EdgeSplit", "[unittests][Core][Core/Geometry][TopologicalMesh]" ) { using Ra::Core::Vector3; using Ra::Core::Geometry::TopologicalMesh; - using Ra::Core::Geometry::TriangleMesh; // create a triangle mesh with 4 vertices - TriangleMesh meshSplit; + MultiIndexedGeometry meshSplit; meshSplit.setVertices( { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 } } ); meshSplit.setNormals( { { -1, -1, 1 }, { 1, -1, 1 }, { 1, 1, 1 }, { -1, 1, 1 } } ); - meshSplit.setIndices( { Vector3ui( 0, 1, 2 ), Vector3ui( 0, 2, 3 ) } ); + meshSplit.set_indices( { Vector3ui( 0, 1, 2 ), Vector3ui( 0, 2, 3 ) } ); // add a float attrib auto handle = meshSplit.addAttrib( "test", { 0_ra, 1_ra, 2_ra, 3_ra } ); CORE_UNUSED( handle ); // until unit test is finished. @@ -724,10 +722,10 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Manifold", }; VectorArray indices { { 0, 2, 1 }, { 2, 3, 4 } }; - TriangleMesh mesh; + MultiIndexedGeometry mesh; // do not move vertices, we need to compare afterward mesh.setVertices( vertices ); - mesh.setIndices( std::move( indices ) ); + mesh.set_indices( std::move( indices ) ); TopologicalMesh topo { mesh }; @@ -771,9 +769,9 @@ TEST_CASE( "Core/Geometry/TopologicalMesh/Manifold", { 4, 6, 3 }, { 6, 5, 3 } }; - TriangleMesh mesh; + MultiIndexedGeometry mesh; mesh.setVertices( std::move( vertices ) ); - mesh.setIndices( std::move( indices ) ); + mesh.set_indices( std::move( indices ) ); std::vector> faulty; NonManifoldCommand2 command { faulty }; @@ -1116,13 +1114,13 @@ TEST_CASE( "Core/TopologicalMesh/CollapseWedge", "[unittests]" ) { const Vector3& inTo ) { Vector3 from { inFrom }; Vector3 to { inTo }; - TriangleMesh mesh1; + MultiIndexedGeometry mesh1; TopologicalMesh topo1; optional optHe; mesh1.setVertices( points ); mesh1.addAttrib( "color", Vector4Array { colors.begin(), colors.begin() + points.size() } ); - mesh1.setIndices( indices ); + mesh1.set_indices( indices ); topo1 = TopologicalMesh { mesh1 }; topo1.mergeEqualWedges(); @@ -1193,13 +1191,13 @@ TEST_CASE( "Core/TopologicalMesh/CollapseWedge", "[unittests]" ) { const Vector3uArray& indices, Vector3 from, Vector3 to ) { - TriangleMesh mesh; + MultiIndexedGeometry mesh; TopologicalMesh topo; optional optHe; mesh.setVertices( points ); mesh.addAttrib( "color", Vector4Array { colors.begin(), colors.begin() + points.size() } ); - mesh.setIndices( indices ); + mesh.set_indices( indices ); topo = TopologicalMesh { mesh }; topo.mergeEqualWedges(); @@ -1340,9 +1338,6 @@ void testConverter( MultiIndexedGeometry&& mesh ) { TEST_CASE( "Core/Geometry/TopologicalMesh/Updates", "[unittests][Core][Core/Geometry][TopologicalMesh]" ) { - using Ra::Core::Vector3; - using Ra::Core::Geometry::TopologicalMesh; - using Ra::Core::Geometry::TriangleMesh; SECTION( "Closed mesh" ) { testConverter( Ra::Core::Geometry::makeBox() ); From 8d2fc319086f1d9fffea73c13aac3eaa8af8509d Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 18 May 2026 09:34:49 +0200 Subject: [PATCH 136/144] [core] Replace TriangleMesh by MultiIndexed equiv. --- src/Core/Asset/MaterialData.hpp | 2 +- src/Core/Geometry/IndexedGeometry.hpp | 9 ++++++++- src/Core/Geometry/RayCast.cpp | 21 ++++++++++++++++++--- src/Core/Geometry/RayCast.hpp | 2 +- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/Core/Asset/MaterialData.hpp b/src/Core/Asset/MaterialData.hpp index 052427e19ca..fd431cbb8db 100644 --- a/src/Core/Asset/MaterialData.hpp +++ b/src/Core/Asset/MaterialData.hpp @@ -13,7 +13,7 @@ namespace Asset { * Material data must be identified by a unique name. * Radium Engine reserves the following names * "AbstractMaterial" --> unknown material, might serve for error management - * "BlinnPhong" --> standar Blinn-Phong Material + * "BlinnPhong" --> standard Blinn-Phong Material * * When extending the material system with a loader plugin (or something similar) : * Define your own "Asset" class derived from Ra::Core::Asset::MaterialData with the "type" diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index f2cb78c06cb..3f602b90a62 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -210,6 +210,7 @@ DECLARE_INDEX_LAYER( StripOrFanIndexLayer, VectorNui ) * \note, This layer ensures that all faces have exactly 2 vertices */ DECLARE_INDEX_LAYER( LineIndexLayer, Vector2ui ) +///\todo add primitive restart index ? or leave it to the engine ? /** * \} @@ -529,7 +530,11 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util auto result = getFirstLayerOccurrence( IndexLayer::staticSemanticName ); return static_cast( result.second ).collection(); } - + template + const typename IndexLayer::IndexContainerType& indices( LayerKeyType layer_key ) const { + auto& result = getLayer( layer_key ); + return static_cast( result ).collection(); + } /// Call triangulate, if there isn't any triangle index, on the first found index between quad /// and poly. /// \return the layer key of the triangle layer (old or new) @@ -681,6 +686,8 @@ class IndexedGeometry : public MultiIndexedGeometry class RA_CORE_API IndexedPointCloud : public IndexedGeometry {}; +// only used it deprecated / outdated code. \todo remove when deprecated/TopologicalMesh and +// IO/deprecated has been deleted. using TriangleMesh = IndexedGeometry; //----------------------------------------------------------------------------- diff --git a/src/Core/Geometry/RayCast.cpp b/src/Core/Geometry/RayCast.cpp index a56dc1cc5e5..28bd3d120a2 100644 --- a/src/Core/Geometry/RayCast.cpp +++ b/src/Core/Geometry/RayCast.cpp @@ -1,3 +1,5 @@ +#include "Core/Geometry/IndexedGeometry.hpp" +#include "Core/Utils/ObjectWithSemantic.hpp" #include #include #include // Math::sign @@ -319,11 +321,24 @@ bool RayCastTriangle( const Ray& ray, } bool RayCastTriangleMesh( const Ray& r, - const TriangleMesh& mesh, + const MultiIndexedGeometry& mesh, std::vector& hitsOut, std::vector& trianglesIdxOut ) { - bool hit = false; - const auto& indices = mesh.getIndices(); + bool hit = false; + + auto triangle_layer = mesh.default_layer_key(); + if ( !Utils::hasSemantic( triangle_layer.first, TriangleIndexLayer::staticSemanticName ) ) { + if ( mesh.containsLayer( TriangleIndexLayer::staticSemanticName ) ) { + auto found = mesh.getFirstLayerOccurrence( TriangleIndexLayer::staticSemanticName ); + triangle_layer = found.first; + } + else { + LOG( Utils::logINFO ) << "Ray cast only on triangle"; + return false; + } + } + + const auto& indices = mesh.indices( triangle_layer ); const auto& vertices = mesh.vertices(); for ( size_t i = 0; i < indices.size(); ++i ) { const auto& t = indices[i]; diff --git a/src/Core/Geometry/RayCast.hpp b/src/Core/Geometry/RayCast.hpp index e46f20efaf3..908890c8f9d 100644 --- a/src/Core/Geometry/RayCast.hpp +++ b/src/Core/Geometry/RayCast.hpp @@ -49,7 +49,7 @@ bool RA_CORE_API RayCastTriangle( const Ray& r, std::vector& hitsOut ); bool RA_CORE_API RayCastTriangleMesh( const Ray& r, - const TriangleMesh& mesh, + const MultiIndexedGeometry& mesh, std::vector& hitsOut, std::vector& trianglesIdxOut ); } // namespace Geometry From 0bc5e08e84f0b43c3bd8d09505a1625e7738b557 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 18 May 2026 10:35:41 +0200 Subject: [PATCH 137/144] [core] Refactor semantics, use std helper in IndexedGeometry. --- src/Core/Geometry/IndexedGeometry.cpp | 36 ++++++++++----------- src/Core/Utils/ObjectWithSemantic.hpp | 46 ++++++++++++++++----------- 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index 59c8c4034b9..15518b6b6a5 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -1,3 +1,4 @@ +#include "Core/Utils/ObjectWithSemantic.hpp" #include #include @@ -100,14 +101,14 @@ bool MultiIndexedGeometry::append( const MultiIndexedGeometry& other ) { bool MultiIndexedGeometry::containsLayer( const LayerSemantic& semanticName ) const { for ( const auto& [key, value] : m_indices ) { - if ( key.first.find( semanticName ) != key.first.end() ) return true; + if ( Utils::hasSemantic( key.first, semanticName ) ) return true; } return false; } bool MultiIndexedGeometry::containsLayer( const LayerSemanticCollection& semantics ) const { for ( const auto& [key, value] : m_indices ) { - if ( key.first == semantics ) return true; + if ( Utils::sameSemantics( key.first, semantics ) ) return true; } return false; } @@ -116,19 +117,15 @@ bool MultiIndexedGeometry::containsLayer( const LayerSemanticCollection& semanti ////////////////////////////////////////////////////////////////////// size_t MultiIndexedGeometry::countLayers( const LayerSemantic& semanticName ) const { - size_t c = 0; - for ( const auto& [key, value] : m_indices ) { - if ( key.first.find( semanticName ) != key.first.end() ) ++c; - } - return c; + return std::count_if( m_indices.cbegin(), m_indices.cend(), [&semanticName]( const auto& l ) { + return Utils::hasSemantic( l.first.first, semanticName ); + } ); } size_t MultiIndexedGeometry::countLayers( const LayerSemanticCollection& semantics ) const { - size_t c = 0; - for ( const auto& [key, value] : m_indices ) { - if ( key.first == semantics ) ++c; - } - return c; + return std::count_if( m_indices.cbegin(), m_indices.cend(), [&semantics]( const auto& l ) { + return Utils::sameSemantics( l.first.first, semantics ); + } ); } ////////////////////////////////////////////////////////////////////// @@ -136,18 +133,19 @@ 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() ) - return { key, *( value.second.get() ) }; - } + auto itr = std::find_if( m_indices.cbegin(), m_indices.cend(), [&]( const auto& entry ) { + return Utils::hasSemantic( entry.first.first, semanticName ); + } ); + if ( itr != m_indices.cend() ) { return { itr->first, *( itr->second.second.get() ) }; } throw std::out_of_range( "Layer entry not found" ); } std::pair MultiIndexedGeometry::getFirstLayerOccurrence( const LayerSemanticCollection& semantics ) const { - for ( const auto& [key, value] : m_indices ) { - if ( key.first == semantics ) return { key, *( value.second.get() ) }; - } + auto itr = std::find_if( m_indices.cbegin(), m_indices.cend(), [&]( const auto& entry ) { + return Utils::sameSemantics( entry.first.first, semantics ); + } ); + if ( itr != m_indices.cend() ) { return { itr->first, *( itr->second.second.get() ) }; } throw std::out_of_range( "Layer entry not found" ); } diff --git a/src/Core/Utils/ObjectWithSemantic.hpp b/src/Core/Utils/ObjectWithSemantic.hpp index afb031f4296..1760e2a8bf9 100644 --- a/src/Core/Utils/ObjectWithSemantic.hpp +++ b/src/Core/Utils/ObjectWithSemantic.hpp @@ -24,43 +24,34 @@ class RA_CORE_API ObjectWithSemantic /// \todo move out of class ? extends set to add helper functions ? using SemanticNameCollection = std::set; - inline explicit ObjectWithSemantic( const ObjectWithSemantic& other ) : - m_names { other.m_names } {} + explicit ObjectWithSemantic( const ObjectWithSemantic& other ) : m_names { other.m_names } {} - virtual inline ~ObjectWithSemantic() = default; + virtual ~ObjectWithSemantic() = default; - inline bool hasSemantic( const SemanticName& name ) const { - return m_names.find( name ) != m_names.end(); - } + bool hasSemantic( const SemanticName& name ) const; - inline const SemanticNameCollection& semantics() const { return m_names; } + const SemanticNameCollection& semantics() const { return m_names; } - inline ObjectWithSemantic& operator=( const ObjectWithSemantic& other ) { + ObjectWithSemantic& operator=( const ObjectWithSemantic& other ) { CORE_UNUSED( other ); CORE_ASSERT( m_names == other.m_names, "Try to assign object with different semantics" ); return *this; } - inline ObjectWithSemantic& operator=( ObjectWithSemantic&& other ) { + ObjectWithSemantic& operator=( ObjectWithSemantic&& other ) { CORE_UNUSED( other ); CORE_ASSERT( m_names == other.m_names, "Try to assign object with different semantics" ); return *this; } - inline bool shareSemantic( const ObjectWithSemantic& other ) const { - return std::any_of( m_names.begin(), m_names.end(), [&other]( const auto& s ) { - return other.hasSemantic( s ); - } ); - } + bool shareSemantic( const ObjectWithSemantic& other ) const; - inline bool sameSemantics( const ObjectWithSemantic& other ) const { - return m_names == other.m_names; - } + bool sameSemantics( const ObjectWithSemantic& other ) const; protected: template - inline explicit ObjectWithSemantic( SemanticNames... names ) : m_names { names... } {} + explicit ObjectWithSemantic( SemanticNames... names ) : m_names { names... } {} - inline explicit ObjectWithSemantic( const SemanticNameCollection& otherNames ) : + explicit ObjectWithSemantic( const SemanticNameCollection& otherNames ) : m_names { otherNames } {} private: @@ -77,6 +68,23 @@ inline bool shareSemantic( const ObjectWithSemantic::SemanticNameCollection& a, return std::any_of( a.begin(), a.end(), [&b]( const auto& s ) { return hasSemantic( b, s ); } ); } +inline bool sameSemantics( const ObjectWithSemantic::SemanticNameCollection& a, + const ObjectWithSemantic::SemanticNameCollection& b ) { + return a == b; +} + +inline bool ObjectWithSemantic::hasSemantic( const SemanticName& name ) const { + return ::Ra::Core::Utils::hasSemantic( m_names, name ); +} + +inline bool ObjectWithSemantic::shareSemantic( const ObjectWithSemantic& other ) const { + return ::Ra::Core::Utils::shareSemantic( m_names, other.semantics() ); +} + +inline bool ObjectWithSemantic::sameSemantics( const ObjectWithSemantic& other ) const { + return ::Ra::Core::Utils::sameSemantics( m_names, other.m_names ); +} + } // namespace Utils } // namespace Core } // namespace Ra From 5004611bb11bddc8d37a7da6f73404f442a6d285 Mon Sep 17 00:00:00 2001 From: dlyr Date: Mon, 18 May 2026 11:40:07 +0200 Subject: [PATCH 138/144] [*] Some comments, revome deprecadted point cloud, /*! -> /**. --- examples/SimpleAnimation/main.cpp | 2 +- src/Core/Asset/GeometryData.hpp | 1 + src/Core/Containers/AdjacencyList.hpp | 2 +- src/Core/CoreMacros.hpp | 4 +- src/Core/Geometry/IndexedGeometry.hpp | 6 +-- src/Core/Utils/Attribs.hpp | 12 +++--- src/Core/Utils/Color.hpp | 2 +- src/Core/Utils/IndexMap.hpp | 2 +- src/Engine/Scene/GeometryComponent.hpp | 8 ++-- src/Gui/Timeline/Timeline.hpp | 52 +++++++++++++------------- src/Gui/Viewer/WindowQt.hpp | 2 +- src/PluginBase/PluginContext.hpp | 2 +- 12 files changed, 47 insertions(+), 48 deletions(-) diff --git a/examples/SimpleAnimation/main.cpp b/examples/SimpleAnimation/main.cpp index a260e788d93..d79b4a7717a 100644 --- a/examples/SimpleAnimation/main.cpp +++ b/examples/SimpleAnimation/main.cpp @@ -42,7 +42,7 @@ class KeyFramedGeometryComponent : public Ra::Engine::Scene::SurfaceMeshComponent { public: - /*! + /** * Constructor from an existing core mesh * \warning Moves the mesh and takes its ownership */ diff --git a/src/Core/Asset/GeometryData.hpp b/src/Core/Asset/GeometryData.hpp index b084d1ae284..c02fdaa7629 100644 --- a/src/Core/Asset/GeometryData.hpp +++ b/src/Core/Asset/GeometryData.hpp @@ -140,6 +140,7 @@ class RA_CORE_API GeometryData : public AssetData GeometryType m_type; /// Named attributes + /// \todo switch to shared ptr ? Core::Geometry::MultiIndexedGeometry m_geometry; /// Simple tracking of geometric primitive number diff --git a/src/Core/Containers/AdjacencyList.hpp b/src/Core/Containers/AdjacencyList.hpp index 654dadd773f..329f49713b1 100644 --- a/src/Core/Containers/AdjacencyList.hpp +++ b/src/Core/Containers/AdjacencyList.hpp @@ -56,7 +56,7 @@ class RA_CORE_API AdjacencyList void pruneLeaves( std::vector& pruned, std::vector& delete_flag ); /// Prune the leaves of the graph. void pruneLeaves(); - /*! + /** * Return the edge list built from the given adjacency list. * If include_leaf is true, the list will contain the pairs: * ... diff --git a/src/Core/CoreMacros.hpp b/src/Core/CoreMacros.hpp index 80fba1606af..af393ca4202 100644 --- a/src/Core/CoreMacros.hpp +++ b/src/Core/CoreMacros.hpp @@ -259,7 +259,7 @@ using Scalar = float; using Scalar = double; #endif -/*! +/** * User litteral for Radium's Scalar type for floating point numbers * \see https://en.cppreference.com/w/cpp/language/user_literal * To create a Scalar from a litteral float, do: @@ -272,7 +272,7 @@ constexpr Scalar operator"" _ra ( long double n ) return Scalar( n ); } -/*! +/** * \brief User litteral for Radium's Scalar type for floating point numbers * \see https://en.cppreference.com/w/cpp/language/user_literal * To create a Scalar from a litteral, do: diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 3f602b90a62..30851264c39 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -537,7 +537,8 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util } /// Call triangulate, if there isn't any triangle index, on the first found index between quad /// and poly. - /// \return the layer key of the triangle layer (old or new) + /// \todo triangulate strip or fan... + /// \return the layer key of the triangle layer (existing or newly added) LayerKeyType triangulate_any() { if ( !containsLayer( TriangleIndexLayer::staticSemanticName ) ) { if ( containsLayer( QuadIndexLayer::staticSemanticName ) ) @@ -683,9 +684,6 @@ class IndexedGeometry : public MultiIndexedGeometry const LayerKeyType& getLayerKey() const; }; -class RA_CORE_API IndexedPointCloud : public IndexedGeometry -{}; - // only used it deprecated / outdated code. \todo remove when deprecated/TopologicalMesh and // IO/deprecated has been deleted. using TriangleMesh = IndexedGeometry; diff --git a/src/Core/Utils/Attribs.hpp b/src/Core/Utils/Attribs.hpp index 5c605d699f4..a60b0790ca5 100644 --- a/src/Core/Utils/Attribs.hpp +++ b/src/Core/Utils/Attribs.hpp @@ -179,7 +179,7 @@ class AttribHandle friend class AttribManager; }; -/*! +/** * \brief The AttribManager provides attributes management by handles. * * The AttribManager stores a container of AttribBase *, which can @@ -250,7 +250,7 @@ class RA_CORE_API AttribManager : public Observable template bool isValid( const AttribHandle& h ) const; - /*! + /** * \brief contains Check if an attribute with the given \p name exists. * \param name Name of the attribute. * \warning There is no error check on the attribute type. @@ -258,7 +258,7 @@ class RA_CORE_API AttribManager : public Observable */ bool contains( const std::string& name ) const; - /*! + /** * \brief findAttrib Grab an attribute handler by \p name. * \param name Name of the attribute. * \return Attribute handler if found, an invalid handler otherwise. @@ -268,7 +268,7 @@ class RA_CORE_API AttribManager : public Observable template AttribHandle findAttrib( const std::string& name ) const; - /*! + /** * \brief Get the locked data container from the attrib handle * \tparam T The type of the attribute data * \param h the attribute handle @@ -277,7 +277,7 @@ class RA_CORE_API AttribManager : public Observable template typename Attrib::Container& getDataWithLock( const AttribHandle& h ); - /*! + /** * \brief Get read access to the data container from the attrib handle * \tparam T The type of the attribute data * \param h the attribute handle @@ -286,7 +286,7 @@ class RA_CORE_API AttribManager : public Observable template const typename Attrib::Container& getData( const AttribHandle& h ); - /*! + /** * \brief Unlock the handle data * \tparam T * \param h diff --git a/src/Core/Utils/Color.hpp b/src/Core/Utils/Color.hpp index 0fcd3040e5b..00bfbb851ec 100644 --- a/src/Core/Utils/Color.hpp +++ b/src/Core/Utils/Color.hpp @@ -20,7 +20,7 @@ namespace Utils { */ uint32_t RA_CORE_API getNamedColorCode( std::string_view name ); -/*! +/** * Colors are defined as vector4, i.e. 4 Scalars in RGBA order. * displayable colors should have all their coordinates between 0 and 1. * diff --git a/src/Core/Utils/IndexMap.hpp b/src/Core/Utils/IndexMap.hpp index 5dcda953467..1ea92027986 100644 --- a/src/Core/Utils/IndexMap.hpp +++ b/src/Core/Utils/IndexMap.hpp @@ -12,7 +12,7 @@ namespace Ra { namespace Core { namespace Utils { -/*! +/** * The class IndexMap define a map where a object is coupled with a index. * The index is unique, it is assigned to a object when it's inserted and is kept until the object * is removed. After a removal, the index becomes free again. A object will be given the first free diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index 3277020a167..3d7038329ea 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -48,7 +48,7 @@ class RA_ENGINE_API GeometryComponent : public Component std::string m_contentName {}; }; -/*! +/** * \brief Component class for surface mesh ( Engine::Data::GeometryDisplayable / * Core::Geometry::MultiIndexedGeometry ) * @@ -73,7 +73,7 @@ class SurfaceMeshComponent : public GeometryComponent Entity* entity, std::shared_ptr data ); - /*! + /** * Constructor from an existing mesh * \warning Moves the mesh and takes its ownership */ @@ -124,7 +124,7 @@ class RA_ENGINE_API PointCloudComponent : public GeometryComponent Entity* entity, const Ra::Core::Asset::GeometryData* data ); - /*! + /** * Constructor from an existing mesh * \warning Moves the mesh and takes its ownership */ @@ -170,7 +170,7 @@ class RA_ENGINE_API PointCloudComponent : public GeometryComponent //------------------------------------------------------------------------------------------------- -/*! +/** * \brief Main class to convert Ra::Core::Asset::VolumeData to Ra::Engine::VolumeObject * * Exports access to the volume: diff --git a/src/Gui/Timeline/Timeline.hpp b/src/Gui/Timeline/Timeline.hpp index 8245484c19b..d88ce4e198c 100644 --- a/src/Gui/Timeline/Timeline.hpp +++ b/src/Gui/Timeline/Timeline.hpp @@ -15,7 +15,7 @@ class Timeline; namespace Ra::Gui { -/*! +/** * \brief The Timeline class provides display and management of time, as well as * keyframes. * @@ -95,67 +95,67 @@ class RA_GUI_API Timeline : public QDialog void detachFromEngine(); signals: - /*! + /** * \brief startChanged is emitted when user move left slider of playzone or set new value in * start spin (green) \param time is the new start time for playzone. */ void startChanged( Scalar time ); - /*! + /** * \brief endChanged is emitted when user move right slider of playzone or set new value in end * spin (red) \param time is the new end time for playzone. */ void endChanged( Scalar time ); - /*! + /** * \brief cursorChanged is emitted when user move cursor. * \param time is the new time of cursor to render in engine. */ void cursorChanged( Scalar time ); - /*! + /** * \brief durationChanged is emitted when user change duration time in top right spin. * \param time is the new time for animation. */ void durationChanged( Scalar time ); - /*! + /** * \brief playClicked is emitted when user click on play button. */ void playClicked( bool play ); - /*! + /** * \brief setPingPong is emitted when user click on PingPong button. */ void setPingPong( bool ); - /*! + /** * \brief keyFrameAdded is emitted when user add new keyFrame. * \param time is the time of new keyFrame, if a keyFrame is already here so signal * keyFrameChanged is called. */ void keyFrameAdded( Scalar time ); - /*! + /** * \brief keyFrameDeleted is emitted when user remove keyFrame. * \param i is the ith keyFrame to remove (chronological order). */ void keyFrameDeleted( size_t i ); - /*! + /** * \brief keyFrameChanged is emitted when user insert keyFrame in a known keyFrame position. * \param i is the ith keyFrame to change. */ void keyFrameChanged( size_t i ); - /*! + /** * \brief keyFrameMoved is emitted when user move the keyFrame on cursor to a new position (on * mouse) \param i is the index of the keyFrame. \param time1 is the new time of the * keyFrame. */ void keyFrameMoved( size_t i, Scalar time1 ); - /*! + /** * \brief keyFramesMoved is emitted when user move keyFrames. * \param first is the index of the first keyFrame to move. * \param offset is sliding distance for moving. @@ -163,31 +163,31 @@ class RA_GUI_API Timeline : public QDialog void keyFramesMoved( size_t first, Scalar offset ); public slots: - /*! + /** * \brief onChangeStart change start in timeline. * \param time is the new start. */ void onChangeStart( Scalar time ); - /*! + /** * \brief onChangeEnd change end in timeline. * \param time is the new end. */ void onChangeEnd( Scalar time ); - /*! + /** * \brief onChangeDuration change duration in timeline. * \param time is the new duration. */ void onChangeDuration( Scalar time ); - /*! + /** * \brief onChangeCursor change cursor in timeline. * \param time is the new cursor. */ void onChangeCursor( Scalar time ); - /*! + /** * \brief onSetPlay set play mode in timeline. */ void onSetPlay( bool play ); // use it if external play button @@ -206,47 +206,47 @@ class RA_GUI_API Timeline : public QDialog */ void updateKeyFrames( Scalar time ); - /*! + /** * \brief onClearKeyFrames remove all KeyFrames in timeline. */ void onClearKeyFrames(); - /*! + /** * \brief onAddingKeyFrame add the current KeyFrame to the timeline. */ void onAddingKeyFrame( Scalar time ); - /*! + /** * \brief onRemovingKeyFrame removes the current KeyFrame from the timeline. */ void onRemovingKeyFrame( size_t i ); - /*! + /** * \brief onChangingKeyFrame updates the current KeyFrame of the timeline. */ void onChangingKeyFrame( size_t i ); - /*! + /** * \brief onMovingKeyFrame moves the KeyFrame at time0 to time1. */ void onMovingKeyFrame( size_t i, Scalar time1 ); - /*! + /** * \brief onMovingKeyFrames offsets all Keyframes from the one at time by offset. */ void onMovingKeyFrames( size_t first, Scalar offset ); - /*! + /** * \brief on_comboBox_attribute_currentTextChanged set the current keyframe */ void on_comboBox_attribute_currentTextChanged( const QString& arg1 ); - /*! + /** * \brief on_pushButton_editAttribute_clicked make the keyframe editor pop up */ void on_pushButton_editAttribute_clicked(); - /*! + /** * \brief on_toolButton_help_clicked make the help dialog pop up */ void on_toolButton_help_clicked(); diff --git a/src/Gui/Viewer/WindowQt.hpp b/src/Gui/Viewer/WindowQt.hpp index ddcb44de485..4dc3802d580 100644 --- a/src/Gui/Viewer/WindowQt.hpp +++ b/src/Gui/Viewer/WindowQt.hpp @@ -23,7 +23,7 @@ class QScreen; namespace Ra { namespace Gui { -/*! +/** * \brief Base class for OpenGL widgets, compatble with Qt and globjects/glbindings. * \note This class has been extracted from globjects example * https://github.com/cginternals/globjects/blob/master/source/examples/qtexample/WindowQt.h diff --git a/src/PluginBase/PluginContext.hpp b/src/PluginBase/PluginContext.hpp index 94267a8fbb4..3a544b0419f 100644 --- a/src/PluginBase/PluginContext.hpp +++ b/src/PluginBase/PluginContext.hpp @@ -34,7 +34,7 @@ class RA_PLUGINBASE_API Context : public QObject std::string m_exportDir { "." }; signals: - /*! + /** * \brief enable continuous rendering update * \see BaseApplication::setContinuousUpdate * From bd9793f2658e70c900dde11092c9650552f4a850 Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 21 May 2026 10:22:17 +0200 Subject: [PATCH 139/144] [core] Remove conversion ctor Since not used and error prone, if needed add back as explicit. Also remove redundent typename keyword. --- src/Core/Geometry/IndexedGeometry.cpp | 6 ------ src/Core/Geometry/IndexedGeometry.hpp | 2 -- src/Engine/Data/Mesh.hpp | 3 ++- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.cpp b/src/Core/Geometry/IndexedGeometry.cpp index 15518b6b6a5..cdcf118f105 100644 --- a/src/Core/Geometry/IndexedGeometry.cpp +++ b/src/Core/Geometry/IndexedGeometry.cpp @@ -18,12 +18,6 @@ MultiIndexedGeometry::MultiIndexedGeometry( const MultiIndexedGeometry& other ) MultiIndexedGeometry::MultiIndexedGeometry( MultiIndexedGeometry&& other ) : AttribArrayGeometry( std::move( other ) ), m_indices( std::move( other.m_indices ) ) {} -MultiIndexedGeometry::MultiIndexedGeometry( const AttribArrayGeometry& other ) : - AttribArrayGeometry( other ) {} - -MultiIndexedGeometry::MultiIndexedGeometry( AttribArrayGeometry&& other ) : - AttribArrayGeometry( std::move( other ) ) {} - MultiIndexedGeometry& MultiIndexedGeometry::operator=( const MultiIndexedGeometry& other ) { invalidateAabb(); AttribArrayGeometry::operator=( other ); diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 30851264c39..8129c6de0c6 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -292,8 +292,6 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util MultiIndexedGeometry() = default; MultiIndexedGeometry( const MultiIndexedGeometry& other ); MultiIndexedGeometry( MultiIndexedGeometry&& other ); - MultiIndexedGeometry( const AttribArrayGeometry& other ); - MultiIndexedGeometry( AttribArrayGeometry&& other ); MultiIndexedGeometry& operator=( const MultiIndexedGeometry& other ); MultiIndexedGeometry& operator=( MultiIndexedGeometry&& other ); diff --git a/src/Engine/Data/Mesh.hpp b/src/Engine/Data/Mesh.hpp index 209c04cfac8..91fb1a251b1 100644 --- a/src/Engine/Data/Mesh.hpp +++ b/src/Engine/Data/Mesh.hpp @@ -350,9 +350,10 @@ class RA_ENGINE_API GeometryDisplayable : public AttribArrayDisplayable using ArrayOfLayerKeys = std::array< std::pair, N>; + explicit GeometryDisplayable( const std::string& name ); explicit GeometryDisplayable( const std::string& name, - typename Core::Geometry::MultiIndexedGeometry&& geom ); + Core::Geometry::MultiIndexedGeometry&& geom ); virtual ~GeometryDisplayable(); void render( const ShaderProgram* prog ) override; void render( const ShaderProgram* prog, const LayerKeyType& key ); From 9d16fe6176538b9a78d2784f82c1f944cfa52f7f Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 21 May 2026 10:25:51 +0200 Subject: [PATCH 140/144] [core] Remove using redefinition in derived class. --- src/Core/Geometry/IndexedGeometry.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 8129c6de0c6..8a0c1ed7ac1 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -282,13 +282,6 @@ class RA_CORE_API MultiIndexedGeometry : public AttribArrayGeometry, public Util using LayerEntryType = std::pair>; using IndexCollection = std::unordered_map; - using PointAttribHandle = AttribArrayGeometry::PointAttribHandle; - using NormalAttribHandle = AttribArrayGeometry::NormalAttribHandle; - using FloatAttribHandle = AttribArrayGeometry::FloatAttribHandle; - using Vec2AttribHandle = AttribArrayGeometry::Vec2AttribHandle; - using Vec3AttribHandle = AttribArrayGeometry::Vec3AttribHandle; - using Vec4AttribHandle = AttribArrayGeometry::Vec4AttribHandle; - MultiIndexedGeometry() = default; MultiIndexedGeometry( const MultiIndexedGeometry& other ); MultiIndexedGeometry( MultiIndexedGeometry&& other ); From 73c54ff9acd12e1eb93ee1d42ac05e89fda23616 Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 21 May 2026 10:30:29 +0200 Subject: [PATCH 141/144] [core] Remove redundant inline in indexed geometry. --- src/Core/Geometry/IndexedGeometry.hpp | 69 ++++++++++++++------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/Core/Geometry/IndexedGeometry.hpp b/src/Core/Geometry/IndexedGeometry.hpp index 8a0c1ed7ac1..9c080519682 100644 --- a/src/Core/Geometry/IndexedGeometry.hpp +++ b/src/Core/Geometry/IndexedGeometry.hpp @@ -16,7 +16,7 @@ namespace Core { namespace Geometry { namespace Helper { template -VectorArray triangulate( const VectorArray& in ) { +inline VectorArray triangulate( const VectorArray& in ) { VectorArray out; out.reserve( in.size() ); @@ -52,7 +52,8 @@ inline VectorArray triangulate( const VectorArray& in ) { } return out; } -} +} // namespace Helper + /** * \brief Base class for index collections stored in MultiIndexedGeometry. */ @@ -63,13 +64,13 @@ class RA_CORE_API GeometryIndexLayerBase : public Utils::ObservableVoid, public: /// \brief Copy constructor /// \note Do not copy observers - inline explicit GeometryIndexLayerBase( const GeometryIndexLayerBase& other ); + explicit GeometryIndexLayerBase( const GeometryIndexLayerBase& other ); /// \brief Assignment operator /// \copydetails GeometryIndexLayerBase(const GeometryIndexLayerBase&) - inline GeometryIndexLayerBase& operator=( const GeometryIndexLayerBase& other ); + GeometryIndexLayerBase& operator=( const GeometryIndexLayerBase& other ); /// \brief Move assignment operator /// \copydetails GeometryIndexLayerBase(const GeometryIndexLayerBase&) - inline GeometryIndexLayerBase& operator=( GeometryIndexLayerBase&& other ); + GeometryIndexLayerBase& operator=( GeometryIndexLayerBase&& other ); virtual ~GeometryIndexLayerBase() {} /// \brief Create new layer with duplicated content @@ -81,13 +82,13 @@ class RA_CORE_API GeometryIndexLayerBase : public Utils::ObservableVoid, virtual void offset( int offset, uint start_index = 0 ) = 0; /// \brief Compare if two layers have the same content - virtual inline bool operator==( const GeometryIndexLayerBase& ) const { return false; } + virtual bool operator==( const GeometryIndexLayerBase& ) const { return false; } protected: /// \brief Hidden constructor that must be called by inheriting classes to define the object /// semantics. template - inline GeometryIndexLayerBase( SemanticNames... names ) : ObjectWithSemantic( names... ) {} + GeometryIndexLayerBase( SemanticNames... names ) : ObjectWithSemantic( names... ) {} }; /** @@ -98,53 +99,53 @@ struct GeometryIndexLayer : public GeometryIndexLayerBase { using IndexType = T; using IndexContainerType = VectorArray; - inline IndexContainerType& collection() { return m_collection; } + IndexContainerType& collection() { return m_collection; } const IndexContainerType& collection() const { return m_collection; } - inline bool append( const GeometryIndexLayerBase& other, int offset = 0 ) final; - inline void offset( int offset, uint start_index = 0 ) final; + bool append( const GeometryIndexLayerBase& other, int offset = 0 ) final; + void offset( int offset, uint start_index = 0 ) final; /// \warning Does not account for elements permutations - inline bool operator==( const GeometryIndexLayerBase& other ) const final; + bool operator==( const GeometryIndexLayerBase& other ) const final; - inline size_t getSize() const override final { return m_collection.size(); } + size_t getSize() const override final { return m_collection.size(); } - inline std::unique_ptr clone() override; + std::unique_ptr clone() override; - inline size_t getNumberOfComponents() const override final; + size_t getNumberOfComponents() const override final; - inline size_t getBufferSize() const override final; + size_t getBufferSize() const override final; /// \warning it's meaningful only if the attrib do not contain heap /// allocated data. - inline int getStride() const override final; + int getStride() const override final; - inline const void* dataPtr() const override final; + const void* dataPtr() const override final; protected: template - inline GeometryIndexLayer( SemanticNames... names ) : GeometryIndexLayerBase( names... ) {} + GeometryIndexLayer( SemanticNames... names ) : GeometryIndexLayerBase( names... ) {} private: IndexContainerType m_collection; }; -#define INDEX_LAYER_CLONE_IMPLEMENTATION( TYPE ) \ - inline std::unique_ptr clone() override { \ - auto copy = std::make_unique( *this ); \ - copy->collection() = collection(); \ - return copy; \ +#define INDEX_LAYER_CLONE_IMPLEMENTATION( TYPE ) \ + std::unique_ptr clone() override { \ + auto copy = std::make_unique( *this ); \ + copy->collection() = collection(); \ + return copy; \ } -#define OPEN_DECLARATION_INDEX_LAYER( NAME, TYPE ) \ - struct RA_CORE_API NAME : public GeometryIndexLayer { \ - inline NAME() : GeometryIndexLayer( NAME::staticSemanticName ) {} \ - static constexpr const char* staticSemanticName = #NAME; \ - INDEX_LAYER_CLONE_IMPLEMENTATION( NAME ) \ - protected: \ - template \ - inline explicit NAME( SemanticNames... names ) : \ - GeometryIndexLayer( NAME::staticSemanticName, names... ) {} \ - \ +#define OPEN_DECLARATION_INDEX_LAYER( NAME, TYPE ) \ + struct RA_CORE_API NAME : public GeometryIndexLayer { \ + NAME() : GeometryIndexLayer( NAME::staticSemanticName ) {} \ + static constexpr const char* staticSemanticName = #NAME; \ + INDEX_LAYER_CLONE_IMPLEMENTATION( NAME ) \ + protected: \ + template \ + explicit NAME( SemanticNames... names ) : \ + GeometryIndexLayer( NAME::staticSemanticName, names... ) {} \ + \ public: #define DECLARE_INDEX_LAYER( NAME, TYPE ) \ @@ -164,7 +165,7 @@ OPEN_DECLARATION_INDEX_LAYER( PointCloudIndexLayer, Vector1ui ) /// \brief Constructor of an index layer with linearly spaced indices ranging from \f$0\f$ to /// \f$n-1\f$ -inline explicit PointCloudIndexLayer( size_t n ) : +explicit PointCloudIndexLayer( size_t n ) : GeometryIndexLayer( PointCloudIndexLayer::staticSemanticName ) { collection().resize( n ); collection().getMap() = IndexContainerType::Matrix::LinSpaced( n, 0, n - 1 ); From a6b689d446acf39ff41d15760f0382486c70450d Mon Sep 17 00:00:00 2001 From: dlyr Date: Thu, 21 May 2026 11:19:52 +0200 Subject: [PATCH 142/144] [engine] Add missing SurfaceMeshComponent ctor. --- src/Engine/Scene/GeometryComponent.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engine/Scene/GeometryComponent.hpp b/src/Engine/Scene/GeometryComponent.hpp index 3d7038329ea..5462d60a409 100644 --- a/src/Engine/Scene/GeometryComponent.hpp +++ b/src/Engine/Scene/GeometryComponent.hpp @@ -58,7 +58,7 @@ class RA_ENGINE_API GeometryComponent : public Component * - normals: rw (if deformable) * - triangles: rw (if deformable) */ -class SurfaceMeshComponent : public GeometryComponent +class RA_ENGINE_API SurfaceMeshComponent : public GeometryComponent { using base = GeometryComponent; From f9180b96f8f1eeb6fe5025732a8f1f6a873e08ec Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 29 May 2026 10:38:26 +0200 Subject: [PATCH 143/144] [gui] Add missing include. --- src/Gui/RadiumWindow/SimpleWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Gui/RadiumWindow/SimpleWindow.cpp b/src/Gui/RadiumWindow/SimpleWindow.cpp index 0a8c3547181..b29ea6926d6 100644 --- a/src/Gui/RadiumWindow/SimpleWindow.cpp +++ b/src/Gui/RadiumWindow/SimpleWindow.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include namespace Ra { From 90ee00d1b22ad7a21bd803e8c0d76082b73dbb43 Mon Sep 17 00:00:00 2001 From: dlyr Date: Fri, 26 Jun 2026 09:20:38 +0200 Subject: [PATCH 144/144] [io] Recenter point cloud data (wip, need to add control on this). --- src/IO/TinyPlyLoader/TinyPlyFileLoader.cpp | 42 +++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/IO/TinyPlyLoader/TinyPlyFileLoader.cpp b/src/IO/TinyPlyLoader/TinyPlyFileLoader.cpp index 559af21b066..f0924e76a40 100644 --- a/src/IO/TinyPlyLoader/TinyPlyFileLoader.cpp +++ b/src/IO/TinyPlyLoader/TinyPlyFileLoader.cpp @@ -98,6 +98,44 @@ void copyArrayToContainer( const uint8_t* buffer, } } +template +void r( S* data, size_t count ) { + using V = Eigen::Matrix; + V min = { data[0], data[1], data[2] }; + V max = { data[0], data[1], data[2] }; + for ( size_t i = 0; i < count; ++i ) { + V v = { data[i * 3 + 0], data[i * 3 + 1], data[i * 3 + 2] }; + min = min.cwiseMin( v ); + max = max.cwiseMax( v ); + } + V mid = (S).5 * ( min + max ); + for ( size_t i = 0; i < count; ++i ) { + data[i * 3 + 0] -= mid[0]; + data[i * 3 + 1] -= mid[1]; + data[i * 3 + 2] -= mid[2]; + } +} + +void recenterVertices( std::shared_ptr& buffer ) { + + if ( buffer && buffer->count != 0 ) { + switch ( buffer->t ) { + case tinyply::Type::FLOAT32: { + auto data = reinterpret_cast( buffer->buffer.get() ); + auto count = buffer->count; + r( data, count ); + } break; + case tinyply::Type::FLOAT64: { + auto data = reinterpret_cast( buffer->buffer.get() ); + auto count = buffer->count; + r( data, count ); + } break; + default: + break; + } + } +} + template void copyBufferToContainer( const std::shared_ptr& buffer, ContainerType& container ) { @@ -204,7 +242,8 @@ FileData* TinyPlyFileLoader::loadFile( const std::string& filename ) { return nullptr; } /// request for standard vertex attributes - /// \todo merge with non standard attributes when all will be stored as Attribs in GeometryData + /// \todo merge with non standard attributes when all will be stored as Attribs in + /// GeometryData auto normalBuffer { initBuffer( "vertex", { "nx", "ny", "nz" } ) }; auto alphaBuffer { initBuffer( "vertex", { "alpha" } ) }; auto colorBuffer { initBuffer( "vertex", { "red", "green", "blue" } ) }; @@ -229,6 +268,7 @@ FileData* TinyPlyFileLoader::loadFile( const std::string& filename ) { file.read( *file_stream ); { auto unlocker = geomData->getGeometry().vertexAttribs().getScopedLockState(); + recenterVertices( vertBuffer ); copyBufferToContainer( vertBuffer, geomData->getGeometry().verticesWithLock() ); copyBufferToContainer( normalBuffer, geomData->getGeometry().normalsWithLock() ); }