vhacdVHACD.h
Go to the documentation of this file.
1 /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
2 All rights reserved.
3 
4 
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 
7 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 
9 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10 
11 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
12 
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14 */
15 #pragma once
16 #ifndef VHACD_VHACD_H
17 #define VHACD_VHACD_H
18 
19 #ifdef OPENCL_FOUND
20 #ifdef __MACH__
21 #include <OpenCL/cl.h>
22 #else
23 #include <CL/cl.h>
24 #endif
25 #endif //OPENCL_FOUND
26 
27 #include "vhacdMutex.h"
28 #include "vhacdVolume.h"
29 #include "vhacdRaycastMesh.h"
30 #include <vector>
31 
32 typedef std::vector< VHACD::IVHACD::Constraint > ConstraintVector;
33 
34 #define USE_THREAD 1
35 #define OCL_MIN_NUM_PRIMITIVES 4096
36 #define CH_APP_MIN_NUM_PRIMITIVES 64000
37 namespace VHACD {
38 class VHACD : public IVHACD {
39 public:
42  {
43 #if USE_THREAD == 1 && _OPENMP
44  m_ompNumProcessors = 2 * omp_get_num_procs();
45  omp_set_num_threads(m_ompNumProcessors);
46 #else //USE_THREAD == 1 && _OPENMP
47  m_ompNumProcessors = 1;
48 #endif //USE_THREAD == 1 && _OPENMP
49 #ifdef CL_VERSION_1_1
50  m_oclWorkGroupSize = 0;
51  m_oclDevice = 0;
52  m_oclQueue = 0;
53  m_oclKernelComputePartialVolumes = 0;
54  m_oclKernelComputeSum = 0;
55 #endif //CL_VERSION_1_1
56  Init();
57  }
59  ~VHACD(void)
60  {
61  }
62  uint32_t GetNConvexHulls() const
63  {
64  return (uint32_t)m_convexHulls.Size();
65  }
66  void Cancel()
67  {
68  SetCancel(true);
69  }
70  void GetConvexHull(const uint32_t index, ConvexHull& ch) const
71  {
72  Mesh* mesh = m_convexHulls[index];
73  ch.m_nPoints = (uint32_t)mesh->GetNPoints();
74  ch.m_nTriangles = (uint32_t)mesh->GetNTriangles();
75  ch.m_points = mesh->GetPoints();
76  ch.m_triangles = (uint32_t *)mesh->GetTriangles();
77  ch.m_volume = mesh->ComputeVolume();
78  Vec3<double> &center = mesh->ComputeCenter();
79  ch.m_center[0] = center.X();
80  ch.m_center[1] = center.Y();
81  ch.m_center[2] = center.Z();
82  }
83  void Clean(void)
84  {
85  if (mRaycastMesh)
86  {
87  mRaycastMesh->release();
88  mRaycastMesh = nullptr;
89  }
90  delete m_volume;
91  delete m_pset;
92  size_t nCH = m_convexHulls.Size();
93  for (size_t p = 0; p < nCH; ++p) {
94  delete m_convexHulls[p];
95  }
96  m_convexHulls.Clear();
97  Init();
98  }
99  void Release(void)
100  {
101  delete this;
102  }
103  bool Compute(const float* const points,
104  const uint32_t nPoints,
105  const uint32_t* const triangles,
106  const uint32_t nTriangles,
107  const Parameters& params);
108  bool Compute(const double* const points,
109  const uint32_t nPoints,
110  const uint32_t* const triangles,
111  const uint32_t nTriangles,
112  const Parameters& params);
113  bool OCLInit(void* const oclDevice,
114  IUserLogger* const logger = 0);
115  bool OCLRelease(IUserLogger* const logger = 0);
116 
117  virtual bool ComputeCenterOfMass(double centerOfMass[3]) const;
118 
119  // Will analyze the HACD results and compute the constraints solutions.
120  // It will analyze the point at which any two convex hulls touch each other and
121  // return the total number of constraint pairs found
122  virtual uint32_t ComputeConstraints(void);
123 
124  // Returns a pointer to the constraint index; null if the index is not valid or
125  // the user did not previously call 'ComputeConstraints'
126  virtual const Constraint *GetConstraint(uint32_t index) const;
127 
128 private:
129  void SetCancel(bool cancel)
130  {
131  m_cancelMutex.Lock();
132  m_cancel = cancel;
133  m_cancelMutex.Unlock();
134  }
135  bool GetCancel()
136  {
137 
138  m_cancelMutex.Lock();
139  bool cancel = m_cancel;
140  m_cancelMutex.Unlock();
141  return cancel;
142  }
143  void Update(const double stageProgress,
144  const double operationProgress,
145  const Parameters& params)
146  {
147  m_stageProgress = stageProgress;
148  m_operationProgress = operationProgress;
149  if (params.m_callback) {
150  params.m_callback->Update(m_overallProgress,
151  m_stageProgress,
152  m_operationProgress,
153  m_stage.c_str(),
154  m_operation.c_str());
155  }
156  }
157  void Init()
158  {
159  if (mRaycastMesh)
160  {
161  mRaycastMesh->release();
162  mRaycastMesh = nullptr;
163  }
164  memset(m_rot, 0, sizeof(double) * 9);
165  m_dim = 64;
166  m_volume = 0;
167  m_volumeCH0 = 0.0;
168  m_pset = 0;
169  m_overallProgress = 0.0;
170  m_stageProgress = 0.0;
171  m_operationProgress = 0.0;
172  m_stage = "";
173  m_operation = "";
174  m_barycenter[0] = m_barycenter[1] = m_barycenter[2] = 0.0;
175  m_rot[0][0] = m_rot[1][1] = m_rot[2][2] = 1.0;
176  SetCancel(false);
177  }
178  void ComputePrimitiveSet(const Parameters& params);
179  void ComputeACD(const Parameters& params);
180  void MergeConvexHulls(const Parameters& params);
181  void SimplifyConvexHull(Mesh* const ch, const size_t nvertices, const double minVolume);
182  void SimplifyConvexHulls(const Parameters& params);
183  void ComputeBestClippingPlane(const PrimitiveSet* inputPSet,
184  const double volume,
185  const SArray<Plane>& planes,
186  const Vec3<double>& preferredCuttingDirection,
187  const double w,
188  const double alpha,
189  const double beta,
190  const int32_t convexhullDownsampling,
191  const double progress0,
192  const double progress1,
193  Plane& bestPlane,
194  double& minConcavity,
195  const Parameters& params);
196  template <class T>
197  void AlignMesh(const T* const points,
198  const uint32_t stridePoints,
199  const uint32_t nPoints,
200  const int32_t* const triangles,
201  const uint32_t strideTriangles,
202  const uint32_t nTriangles,
203  const Parameters& params)
204  {
205  if (GetCancel() || !params.m_pca) {
206  return;
207  }
208  m_timer.Tic();
209 
210  m_stage = "Align mesh";
211  m_operation = "Voxelization";
212 
213  std::ostringstream msg;
214  if (params.m_logger) {
215  msg << "+ " << m_stage << std::endl;
216  params.m_logger->Log(msg.str().c_str());
217  }
218 
219  Update(0.0, 0.0, params);
220  if (GetCancel()) {
221  return;
222  }
223  m_dim = (size_t)(pow((double)params.m_resolution, 1.0 / 3.0) + 0.5);
224  Volume volume;
225  volume.Voxelize(points, stridePoints, nPoints,
226  triangles, strideTriangles, nTriangles,
227  m_dim, m_barycenter, m_rot);
228  size_t n = volume.GetNPrimitivesOnSurf() + volume.GetNPrimitivesInsideSurf();
229  Update(50.0, 100.0, params);
230 
231  if (params.m_logger) {
232  msg.str("");
233  msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl;
234  params.m_logger->Log(msg.str().c_str());
235  }
236  if (GetCancel()) {
237  return;
238  }
239  m_operation = "PCA";
240  Update(50.0, 0.0, params);
241  volume.AlignToPrincipalAxes(m_rot);
242  m_overallProgress = 1.0;
243  Update(100.0, 100.0, params);
244 
245  m_timer.Toc();
246  if (params.m_logger) {
247  msg.str("");
248  msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
249  params.m_logger->Log(msg.str().c_str());
250  }
251  }
252  template <class T>
253  void VoxelizeMesh(const T* const points,
254  const uint32_t stridePoints,
255  const uint32_t nPoints,
256  const int32_t* const triangles,
257  const uint32_t strideTriangles,
258  const uint32_t nTriangles,
259  const Parameters& params)
260  {
261  if (GetCancel()) {
262  return;
263  }
264 
265  m_timer.Tic();
266  m_stage = "Voxelization";
267 
268  std::ostringstream msg;
269  if (params.m_logger) {
270  msg << "+ " << m_stage << std::endl;
271  params.m_logger->Log(msg.str().c_str());
272  }
273 
274  delete m_volume;
275  m_volume = 0;
276  int32_t iteration = 0;
277  const int32_t maxIteration = 5;
278  double progress = 0.0;
279  while (iteration++ < maxIteration && !m_cancel) {
280  msg.str("");
281  msg << "Iteration " << iteration;
282  m_operation = msg.str();
283 
284  progress = iteration * 100.0 / maxIteration;
285  Update(progress, 0.0, params);
286 
287  m_volume = new Volume;
288  m_volume->Voxelize(points, stridePoints, nPoints,
289  triangles, strideTriangles, nTriangles,
290  m_dim, m_barycenter, m_rot);
291 
292  Update(progress, 100.0, params);
293 
294  size_t n = m_volume->GetNPrimitivesOnSurf() + m_volume->GetNPrimitivesInsideSurf();
295  if (params.m_logger) {
296  msg.str("");
297  msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl;
298  params.m_logger->Log(msg.str().c_str());
299  }
300 
301  double a = pow((double)(params.m_resolution) / n, 0.33);
302  size_t dim_next = (size_t)(m_dim * a + 0.5);
303  if (n < params.m_resolution && iteration < maxIteration && m_volume->GetNPrimitivesOnSurf() < params.m_resolution / 8 && m_dim != dim_next) {
304  delete m_volume;
305  m_volume = 0;
306  m_dim = dim_next;
307  }
308  else {
309  break;
310  }
311  }
312  m_overallProgress = 10.0;
313  Update(100.0, 100.0, params);
314 
315  m_timer.Toc();
316  if (params.m_logger) {
317  msg.str("");
318  msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
319  params.m_logger->Log(msg.str().c_str());
320  }
321  }
322  template <class T>
323  bool ComputeACD(const T* const points,
324  const uint32_t nPoints,
325  const uint32_t* const triangles,
326  const uint32_t nTriangles,
327  const Parameters& params)
328  {
329  Init();
330  if (params.m_projectHullVertices)
331  {
332  mRaycastMesh = RaycastMesh::createRaycastMesh(nPoints, points, nTriangles, (const uint32_t *)triangles);
333  }
334  if (params.m_oclAcceleration) {
335  // build kernels
336  }
337  AlignMesh(points, 3, nPoints, (int32_t *)triangles, 3, nTriangles, params);
338  VoxelizeMesh(points, 3, nPoints, (int32_t *)triangles, 3, nTriangles, params);
339  ComputePrimitiveSet(params);
340  ComputeACD(params);
341  MergeConvexHulls(params);
342  SimplifyConvexHulls(params);
343  if (params.m_oclAcceleration) {
344  // Release kernels
345  }
346  if (GetCancel()) {
347  Clean();
348  return false;
349  }
350  return true;
351  }
352 
353 private:
354  RaycastMesh *mRaycastMesh{ nullptr };
355  SArray<Mesh*> m_convexHulls;
356  std::string m_stage;
357  std::string m_operation;
358  double m_overallProgress;
359  double m_stageProgress;
360  double m_operationProgress;
361  double m_rot[3][3];
362  double m_volumeCH0;
363  Vec3<double> m_barycenter;
364  Timer m_timer;
365  size_t m_dim;
366  Volume* m_volume;
367  PrimitiveSet* m_pset;
368  Mutex m_cancelMutex;
369  bool m_cancel;
370  int32_t m_ompNumProcessors;
371 #ifdef CL_VERSION_1_1
372  cl_device_id* m_oclDevice;
373  cl_context m_oclContext;
374  cl_program m_oclProgram;
375  cl_command_queue* m_oclQueue;
376  cl_kernel* m_oclKernelComputePartialVolumes;
377  cl_kernel* m_oclKernelComputeSum;
378  size_t m_oclWorkGroupSize;
379 #endif //CL_VERSION_1_1
380  ConstraintVector mConstraints;
381 };
382 }
383 #endif // VHACD_VHACD_H
Definition: VHACD.h:56
Vec3< double > & ComputeCenter(void)
void AlignToPrincipalAxes(double(&rot)[3][3]) const
Definition: VHACD.h:43
const size_t GetNPrimitivesInsideSurf() const
Definition: vhacdVolume.h:239
Definition: vhacdMutex.h:88
uint32_t * m_triangles
Definition: VHACD.h:65
std::vector< VHACD::IVHACD::Constraint > ConstraintVector
Definition: vhacdVHACD.h:32
void Clean(void)
Definition: vhacdVHACD.h:83
Definition: vhacdMesh.h:29
double ComputeVolume() const
size_t GetNTriangles() const
Definition: vhacdMesh.h:80
IUserCallback * m_callback
Definition: VHACD.h:98
SArray.
Definition: vhacdSArray.h:27
double m_center[3]
Definition: VHACD.h:69
virtual void Log(const char *const msg)=0
VHACD()
Constructor.
Definition: vhacdVHACD.h:41
uint32_t m_resolution
Definition: VHACD.h:100
Triangular mesh data structure.
Definition: vhacdMesh.h:65
Definition: VHACD.h:112
int32_t * GetTriangles()
Definition: vhacdMesh.h:81
Definition: vhacdRaycastMesh.h:12
double * GetPoints()
Definition: vhacdMesh.h:72
const size_t GetNPrimitivesOnSurf() const
Definition: vhacdVolume.h:238
Definition: vhacdCircularList.h:19
double m_volume
Definition: VHACD.h:68
Definition: VHACD.h:72
uint32_t m_pca
Definition: VHACD.h:104
Definition: vhacdVolume.h:42
Definition: vhacdTimer.h:95
uint32_t m_oclAcceleration
Definition: VHACD.h:107
Definition: vhacdVolume.h:211
size_t GetNPoints() const
Definition: vhacdMesh.h:71
void GetConvexHull(const uint32_t index, ConvexHull &ch) const
Definition: vhacdVHACD.h:70
static RaycastMesh * createRaycastMesh(uint32_t vcount, const double *vertices, uint32_t tcount, const uint32_t *indices)
uint32_t GetNConvexHulls() const
Definition: vhacdVHACD.h:62
bool m_projectHullVertices
Definition: VHACD.h:109
uint32_t m_nTriangles
Definition: VHACD.h:67
~VHACD(void)
Destructor.
Definition: vhacdVHACD.h:59
uint32_t m_nPoints
Definition: VHACD.h:66
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btVector3.h:281
virtual void Update(const double overallProgress, const double stageProgress, const double operationProgress, const char *const stage, const char *const operation)=0
Definition: VHACD.h:62
double * m_points
Definition: VHACD.h:64
void Release(void)
Definition: vhacdVHACD.h:99
void Cancel()
Definition: vhacdVHACD.h:66
IUserLogger * m_logger
Definition: VHACD.h:99
void Voxelize(const T *const points, const uint32_t stridePoints, const uint32_t nPoints, const int32_t *const triangles, const uint32_t strideTriangles, const uint32_t nTriangles, const size_t dim, const Vec3< double > &barycenter, const double(&rot)[3][3])
Voxelize.
Definition: vhacdVolume.h:308