00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #pragma once
00016 #ifndef VHACD_VHACD_H
00017 #define VHACD_VHACD_H
00018
00019 #ifdef OPENCL_FOUND
00020 #ifdef __MACH__
00021 #include <OpenCL/cl.h>
00022 #else
00023 #include <CL/cl.h>
00024 #endif
00025 #endif //OPENCL_FOUND
00026
00027 #include "vhacdMutex.h"
00028 #include "vhacdVolume.h"
00029 #include "vhacdRaycastMesh.h"
00030 #include <vector>
00031
00032 typedef std::vector< VHACD::IVHACD::Constraint > ConstraintVector;
00033
00034 #define USE_THREAD 1
00035 #define OCL_MIN_NUM_PRIMITIVES 4096
00036 #define CH_APP_MIN_NUM_PRIMITIVES 64000
00037 namespace VHACD {
00038 class VHACD : public IVHACD {
00039 public:
00041 VHACD()
00042 {
00043 #if USE_THREAD == 1 && _OPENMP
00044 m_ompNumProcessors = 2 * omp_get_num_procs();
00045 omp_set_num_threads(m_ompNumProcessors);
00046 #else //USE_THREAD == 1 && _OPENMP
00047 m_ompNumProcessors = 1;
00048 #endif //USE_THREAD == 1 && _OPENMP
00049 #ifdef CL_VERSION_1_1
00050 m_oclWorkGroupSize = 0;
00051 m_oclDevice = 0;
00052 m_oclQueue = 0;
00053 m_oclKernelComputePartialVolumes = 0;
00054 m_oclKernelComputeSum = 0;
00055 #endif //CL_VERSION_1_1
00056 Init();
00057 }
00059 ~VHACD(void)
00060 {
00061 }
00062 uint32_t GetNConvexHulls() const
00063 {
00064 return (uint32_t)m_convexHulls.Size();
00065 }
00066 void Cancel()
00067 {
00068 SetCancel(true);
00069 }
00070 void GetConvexHull(const uint32_t index, ConvexHull& ch) const
00071 {
00072 Mesh* mesh = m_convexHulls[index];
00073 ch.m_nPoints = (uint32_t)mesh->GetNPoints();
00074 ch.m_nTriangles = (uint32_t)mesh->GetNTriangles();
00075 ch.m_points = mesh->GetPoints();
00076 ch.m_triangles = (uint32_t *)mesh->GetTriangles();
00077 ch.m_volume = mesh->ComputeVolume();
00078 Vec3<double> ¢er = mesh->ComputeCenter();
00079 ch.m_center[0] = center.X();
00080 ch.m_center[1] = center.Y();
00081 ch.m_center[2] = center.Z();
00082 }
00083 void Clean(void)
00084 {
00085 if (mRaycastMesh)
00086 {
00087 mRaycastMesh->release();
00088 mRaycastMesh = nullptr;
00089 }
00090 delete m_volume;
00091 delete m_pset;
00092 size_t nCH = m_convexHulls.Size();
00093 for (size_t p = 0; p < nCH; ++p) {
00094 delete m_convexHulls[p];
00095 }
00096 m_convexHulls.Clear();
00097 Init();
00098 }
00099 void Release(void)
00100 {
00101 delete this;
00102 }
00103 bool Compute(const float* const points,
00104 const uint32_t nPoints,
00105 const uint32_t* const triangles,
00106 const uint32_t nTriangles,
00107 const Parameters& params);
00108 bool Compute(const double* const points,
00109 const uint32_t nPoints,
00110 const uint32_t* const triangles,
00111 const uint32_t nTriangles,
00112 const Parameters& params);
00113 bool OCLInit(void* const oclDevice,
00114 IUserLogger* const logger = 0);
00115 bool OCLRelease(IUserLogger* const logger = 0);
00116
00117 virtual bool ComputeCenterOfMass(double centerOfMass[3]) const;
00118
00119
00120
00121
00122 virtual uint32_t ComputeConstraints(void);
00123
00124
00125
00126 virtual const Constraint *GetConstraint(uint32_t index) const;
00127
00128 private:
00129 void SetCancel(bool cancel)
00130 {
00131 m_cancelMutex.Lock();
00132 m_cancel = cancel;
00133 m_cancelMutex.Unlock();
00134 }
00135 bool GetCancel()
00136 {
00137
00138 m_cancelMutex.Lock();
00139 bool cancel = m_cancel;
00140 m_cancelMutex.Unlock();
00141 return cancel;
00142 }
00143 void Update(const double stageProgress,
00144 const double operationProgress,
00145 const Parameters& params)
00146 {
00147 m_stageProgress = stageProgress;
00148 m_operationProgress = operationProgress;
00149 if (params.m_callback) {
00150 params.m_callback->Update(m_overallProgress,
00151 m_stageProgress,
00152 m_operationProgress,
00153 m_stage.c_str(),
00154 m_operation.c_str());
00155 }
00156 }
00157 void Init()
00158 {
00159 if (mRaycastMesh)
00160 {
00161 mRaycastMesh->release();
00162 mRaycastMesh = nullptr;
00163 }
00164 memset(m_rot, 0, sizeof(double) * 9);
00165 m_dim = 64;
00166 m_volume = 0;
00167 m_volumeCH0 = 0.0;
00168 m_pset = 0;
00169 m_overallProgress = 0.0;
00170 m_stageProgress = 0.0;
00171 m_operationProgress = 0.0;
00172 m_stage = "";
00173 m_operation = "";
00174 m_barycenter[0] = m_barycenter[1] = m_barycenter[2] = 0.0;
00175 m_rot[0][0] = m_rot[1][1] = m_rot[2][2] = 1.0;
00176 SetCancel(false);
00177 }
00178 void ComputePrimitiveSet(const Parameters& params);
00179 void ComputeACD(const Parameters& params);
00180 void MergeConvexHulls(const Parameters& params);
00181 void SimplifyConvexHull(Mesh* const ch, const size_t nvertices, const double minVolume);
00182 void SimplifyConvexHulls(const Parameters& params);
00183 void ComputeBestClippingPlane(const PrimitiveSet* inputPSet,
00184 const double volume,
00185 const SArray<Plane>& planes,
00186 const Vec3<double>& preferredCuttingDirection,
00187 const double w,
00188 const double alpha,
00189 const double beta,
00190 const int32_t convexhullDownsampling,
00191 const double progress0,
00192 const double progress1,
00193 Plane& bestPlane,
00194 double& minConcavity,
00195 const Parameters& params);
00196 template <class T>
00197 void AlignMesh(const T* const points,
00198 const uint32_t stridePoints,
00199 const uint32_t nPoints,
00200 const int32_t* const triangles,
00201 const uint32_t strideTriangles,
00202 const uint32_t nTriangles,
00203 const Parameters& params)
00204 {
00205 if (GetCancel() || !params.m_pca) {
00206 return;
00207 }
00208 m_timer.Tic();
00209
00210 m_stage = "Align mesh";
00211 m_operation = "Voxelization";
00212
00213 std::ostringstream msg;
00214 if (params.m_logger) {
00215 msg << "+ " << m_stage << std::endl;
00216 params.m_logger->Log(msg.str().c_str());
00217 }
00218
00219 Update(0.0, 0.0, params);
00220 if (GetCancel()) {
00221 return;
00222 }
00223 m_dim = (size_t)(pow((double)params.m_resolution, 1.0 / 3.0) + 0.5);
00224 Volume volume;
00225 volume.Voxelize(points, stridePoints, nPoints,
00226 triangles, strideTriangles, nTriangles,
00227 m_dim, m_barycenter, m_rot);
00228 size_t n = volume.GetNPrimitivesOnSurf() + volume.GetNPrimitivesInsideSurf();
00229 Update(50.0, 100.0, params);
00230
00231 if (params.m_logger) {
00232 msg.str("");
00233 msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl;
00234 params.m_logger->Log(msg.str().c_str());
00235 }
00236 if (GetCancel()) {
00237 return;
00238 }
00239 m_operation = "PCA";
00240 Update(50.0, 0.0, params);
00241 volume.AlignToPrincipalAxes(m_rot);
00242 m_overallProgress = 1.0;
00243 Update(100.0, 100.0, params);
00244
00245 m_timer.Toc();
00246 if (params.m_logger) {
00247 msg.str("");
00248 msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
00249 params.m_logger->Log(msg.str().c_str());
00250 }
00251 }
00252 template <class T>
00253 void VoxelizeMesh(const T* const points,
00254 const uint32_t stridePoints,
00255 const uint32_t nPoints,
00256 const int32_t* const triangles,
00257 const uint32_t strideTriangles,
00258 const uint32_t nTriangles,
00259 const Parameters& params)
00260 {
00261 if (GetCancel()) {
00262 return;
00263 }
00264
00265 m_timer.Tic();
00266 m_stage = "Voxelization";
00267
00268 std::ostringstream msg;
00269 if (params.m_logger) {
00270 msg << "+ " << m_stage << std::endl;
00271 params.m_logger->Log(msg.str().c_str());
00272 }
00273
00274 delete m_volume;
00275 m_volume = 0;
00276 int32_t iteration = 0;
00277 const int32_t maxIteration = 5;
00278 double progress = 0.0;
00279 while (iteration++ < maxIteration && !m_cancel) {
00280 msg.str("");
00281 msg << "Iteration " << iteration;
00282 m_operation = msg.str();
00283
00284 progress = iteration * 100.0 / maxIteration;
00285 Update(progress, 0.0, params);
00286
00287 m_volume = new Volume;
00288 m_volume->Voxelize(points, stridePoints, nPoints,
00289 triangles, strideTriangles, nTriangles,
00290 m_dim, m_barycenter, m_rot);
00291
00292 Update(progress, 100.0, params);
00293
00294 size_t n = m_volume->GetNPrimitivesOnSurf() + m_volume->GetNPrimitivesInsideSurf();
00295 if (params.m_logger) {
00296 msg.str("");
00297 msg << "\t dim = " << m_dim << "\t-> " << n << " voxels" << std::endl;
00298 params.m_logger->Log(msg.str().c_str());
00299 }
00300
00301 double a = pow((double)(params.m_resolution) / n, 0.33);
00302 size_t dim_next = (size_t)(m_dim * a + 0.5);
00303 if (n < params.m_resolution && iteration < maxIteration && m_volume->GetNPrimitivesOnSurf() < params.m_resolution / 8 && m_dim != dim_next) {
00304 delete m_volume;
00305 m_volume = 0;
00306 m_dim = dim_next;
00307 }
00308 else {
00309 break;
00310 }
00311 }
00312 m_overallProgress = 10.0;
00313 Update(100.0, 100.0, params);
00314
00315 m_timer.Toc();
00316 if (params.m_logger) {
00317 msg.str("");
00318 msg << "\t time " << m_timer.GetElapsedTime() / 1000.0 << "s" << std::endl;
00319 params.m_logger->Log(msg.str().c_str());
00320 }
00321 }
00322 template <class T>
00323 bool ComputeACD(const T* const points,
00324 const uint32_t nPoints,
00325 const uint32_t* const triangles,
00326 const uint32_t nTriangles,
00327 const Parameters& params)
00328 {
00329 Init();
00330 if (params.m_projectHullVertices)
00331 {
00332 mRaycastMesh = RaycastMesh::createRaycastMesh(nPoints, points, nTriangles, (const uint32_t *)triangles);
00333 }
00334 if (params.m_oclAcceleration) {
00335
00336 }
00337 AlignMesh(points, 3, nPoints, (int32_t *)triangles, 3, nTriangles, params);
00338 VoxelizeMesh(points, 3, nPoints, (int32_t *)triangles, 3, nTriangles, params);
00339 ComputePrimitiveSet(params);
00340 ComputeACD(params);
00341 MergeConvexHulls(params);
00342 SimplifyConvexHulls(params);
00343 if (params.m_oclAcceleration) {
00344
00345 }
00346 if (GetCancel()) {
00347 Clean();
00348 return false;
00349 }
00350 return true;
00351 }
00352
00353 private:
00354 RaycastMesh *mRaycastMesh{ nullptr };
00355 SArray<Mesh*> m_convexHulls;
00356 std::string m_stage;
00357 std::string m_operation;
00358 double m_overallProgress;
00359 double m_stageProgress;
00360 double m_operationProgress;
00361 double m_rot[3][3];
00362 double m_volumeCH0;
00363 Vec3<double> m_barycenter;
00364 Timer m_timer;
00365 size_t m_dim;
00366 Volume* m_volume;
00367 PrimitiveSet* m_pset;
00368 Mutex m_cancelMutex;
00369 bool m_cancel;
00370 int32_t m_ompNumProcessors;
00371 #ifdef CL_VERSION_1_1
00372 cl_device_id* m_oclDevice;
00373 cl_context m_oclContext;
00374 cl_program m_oclProgram;
00375 cl_command_queue* m_oclQueue;
00376 cl_kernel* m_oclKernelComputePartialVolumes;
00377 cl_kernel* m_oclKernelComputeSum;
00378 size_t m_oclWorkGroupSize;
00379 #endif //CL_VERSION_1_1
00380 ConstraintVector mConstraints;
00381 };
00382 }
00383 #endif // VHACD_VHACD_H