Openholo  v1.0
Open Source Digital Holographic Library
ophTriMesh.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 "ophTriMesh.h"
47 
48 #include "sys.h"
49 #include "tinyxml2.h"
50 #include "PLYparser.h"
51 
52 #define for_i(iter, oper) for(int i=0;i<iter;i++){oper}
53 
54 #define _X1 0
55 #define _Y1 1
56 #define _Z1 2
57 #define _X2 3
58 #define _Y2 4
59 #define _Z2 5
60 #define _X3 6
61 #define _Y3 7
62 #define _Z3 8
63 
64 void ophTri::setMode(bool isCPU)
65 {
66  is_CPU = isCPU;
67 }
68 
69 void ophTri::setViewingWindow(bool is_ViewingWindow)
70 {
71  this->is_ViewingWindow = is_ViewingWindow;
72 }
73 
74 uint ophTri::loadMeshText(const char* fileName) {
75 
76  cout << "Mesh Text File Load..." << endl;
77 
78  ifstream file;
79  file.open(fileName);
80 
81  if (!file) {
82  cout << "Open failed - no such file" << endl;
83  cin.get();
84  return 0;
85  }
86 
87  triMeshArray = new Real[9 * 10000];
88 
89  Real data;
90  uint num_data;
91 
92  num_data = 0;
93  do {
94  file >> data;
95  triMeshArray[num_data] = data;
96  num_data++;
97  } while (file.get() != EOF);
98 
99  meshData->n_faces = num_data / 9;
100  triMeshArray[meshData->n_faces * 9] = EOF;
101 
102  return 1;
103 }
104 
105 bool ophTri::loadMeshData(const char* fileName, const char* ext) {
106  meshData = new OphMeshData;
107  cout << "ext = " << ext << endl;
108 
109  if (!strcmp(ext, "txt")) {
110  cout << "Text File.." << endl;
111  if (loadMeshText(fileName))
112  cout << "Mesh Data Load Finished.." << endl;
113  else
114  cout << "Mesh Data Load Failed.." << endl;
115  }
116  else if (!strcmp(ext, "ply")) {
117  cout << "PLY File.." << endl;
118  PLYparser meshPLY;
119  if (meshPLY.loadPLY(fileName, meshData->n_faces, meshData->color_channels, &meshData->face_idx, &meshData->vertex, &meshData->color))
120  cout << "Mesh Data Load Finished.." << endl;
121  else
122  {
123  cout << "Mesh Data Load Failed.." << endl;
124  return false;
125  }
126  }
127  else {
128  cout << "Error: Mesh data must be .txt or .ply" << endl;
129  return false;
130  }
131  meshData->n_faces /= 3;
132  triMeshArray = meshData->vertex;
133 
134  return true;
135 }
136 
137 bool ophTri::readConfig(const char* fname)
138 {
139  if (!ophGen::readConfig(fname))
140  return false;
141 
142  LOG("Reading....%s...", fname);
143 
144  auto start = CUR_TIME;
145 
146  using namespace tinyxml2;
147  /*XML parsing*/
148  tinyxml2::XMLDocument xml_doc;
149  XMLNode *xml_node;
150 
151  if (!checkExtension(fname, ".xml"))
152  {
153  LOG("file's extension is not 'xml'\n");
154  return false;
155  }
156  if (xml_doc.LoadFile(fname) != XML_SUCCESS)
157  {
158  LOG("Failed to load file \"%s\"\n", fname);
159  return false;
160  }
161 
162  xml_node = xml_doc.FirstChild();
163 
164  // about viewing window
165  auto next = xml_node->FirstChildElement("FieldLength");
166  if (!next || XML_SUCCESS != next->QueryDoubleText(&fieldLength))
167  return false;
168 
169  // about object
170  next = xml_node->FirstChildElement("ObjectSize");
171  if (!next || XML_SUCCESS != next->QueryDoubleText(&objSize))
172  return false;
173  next = xml_node->FirstChildElement("ObjectShiftX");
174  if (!next || XML_SUCCESS != next->QueryDoubleText(&objShift[_X]))
175  return false;
176  next = xml_node->FirstChildElement("ObjectShiftY");
177  if (!next || XML_SUCCESS != next->QueryDoubleText(&objShift[_Y]))
178  return false;
179  next = xml_node->FirstChildElement("ObjectShiftZ");
180  if (!next || XML_SUCCESS != next->QueryDoubleText(&objShift[_Z]))
181  return false;
182  next = xml_node->FirstChildElement("LampDirectionX");
183  if (!next || XML_SUCCESS != next->QueryDoubleText(&illumination[_X]))
184  return false;
185  next = xml_node->FirstChildElement("LampDirectionY");
186  if (!next || XML_SUCCESS != next->QueryDoubleText(&illumination[_Y]))
187  return false;
188  next = xml_node->FirstChildElement("LampDirectionZ");
189  if (!next || XML_SUCCESS != next->QueryDoubleText(&illumination[_Z]))
190  return false;
191 
192  auto end = CUR_TIME;
193  auto during = ((chrono::duration<Real>)(end - start)).count();
194  LOG("%lf (s)..done\n", during);
195 
196  initialize();
197  return true;
198 }
199 
200 
201 //int ophTri::saveAsOhc(const char * fname)
202 //{
203 // setPixelNumberOHC(getEncodeSize());
204 //
205 // Openholo::saveAsOhc(fname);
206 //
207 // return 0;
208 //}
209 
210 void ophTri::initializeAS()
211 {
212  const uint pnX = context_.pixel_number[_X];
213  const uint pnY = context_.pixel_number[_Y];
214  const uint pnXY = pnX * pnY;
215 
216  if (angularSpectrum) {
217  delete[] angularSpectrum;
218  angularSpectrum = nullptr;
219  }
220  angularSpectrum = new Complex<Real>[pnXY];
221  memset(angularSpectrum, 0, sizeof(Complex<Real>) * pnXY);
222 }
223 
224 
225 void ophTri::objNormCenter()
226 {
227  if (normalizedMeshData) {
228  delete[] normalizedMeshData;
229  normalizedMeshData = nullptr;
230  }
231  normalizedMeshData = new Real[meshData->n_faces * 9];
232 
233  Real* x_point = new Real[meshData->n_faces * 3];
234  Real* y_point = new Real[meshData->n_faces * 3];
235  Real* z_point = new Real[meshData->n_faces * 3];
236 
237  for_i(meshData->n_faces * 3,
238  *(x_point + i) = *(triMeshArray + 3 * i);
239  *(y_point + i) = *(triMeshArray + 3 * i + 1);
240  *(z_point + i) = *(triMeshArray + 3 * i + 2);
241  );
242  Real x_cen = (maxOfArr(x_point, meshData->n_faces * 3) + minOfArr(x_point, meshData->n_faces * 3)) / 2;
243  Real y_cen = (maxOfArr(y_point, meshData->n_faces * 3) + minOfArr(y_point, meshData->n_faces * 3)) / 2;
244  Real z_cen = (maxOfArr(z_point, meshData->n_faces * 3) + minOfArr(z_point, meshData->n_faces * 3)) / 2;
245 
246  Real* centered = new Real[meshData->n_faces * 9];
247 
248  for_i(meshData->n_faces * 3,
249  *(centered + 3 * i) = *(x_point + i) - x_cen;
250  *(centered + 3 * i + 1) = *(y_point + i) - y_cen;
251  *(centered + 3 * i + 2) = *(z_point + i) - z_cen;
252  );
253 
254  //
255  Real x_cen1 = (maxOfArr(x_point, meshData->n_faces * 3) + minOfArr(x_point, meshData->n_faces * 3)) / 2;
256  Real y_cen1 = (maxOfArr(y_point, meshData->n_faces * 3) + minOfArr(y_point, meshData->n_faces * 3)) / 2;
257  Real z_cen1 = (maxOfArr(z_point, meshData->n_faces * 3) + minOfArr(z_point, meshData->n_faces * 3)) / 2;
258 
259  cout << "center: "<< x_cen1 << ", " << y_cen1 << ", " << z_cen1 << endl;
260 
261  //
262 
263  Real x_del = (maxOfArr(x_point, meshData->n_faces * 3) - minOfArr(x_point, meshData->n_faces * 3));
264  Real y_del = (maxOfArr(y_point, meshData->n_faces * 3) - minOfArr(y_point, meshData->n_faces * 3));
265  Real z_del = (maxOfArr(z_point, meshData->n_faces * 3) - minOfArr(z_point, meshData->n_faces * 3));
266 
267  Real del = maxOfArr({ x_del, y_del, z_del });
268 
269  for_i(meshData->n_faces * 9,
270  *(normalizedMeshData + i) = *(centered + i) / del;
271  );
272 
273  delete[] centered, x_point, y_point, z_point;
274 }
275 
276 
278 {
279  if (scaledMeshData) {
280  delete[] scaledMeshData;
281  scaledMeshData = nullptr;
282  }
283  scaledMeshData = new Real[meshData->n_faces * 9];
284 
285  objNormCenter();
286 
287  int i;
288 #if 1
289 #ifdef _OPENMP
290  int num_threads;
291 #pragma omp parallel
292  num_threads = omp_get_num_threads(); // get number of Multi Threading
293 #pragma omp for private(i)
294 #endif
295 #endif
296  for (i = 0; i < meshData->n_faces * 3; i++) {
297  Real pcx = (is_ViewingWindow) ?
298  transVW(*(normalizedMeshData + 3 * i + _X)) : *(normalizedMeshData + 3 * i + _X);
299  Real pcy = (is_ViewingWindow) ?
300  transVW(*(normalizedMeshData + 3 * i + _Y)) : *(normalizedMeshData + 3 * i + _Y);
301  Real pcz = (is_ViewingWindow) ?
302  transVW(*(normalizedMeshData + 3 * i + _Z)) : *(normalizedMeshData + 3 * i + _Z);
303 
304  *(scaledMeshData + 3 * i + _X) = pcx * objSize + objShift[_X];
305  *(scaledMeshData + 3 * i + _Y) = pcy * objSize + objShift[_Y];
306  *(scaledMeshData + 3 * i + _Z) = pcz * objSize + objShift[_Z];
307  }
308 
309  delete[] normalizedMeshData;
310 
311  cout << "Object Scaling and Shifting Finishied.." << endl;
312 #if 1
313 #ifdef _OPENMP
314  cout << ">>> All " << num_threads << " threads" << endl;
315 #endif
316 #endif
317 }
318 
319 void ophTri::objScaleShift(Real objSize_, vector<Real> objShift_)
320 {
321  setObjSize(objSize_);
322  setObjShift(objShift_);
323 
324  scaledMeshData = new Real[meshData->n_faces * 9];
325 
326  objNormCenter();
327  int i;
328 
329 #ifdef _OPENMP
330  int num_threads;
331 #pragma omp parallel
332  num_threads = omp_get_num_threads(); // get number of Multi Threading
333 #pragma omp for private(i)
334 #endif
335  for (i = 0; i < meshData->n_faces * 3; i++) {
336  Real pcx = (is_ViewingWindow) ?
337  transVW(*(normalizedMeshData + 3 * i + _X)) : *(normalizedMeshData + 3 * i + _X);
338  Real pcy = (is_ViewingWindow) ?
339  transVW(*(normalizedMeshData + 3 * i + _Y)) : *(normalizedMeshData + 3 * i + _Y);
340  Real pcz = (is_ViewingWindow) ?
341  transVW(*(normalizedMeshData + 3 * i + _Z)) : *(normalizedMeshData + 3 * i + _Z);
342 
343  *(scaledMeshData + 3 * i + _X) = pcx * objSize + objShift[_X];
344  *(scaledMeshData + 3 * i + _Y) = pcy * objSize + objShift[_Y];
345  *(scaledMeshData + 3 * i + _Z) = pcz * objSize + objShift[_Z];
346  }
347 
348  delete[] normalizedMeshData;
349  cout << "Object Scaling and Shifting Finishied.." << endl;
350 
351 #ifdef _OPENMP
352  cout << ">>> All " << num_threads << " threads" << endl;
353 #endif
354 }
355 
356 void ophTri::objScaleShift(Real objSize_, vec3 objShift_)
357 {
358  setObjSize(objSize_);
359  setObjShift(objShift_);
360 
361  scaledMeshData = new Real[meshData->n_faces * 9];
362 
363  objNormCenter();
364  int i;
365 
366 #ifdef _OPENMP
367  int num_threads;
368 #pragma omp parallel
369  {
370  num_threads = omp_get_num_threads(); // get number of Multi Threading
371 #pragma omp for private(i)
372 #endif
373  for (i = 0; i < meshData->n_faces * 3; i++) {
374  Real pcx = (is_ViewingWindow) ?
375  transVW(*(normalizedMeshData + 3 * i + _X)) : *(normalizedMeshData + 3 * i + _X);
376  Real pcy = (is_ViewingWindow) ?
377  transVW(*(normalizedMeshData + 3 * i + _Y)) : *(normalizedMeshData + 3 * i + _Y);
378  Real pcz = (is_ViewingWindow) ?
379  transVW(*(normalizedMeshData + 3 * i + _Z)) : *(normalizedMeshData + 3 * i + _Z);
380 
381  *(scaledMeshData + 3 * i + _X) = pcx * objSize + objShift[_X];
382  *(scaledMeshData + 3 * i + _Y) = pcy * objSize + objShift[_Y];
383  *(scaledMeshData + 3 * i + _Z) = pcz * objSize + objShift[_Z];
384  }
385 
386  delete[] normalizedMeshData;
387  cout << "Object Scaling and Shifting Finishied.." << endl;
388 
389 #ifdef _OPENMP
390  }
391  cout << ">>> All " << num_threads << " threads" << endl;
392 #endif
393 }
394 
395 vec3 vecCross(const vec3& a, const vec3& b)
396 {
397  vec3 c;
398 
399  c(0) = a(0 + 1) * b(0 + 2) - a(0 + 2) * b(0 + 1);
400 
401  c(1) = a(1 + 1) * b(1 + 2) - a(1 + 2) * b(1 + 1);
402 
403  c(2) = a(2 + 1) * b(2 + 2) - a(2 + 2) * b(2 + 1);
404 
405 
406  return c;
407 }
408 
409 
411 {
412  resetBuffer();
413 
414  auto start_time = CUR_TIME;
415  LOG("1) Algorithm Method : Tri Mesh\n");
416  LOG("2) Generate Hologram with %s\n", is_CPU ?
417 #ifdef _OPENMP
418  "Multi Core CPU" :
419 #else
420  "Single Core CPU" :
421 #endif
422  "GPU");
423  LOG("3) Transform Viewing Window : %s\n", is_ViewingWindow ? "ON" : "OFF");
424 
425 
426  auto start = CUR_TIME;
427  objScaleShift();
428  (is_CPU) ? initializeAS() : initialize_GPU();
429  (is_CPU) ? generateAS(SHADING_FLAG) : generateAS_GPU(SHADING_FLAG);
430 
431  if (is_CPU) {
432  fft2(context_.pixel_number, angularSpectrum, OPH_BACKWARD, OPH_ESTIMATE);
434  /*fftExecute((*complex_H));*/
435  }
436  //fresnelPropagation(*(complex_H), *(complex_H), objShift[_Z]);
437 
438  auto end = CUR_TIME;
439  elapsedTime = ((std::chrono::duration<Real>)(end - start)).count();
440 
441  LOG("Total Elapsed Time: %lf (s)\n", elapsedTime);
442 }
443 
445  cout << "Hologram Generation ..." << endl;
446  auto start = CUR_TIME;
447  resetBuffer();
448  initializeAS();
449  generateAS(SHADING_TYPE);
450 
451  fft2(context_.pixel_number, angularSpectrum, OPH_BACKWARD, OPH_ESTIMATE);
453  //fftExecute((*complex_H));
454 
455  auto end = CUR_TIME;
456  auto during = ((std::chrono::duration<Real>)(end - start)).count();
457 
458  LOG("Total Elapsed Time: %lf (sec)\n", during);
459 }
460 
461 
462 void ophTri::generateAS(uint SHADING_FLAG)
463 {
464  Real mesh[9] = { 0.0, };
465  calGlobalFrequency();
466 
467  const uint pnX = context_.pixel_number[_X];
468  const uint pnY = context_.pixel_number[_Y];
469  const uint pnXY = pnX * pnY;
470 
471  flx = new Real[pnXY];
472  fly = new Real[pnXY];
473  flz = new Real[pnXY];
474 
475  freqTermX = new Real[pnXY];
476  freqTermY = new Real[pnXY];
477 
478  refAS = new Complex<Real>[pnXY];
479 
480  ASTerm = new Complex<Real>[pnXY];
481  randTerm = new Complex<Real>[pnXY];
482  phaseTerm = new Complex<Real>[pnXY];
483  convol = new Complex<Real>[pnXY];
484 
485  findNormals(SHADING_FLAG);
486 
487 #if 0
488  int tid;
489  int j;
490 #ifdef _OPENMP
491  int num_threads = 0;
492 #pragma omp parallel
493  {
494  num_threads = omp_get_num_threads(); // get number of Multi Threading
495  tid = omp_get_thread_num();
496 #pragma omp for private(j, tid, mesh)
497 #endif
498  //int j; // private variable for Multi Threading
499  for (j = 0; j < meshData->n_faces; j++) {
500 #if 0
501  for (int i = 0; i > 9; i++) {
502  mesh[i] = scaledMeshData[9 * j + i];
503  }
504 #else
505  memcpy(mesh, &scaledMeshData[9 * j], sizeof(Real) * 9);
506 #endif
507  if (checkValidity(mesh, *(no + j)) != 1)
508  continue;
509 
510  if (findGeometricalRelations(mesh, *(no + j)) != 1)
511  continue;
512 
513  if (calFrequencyTerm() != 1)
514  continue;
515 
516  switch (SHADING_FLAG)
517  {
518  case SHADING_FLAT:
519  refAS_Flat(*(no + j));
520  break;
521  case SHADING_CONTINUOUS:
522  refAS_Continuous(j);
523  break;
524  default:
525  LOG("error: WRONG SHADING_FLAG\n");
526  cin.get();
527  }
528  if (refToGlobal() != 1)
529  continue;
530 
531  //char szLog[MAX_PATH];
532  //sprintf(szLog, "[%d] : %d / %d\n", tid, j + 1, meshData->n_faces);
533  //LOG(szLog);
534  }
535  }
536 #else
537  //int j; // private variable for Multi Threading
538  for (int j = 0; j < meshData->n_faces; j++) {
539  memcpy(mesh, &scaledMeshData[9 * j], sizeof(Real) * 9);
540 
541  if (checkValidity(mesh, *(no + j)) != 1)
542  continue;
543 
544  if (findGeometricalRelations(mesh, *(no + j)) != 1)
545  continue;
546 
547  if (calFrequencyTerm() != 1)
548  continue;
549 
550  switch (SHADING_FLAG)
551  {
552  case SHADING_FLAT:
553  refAS_Flat(*(no + j));
554  break;
555  case SHADING_CONTINUOUS:
556  refAS_Continuous(j);
557  break;
558  default:
559  LOG("error: WRONG SHADING_FLAG\n");
560  cin.get();
561  }
562  if (refToGlobal() != 1)
563  continue;
564 
565  char szLog[MAX_PATH];
566  sprintf_s(szLog, "%d / %llu\n", j + 1, meshData->n_faces);
567  LOG(szLog);
568  }
569 #endif
570  LOG("Angular Spectrum Generated...\n");
571 
572  delete[]/* mesh, mesh_local,*/scaledMeshData, fx, fy, fz, flx, fly, flz, freqTermX, freqTermY, refAS, ASTerm, randTerm, phaseTerm, convol;
573 }
574 
575 
576 uint ophTri::findNormals(uint SHADING_FLAG)
577 {
578  no = new vec3[meshData->n_faces];
579  na = new vec3[meshData->n_faces];
580  nv = new vec3[meshData->n_faces * 3];
581 
582  for (uint num = 0; num < meshData->n_faces; num++)
583  {
584  *(no + num) = vecCross({ scaledMeshData[num * 9 + _X1] - scaledMeshData[num * 9 + _X2],
585  scaledMeshData[num * 9 + _Y1] - scaledMeshData[num * 9 + _Y2],
586  scaledMeshData[num * 9 + _Z1] - scaledMeshData[num * 9 + _Z2] },
587  { scaledMeshData[num * 9 + _X3] - scaledMeshData[num * 9 + _X2],
588  scaledMeshData[num * 9 + _Y3] - scaledMeshData[num * 9 + _Y2],
589  scaledMeshData[num * 9 + _Z3] - scaledMeshData[num * 9 + _Z2] });
590  // 'vec.h'의 cross함수가 전역으로 되어있어서 오류뜸.
591  // 'vec.h'에 extern을 하라해서 했는데 그래도 안 됨.
592  // 그래서그냥함수우선 가져옴.
593  }
594  Real normNo = 0;
595  for (uint num = 0; num < meshData->n_faces; num++) {
596  normNo = normNo + norm(no[num])*norm(no[num]);
597  }
598  normNo = sqrt(normNo);
599 
600  for (uint num = 0; num < meshData->n_faces; num++) {
601  *(na + num) = no[num] / normNo;
602  }
603 
605  vec3* vertices = new vec3[meshData->n_faces * 3];
606  vec3 zeros(0, 0, 0);
607 
608  for (uint idx = 0; idx < meshData->n_faces * 3; idx++) {
609  *(vertices + idx) = { scaledMeshData[idx * 3 + 0], scaledMeshData[idx * 3 + 1], scaledMeshData[idx * 3 + 2] };
610  }
611  for (uint idx1 = 0; idx1 < meshData->n_faces * 3; idx1++) {
612  if (*(vertices + idx1) == zeros)
613  continue;
614  vec3 sum = *(na + idx1 / 3);
615  uint count = 1;
616  uint* idxes = new uint[meshData->n_faces * 3];
617  *(idxes) = idx1;
618  for (uint idx2 = idx1 + 1; idx2 < meshData->n_faces * 3; idx2++) {
619  if (*(vertices + idx2) == zeros)
620  continue;
621  if ((vertices[idx1][0] == vertices[idx2][0])
622  & (vertices[idx1][1] == vertices[idx2][1])
623  & (vertices[idx1][2] == vertices[idx2][2])) {
624  sum += *(na + idx2 / 3);
625  *(vertices + idx2) = zeros;
626  *(idxes + count) = idx2;
627  count++;
628  }
629  }
630  *(vertices + idx1) = zeros;
631 
632  sum = sum / count;
633  sum = sum / norm(sum);
634  for (uint i = 0; i < count; i++)
635  *(nv + *(idxes + i)) = sum;
636 
637  delete[] idxes;
638  }
639 
640  delete[] vertices;
641  }
642 
643  return 1;
644 }
645 
646 uint ophTri::checkValidity(Real* mesh, vec3 no) {
647 
648  if (no[_Z] < 0 || (no[_X] == 0 && no[_Y] == 0 && no[_Z] == 0)) {
649  return -1;
650  }
651  if (no[_Z] >= 0)
652  return 1;
653 
654  return 0;
655 }
656 
657 uint ophTri::findGeometricalRelations(Real* mesh, vec3 no)
658 {
659  vec3 n = no / norm(no);
660  Real mesh_local[9] = { 0.0 };
661  Real th, ph;
662  if (n[_X] == 0 && n[_Z] == 0)
663  th = 0;
664  else
665  th = atan(n[_X] / n[_Z]);
666 
667  Real temp = n[_Y] / sqrt(n[_X] * n[_X] + n[_Z] * n[_Z]);
668  ph = atan(temp);
669  geom.glRot[0] = cos(th); geom.glRot[1] = 0; geom.glRot[2] = -sin(th);
670  geom.glRot[3] = -sin(ph)*sin(th); geom.glRot[4] = cos(ph); geom.glRot[5] = -sin(ph)*cos(th);
671  geom.glRot[6] = cos(ph)*sin(th); geom.glRot[7] = sin(ph); geom.glRot[8] = cos(ph)*cos(th);
672 
673  for_i(3,
674  mesh_local[3 * i] = geom.glRot[0] * mesh[3 * i] + geom.glRot[1] * mesh[3 * i + 1] + geom.glRot[2] * mesh[3 * i + 2];
675  mesh_local[3 * i + 1] = geom.glRot[3] * mesh[3 * i] + geom.glRot[4] * mesh[3 * i + 1] + geom.glRot[5] * mesh[3 * i + 2];
676  mesh_local[3 * i + 2] = geom.glRot[6] * mesh[3 * i] + geom.glRot[7] * mesh[3 * i + 1] + geom.glRot[8] * mesh[3 * i + 2];
677  )
678 
679  geom.glShift[_X] = -mesh_local[_X1];
680  geom.glShift[_Y] = -mesh_local[_Y1];
681  geom.glShift[_Z] = -mesh_local[_Z1];
682 
683  for_i(3,
684  mesh_local[3 * i] += geom.glShift[_X];
685  mesh_local[3 * i + 1] += geom.glShift[_Y];
686  mesh_local[3 * i + 2] += geom.glShift[_Z];
687  );
688 
689  if (mesh_local[_X3] * mesh_local[_Y2] == mesh_local[_Y3] * mesh_local[_X2])
690  return -1;
691 
692  geom.loRot[0] = (refTri[_X3] * mesh_local[_Y2] - refTri[_X2] * mesh_local[_Y3]) / (mesh_local[_X3] * mesh_local[_Y2] - mesh_local[_Y3] * mesh_local[_X2]);
693  geom.loRot[1] = (refTri[_X3] * mesh_local[_X2] - refTri[_X2] * mesh_local[_X3]) / (-mesh_local[_X3] * mesh_local[_Y2] + mesh_local[_Y3] * mesh_local[_X2]);
694  geom.loRot[2] = (refTri[_Y3] * mesh_local[_Y2] - refTri[_Y2] * mesh_local[_Y3]) / (mesh_local[_X3] * mesh_local[_Y2] - mesh_local[_Y3] * mesh_local[_X2]);
695  geom.loRot[3] = (refTri[_Y3] * mesh_local[_X2] - refTri[_Y2] * mesh_local[_X3]) / (-mesh_local[_X3] * mesh_local[_Y2] + mesh_local[_Y3] * mesh_local[_X2]);
696 
697  if ((geom.loRot[0] * geom.loRot[3] - geom.loRot[1] * geom.loRot[2]) == 0)
698  return -1;
699 
700  /*
701  cout << "global rotation" << endl;
702  for_i(9,
703  cout << geom.glRot[i] << ", ";
704  );
705  cout << endl << endl;
706 
707  cout << "global shift" << endl;
708  for_i(3,
709  cout << geom.glShift[i] << ", ";
710  );
711  cout << endl << endl;
712 
713  cout << "mesh local" << endl;
714  for_i(9,
715  cout << mesh_local[i] << ", ";
716  );
717  cout << endl << endl;
718 
719  cout << "local rotation" << endl;
720  for_i(4,
721  cout << geom.loRot[i] << ", ";
722  );
723  cout << endl << "." << endl << "." << endl << "." << endl << endl;
724 
725  cin.get();
726  */
727  return 1;
728 }
729 
730 void ophTri::calGlobalFrequency()
731 {
732  const uint pnX = context_.pixel_number[_X];
733  const uint pnY = context_.pixel_number[_Y];
734  const uint pnXY = pnX * pnY;
735  const uint nChannel = context_.waveNum;
736 
737  Real dfx = 1 / context_.pixel_pitch[_X] / pnX;
738  Real dfy = 1 / context_.pixel_pitch[_Y] / pnY;
739  fx = new Real[pnXY];
740  fy = new Real[pnXY];
741  fz = new Real[pnXY];
742  uint i = 0;
743 
744  for (uint ch = 0; ch < 1; ch++) {
745  Real lambda = context_.wave_length[ch];
746  for (uint idxFy = pnY / 2; idxFy > -pnY / 2; idxFy--) {
747  for (uint idxFx = -pnX / 2; idxFx < pnX / 2; idxFx++) {
748  fx[i] = idxFx * dfx;
749  fy[i] = idxFy * dfy;
750  fz[i] = sqrt((1 / lambda)*(1 / lambda) - fx[i] * fx[i] - fy[i] * fy[i]);
751 
752  i++;
753  }
754  }
755  }
756 }
757 
758 uint ophTri::calFrequencyTerm()
759 {
760  const uint pnX = context_.pixel_number[_X];
761  const uint pnY = context_.pixel_number[_Y];
762  const uint pnXY = pnX * pnY;
763 
764  Real* flxShifted = new Real[pnXY];
765  Real* flyShifted = new Real[pnXY];
766 
767  for_i(pnXY,
768  flx[i] = geom.glRot[0] * fx[i] + geom.glRot[1] * fy[i] + geom.glRot[2] * fz[i];
769  fly[i] = geom.glRot[3] * fx[i] + geom.glRot[4] * fy[i] + geom.glRot[5] * fz[i];
770  flz[i] = sqrt((1 / context_.wave_length[0])*(1 / context_.wave_length[0]) - flx[i] * flx[i] - fly[i] * fly[i]);
771 
772  flxShifted[i] = flx[i] - (1 / context_.wave_length[0])*(geom.glRot[0] * carrierWave[_X] + geom.glRot[1] * carrierWave[_Y] + geom.glRot[2] * carrierWave[_Z]);
773  flyShifted[i] = fly[i] - (1 / context_.wave_length[0])*(geom.glRot[3] * carrierWave[_X] + geom.glRot[4] * carrierWave[_Y] + geom.glRot[5] * carrierWave[_Z]);
774  );
775 
776  Real det = geom.loRot[0] * geom.loRot[3] - geom.loRot[1] * geom.loRot[2];
777 
778  Real* invLoRot = new Real[4];
779  invLoRot[0] = (1 / det)*geom.loRot[3];
780  invLoRot[1] = -(1 / det)*geom.loRot[2];
781  invLoRot[2] = -(1 / det)*geom.loRot[1];
782  invLoRot[3] = (1 / det)*geom.loRot[0];
783 
784  for_i(pnXY,
785  freqTermX[i] = invLoRot[0] * flxShifted[i] + invLoRot[1] * flyShifted[i];
786  freqTermY[i] = invLoRot[2] * flxShifted[i] + invLoRot[3] * flyShifted[i];
787  );
788 
789  delete[] flxShifted;
790  delete[] flyShifted;
791  delete[] invLoRot;
792  return 1;
793 }
794 
795 uint ophTri::refAS_Flat(vec3 no)
796 {
797  const uint pnX = context_.pixel_number[_X];
798  const uint pnY = context_.pixel_number[_Y];
799  const uint pnXY = pnX * pnY;
800 
801  n = no / norm(no);
802 
803  refTerm1(0,0);
804  refTerm2(0,0);
805 
806  if (illumination[_X] == 0 && illumination[_Y] == 0 && illumination[_Z] == 0) {
807  shadingFactor = 1;
808  }
809  else {
810  vec3 normIllu = illumination / norm(illumination);
811  shadingFactor = 2 * (n[_X] * normIllu[_X] + n[_Y] * normIllu[_Y] + n[_Z] * normIllu[_Z]) + 0.3;
812  if (shadingFactor < 0)
813  shadingFactor = 0;
814  }
815  for (int i = 0; i < pnXY; i++) {
816  if (freqTermX[i] == -freqTermY[i] && freqTermY[i] != 0) {
817  refTerm1[_IM] = 2 * M_PI*freqTermY[i];
818  refTerm2[_IM] = 1;
819  refAS[i] = shadingFactor*(((Complex<Real>)1 - exp(refTerm1)) / (4 * M_PI*M_PI*freqTermY[i] * freqTermY[i]) + refTerm2 / (2 * M_PI*freqTermY[i]));
820  }
821  else if (freqTermX[i] == freqTermY[i] && freqTermX[i] == 0) {
822  refAS[i] = shadingFactor * 1 / 2;
823  }
824  else if (freqTermX[i] != 0 && freqTermY[i] == 0) {
825  refTerm1[_IM] = -2 * M_PI*freqTermX[i];
826  refTerm2[_IM] = 1;
827  refAS[i] = shadingFactor*((exp(refTerm1) - (Complex<Real>)1) / (2 * M_PI*freqTermX[i] * 2 * M_PI*freqTermX[i]) + (refTerm2 * exp(refTerm1)) / (2 * M_PI*freqTermX[i]));
828  }
829  else if (freqTermX[i] == 0 && freqTermY[i] != 0) {
830  refTerm1[_IM] = 2 * M_PI*freqTermY[i];
831  refTerm2[_IM] = 1;
832  refAS[i] = shadingFactor*(((Complex<Real>)1 - exp(refTerm1)) / (4 * M_PI*M_PI*freqTermY[i] * freqTermY[i]) - refTerm2 / (2 * M_PI*freqTermY[i]));
833  }
834  else {
835  refTerm1[_IM] = -2 * M_PI*freqTermX[i];
836  refTerm2[_IM] = -2 * M_PI*(freqTermX[i] + freqTermY[i]);
837  refAS[i] = shadingFactor*((exp(refTerm1) - (Complex<Real>)1) / (4 * M_PI*M_PI*freqTermX[i] * freqTermY[i]) + ((Complex<Real>)1 - exp(refTerm2)) / (4 * M_PI*M_PI*freqTermY[i] * (freqTermX[i] + freqTermY[i])));
838  }
839  }
840 
841  //randPhaseDist(refAS);
842 
843  return 1;
844 }
845 
846 uint ophTri::refAS_Continuous(uint n)
847 {
848  const uint pnX = context_.pixel_number[_X];
849  const uint pnY = context_.pixel_number[_Y];
850  const uint pnXY = pnX * pnY;
851 
852  vec3 av(0, 0, 0);
853  av[0] = nv[3 * n + 0][0] * illumination[0] + nv[3 * n + 0][1] * illumination[1] + nv[3 * n + 0][2] * illumination[2] + 0.1;
854  av[2] = nv[3 * n + 1][0] * illumination[0] + nv[3 * n + 1][1] * illumination[1] + nv[3 * n + 1][2] * illumination[2] + 0.1;
855  av[1] = nv[3 * n + 2][0] * illumination[0] + nv[3 * n + 2][1] * illumination[1] + nv[3 * n + 2][2] * illumination[2] + 0.1;
856 
857  D1(0, 0);
858  D2(0, 0);
859  D3(0, 0);
860 
861  refTerm1(0, 0);
862  refTerm2(0, 0);
863  refTerm3(0, 0);
864 
865  for (int i = 0; i < pnXY; i++) {
866  if (freqTermX[i] == 0 && freqTermY[i] == 0) {
867  D1((Real)1 / (Real)3, 0);
868  D2((Real)1 / (Real)5, 0);
869  D3((Real)1 / (Real)2, 0);
870  }
871  else if (freqTermX[i] == 0 && freqTermY[i] != 0) {
872  refTerm1[_IM] = -2 * M_PI*freqTermY[i];
873  refTerm2[_IM] = 1;
874 
875  D1 = (refTerm1 - (Real)1)*refTerm1.exp() / (8 * M_PI*M_PI*M_PI*freqTermY[i] * freqTermY[i] * freqTermY[i])
876  - refTerm1 / (4 * M_PI*M_PI*M_PI*freqTermY[i] * freqTermY[i] * freqTermY[i]);
877  D2 = -(M_PI*freqTermY[i] + refTerm2) / (4 * M_PI*M_PI*M_PI*freqTermY[i] * freqTermY[i] * freqTermY[i])*exp(refTerm1)
878  + refTerm1 / (8 * M_PI*M_PI*M_PI*freqTermY[i] * freqTermY[i] * freqTermY[i]);
879  D3 = exp(refTerm1) / (2 * M_PI*freqTermY[i]) + ((Real)1 - refTerm2) / (2 * M_PI*freqTermY[i]);
880  }
881  else if (freqTermX[i] != 0 && freqTermY[i] == 0) {
882  refTerm1[_IM] = 4 * M_PI*M_PI*freqTermX[i] * freqTermX[i];
883  refTerm2[_IM] = 1;
884  refTerm3[_IM] = 2 * M_PI*freqTermX[i];
885 
886  D1 = (refTerm1 + 4 * M_PI*freqTermX[i] - (Real)2 * refTerm2) / (8 * M_PI*M_PI*M_PI*freqTermY[i] * freqTermY[i] * freqTermY[i])*exp(-refTerm3)
887  + refTerm2 / (4 * M_PI*M_PI*M_PI*freqTermX[i] * freqTermX[i] * freqTermX[i]);
888  D2 = (Real)1 / (Real)2 * D1;
889  D3 = ((refTerm3 + (Real)1)*exp(-refTerm3) - (Real)1) / (4 * M_PI*M_PI*freqTermX[i] * freqTermX[i]);
890  }
891  else if (freqTermX[i] == -freqTermY[i]) {
892  refTerm1[_IM] = 1;
893  refTerm2[_IM] = 2 * M_PI*freqTermX[i];
894  refTerm3[_IM] = 2 * M_PI*M_PI*freqTermX[i] * freqTermX[i];
895 
896  D1 = (-2 * M_PI*freqTermX[i] + refTerm1) / (8 * M_PI*M_PI*M_PI*freqTermX[i] * freqTermX[i] * freqTermX[i])*exp(-refTerm2)
897  - (refTerm3 + refTerm1) / (8 * M_PI*M_PI*M_PI*freqTermX[i] * freqTermX[i] * freqTermX[i]);
898  D2 = (-refTerm1) / (8 * M_PI*M_PI*M_PI*freqTermX[i] * freqTermX[i] * freqTermX[i])*exp(-refTerm2)
899  + (-refTerm3 + refTerm1 + 2 * M_PI*freqTermX[i]) / (8 * M_PI*M_PI*M_PI*freqTermX[i] * freqTermX[i] * freqTermX[i]);
900  D3 = (-refTerm1) / (4 * M_PI*M_PI*freqTermX[i] * freqTermX[i])*exp(-refTerm2)
901  + (-refTerm2 + (Real)1) / (4 * M_PI*M_PI*freqTermX[i] * freqTermX[i]);
902  }
903  else {
904  refTerm1[_IM] = -2 * M_PI*(freqTermX[i] + freqTermY[i]);
905  refTerm2[_IM] = 1;
906  refTerm3[_IM] = -2 * M_PI*freqTermX[i];
907 
908  D1 = exp(refTerm1)*(refTerm2 - 2 * M_PI*(freqTermX[i] + freqTermY[i])) / (8 * M_PI*M_PI*M_PI*freqTermY[i] * (freqTermX[i] + freqTermY[i])*(freqTermX[i] + freqTermY[i]))
909  + exp(refTerm3)*(2 * M_PI*freqTermX[i] - refTerm2) / (8 * M_PI*M_PI*M_PI*freqTermX[i] * freqTermX[i] * freqTermY[i])
910  + ((2 * freqTermX[i] + freqTermY[i])*refTerm2) / (8 * M_PI*M_PI*M_PI*freqTermX[i] * freqTermX[i] * (freqTermX[i] + freqTermY[i])*(freqTermX[i] + freqTermY[i]));
911  D2 = exp(refTerm1)*(refTerm2*(freqTermX[i] + 2 * freqTermY[i]) - 2 * M_PI*freqTermY[i] * (freqTermX[i] + freqTermY[i])) / (8 * M_PI*M_PI*M_PI*freqTermY[i] * freqTermY[i] * (freqTermX[i] + freqTermY[i])*(freqTermX[i] + freqTermY[i]))
912  + exp(refTerm3)*(-refTerm2) / (8 * M_PI*M_PI*M_PI*freqTermX[i] * freqTermY[i] * freqTermY[i])
913  + refTerm2 / (8 * M_PI*M_PI*M_PI*freqTermX[i] * (freqTermX[i] + freqTermY[i])* (freqTermX[i] + freqTermY[i]));
914  D3 = -exp(refTerm1) / (4 * M_PI*M_PI*freqTermY[i] * (freqTermX[i] + freqTermY[i]))
915  + exp(refTerm3) / (4 * M_PI*M_PI*freqTermX[i] * freqTermY[i])
916  - (Real)1 / (4 * M_PI*M_PI*freqTermX[i] * (freqTermX[i] + freqTermY[i]));
917  }
918  refAS[i] = (av[1] - av[0])*D1 + (av[2] - av[1])*D2 + av[0] * D3;
919  }
920 
921 
922  //randPhaseDist(refAS);
923 
924  return 1;
925 }
926 
927 void ophTri::randPhaseDist(Complex<Real>* AS)
928 {
929  ivec2 px = context_.pixel_number;
930 
931  fft2(px, AS, OPH_FORWARD, OPH_ESTIMATE);
932  fftwShift(AS, ASTerm, px[_X], px[_Y], OPH_FORWARD, (bool)OPH_ESTIMATE);
933  //fftExecute(ASTerm);
934 
935  Real randVal;
936  Complex<Real> phase;
937 
938  for_i(px[_X] * px[_Y],
939  randVal = rand((Real)0, (Real)1, px[_X] * px[_Y]);
940  phase[_RE] = 0;
941  phase[_IM] = 2 * M_PI*randVal;
942  phaseTerm[i] = exp(phase);
943  );
944 
945  fft2(px, phaseTerm, OPH_FORWARD, OPH_ESTIMATE);
946  fftwShift(phaseTerm, randTerm, px[_X], px[_Y], OPH_FORWARD, (bool)OPH_ESTIMATE);
947  //fftExecute(randTerm);
948 
949  for_i(px[_X] * px[_Y],
950  convol[i] = ASTerm[i] * randTerm[i];);
951 
952  fft2(px, convol, OPH_BACKWARD, OPH_ESTIMATE);
953  fftwShift(convol, AS, px[_X], px[_Y], OPH_BACKWARD, (bool)OPH_ESTIMATE);
954  //fftExecute(AS);
955 
956 }
957 
958 uint ophTri::refToGlobal()
959 {
960  int Nx = context_.pixel_number[_X];
961  int Ny = context_.pixel_number[_Y];
962 
963  Complex<Real> term1(0,0);
964  Complex<Real> term2(0,0);
965 
966  Real det = geom.loRot[0] * geom.loRot[3] - geom.loRot[1] * geom.loRot[2];
967 
968  if (det == 0)
969  return -1;
970 
971  term1[_IM] = -2 * M_PI / context_.wave_length[0]*(
972  carrierWave[_X] * (geom.glRot[0] * geom.glShift[_X] + geom.glRot[3] * geom.glShift[_Y] + geom.glRot[6] * geom.glShift[_Z])
973  + carrierWave[_Y] * (geom.glRot[1] * geom.glShift[_X] + geom.glRot[4] * geom.glShift[_Y] + geom.glRot[7] * geom.glShift[_Z])
974  + carrierWave[_Z] * (geom.glRot[2] * geom.glShift[_X] + geom.glRot[5] * geom.glShift[_Y] + geom.glRot[8] * geom.glShift[_Z]));
975  Complex<Real> temp(0,0);
976 
977  for (int i = 0; i < Nx*Ny; i++) {
978  if (fz[i] == 0)
979  temp = 0;
980  else {
981  term2[_IM] = 2 * M_PI*(flx[i] * geom.glShift[_X] + fly[i] * geom.glShift[_Y] + flz[i] * geom.glShift[_Z]);
982  temp = refAS[i] / det * exp(term1)* flz[i] / fz[i] * exp(term2);
983  }
984  if (abs(temp) > MIN_DOUBLE) {}
985  else { temp = 0; }
986  angularSpectrum[i] += temp;
987  }
988 
989  return 1;
990 }
#define OPH_BACKWARD
Definition: define.h:67
void abs(const oph::Complex< T > &src, oph::Complex< T > &dst)
Definition: function.h:112
Real glRot[9]
Definition: ophTriMesh.h:62
Real loRot[4]
Definition: ophTriMesh.h:64
int color_channels
The number of color.
Definition: ophGen.h:498
#define _X1
Definition: ophTriMesh.cpp:54
Real * wave_length
Definition: Openholo.h:69
ulonglong n_faces
The number of faces in object.
Definition: ophGen.h:496
#define for_i(iter, oper)
Definition: ophTriMesh.cpp:52
void setViewingWindow(bool is_ViewingWindow)
Set the value of a variable is_ViewingWindow(true or false)
Definition: ophTriMesh.cpp:69
SHADING_FLAG
Definition: ophTriMesh.h:199
#define _Y2
Definition: ophTriMesh.cpp:58
float Real
Definition: typedef.h:55
void initialize(void)
Initialize variables for Hologram complex field, encoded data, normalized data.
Definition: ophGen.cpp:69
#define _X3
Definition: ophTriMesh.cpp:60
#define CUR_TIME
Definition: function.h:58
Real norm(const vec2 &a)
Definition: vec.h:417
#define _Z1
Definition: ophTriMesh.cpp:56
bool checkExtension(const char *fname, const char *ext)
Functions for extension checking.
Definition: Openholo.cpp:80
#define OPH_ESTIMATE
Definition: define.h:76
void setObjSize(Real in)
SHADING_FLAT, SHADING_CONTINUOUS.
Definition: ophTriMesh.h:143
const XMLNode * FirstChild() const
Get the first child node, or null if none exists.
Definition: tinyxml2.h:761
#define _Z2
Definition: ophTriMesh.cpp:59
Real elapsedTime
Elapsed time of generate hologram.
Definition: ophGen.h:246
#define MIN_DOUBLE
Definition: define.h:132
#define _Y
Definition: define.h:84
#define _IM
Definition: complex.h:57
#define _X
Definition: define.h:80
Real glShift[3]
Definition: ophTriMesh.h:63
Openholo Triangular Mesh based CGH generation.
Definition: ophTriMesh.h:100
uint * face_idx
Face indexes.
Definition: ophGen.h:500
#define _Z3
Definition: ophTriMesh.cpp:62
oph::ivec2 pixel_number
Definition: Openholo.h:63
#define _RE
Definition: complex.h:54
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:416
bool loadMeshData(const char *fileName, const char *ext)
Mesh data load.
Definition: ophTriMesh.cpp:105
Real * vertex
Vertex array.
Definition: ophGen.h:502
void objScaleShift()
Mesh object data scaling and shifting.
Definition: ophTriMesh.cpp:277
void setObjShift(vec3 in)
Definition: ophTriMesh.h:144
#define _X2
Definition: ophTriMesh.cpp:57
uint waveNum
Definition: Openholo.h:68
Data for triangular mesh.
Definition: ophGen.h:494
#define _Y3
Definition: ophTriMesh.cpp:61
void generateHologram(uint SHADING_FLAG)
Hologram generation.
Definition: ophTriMesh.cpp:410
Real * color
Color array.
Definition: ophGen.h:504
bool readConfig(const char *fname)
load to configuration file.
Definition: ophGen.cpp:150
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2157
Real rand(const Real min, const Real max, oph::ulong _SEED_VALUE=0)
Get random Real value from min to max.
Definition: function.h:287
void setMode(bool is_CPU)
Set the value of a variable is_CPU(true or false)
Definition: ophTriMesh.cpp:64
void generateMeshHologram()
Definition: ophTriMesh.cpp:444
Real minOfArr(const std::vector< Real > &arr)
Definition: function.h:72
bool readConfig(const char *fname)
Triangular mesh basc CGH configuration file load.
Definition: ophTriMesh.cpp:137
Real maxOfArr(const std::vector< Real > &arr)
Definition: function.h:86
void resetBuffer()
reset buffer
Definition: ophGen.cpp:363
void fftwShift(Complex< Real > *src, Complex< Real > *dst, int nx, int ny, int type, bool bNormalized=false)
Convert data from the spatial domain to the frequency domain using 2D FFT on CPU. ...
Definition: Openholo.cpp:530
OphConfig context_
Definition: Openholo.h:297
#define _Y1
Definition: ophTriMesh.cpp:55
#define OPH_FORWARD
Definition: define.h:66
Complex< Real > ** complex_H
Definition: Openholo.h:298
vec3 vecCross(const vec3 &a, const vec3 &b)
Definition: ophTriMesh.cpp:395
#define _Z
Definition: define.h:88
Real sum(const vec2 &a)
Definition: vec.h:401
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
oph::vec2 pixel_pitch
Definition: Openholo.h:64