Radium Engine  1.5.20
Loading...
Searching...
No Matches
Mesh.cpp
1#include <Engine/Data/Mesh.hpp>
2
3#include <numeric>
4
5#include <Core/Utils/Attribs.hpp>
6#include <Core/Utils/Log.hpp>
7#include <Engine/Data/ShaderProgram.hpp>
8#include <Engine/OpenGL.hpp>
9
10#include <globjects/Buffer.h>
11#include <globjects/VertexArray.h>
12
13namespace Ra {
14namespace Engine {
15namespace Data {
16using namespace Ra::Core::Utils;
17
18// Dirty is initializes as false so that we do not create the vao while
19// we have no data to send to the gpu.
20AttribArrayDisplayable::AttribArrayDisplayable( const std::string& name,
21 MeshRenderMode renderMode ) :
22 Displayable( name ), m_renderMode { renderMode } {
23 CORE_ASSERT( m_renderMode == RM_POINTS || m_renderMode == RM_LINES ||
24 m_renderMode == RM_LINE_LOOP || m_renderMode == RM_LINE_STRIP ||
25 m_renderMode == RM_TRIANGLES || m_renderMode == RM_TRIANGLE_STRIP ||
26 m_renderMode == RM_TRIANGLE_FAN || m_renderMode == RM_LINES_ADJACENCY ||
27 m_renderMode == RM_LINE_STRIP_ADJACENCY,
28 "Unsupported render mode" );
29
30 updatePickingRenderMode();
31}
32
33size_t Mesh::getNumFaces() const {
35 switch ( getRenderMode() ) {
36 case MeshRenderMode::RM_TRIANGLE_STRIP:
37 [[fallthrough]];
38 case MeshRenderMode::RM_TRIANGLE_FAN:
39 return ( getCoreGeometry().getIndices().size() - 1 ) * 3 + 1;
40 case MeshRenderMode::RM_TRIANGLES:
41 return getCoreGeometry().getIndices().size();
42 default:
43 return size_t( 0 );
44 }
45}
46
47void Mesh::loadGeometry( const Core::Vector3Array& vertices, const std::vector<uint>& indices ) {
48 // Do not remove this function to force everyone to use TriangleMesh.
49 // ... because we have some line meshes as well...
51 Core::Geometry::TriangleMesh mesh;
52
53 auto nIdx = indices.size();
54
55 if ( indices.empty() ) {
56 m_numElements = vertices.size();
57 setRenderMode( RM_POINTS );
58 }
59 else
60 m_numElements = nIdx;
61 mesh.setVertices( vertices );
62
63 // Check that when loading a TriangleMesh we actually have triangles or lines.
64 CORE_ASSERT( m_renderMode != GL_TRIANGLES || nIdx % 3 == 0,
65 "There should be 3 indices per triangle " );
66 CORE_ASSERT( m_renderMode != GL_LINES || nIdx % 2 == 0, "There should be 2 indices per line" );
67 CORE_ASSERT( m_renderMode != GL_LINES_ADJACENCY || nIdx % 4 == 0,
68 "There should be 4 indices per line adjacency" );
70 for ( uint i = 0; i < indices.size(); i = i + 3 ) {
71 // We store all indices in order. This means that for lines we have
72 // (L00, L01, L10), (L11, L20, L21) etc. We fill the missing by wrapping around indices.
73 mindices.push_back( { indices[i], indices[( i + 1 ) % nIdx], indices[( i + 2 ) % nIdx] } );
74 }
75
76 mesh.setIndices( std::move( mindices ) );
77 m_dataDirty.clear();
78 m_vbos.clear();
79
81 loadGeometry( std::move( mesh ) );
82}
83
84void AttribArrayDisplayable::updatePickingRenderMode() {
85 switch ( getRenderMode() ) {
86 case AttribArrayDisplayable::RM_POINTS: {
87 Displayable::m_pickingRenderMode = PKM_POINTS;
88 break;
89 }
90 case AttribArrayDisplayable::RM_LINES: // fall through
91 [[fallthrough]];
92 case AttribArrayDisplayable::RM_LINE_LOOP: // fall through
93 [[fallthrough]];
94 case AttribArrayDisplayable::RM_LINE_STRIP: {
95 Displayable::m_pickingRenderMode = PKM_LINES;
96 break;
97 }
98 case AttribArrayDisplayable::RM_LINES_ADJACENCY: // fall through
99 [[fallthrough]];
100 case AttribArrayDisplayable::RM_LINE_STRIP_ADJACENCY: {
101 Displayable::m_pickingRenderMode = PKM_LINE_ADJ;
102 break;
103 }
104 case AttribArrayDisplayable::RM_TRIANGLES:
105 [[fallthrough]];
106 case AttribArrayDisplayable::RM_TRIANGLE_STRIP:
107 [[fallthrough]];
108 case AttribArrayDisplayable::RM_TRIANGLE_FAN: {
109 Displayable::m_pickingRenderMode = PKM_TRI;
110 break;
111 }
112 default: {
113 Displayable::m_pickingRenderMode = NO_PICKING;
114 break;
115 }
116 }
117}
118
119void AttribArrayDisplayable::setDirty( const std::string& name ) {
120 auto itr = m_handleToBuffer.find( name );
121 if ( itr == m_handleToBuffer.end() ) {
122 m_handleToBuffer[name] = m_dataDirty.size();
123 m_dataDirty.push_back( true );
124 m_vbos.emplace_back( nullptr );
125 }
126 else
127 m_dataDirty[itr->second] = true;
128
129 m_isDirty = true;
130}
131
132void AttribArrayDisplayable::setDirty( unsigned int index ) {
133 if ( index < m_dataDirty.size() ) {
134 m_dataDirty[index] = true;
135 m_isDirty = true;
136 }
137}
138
139void AttribArrayDisplayable::setDirty( const Ra::Core::Geometry::MeshAttrib& type ) {
140 auto name = Core::Geometry::getAttribName( type );
141 auto itr = m_handleToBuffer.find( name );
142 if ( itr == m_handleToBuffer.end() ) {
143 m_handleToBuffer[name] = m_dataDirty.size();
144 m_dataDirty.push_back( true );
145 m_vbos.emplace_back( nullptr );
146 }
147 else
148 m_dataDirty[itr->second] = true;
149
150 m_isDirty = true;
151}
152
153Ra::Core::Utils::optional<gl::GLuint> AttribArrayDisplayable::getVaoHandle() {
154 if ( m_vao ) return m_vao->id();
155 return {};
156}
157Ra::Core::Utils::optional<gl::GLuint>
158AttribArrayDisplayable::getVboHandle( const std::string& name ) {
159 auto idx = m_handleToBuffer.find( name );
160 if ( idx != m_handleToBuffer.end() && m_vbos[idx->second] ) return m_vbos[idx->second]->id();
161 return {};
162}
163
164void PointCloud::render( const ShaderProgram* prog ) {
165 if ( m_vao ) {
166 autoVertexAttribPointer( prog );
167 m_vao->bind();
168 m_vao->drawArrays(
169 static_cast<GLenum>( m_renderMode ), 0, GLsizei( m_mesh.vertices().size() ) );
170 m_vao->unbind();
171 }
172}
173
174void PointCloud::loadGeometry( Core::Geometry::PointCloud&& mesh ) {
175 loadGeometry_common( std::move( mesh ) );
176}
177
178void PointCloud::updateGL_specific_impl() {
179 if ( !m_vao ) { m_vao = globjects::VertexArray::create(); }
180}
181
182} // namespace Data
183} // namespace Engine
184} // namespace Ra
void setVertices(PointAttribHandle::Container &&vertices)
Set vertices.
void setIndices(IndexContainerType &&indices)
T empty(T... args)
T move(T... args)
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:3
T push_back(T... args)
T size(T... args)