Some memory footprint improvement by separating flat surfaces which do not have normals.

This commit is contained in:
Matthias Koefferlein 2024-05-18 22:04:45 +02:00
parent 48b32733c2
commit cfdb3486ef
3 changed files with 139 additions and 49 deletions

View File

@ -171,11 +171,11 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
"\n"
"* 1/0 2/0 3/0-255:17/0\n"
" Selects 1/0, 2/0 and maps layer 3, datatype 0 to 255 to layer 17, datatype 0.\n"
" If clarity, the mapping can also be written with brackets like this: '(1/0) (2/0) (3/0-255:17/0)'.\n"
" For clarity, the mapping can also be written with brackets like this: '(1/0) (2/0) (3/0-255:17/0)'.\n"
"\n"
"* A:1/0 B:2/0\n"
" Maps named layer A to 1/0 and named layer B to 2/0.\n"
" If clarity, the mapping can also be written with brackets like this: '(A:1/0) (B:2/0)'.\n"
" For clarity, the mapping can also be written with brackets like this: '(A:1/0) (B:2/0)'.\n"
"\n"
"* [*/*] +(10/*:1000)/*\n"
" Includes all layers, but in addition copies all datatypes of layer 10 to 1000 while keeping the datatype.\n"

View File

@ -196,7 +196,7 @@ private:
D25ViewWidget::D25ViewWidget (QWidget *parent)
: QOpenGLWidget (parent),
m_shapes_program (0), m_lines_program (0), m_gridplane_program (0)
m_shapes_program (0), m_shapes_program_uniform_normals (0), m_lines_program (0), m_gridplane_program (0)
{
QSurfaceFormat format;
format.setDepthBufferSize (24);
@ -220,6 +220,7 @@ D25ViewWidget::~D25ViewWidget ()
makeCurrent ();
delete m_shapes_program;
delete m_shapes_program_uniform_normals;
delete m_lines_program;
delete m_gridplane_program;
@ -569,6 +570,7 @@ static void lp_to_info (const lay::LayerPropertiesNode &lp, D25ViewWidget::Layer
void
D25ViewWidget::open_display (const tl::color_t *frame_color, const tl::color_t *fill_color, const db::LayerProperties *like, const std::string *name)
{
m_flat_vertex_chunks.push_back (triangle_chunks_type ());
m_vertex_chunks.push_back (triangle_chunks_type ());
m_normals_chunks.push_back (triangle_chunks_type ());
m_line_chunks.push_back (line_chunks_type ());
@ -671,7 +673,7 @@ D25ViewWidget::entry (const db::Region &data, double dbu, double zstart, double
enter (iter, zstart, zstop);
tl::AbsoluteProgress progress (tl::to_string (tr ("Rendering ...")));
render_region (progress, *m_layers.back ().vertex_chunk, *m_layers.back ().normals_chunk, *m_layers.back ().line_chunk, data, dbu, db::CplxTrans (dbu).inverted () * m_bbox, zstart, zstop);
render_region (progress, *m_layers.back ().get_flat_vertex_chunks (zstart, zstop, m_flat_vertex_chunks), *m_layers.back ().vertex_chunk, *m_layers.back ().normals_chunk, *m_layers.back ().line_chunk, data, dbu, db::CplxTrans (dbu).inverted () * m_bbox, zstart, zstop);
}
void
@ -719,7 +721,7 @@ D25ViewWidget::attach_view (LayoutViewBase *view)
}
void
D25ViewWidget::render_polygon (D25ViewWidget::triangle_chunks_type &chunks, D25ViewWidget::triangle_chunks_type &normals, D25ViewWidget::line_chunks_type &line_chunks, const db::Polygon &poly, double dbu, double zstart, double zstop)
D25ViewWidget::render_polygon (D25ViewWidget::triangle_chunks_type &flat_chunks, const db::Polygon &poly, double dbu)
{
if (poly.holes () > 0) {
@ -735,7 +737,7 @@ D25ViewWidget::render_polygon (D25ViewWidget::triangle_chunks_type &chunks, D25V
ep.process (out, op);
for (std::vector<db::Polygon>::const_iterator p = poly_heap.begin (); p != poly_heap.end (); ++p) {
render_polygon (chunks, normals, line_chunks, *p, dbu, zstart, zstop);
render_polygon (flat_chunks, *p, dbu);
}
} else if (poly.hull ().size () > 4) {
@ -744,7 +746,7 @@ D25ViewWidget::render_polygon (D25ViewWidget::triangle_chunks_type &chunks, D25V
db::split_polygon (poly, poly_heap);
for (std::vector<db::Polygon>::const_iterator p = poly_heap.begin (); p != poly_heap.end (); ++p) {
render_polygon (chunks, normals, line_chunks, *p, dbu, zstart, zstop);
render_polygon (flat_chunks, *p, dbu);
}
} else if (poly.hull ().size () >= 3) {
@ -753,46 +755,16 @@ D25ViewWidget::render_polygon (D25ViewWidget::triangle_chunks_type &chunks, D25V
std::copy (poly.hull ().begin (), poly.hull ().end (), &pts [0]);
// triangle bottom
chunks.add (pts[0].x () * dbu, zstart, pts[0].y () * dbu);
chunks.add (pts[2].x () * dbu, zstart, pts[2].y () * dbu);
chunks.add (pts[1].x () * dbu, zstart, pts[1].y () * dbu);
// normals
for (unsigned int i = 0; i < 3; ++i) {
normals.add (0.0, 1.0, 0.0);
}
// triangle top
chunks.add (pts[0].x () * dbu, zstop, pts[0].y () * dbu);
chunks.add (pts[1].x () * dbu, zstop, pts[1].y () * dbu);
chunks.add (pts[2].x () * dbu, zstop, pts[2].y () * dbu);
// normals
for (unsigned int i = 0; i < 3; ++i) {
normals.add (0.0, -1.0, 0.0);
}
flat_chunks.add (pts[0].x () * dbu, 0.0, pts[0].y () * dbu);
flat_chunks.add (pts[2].x () * dbu, 0.0, pts[2].y () * dbu);
flat_chunks.add (pts[1].x () * dbu, 0.0, pts[1].y () * dbu);
if (poly.hull ().size () == 4) {
// triangle bottom
chunks.add (pts[0].x () * dbu, zstart, pts[0].y () * dbu);
chunks.add (pts[3].x () * dbu, zstart, pts[3].y () * dbu);
chunks.add (pts[2].x () * dbu, zstart, pts[2].y () * dbu);
// normals
for (unsigned int i = 0; i < 3; ++i) {
normals.add (0.0, 1.0, 0.0);
}
// triangle top
chunks.add (pts[0].x () * dbu, zstop, pts[0].y () * dbu);
chunks.add (pts[2].x () * dbu, zstop, pts[2].y () * dbu);
chunks.add (pts[3].x () * dbu, zstop, pts[3].y () * dbu);
// normals
for (unsigned int i = 0; i < 3; ++i) {
normals.add (0.0, -1.0, 0.0);
}
flat_chunks.add (pts[0].x () * dbu, 0.0, pts[0].y () * dbu);
flat_chunks.add (pts[3].x () * dbu, 0.0, pts[3].y () * dbu);
flat_chunks.add (pts[2].x () * dbu, 0.0, pts[2].y () * dbu);
}
@ -830,7 +802,7 @@ D25ViewWidget::render_wall (D25ViewWidget::triangle_chunks_type &chunks, D25View
}
void
D25ViewWidget::render_region (tl::AbsoluteProgress &progress, D25ViewWidget::triangle_chunks_type &chunks, D25ViewWidget::triangle_chunks_type &normals, D25ViewWidget::line_chunks_type &line_chunks, const db::Region &region, double dbu, const db::Box &clip_box, double zstart, double zstop)
D25ViewWidget::render_region (tl::AbsoluteProgress &progress, triangle_chunks_type &flat_chunks, D25ViewWidget::triangle_chunks_type &chunks, D25ViewWidget::triangle_chunks_type &normals, D25ViewWidget::line_chunks_type &line_chunks, const db::Region &region, double dbu, const db::Box &clip_box, double zstart, double zstop)
{
std::vector<db::Polygon> poly_heap;
@ -843,7 +815,7 @@ D25ViewWidget::render_region (tl::AbsoluteProgress &progress, D25ViewWidget::tri
++progress;
render_polygon (chunks, normals, line_chunks, *p, dbu, zstart, zstop);
render_polygon (flat_chunks, *p, dbu);
for (db::Polygon::polygon_edge_iterator e = p->begin_edge (); ! e.at_end (); ++e) {
render_wall (chunks, normals, line_chunks, *e, dbu, zstart, zstop);
@ -915,6 +887,7 @@ void
D25ViewWidget::initializeGL ()
{
tl_assert (m_shapes_program == 0);
tl_assert (m_shapes_program_uniform_normals == 0);
tl_assert (m_gridplane_program == 0);
tl_assert (m_lines_program == 0);
@ -937,6 +910,8 @@ D25ViewWidget::initializeGL ()
delete m_shapes_program;
m_shapes_program = 0;
delete m_shapes_program_uniform_normals;
m_shapes_program_uniform_normals = 0;
delete m_lines_program;
m_lines_program = 0;
delete m_gridplane_program;
@ -969,6 +944,21 @@ D25ViewWidget::do_initialize_gl ()
" dp = dot(normalsAttr.xyz, illum);\n"
"}\n";
static const char *shapes_vertex_shader_uniform_normals_source =
"#version 120\n"
"\n"
"attribute vec4 posAttr;\n"
"uniform vec4 normal;\n"
"uniform mat4 matrix;\n"
"uniform vec3 illum;\n"
// NOTE: dp is not really varying currently, but we can use the same fragment shader this way
"varying float dp;\n"
"\n"
"void main() {\n"
" gl_Position = matrix * posAttr;\n"
" dp = dot(normal.xyz, illum);\n"
"}\n";
static const char *shapes_fragment_shader_source =
"#version 120\n"
"\n"
@ -1009,6 +999,17 @@ D25ViewWidget::do_initialize_gl ()
throw tl::Exception (std::string ("Shapes shader program linking failed failed:\n") + tl::to_string (m_shapes_program->log ()));
}
m_shapes_program_uniform_normals = new QOpenGLShaderProgram (this);
if (! m_shapes_program_uniform_normals->addShaderFromSourceCode (QOpenGLShader::Vertex, shapes_vertex_shader_uniform_normals_source)) {
throw tl::Exception (std::string ("Shapes vertex shader compilation failed (uniform normals):\n") + tl::to_string (m_shapes_program_uniform_normals->log ()));
}
if (! m_shapes_program_uniform_normals->addShaderFromSourceCode (QOpenGLShader::Fragment, shapes_fragment_shader_source)) {
throw tl::Exception (std::string ("Shapes fragment shader compilation failed (uniform normals):\n") + tl::to_string (m_shapes_program_uniform_normals->log ()));
}
if (! m_shapes_program_uniform_normals->link ()) {
throw tl::Exception (std::string ("Shapes shader program linking failed failed (uniform normals):\n") + tl::to_string (m_shapes_program_uniform_normals->log ()));
}
static const char *lines_vertex_shader_source =
"#version 120\n"
"\n"
@ -1105,7 +1106,7 @@ D25ViewWidget::paintGL ()
glClearColor (float (c.red ()) / 255.0f, float (c.green ()) / 255.0f, float (c.blue ()) / 255.0f, 1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (! m_shapes_program || ! m_lines_program || ! m_gridplane_program) {
if (! m_shapes_program || ! m_shapes_program_uniform_normals || ! m_lines_program || ! m_gridplane_program) {
return;
}
@ -1167,6 +1168,69 @@ D25ViewWidget::paintGL ()
m_shapes_program->release ();
m_shapes_program_uniform_normals->bind ();
// NOTE: z axis of illum points towards the scene because we include the z inversion in the scene transformation matrix
m_shapes_program_uniform_normals->setUniformValue ("illum", QVector3D (-3.0, -4.0, 2.0).normalized ());
m_shapes_program_uniform_normals->setUniformValue ("ambient", QVector4D (ambient, ambient, ambient, 1.0));
m_shapes_program_uniform_normals->setUniformValue ("mist_factor", mist_factor);
m_shapes_program_uniform_normals->setUniformValue ("mist_add", mist_add);
glEnable (GL_DEPTH_TEST);
glEnableVertexAttribArray (positions);
for (std::vector<LayerInfo>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
if (l->visible && l->fill_color [3] > 0.5) {
const LayerInfo &li = *l;
for (auto z = li.flat_vertex_chunks.begin (); z != li.flat_vertex_chunks.end (); ++z) {
QMatrix4x4 ytop;
ytop.translate (QVector3D (0.0, z->first.second, 0.0));
m_shapes_program_uniform_normals->setUniformValue ("matrix", cam_perspective () * cam_trans () * scene_trans * ytop);
m_shapes_program_uniform_normals->setUniformValue ("normal", QVector4D (0.0, -1.0, 0.0, 1.0));
m_shapes_program_uniform_normals->setUniformValue ("color", l->fill_color [0], l->fill_color [1], l->fill_color [2], l->fill_color [3]);
triangle_chunks_type::iterator v = z->second->begin ();
while (v != z->second->end ()) {
glVertexAttribPointer (positions, 3, gl_type2enum<GLfloat> () (), GL_FALSE, 0, v->front ());
// TODO: use glDrawElements to draw indexed buffers for better memory usage
glDrawArrays (GL_TRIANGLES, 0, GLsizei (v->size () / 3));
++v;
}
QMatrix4x4 ybottom;
ybottom.translate (QVector3D (0.0, z->first.first, 0.0));
m_shapes_program_uniform_normals->setUniformValue ("matrix", cam_perspective () * cam_trans () * scene_trans * ybottom);
m_shapes_program_uniform_normals->setUniformValue ("normal", QVector4D (0.0, 1.0, 0.0, 1.0));
m_shapes_program_uniform_normals->setUniformValue ("color", l->fill_color [0], l->fill_color [1], l->fill_color [2], l->fill_color [3]);
v = z->second->begin ();
while (v != z->second->end ()) {
glVertexAttribPointer (positions, 3, gl_type2enum<GLfloat> () (), GL_FALSE, 0, v->front ());
// TODO: use glDrawElements to draw indexed buffers for better memory usage
glDrawArrays (GL_TRIANGLES, 0, GLsizei (v->size () / 3));
++v;
}
}
}
}
glDisableVertexAttribArray (positions);
glDisableVertexAttribArray (normals);
m_shapes_program_uniform_normals->release ();
// wire lines

View File

@ -87,7 +87,21 @@ public:
struct LayerInfo
{
struct ZRangeCompare
{
bool operator() (const std::pair<double, double> &a, const std::pair<double, double> &b) const
{
typedef db::coord_traits<double> coord_traits;
if (coord_traits::equal (a.first, b.first)) {
return coord_traits::less (a.second, b.second);
} else {
return coord_traits::less (a.first, b.first);
}
}
};
triangle_chunks_type *vertex_chunk;
std::map<std::pair<double, double>, triangle_chunks_type *, ZRangeCompare> flat_vertex_chunks;
triangle_chunks_type *normals_chunk;
line_chunks_type *line_chunk;
GLfloat fill_color [4];
@ -95,6 +109,17 @@ public:
bool visible;
std::string name;
bool has_name;
triangle_chunks_type *get_flat_vertex_chunks (double zstart, double zstop, std::list<triangle_chunks_type> &flat_vertex_chunk_list)
{
auto i = flat_vertex_chunks.find (std::make_pair (zstart, zstop));
if (i != flat_vertex_chunks.end ()) {
return i->second;
}
flat_vertex_chunk_list.push_back (triangle_chunks_type ());
return flat_vertex_chunks.insert (std::make_pair (std::make_pair (zstart, zstop), &flat_vertex_chunk_list.back ())).first->second;
}
};
D25ViewWidget (QWidget *parent);
@ -182,7 +207,7 @@ public slots:
private:
std::unique_ptr<D25InteractionMode> mp_mode;
QOpenGLShaderProgram *m_shapes_program, *m_lines_program, *m_gridplane_program;
QOpenGLShaderProgram *m_shapes_program, *m_shapes_program_uniform_normals, *m_lines_program, *m_gridplane_program;
std::string m_error;
bool m_has_error;
double m_scale_factor;
@ -195,6 +220,7 @@ private:
bool m_display_open;
std::list<triangle_chunks_type> m_vertex_chunks;
std::list<triangle_chunks_type> m_flat_vertex_chunks;
std::list<triangle_chunks_type> m_normals_chunks;
std::list<line_chunks_type> m_line_chunks;
@ -205,10 +231,10 @@ private:
void resizeGL (int w, int h);
void do_initialize_gl ();
void render_region (tl::AbsoluteProgress &progress, D25ViewWidget::triangle_chunks_type &vertex_chunks, triangle_chunks_type &normals, D25ViewWidget::line_chunks_type &line_chunks, const db::Region &region, double dbu, const db::Box &clip_box, double zstart, double zstop);
void render_region (tl::AbsoluteProgress &progress, triangle_chunks_type &flat_chunks, D25ViewWidget::triangle_chunks_type &vertex_chunks, triangle_chunks_type &normals, D25ViewWidget::line_chunks_type &line_chunks, const db::Region &region, double dbu, const db::Box &clip_box, double zstart, double zstop);
void render_edges (tl::AbsoluteProgress &progress, D25ViewWidget::triangle_chunks_type &vertex_chunks, triangle_chunks_type &normals, D25ViewWidget::line_chunks_type &line_chunks, const db::Edges &region, double dbu, const db::Box &clip_box, double zstart, double zstop);
void render_edge_pairs (tl::AbsoluteProgress &progress, D25ViewWidget::triangle_chunks_type &vertex_chunks, triangle_chunks_type &normals, D25ViewWidget::line_chunks_type &line_chunks, const db::EdgePairs &region, double dbu, const db::Box &clip_box, double zstart, double zstop);
void render_polygon (D25ViewWidget::triangle_chunks_type &vertex_chunks, triangle_chunks_type &normals, D25ViewWidget::line_chunks_type &line_chunks, const db::Polygon &poly, double dbu, double zstart, double zstop);
void render_polygon (D25ViewWidget::triangle_chunks_type &vertex_chunks, const db::Polygon &poly, double dbu);
void render_wall (D25ViewWidget::triangle_chunks_type &vertex_chunks, triangle_chunks_type &normals, D25ViewWidget::line_chunks_type &line_chunks, const db::Edge &poly, double dbu, double zstart, double zstop);
void reset_viewport ();
void enter (const db::RecursiveShapeIterator *iter, double zstart, double zstop);