DGtalTools  1.5.beta
meshViewer.cpp
1 
30 #include <iostream>
31 #include <sstream>
32 #include "DGtal/base/Common.h"
33 
34 #include "DGtal/io/Display3D.h"
35 #include "DGtal/io/viewers/Viewer3D.h"
36 #include "DGtal/io/readers/MeshReader.h"
37 #include "DGtal/helpers/StdDefs.h"
38 #include "DGtal/io/readers/PointListReader.h"
39 
40 #include "CLI11.hpp"
41 
42 using namespace std;
43 using namespace DGtal;
44 
104 class CustomViewer3D : public Viewer3D<>
105 {
106 protected:
107  virtual void init()
108  {
110  Viewer3D<>::setKeyDescription(Qt::Key_I, "Display mesh informations about #faces, #vertices");
112  }
113 
114  virtual void keyPressEvent(QKeyEvent *e)
115  {
116  bool handled = false;
117  if (e->key() == Qt::Key_I)
118  {
119  handled = true;
120  myIsDisplayingInfoMode = !myIsDisplayingInfoMode;
121  stringstream ss;
122  qglviewer::Vec camPos = camera()->position();
123  DGtal::Z3i::RealPoint c(camPos[0], camPos[1], camPos[2]);
124  ss << myInfoDisplay << " distance to camera: " << (c - centerMesh).norm();
125  Viewer3D<>::displayMessage(QString(myIsDisplayingInfoMode ? ss.str().c_str() : " "), 1000000);
126 
128  }
129 
130  if (!handled)
131  {
133  }
134  };
135 
136 public:
137  void changeDefaultBGColor(const DGtal::Color &col)
138  {
139  myDefaultBackgroundColor = col;
142  }
143  std::string myInfoDisplay = "No information loaded...";
144  bool myIsDisplayingInfoMode = false;
145  DGtal::Z3i::RealPoint centerMesh;
146 };
147 
148 int main(int argc, char **argv)
149 {
150  float sx{1.0};
151  float sy{1.0};
152  float sz{1.0};
153 
154  unsigned int meshColorR{240};
155  unsigned int meshColorG{240};
156  unsigned int meshColorB{240};
157  unsigned int meshColorA{255};
158 
159  unsigned int meshColorRLine{0};
160  unsigned int meshColorGLine{0};
161  unsigned int meshColorBLine{0};
162  unsigned int meshColorALine{255};
163 
164  unsigned int sdpColorR{240};
165  unsigned int sdpColorG{240};
166  unsigned int sdpColorB{240};
167  unsigned int sdpColorA{255};
168 
169  float lineWidth{1.5};
170 
171  std::vector<unsigned int> customColorMesh;
172  std::vector<unsigned int> customColorSDP;
173  std::vector<unsigned int> customLineColor;
174  std::vector<unsigned int> customBGColor;
175  std::vector<unsigned int> customAlphaMesh;
176  std::vector<unsigned int> vectFieldIndices = {0, 1, 2, 3, 4, 5};
177  std::string displayVectorField;
178 
179  std::string snapshotFile;
180  std::string filenameSDP;
181  double ballRadius{0.5};
182  bool invertNormal{false};
183  bool drawVertex{false};
184  bool useLastCamSet{false};
185  bool fixLightToScene{false};
186  float ambiantLight{0.0};
187 
188  // parse command line using CLI ----------------------------------------------
189  CLI::App app;
190  std::vector<std::string> inputFileNames;
191  std::string outputFileName{"result.raw"};
192  app.description("Display OFF mesh file by using QGLviewer");
193  app.add_option("-i,--input,1", inputFileNames, "inputFileNames.off files (.off), or OFS file (.ofs)")
194  ->check(CLI::ExistingFile)
195  ->required();
196  app.add_option("-x,--scaleX", sx, "set the scale value in the X direction (default 1.0)");
197  app.add_option("-y,--scaleY", sy, "set the scale value in the y direction (default 1.0)");
198  app.add_option("-z,--scaleZ", sz, "set the scale value in the z direction (default 1.0)");
199  app.add_option("--minLineWidth", lineWidth, "set the min line width of the mesh faces (default 1.5)", true);
200  app.add_option("--customColorMesh", customColorMesh, "set the R, G, B, A components of the colors of the mesh faces and eventually the color R, G, B, A of the mesh edge lines (set by default to black).");
201  app.add_option("--customAlphaMesh", customAlphaMesh, "set the alpha(A) components of the colors of the mesh faces (can be applied for each mesh).");
202  app.add_option("--customColorSDP", customColorSDP, "set the R, G, B, A components of the colors of the sdp view")
203  ->expected(4);
204  app.add_option("--displayVectorField,-f", displayVectorField, "display a vector field from a simple sdp file (two points per line)");
205  app.add_option("--vectorFieldIndex", vectFieldIndices, "specify special indices for the two point coordinates (instead usinf the default indices: 0 1, 2, 3, 4, 5)")
206  ->expected(6);
207  app.add_option("--customLineColor", customLineColor, "set the R, G, B components of the colors of the lines displayed from the --displayVectorField option (red by default).")
208  ->expected(4);
209  app.add_option("--SDPradius", ballRadius, "change the ball radius to display a set of discrete points (used with displaySDP option)", true);
210  app.add_option("--displaySDP,-s", filenameSDP, "add the display of a set of discrete points as ball of radius 0.5.");
211  app.add_option("--addAmbientLight,-A", ambiantLight, "add an ambient light for better display (between 0 and 1).");
212  app.add_option("--customBGColor,-b", customBGColor, "set the R, G, B components of the colors of the background color.")
213  ->expected(3);
214  app.add_option("--doSnapShotAndExit,-d", snapshotFile, "save display snapshot into file. Notes that the camera setting is set by default according the last saved configuration (use SHIFT+Key_M to save current camera setting in the Viewer3D). If the camera setting was not saved it will use the default camera setting.");
215  app.add_flag("--useLastCameraSetting,-c", useLastCamSet, "use the last camera setting of the user (i.e if a .qglviewer.xml file is present in the current directory)");
216  app.add_flag("--fixLightToScene,-l", fixLightToScene, "Fix light source to scence instead to camera");
217  app.add_flag("--invertNormal,-n", invertNormal, "invert face normal vectors.");
218  app.add_flag("--drawVertex,-v", drawVertex, "draw the vertex of the mesh");
219 
220  app.get_formatter()->column_width(40);
221  CLI11_PARSE(app, argc, argv);
222  // END parse command line using CLI ----------------------------------------------
223 
224  DGtal::Color vFieldLineColor = DGtal::Color::Red;
225  if (customLineColor.size() == 4)
226  {
227  vFieldLineColor.setRGBi(customLineColor[0], customLineColor[1], customLineColor[2], 255);
228  }
229 
230  if (customColorMesh.size() != 0)
231  {
232  if (customColorMesh.size() < 4)
233  {
234  trace.error() << "colors specification should contain R,G,B and Alpha values" << std::endl;
235  }
236  }
237 
238  if (customColorSDP.size() == 4)
239  {
240  sdpColorR = customColorSDP[0];
241  sdpColorG = customColorSDP[1];
242  sdpColorB = customColorSDP[2];
243  sdpColorA = customColorSDP[3];
244  }
245 
246  QApplication application(argc, argv);
247  CustomViewer3D viewer;
248  if (snapshotFile != "")
249  {
250  viewer.setSnapshotFileName(QString(snapshotFile.c_str()));
251  }
252 
253  std::stringstream title;
254  title << "Simple Mesh Viewer: " << inputFileNames[0];
255  viewer.setWindowTitle(title.str().c_str());
256  viewer.show();
257  viewer.myGLLineMinWidth = lineWidth;
258  viewer.setGLScale(sx, sy, sz);
259  if (customBGColor.size() == 3)
260  {
261  viewer.changeDefaultBGColor(DGtal::Color(customBGColor[0],
262  customBGColor[1],
263  customBGColor[2], 255));
264  }
265  if (ambiantLight != 0.0)
266  {
267  GLfloat lightAmbientCoeffs[4] = {ambiantLight, ambiantLight, ambiantLight, 1.0f};
268  viewer.setGLLightAmbientCoefficients(lightAmbientCoeffs);
269  }
270 
271  trace.info() << "Importing mesh... ";
272 
273  std::vector<Mesh<DGtal::Z3i::RealPoint>> vectMesh;
274  for (unsigned int i = 0; i < inputFileNames.size(); i++)
275  {
276  Mesh<DGtal::Z3i::RealPoint> aMesh(customColorMesh.size() != 4 && customColorMesh.size() != 8);
277  aMesh << inputFileNames[i];
278  // for obj mesh by default the mesh color face are not necessary uniform.
279  if (aMesh.isStoringFaceColors() && customColorMesh.size() >= 4)
280  {
281  if (i * 8 < customColorMesh.size())
282  {
283  meshColorR = customColorMesh[i * 8];
284  }
285  if (i * 8 + 1 < customColorMesh.size())
286  {
287  meshColorG = customColorMesh[i * 8 + 1];
288  }
289  if (i * 8 + 2 < customColorMesh.size())
290  {
291  meshColorB = customColorMesh[i * 8 + 2];
292  }
293  if (i * 8 + 3 < customColorMesh.size())
294  {
295  meshColorA = customColorMesh[i * 8 + 3];
296  }
297  for (unsigned int j = 0; j < aMesh.nbFaces(); j++)
298  {
299  aMesh.setFaceColor(j, Color(meshColorR, meshColorG, meshColorB, meshColorA));
300  }
301  }
302  else if (customAlphaMesh.size() > 0)
303  {
304  for (unsigned int j = 0; j < aMesh.nbFaces(); j++)
305  {
306  auto c = aMesh.getFaceColor(j);
307  aMesh.setFaceColor(j, Color(c.red(), c.green(), c.blue(), customAlphaMesh.at(i < customAlphaMesh.size() ? i : 0)));
308  }
309  }
310 
311  vectMesh.push_back(aMesh);
312  }
313  DGtal::Z3i::RealPoint centerMeshes;
314  unsigned int tot = 0;
315  for (const auto &m : vectMesh)
316  {
317  for (auto p = m.vertexBegin(); p != m.vertexEnd(); ++p)
318  centerMeshes += *p;
319  tot += m.nbVertex();
320  }
321  centerMeshes /= tot;
322  viewer.centerMesh = centerMeshes;
323  bool import = vectMesh.size() == inputFileNames.size();
324  if (!import)
325  {
326  trace.info() << "File import failed. " << std::endl;
327  return 0;
328  }
329 
330  trace.info() << "[done]. " << std::endl;
331  if (filenameSDP != "")
332  {
333  if (customAlphaMesh.size() > 0)
334  {
335  trace.info() << "New meshViewer" << std::endl;
336  auto vOrigins = PointListReader<PointVector<1, DGtal::int32_t>>::getPolygonsFromFile(filenameSDP);
337  viewer << CustomColors3D(Color(sdpColorR, sdpColorG, sdpColorB, sdpColorA),
338  Color(sdpColorR, sdpColorG, sdpColorB, sdpColorA));
339  for (auto l : vOrigins)
340  {
341  DGtal::Z3i::Point pt(l[0][0], l[1][0], l[2][0]);
342  DGtal::Color cl(l[3][0], l[4][0], l[5][0], sdpColorA);
343  viewer.setFillColor(cl);
344  viewer.addBall(pt, ballRadius);
345  }
346  }
347  else
348  {
349  vector<Z3i::RealPoint> vectPoints;
350  vectPoints = PointListReader<Z3i::RealPoint>::getPointsFromFile(filenameSDP);
351  viewer << CustomColors3D(Color(sdpColorR, sdpColorG, sdpColorB, sdpColorA),
352  Color(sdpColorR, sdpColorG, sdpColorB, sdpColorA));
353  for (unsigned int i = 0; i < vectPoints.size(); i++)
354  {
355  viewer.addBall(vectPoints.at(i), ballRadius);
356  }
357  }
358  }
359  if (invertNormal)
360  {
361  for (unsigned int i = 0; i < vectMesh.size(); i++)
362  {
363  vectMesh[i].invertVertexFaceOrder();
364  }
365  }
366 
367  for (unsigned int i = 0; i < vectMesh.size(); i++)
368  {
369  if (i * 8 < customColorMesh.size())
370  {
371  meshColorR = customColorMesh[i * 8];
372  }
373  if (i * 8 + 1 < customColorMesh.size())
374  {
375  meshColorG = customColorMesh[i * 8 + 1];
376  }
377  if (i * 8 + 2 < customColorMesh.size())
378  {
379  meshColorB = customColorMesh[i * 8 + 2];
380  }
381  if (i * 8 + 3 < customColorMesh.size())
382  {
383  meshColorA = customColorMesh[i * 8 + 3];
384  }
385  if (i * 8 + 4 < customColorMesh.size())
386  {
387  meshColorALine = customColorMesh[i * 8 + 4];
388  }
389  if (i * 8 + 5 < customColorMesh.size())
390  {
391  meshColorBLine = customColorMesh[i * 8 + 5];
392  }
393  if (i * 8 + 6 < customColorMesh.size())
394  {
395  meshColorRLine = customColorMesh[i * 8 + 6];
396  }
397  if (i * 8 + 7 < customColorMesh.size())
398  {
399  meshColorALine = customColorMesh[i * 8 + 7];
400  }
401 
402  viewer << CustomColors3D(Color(meshColorRLine, meshColorGLine, meshColorBLine,
403  meshColorALine),
404  Color(meshColorR, meshColorG, meshColorB, meshColorA));
405 
406  viewer << vectMesh[i];
407  }
408 
409  if (drawVertex)
410  {
411  for (unsigned int i = 0; i < vectMesh.size(); i++)
412  {
413  for (Mesh<DGtal::Z3i::RealPoint>::VertexStorage::const_iterator it = vectMesh[i].vertexBegin();
414  it != vectMesh[i].vertexEnd(); ++it)
415  {
417  pt[0] = (*it)[0];
418  pt[1] = (*it)[1];
419  pt[2] = (*it)[2];
420  viewer << pt;
421  }
422  }
423  }
424 
425  if (displayVectorField != "")
426  {
427  std::vector<unsigned int> vectFieldIndices1 = {vectFieldIndices[0], vectFieldIndices[1], vectFieldIndices[2]};
428  std::vector<unsigned int> vectFieldIndices2 = {vectFieldIndices[3], vectFieldIndices[4], vectFieldIndices[5]};
429  std::vector<DGtal::Z3i::RealPoint> vectPt1 = PointListReader<DGtal::Z3i::RealPoint>::getPointsFromFile(displayVectorField, vectFieldIndices1);
430  std::vector<DGtal::Z3i::RealPoint> vectPt2 = PointListReader<DGtal::Z3i::RealPoint>::getPointsFromFile(displayVectorField, vectFieldIndices2);
431  viewer.createNewLineList();
432  for (unsigned int i = 0; i < vectPt1.size(); i++)
433  {
434  viewer.setLineColor(vFieldLineColor);
435  viewer.addLine(vectPt1[i], vectPt2[i]);
436  }
437  }
438  unsigned int nbVertex = 0;
439  unsigned int nbFaces = 0;
440  for (auto const &m : vectMesh)
441  {
442  nbVertex += m.nbVertex();
443  nbFaces += m.nbFaces();
444  }
445  stringstream ss;
446  ss << "# faces: " << std::fixed << nbFaces << " #vertex: " << nbVertex;
447  viewer.myInfoDisplay = ss.str();
449  if (fixLightToScene)
450  {
451  viewer.setLightModeFixToCamera(false, false);
452  }
453 
454  if (useLastCamSet)
455  {
456  viewer.restoreStateFromFile();
457  }
458  else
459  {
460  // useful in non interactive case in order to retain the default camera settings (that are not saved in case of process kill).
461  viewer.saveStateToFile();
462  }
463  // First display transparency improve
464  viewer.sortTriangleFromCamera();
465  viewer.sortQuadFromCamera();
466  viewer.sortSurfelFromCamera();
467  viewer.sortPolygonFromCamera();
469 
470  if (snapshotFile != "")
471  {
472  // Recover mesh position
473  viewer.restoreStateFromFile();
474  viewer.saveSnapshot(QString(snapshotFile.c_str()), true);
475  return 0;
476  }
477  trace.info() << "[display ready]" << std::endl;
478 
479  return application.exec();
480 }
int main(int argc, char **argv)
static const Color Red
Color & setRGBi(const unsigned char aRedValue, const unsigned char aGreenValue, const unsigned char aBlueValue, const unsigned char aAlphaValue)
ConstIterator vertexEnd() const
static Dimension size()
std::ostream & error()
std::ostream & info()
Trace trace(traceWriterTerm)