Openholo  v4.0
Open Source Digital Holographic Library
ophPointCloud.cpp
Go to the documentation of this file.
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install, copy or use the software.
7 //
8 //
9 // License Agreement
10 // For Open Source Digital Holographic Library
11 //
12 // Openholo library is free software;
13 // you can redistribute it and/or modify it under the terms of the BSD 2-Clause license.
14 //
15 // Copyright (C) 2017-2024, Korea Electronics Technology Institute. All rights reserved.
16 // E-mail : contact.openholo@gmail.com
17 // Web : http://www.openholo.org
18 //
19 // Redistribution and use in source and binary forms, with or without modification,
20 // are permitted provided that the following conditions are met:
21 //
22 // 1. Redistribution's of source code must retain the above copyright notice,
23 // this list of conditions and the following disclaimer.
24 //
25 // 2. Redistribution's in binary form must reproduce the above copyright notice,
26 // this list of conditions and the following disclaimer in the documentation
27 // and/or other materials provided with the distribution.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the copyright holder or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 // This software contains opensource software released under GNU Generic Public License,
41 // NVDIA Software License Agreement, or CUDA supplement to Software License Agreement.
42 // Check whether software you use contains licensed software.
43 //
44 //M*/
45 
46 #include "ophPointCloud.h"
47 #include "include.h"
48 #include "tinyxml2.h"
49 #include <sys.h>
50 
52  : ophGen()
53  , is_ViewingWindow(false)
54  , m_nProgress(0)
55 {
56  LOG("*** POINT CLOUD : BUILD DATE: %s %s ***\n\n", __DATE__, __TIME__);
57 }
58 
59 ophPointCloud::ophPointCloud(const char* pc_file, const char* cfg_file)
60  : ophGen()
61  , is_ViewingWindow(false)
62  , m_nProgress(0)
63 {
64  LOG("*** POINT CLOUD : BUILD DATE: %s %s ***\n\n", __DATE__, __TIME__);
65  if (loadPointCloud(pc_file) == -1) LOG("<FAILED> Load point cloud data file(\'%s\')", pc_file);
66  if (!readConfig(cfg_file)) LOG("<FAILED> Load config specification data file(\'%s\')", cfg_file);
67 }
68 
70 {
71 }
72 
73 int ophPointCloud::loadPointCloud(const char* pc_file)
74 {
75  return ophGen::loadPointCloud(pc_file, &pc_data_);
76 }
77 
78 void ophPointCloud::setViewingWindow(bool is_ViewingWindow)
79 {
80  this->is_ViewingWindow = is_ViewingWindow;
81 }
82 
83 bool ophPointCloud::readConfig(const char* fname)
84 {
85  if (!ophGen::readConfig(fname))
86  return false;
87 
88  bool bRet = true;
89 
90  using namespace tinyxml2;
91  /*XML parsing*/
92  tinyxml2::XMLDocument xml_doc;
93  XMLNode *xml_node;
94  XMLError error;
95 
96  if (!checkExtension(fname, ".xml"))
97  {
98  LOG("<FAILED> Wrong file ext.\n");
99  return false;
100  }
101  if ((error = xml_doc.LoadFile(fname)) != XML_SUCCESS)
102  {
103  LOG("<FAILED> Loading file (%d)\n", error);
104  return false;
105  }
106 
107  xml_node = xml_doc.FirstChild();
108 
109  char szNodeName[32] = { 0, };
110  sprintf(szNodeName, "ScaleX");
111  // about point
112  auto next = xml_node->FirstChildElement(szNodeName);
113  if (!next || XML_SUCCESS != next->QueryDoubleText(&pc_config_.scale[_X]))
114  {
115  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
116  bRet = false;
117  }
118  sprintf(szNodeName, "ScaleY");
119  next = xml_node->FirstChildElement(szNodeName);
120  if (!next || XML_SUCCESS != next->QueryDoubleText(&pc_config_.scale[_Y]))
121  {
122  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
123  bRet = false;
124  }
125  sprintf(szNodeName, "ScaleZ");
126  next = xml_node->FirstChildElement(szNodeName);
127  if (!next || XML_SUCCESS != next->QueryDoubleText(&pc_config_.scale[_Z]))
128  {
129  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
130  bRet = false;
131  }
132  sprintf(szNodeName, "Distance");
133  next = xml_node->FirstChildElement(szNodeName);
134  if (!next || XML_SUCCESS != next->QueryDoubleText(&pc_config_.distance))
135  {
136  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
137  bRet = false;
138  }
139 
140  initialize();
141 
142  LOG("**************************************************\n");
143  LOG(" Read Config (Point Cloud) \n");
144  LOG("1) Focal Length : %.5lf\n", pc_config_.distance);
145  LOG("2) Object Scale : %.5lf / %.5lf / %.5lf\n", pc_config_.scale[_X], pc_config_.scale[_Y], pc_config_.scale[_Z]);
146  LOG("**************************************************\n");
147 
148  return bRet;
149 }
150 
152 {
153  auto begin = CUR_TIME;
154  if (diff_flag != PC_DIFF_RS && diff_flag != PC_DIFF_FRESNEL) {
155  LOG("<FAILED> Wrong parameters.");
156  return 0.0;
157  }
158 
159  resetBuffer();
160  LOG("**************************************************\n");
161  LOG(" Generate Hologram \n");
162  LOG("1) Algorithm Method : Point Cloud\n");
163  LOG("2) Generate Hologram with %s\n", m_mode & MODE_GPU ?
164  "GPU" :
165 #ifdef _OPENMP
166  "Multi Core CPU"
167 #else
168  "Single Core CPU"
169 #endif
170  );
171  LOG("3) Diffraction Method : %s\n", diff_flag == PC_DIFF_RS ? "R-S" : "Fresnel");
172  LOG("4) Number of Point Cloud : %llu\n", pc_data_.n_points);
173  LOG("5) Precision Level : %s\n", m_mode & MODE_FLOAT ? "Single" : "Double");
174  if(m_mode & MODE_GPU)
175  LOG("6) Use FastMath : %s\n", m_mode & MODE_FASTMATH ? "Y" : "N");
176  LOG("**************************************************\n");
177 
178  // Create CGH Fringe Pattern by 3D Point Cloud
179  if (m_mode & MODE_GPU) { //Run GPU
180  genCghPointCloudGPU(diff_flag);
181  }
182  else { //Run CPU
183  genCghPointCloudCPU(diff_flag);
184  }
185 
186 
187  Real elapsed_time = ELAPSED_TIME(begin, CUR_TIME);
188  LOG("Total Elapsed Time: %.5lf (s)\n", elapsed_time);
189  m_nProgress = 0;
190  return elapsed_time;
191 }
192 
193 void ophPointCloud::encodeHologram(const vec2 band_limit, const vec2 spectrum_shift)
194 {
195  if (complex_H == nullptr) {
196  LOG("<FAILED> Not found diffracted data.");
197  return;
198  }
199 
200  const uint nChannel = context_.waveNum;
201  const int pnX = context_.pixel_number[_X];
202  const int pnY = context_.pixel_number[_Y];
203  const Real ppX = context_.pixel_pitch[_X];
204  const Real ppY = context_.pixel_pitch[_Y];
205  const long long int pnXY = pnX * pnY;
206 
207  m_vecEncodeSize = ivec2(pnX, pnY);
208  context_.ss[_X] = pnX * ppX;
209  context_.ss[_Y] = pnY * ppY;
210  vec2 ss = context_.ss;
211 
212  Real halfppX = ppX / 2;
213  Real halfssX = ss[_X] / 2;
214 
215  Complex<Real>* tmp = new Complex<Real>[pnXY];
216 
217  for (uint ch = 0; ch < nChannel; ch++) {
218 
219  fft2(ivec2(pnX, pnY), complex_H[ch], OPH_FORWARD);
220  fft2(complex_H[ch], tmp, pnX, pnY, OPH_FORWARD);
221  fft2(ivec2(pnX, pnY), tmp, OPH_BACKWARD);
222  fft2(tmp, tmp, pnX, pnY, OPH_BACKWARD);
223 
224  for (int i = 0; i < pnXY; i++)
225  {
226  Complex<Real> shift_phase(1.0, 0.0);
227 
228  int w = i % pnX;
229  int h = i / pnX;
230  Real y = (ss[_Y] - ppY) - (ppY * h);
231  Real Y = (M_PI * y * spectrum_shift[_Y]) / ppY;
232  Real x = -halfssX + ppX * w + halfppX;
233  Real X = (M_PI * x * spectrum_shift[_X]) / ppX;
234 
235  shift_phase[_RE] = shift_phase[_RE] * (cos(X) * cos(Y) - sin(X) * sin(Y));
236  m_lpEncoded[ch][i] = (tmp[i] * shift_phase).real();
237  }
238  }
239  delete[] tmp;
240 }
241 
243 {
245 }
246 
247 void ophPointCloud::encoding(unsigned int ENCODE_FLAG, unsigned int SSB_PASSBAND)
248 {
251 }
252 
253 void ophPointCloud::genCghPointCloudCPU(uint diff_flag)
254 {
255  auto begin = CUR_TIME;
256 
257  // Output Image Size
258  ivec2 pn;
259  pn[_X] = context_.pixel_number[_X];
260  pn[_Y] = context_.pixel_number[_Y];
261 
262  // Tilt Angle
263  Real thetaX = RADIAN(pc_config_.tilt_angle[_X]);
264  Real thetaY = RADIAN(pc_config_.tilt_angle[_Y]);
265 
266  // Pixel pitch at eyepiece lens plane (by simple magnification) ==> SLM pitch
267  vec2 pp;
268  pp[_X] = context_.pixel_pitch[_X];
269  pp[_Y] = context_.pixel_pitch[_Y];
270 
271  // Length (Width) of complex field at eyepiece plane (by simple magnification)
272  vec2 ss;
273  ss[_X] = context_.ss[_X] = pn[_X] * pp[_X];
274  ss[_Y] = context_.ss[_Y] = pn[_Y] * pp[_Y];
275 
276  uint nChannel = context_.waveNum;
277 
278  int sum = 0;
279  m_nProgress = 0;
280  int n_points = pc_data_.n_points;
281 
282  Vertex *pVertex = nullptr;
283  if (is_ViewingWindow) {
284  pVertex = new Vertex[pc_data_.n_points];
285  std::memcpy(pVertex, pc_data_.vertices, sizeof(Vertex) * pc_data_.n_points);
286  transVW(pc_data_.n_points, pVertex, pVertex);
287  }
288  else {
289  pVertex = pc_data_.vertices;
290  }
291 
292  for (uint ch = 0; ch < nChannel; ++ch) {
293  Real lambda = context_.wave_length[ch];
294  Real k = context_.k = (2 * M_PI / lambda);
295 
296 #ifdef _OPENMP
297 #pragma omp parallel for firstprivate(lambda)
298 #endif
299  for (int i = 0; i < n_points; ++i) { //Create Fringe Pattern
300 
301  Point pc = pVertex[i].point;
302  Real amplitude = pVertex[i].color.color[ch];
303 
304  pc.pos[_X] *= pc_config_.scale[_X];
305  pc.pos[_Y] *= pc_config_.scale[_Y];
306  pc.pos[_Z] *= pc_config_.scale[_Z];
307 
308 
309  switch (diff_flag)
310  {
311  case PC_DIFF_RS:
312  RS_Diffraction(pc, complex_H[ch], lambda, pc_config_.distance, amplitude);
313  break;
314  case PC_DIFF_FRESNEL:
315  Fresnel_Diffraction(pc, complex_H[ch], lambda, pc_config_.distance, amplitude);
316  break;
317  }
318 #ifdef _OPENMP
319 #pragma omp atomic
320 #endif
321  sum++;
322  m_nProgress = (int)((Real)sum * 100 / ((Real)n_points * nChannel));
323  }
324  }
325  if (is_ViewingWindow) {
326  delete[] pVertex;
327  }
328  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
329 }
330 
331 void ophPointCloud::ophFree(void)
332 {
333  if (pc_data_.vertices) {
334  delete[] pc_data_.vertices;
335  pc_data_.vertices = nullptr;
336  }
337 }
#define OPH_BACKWARD
Definition: define.h:67
Color color
Definition: struct.h:104
ENCODE_FLAG
Definition: ophGen.h:84
void RS_Diffraction(Point src, Complex< Real > *dst, Real lambda, Real distance, Real amplitude)
RS-diffraction method.
Definition: ophGen.cpp:356
Point point
Definition: struct.h:103
Real k
Definition: Openholo.h:67
Real distance
Offset value of point cloud.
Definition: ophGen.h:560
Real * wave_length
Definition: Openholo.h:70
#define MODE_FASTMATH
Definition: define.h:159
ulonglong n_points
Number of points.
Definition: ophGen.h:585
SSB_PASSBAND
Definition: ophGen.h:296
#define MODE_GPU
Definition: define.h:156
#define MODE_FLOAT
Definition: define.h:158
Real ** m_lpEncoded
buffer to encoded.
Definition: ophGen.h:339
vec2 tilt_angle
Tilt angle for spatial filtering.
Definition: ophGen.h:572
float Real
Definition: typedef.h:55
void initialize(void)
Initialize variables for Hologram complex field, encoded data, normalized data.
Definition: ophGen.cpp:145
#define CUR_TIME
Definition: function.h:58
Definition: struct.h:86
vec2 ss
Definition: Openholo.h:68
bool checkExtension(const char *fname, const char *ext)
Functions for extension checking.
Definition: Openholo.cpp:86
structure for 2-dimensional integer vector and its arithmetic.
Definition: ivec.h:66
const XMLNode * FirstChild() const
Get the first child node, or null if none exists.
Definition: tinyxml2.h:761
void encodeHologram(vec2 band_limit=vec2(0.8, 0.5), vec2 spectrum_shift=vec2(0.0, 0.5))
encode Single-side band
#define _Y
Definition: define.h:96
vec2 pixel_pitch
Definition: Openholo.h:65
vec3 scale
Scaling factor of coordinate of point cloud.
Definition: ophGen.h:558
ivec2 m_vecEncodeSize
Encoded hologram size, varied from encoding type.
Definition: ophGen.h:331
#define _X
Definition: define.h:92
int loadPointCloud(const char *pc_file)
override
unsigned int m_mode
Definition: ophGen.h:351
bool readConfig(const char *cfg_file)
Import Specification Config File(*.config) file.
#define RADIAN(theta)
Definition: define.h:60
virtual ~ophPointCloud(void)
Destructor.
#define _RE
Definition: complex.h:55
void fft2(ivec2 n, Complex< Real > *in, int sign=OPH_FORWARD, uint flag=OPH_ESTIMATE)
Functions for performing fftw 2-dimension operations inside Openholo.
Definition: Openholo.cpp:559
ophPointCloud(void)
Constructor.
structure for 2-dimensional Real type vector and its arithmetic.
Definition: vec.h:66
void setViewingWindow(bool is_ViewingWindow)
Set the value of a variable is_ViewingWindow(true or false)
Definition: struct.h:102
Real pos[3]
Definition: struct.h:87
#define ELAPSED_TIME(x, y)
Definition: function.h:59
uint waveNum
Definition: Openholo.h:69
ivec2 pixel_number
Definition: Openholo.h:63
Vertex * vertices
Data of point clouds.
Definition: ophGen.h:589
bool readConfig(const char *fname)
load to configuration file.
Definition: ophGen.cpp:220
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2150
void encoding()
Definition: ophGen.cpp:982
void resetBuffer()
reset buffer
Definition: ophGen.cpp:821
w
Definition: Openholo.cpp:429
OphConfig context_
Definition: Openholo.h:449
#define OPH_FORWARD
Definition: define.h:66
void Fresnel_Diffraction(Point src, Complex< Real > *dst, Real lambda, Real distance, Real amplitude)
Fresnel-diffraction method.
Definition: ophGen.cpp:443
Complex< Real > ** complex_H
Definition: Openholo.h:452
Real generateHologram(uint diff_flag=PC_DIFF_RS)
Generate a hologram, main funtion.
void transVW(int nVertex, Vertex *dst, Vertex *src)
Definition: ophGen.cpp:2067
#define _Z
Definition: define.h:100
Real sum(const vec2 &a)
Definition: vec.h:401
int loadPointCloud(const char *pc_file, OphPointCloudData *pc_data_)
load to point cloud data.
Definition: ophGen.cpp:206
Real color[3]
Definition: struct.h:95
const XMLElement * FirstChildElement(const char *name=0) const
Definition: tinyxml2.cpp:940
unsigned int uint
Definition: typedef.h:62
#define M_PI
Definition: define.h:52
h
Definition: Openholo.cpp:430
Definition: ophGen.h:76