ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
PCVContext.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "PCVContext.h"
9 
10 // CV_CORE_LIB
11 #include <CVMiscTools.h>
12 #include <GenericTriangle.h>
13 
14 // Qt
15 #include <QGLPixelBuffer>
16 
17 // OpenGL
18 #ifdef __APPLE__
19 #include <OpenGL/glu.h>
20 #else
21 #include <GL/glu.h>
22 #endif
23 
24 // system
25 #include <assert.h>
26 
27 // type-less glVertex3Xv call (X=f,d)
28 static inline void glVertex3v(const float* v) { glVertex3fv(v); }
29 static inline void glVertex3v(const double* v) { glVertex3dv(v); }
30 
31 // type-less glTranslateX call (X=f,d)
32 static inline void glTranslate(float x, float y, float z) {
33  glTranslatef(x, y, z);
34 }
35 static inline void glTranslate(double x, double y, double z) {
36  glTranslated(x, y, z);
37 }
38 
39 // type-less glScaleX call (X=f,d)
40 static inline void glScale(float x, float y, float z) { glScalef(x, y, z); }
41 static inline void glScale(double x, double y, double z) { glScaled(x, y, z); }
42 
43 using namespace CVLib;
44 
45 #ifndef ZTWIST
46 #define ZTWIST 1e-3f
47 #endif
48 
50  : m_vertices(0),
51  m_mesh(0),
52  m_zoom(1),
53  m_pixBuffer(nullptr),
54  m_width(0),
55  m_height(0),
56  m_snapZ(nullptr),
57  m_snapC(nullptr),
58  m_meshIsClosed(false) {
59  memset(m_viewMat, 0, sizeof(float) * OPENGL_MATRIX_SIZE);
60 }
61 
63  if (m_pixBuffer) delete m_pixBuffer;
64 
65  if (m_snapZ) delete[] m_snapZ;
66  if (m_snapC) delete[] m_snapC;
67 }
68 
69 bool PCVContext::init(unsigned W,
70  unsigned H,
71  CVLib::GenericCloud* cloud,
72  CVLib::GenericMesh* mesh /*=0*/,
73  bool closedMesh /*=true*/) {
74  if (!QGLPixelBuffer::hasOpenGLPbuffers()) return false;
75 
76  assert(!m_pixBuffer);
77 
78  m_pixBuffer = new QGLPixelBuffer(W, H);
79  if (!m_pixBuffer || !m_pixBuffer->isValid()) return false;
80 
81  unsigned size = W * H;
82  m_snapZ = new float[size];
83  if (!m_snapZ) {
84  delete m_pixBuffer;
85  m_pixBuffer = 0;
86  return false;
87  }
88 
89  m_meshIsClosed = (closedMesh || !mesh);
90  if (!m_meshIsClosed) {
91  // buffer for color
92  m_snapC = new unsigned char[4 * size];
93  if (!m_snapC) {
94  delete m_pixBuffer;
95  m_pixBuffer = 0;
96  delete[] m_snapZ;
97  m_snapZ = 0;
98  return false;
99  }
100  }
101 
102  m_width = W;
103  m_height = H;
104 
105  associateToEntity(cloud, mesh);
106 
107  glInit();
108 
109  return true;
110 }
111 
112 void PCVContext::associateToEntity(GenericCloud* cloud, GenericMesh* mesh) {
113  assert(cloud);
114  if (!cloud) return;
115 
116  m_vertices = cloud;
117  m_mesh = mesh;
118 
119  // we get cloud bounding box
120  CCVector3 bbMin, bbMax;
121  m_vertices->getBoundingBox(bbMin, bbMax);
122 
123  // we compute bbox diagonal
124  PointCoordinateType maxD = (bbMax - bbMin).norm();
125 
126  // we deduce default zoom
127  m_zoom = (maxD > ZERO_TOLERANCE ? static_cast<PointCoordinateType>(
129  maxD
130  : PC_ONE);
131 
132  // as well as display center
133  m_viewCenter = (bbMax + bbMin) / 2;
134 }
135 
137  if (!m_pixBuffer || !m_pixBuffer->isValid()) return;
138 
139  // m_pixBuffer->makeCurrent();
140 
141  // glClearColor(0.0, 0.0, 0.0, 0.0);
142  // glEnable(GL_DEPTH_TEST);
143  // glEnable(GL_CULL_FACE);
144  // glDepthMask(GL_TRUE);
145  // glDisable(GL_LIGHTING);
146 
147  // glPixelStorei(GL_PACK_ROW_LENGTH, 0);
148  // glPixelStorei(GL_PACK_ALIGNMENT, 1);
149 
151  // glMatrixMode(GL_MODELVIEW);
152  // glLoadIdentity();
153  // glGetFloatv(GL_MODELVIEW_MATRIX, m_viewMat);
154  // glPushMatrix();
155 
157  // glMatrixMode(GL_PROJECTION);
158  // glLoadIdentity();
159  // float w2 = 0.5f * m_width;
160  // float h2 = 0.5f * m_height;
161  // float maxD = static_cast<float>(std::max(m_width, m_height));
162  // glOrtho(-w2, w2, -h2, h2, -maxD, maxD);
163  // glPushMatrix();
164 }
165 
167  if (!m_pixBuffer || !m_pixBuffer->isValid()) return;
168 
169  /*m_pixBuffer->makeCurrent();
170 
171  glMatrixMode(GL_MODELVIEW);
172  glPushMatrix();
173  glLoadIdentity();
174 
175  CCVector3 U(0, 0, 1);
176  if (1 - fabs(V.dot(U)) < 1.0e-4)
177  {
178  U.y = 1;
179  U.z = 0;
180  }
181 
182  gluLookAt(-V.x, -V.y, -V.z, 0.0, 0.0, 0.0, U.x, U.y, U.z);
183  glGetFloatv(GL_MODELVIEW_MATRIX, m_viewMat);
184  glPopMatrix();*/
185 }
186 
188  // assert(m_vertices);
189 
190  // glMatrixMode(GL_MODELVIEW);
191  // glLoadMatrixf(m_viewMat);
192  // glScale(m_zoom, m_zoom, m_zoom);
193  // glTranslate(-m_viewCenter.x, -m_viewCenter.y, -m_viewCenter.z);
194 
195  // glColor3ub(255, 255, 0); //yellow by default
196 
197  // if (m_mesh)
198  //{
199  // unsigned nTri = m_mesh->size();
200  // m_mesh->placeIteratorAtBeginning();
201 
202  // glBegin(GL_TRIANGLES);
203  // for (unsigned i = 0; i < nTri; ++i)
204  // {
205  // const GenericTriangle* t = m_mesh->_getNextTriangle();
206  // glVertex3v(t->_getA()->u);
207  // glVertex3v(t->_getB()->u);
208  // glVertex3v(t->_getC()->u);
209  // }
210  // glEnd();
211  //}
212  // else
213  //{
214  // unsigned nPts = m_vertices->size();
215  // m_vertices->placeIteratorAtBeginning();
216 
217  // glBegin(GL_POINTS);
218  // for (unsigned i = 0; i < nPts; ++i)
219  // glVertex3v(m_vertices->getNextPoint()->u);
220  // glEnd();
221  //}
222 }
223 
224 void openGLSnapshot(GLenum format, GLenum type, void* buffer) {
225  // assert(buffer);
226 
227  // int vp[4];
228  // glGetIntegerv(GL_VIEWPORT, vp);
229 
230  // glReadPixels(vp[0], vp[1], vp[2], vp[3], format, type, buffer);
231 }
232 
233 // The method below is inspired from ShadeVis' "GLAccumPixel" (Cignoni et al.)
234 /****************************************************************************
235  * VCGLib o o *
236  * Visual and Computer Graphics Library o o *
237  * _ O _ *
238  * Copyright(C) 2004 \/)\/ *
239  * Visual Computing Lab /\/| *
240  * ISTI - Italian National Research Council | *
241  *****************************************************************************/
242 int PCVContext::GLAccumPixel(std::vector<int>& visibilityCount) {
243  if (!m_pixBuffer || !m_pixBuffer->isValid()) return -1;
244  if (!m_vertices) return -1;
245  if (m_vertices->size() != visibilityCount.size()) return -1;
246 
247  assert(m_snapZ);
248 
249  m_pixBuffer->makeCurrent();
250 
251  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
252  glDepthRange(2.0f * ZTWIST, 1.0f);
253 
254  if (m_meshIsClosed)
255  glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
256  else
257  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
258 
259  // display 3D entity (front)
260  glCullFace(GL_BACK);
261  drawEntity();
262 
263  if (!m_meshIsClosed) {
264  // display it again (back)
265  glCullFace(GL_FRONT);
266  drawEntity();
267 
268  assert(m_snapC);
269  openGLSnapshot(GL_RGBA, GL_UNSIGNED_BYTE, m_snapC);
270  }
271  openGLSnapshot(GL_DEPTH_COMPONENT, GL_FLOAT, m_snapZ);
272 
273  if (m_meshIsClosed) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
274 
275  glDepthRange(0, 1.0f - 2.0f * ZTWIST);
276  double MM[OPENGL_MATRIX_SIZE];
277  glGetDoublev(GL_MODELVIEW_MATRIX, MM);
278  double MP[OPENGL_MATRIX_SIZE];
279  glGetDoublev(GL_PROJECTION_MATRIX, MP);
280  int VP[4];
281  glGetIntegerv(GL_VIEWPORT, VP);
282 
283  int count = 0;
284  int sx4 = (m_width << 2);
285 
286  unsigned nVert = m_vertices->size();
288  for (unsigned i = 0; i < nVert; ++i) {
289  const CCVector3* P = m_vertices->getNextPoint();
290 
291  double tx, ty, tz;
292  gluProject(P->x, P->y, P->z, MM, MP, VP, &tx, &ty, &tz);
293 
294  int txi = static_cast<int>(floor(tx));
295  int tyi = static_cast<int>(floor(ty));
296  if (txi >= 0 && txi < static_cast<int>(m_width) && tyi >= 0 &&
297  tyi < static_cast<int>(m_height)) {
298  int dec = txi + tyi * static_cast<int>(m_width);
299  int col = 1;
300 
301  if (!m_meshIsClosed) {
302  // int c1 = std::max(m_snapC[dec],m_snapC[dec<<2+4]);
303  // int c2 = std::max(m_snapC[dec<<2+sx4],m_snapC[dec<<2+sx4+4]);
304  const unsigned char* pix = m_snapC + (dec << 2);
305  int c1 = std::max(pix[0], pix[4]);
306  pix += sx4;
307  int c2 = std::max(pix[0], pix[4]);
308  col = std::max(c1, c2);
309  }
310 
311  if (col != 0) {
312  if (tz < static_cast<double>(m_snapZ[dec])) {
313  assert(i < visibilityCount.size());
314  ++visibilityCount[i];
315  ++count;
316  }
317  }
318  }
319  }
320 
321  return count;
322 }
constexpr double ZERO_TOLERANCE
Numerical threshold for considering a value as "zero".
Definition: CVConst.h:37
constexpr PointCoordinateType PC_ONE
'1' as a PointCoordinateType value
Definition: CVConst.h:67
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
filament::Texture::InternalFormat format
int size
int count
char type
#define ZTWIST
Definition: PCVContext.cpp:46
void openGLSnapshot(GLenum format, GLenum type, void *buffer)
Definition: PCVContext.cpp:224
static void glScale(float x, float y, float z)
Definition: PCVContext.cpp:40
static void glTranslate(float x, float y, float z)
Definition: PCVContext.cpp:32
static void glVertex3v(const float *v)
Definition: PCVContext.cpp:28
bool init(unsigned W, unsigned H, cloudViewer::GenericCloud *cloud, cloudViewer::GenericMesh *mesh=0, bool closedMesh=true)
Initialization.
Definition: PCVContext.cpp:69
void setViewDirection(const CCVector3 &V)
Set the viewing directions.
Definition: PCVContext.cpp:166
void associateToEntity(cloudViewer::GenericCloud *cloud, cloudViewer::GenericMesh *mesh=0)
Definition: PCVContext.cpp:112
void glInit()
Definition: PCVContext.cpp:136
CCVector3 m_viewCenter
Definition: PCVContext.h:69
PointCoordinateType m_zoom
Definition: PCVContext.h:67
void drawEntity()
Definition: PCVContext.cpp:187
unsigned m_height
Pixel buffer height (pixels)
Definition: PCVContext.h:77
float * m_snapZ
Depth buffer.
Definition: PCVContext.h:88
virtual ~PCVContext()
Destructor.
Definition: PCVContext.cpp:62
float m_viewMat[OPENGL_MATRIX_SIZE]
Current model view matrix.
Definition: PCVContext.h:85
QGLPixelBuffer * m_pixBuffer
Definition: PCVContext.h:72
cloudViewer::GenericCloud * m_vertices
Displayed entity (cloud or mesh vertices)
Definition: PCVContext.h:61
static const unsigned OPENGL_MATRIX_SIZE
Model view matrix size (OpenGL)
Definition: PCVContext.h:82
bool m_meshIsClosed
Whether displayed mesh is closed or not.
Definition: PCVContext.h:93
int GLAccumPixel(std::vector< int > &visibilityCount)
Definition: PCVContext.cpp:242
unsigned char * m_snapC
Color buffer.
Definition: PCVContext.h:90
PCVContext()
Default constructor.
Definition: PCVContext.cpp:49
unsigned m_width
Pixel buffer width (pixels)
Definition: PCVContext.h:75
cloudViewer::GenericMesh * m_mesh
Displayed entity (mesh - optional)
Definition: PCVContext.h:64
Type y
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
virtual void getBoundingBox(CCVector3 &bbMin, CCVector3 &bbMax)=0
Returns the cloud bounding box.
virtual void placeIteratorAtBeginning()=0
Sets the cloud iterator at the beginning.
virtual const CCVector3 * getNextPoint()=0
Returns the next point (relatively to the global iterator position)
virtual unsigned size() const =0
Returns the number of points.
int min(int a, int b)
Definition: cutil_math.h:53
int max(int a, int b)
Definition: cutil_math.h:48
MiniVec< float, N > floor(const MiniVec< float, N > &a)
Definition: MiniVec.h:75