#include "ml_selection_buffers.h" MLSelectionBuffers::MLSelectionBuffers(MeshModel& m,unsigned int primitivebatch) :_lock(),_m(m),_primitivebatch(primitivebatch),_selmap(2) { } MLSelectionBuffers::~MLSelectionBuffers() { QWriteLocker locker(&_lock); for (size_t ii = 0; ii < _selmap.size(); ++ii) { if (_selmap[ii].size() != 0) { glDeleteBuffers(_selmap[ii].size(), &(_selmap[ii][0])); _selmap[ii].clear(); } } _selmap.clear(); } void MLSelectionBuffers::updateBuffer(ML_SELECTION_TYPE selbuf) { QWriteLocker locker(&_lock); size_t privchunksize=0; if (selbuf == ML_PERVERT_SEL) { _m.cm.svn = 0; privchunksize = std::min(size_t(_m.cm.VN()), size_t(_primitivebatch)); if (_m.cm.VN() == 0) return; } if (selbuf == ML_PERFACE_SEL) { _m.cm.sfn = 0; privchunksize = std::min(size_t(_m.cm.FN()), size_t(_primitivebatch)); if (_m.cm.FN() == 0) return; } if (_selmap[selbuf].size() != 0) { glDeleteBuffers(_selmap[selbuf].size(), &(_selmap[selbuf][0])); _selmap[selbuf].clear(); } if (selbuf == ML_PERFACE_SEL) { size_t selectedperchunk = 0; std::vector rpv; rpv.resize(privchunksize * 3); for (CFaceO& ff: _m.cm.face) { size_t chunkindex = _m.cm.sfn % privchunksize; if (!ff.IsD() && ff.IsS()) { rpv[chunkindex * 3 + 0].Import(ff.V(0)->P()); rpv[chunkindex * 3 + 1].Import(ff.V(1)->P()); rpv[chunkindex * 3 + 2].Import(ff.V(2)->P()); ++_m.cm.sfn; ++selectedperchunk; } if (((&ff == &_m.cm.face.back()) && (selectedperchunk > 0)) || ((chunkindex == privchunksize - 1) && (selectedperchunk == privchunksize)) ) { _selmap[ML_PERFACE_SEL].push_back(0); glGenBuffers(1, &(_selmap[ML_PERFACE_SEL][_selmap[ML_PERFACE_SEL].size() - 1])); glBindBuffer(GL_ARRAY_BUFFER, _selmap[ML_PERFACE_SEL][_selmap[ML_PERFACE_SEL].size() - 1]); glBufferData(GL_ARRAY_BUFFER,3 * 3 * 4 * selectedperchunk, &rpv[0],GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); selectedperchunk = 0; } } rpv.clear(); } if (selbuf == ML_PERVERT_SEL) { size_t selectedperchunk = 0; std::vector rpv; rpv.resize(privchunksize); _m.cm.svn = 0; for (CVertexO& vv : _m.cm.vert) { size_t chunkindex = _m.cm.svn % privchunksize; if (!vv.IsD() && vv.IsS()) { rpv[chunkindex].Import(vv.cP()); ++_m.cm.svn; ++selectedperchunk; } if (((&vv == &_m.cm.vert.back()) && (selectedperchunk > 0)) || ((chunkindex == privchunksize - 1) && (selectedperchunk == privchunksize))) { _selmap[ML_PERVERT_SEL].push_back(0); glGenBuffers(1, &(_selmap[ML_PERVERT_SEL][_selmap[ML_PERVERT_SEL].size() - 1])); glBindBuffer(GL_ARRAY_BUFFER, _selmap[ML_PERVERT_SEL][_selmap[selbuf].size() - 1]); glBufferData(GL_ARRAY_BUFFER, sizeof(vcg::Point3f) * selectedperchunk, &(rpv[0]), GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); selectedperchunk = 0; } } rpv.clear(); } } void MLSelectionBuffers::drawSelection(ML_SELECTION_TYPE selbuf) const { QReadLocker locker(&_lock); if ((selbuf == ML_PERVERT_SEL) && (_m.cm.svn != 0)) { const size_t privchunksize = std::min(size_t(_m.cm.VN()), size_t(_primitivebatch)); glPushAttrib(GL_ALL_ATTRIB_BITS); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(1.0f, 0.0, 0.0, .3f); glDepthRange(0.00, 0.999); glPointSize(3.0); glPushMatrix(); glMultMatrix(_m.cm.Tr); if (_pointsize > 0.0f) glPointSize((GLfloat)_pointsize); for (size_t ii = 0; ii < _selmap[ML_PERVERT_SEL].size(); ++ii) { glBindBuffer(GL_ARRAY_BUFFER, _selmap[ML_PERVERT_SEL][ii]); glVertexPointer(3, GL_FLOAT, GLsizei(0), 0); glEnableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); unsigned int todraw = privchunksize; if (ii == (_selmap[ML_PERVERT_SEL].size() - 1)) todraw = _m.cm.svn - (privchunksize * ii); //glGetBufferSubData(GL_ARRAY_BUFFER, 0, rp.size() * sizeof(vcg::Point3f), &(rp[0])); glDrawArrays(GL_POINTS, 0, todraw); glBindBuffer(GL_ARRAY_BUFFER, _selmap[ML_PERVERT_SEL][ii]); glDisableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); } glPopMatrix(); glPopAttrib(); } if ((selbuf == ML_PERFACE_SEL) && (_m.cm.sfn != 0)) { const size_t privchunksize = std::min(size_t(_m.cm.FN()), size_t(_primitivebatch)); glPushAttrib(GL_ALL_ATTRIB_BITS); glEnable(GL_POLYGON_OFFSET_FILL); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glDepthMask(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(1.0f, 0.0, 0.0, .3f); glPolygonOffset(-1.0, -1); glPushMatrix(); glMultMatrix(_m.cm.Tr); for (size_t ii = 0; ii < _selmap[ML_PERFACE_SEL].size(); ++ii) { glBindBuffer(GL_ARRAY_BUFFER, _selmap[ML_PERFACE_SEL][ii]); glVertexPointer(3, GL_FLOAT, GLsizei(0), 0); glEnableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); unsigned int todraw = privchunksize; if (ii == _selmap[ML_PERFACE_SEL].size() - 1) todraw = _m.cm.sfn - (privchunksize * ii); glDrawArrays(GL_TRIANGLES, 0, 3 * todraw); glBindBuffer(GL_ARRAY_BUFFER, _selmap[ML_PERFACE_SEL][ii]); glDisableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); } glPopMatrix(); glPopAttrib(); } } void MLSelectionBuffers::deallocateBuffer(ML_SELECTION_TYPE selbuf) { if (_selmap[selbuf].size() != 0) { glDeleteBuffers(_selmap[selbuf].size(), &(_selmap[selbuf][0])); _selmap[selbuf].clear(); } } void MLSelectionBuffers::setPointSize(float ptsz) { _pointsize = ptsz; }