Main Page   Class List   Class Members  

  • Main Page
  • User's Guide
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

sdk/extensions/authoring/source/VHACD/inc/vhacdVHACD.h

Go to the documentation of this file.
00001 /* Copyright (c) 2011 Khaled Mamou (kmamou at gmail dot com)
00002 All rights reserved.
00003 
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
00006 
00007 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00008 
00009 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.
00010 
00011 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
00012 
00013 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.
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> &center = 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     // Will analyze the HACD results and compute the constraints solutions.
00120     // It will analyze the point at which any two convex hulls touch each other and 
00121     // return the total number of constraint pairs found
00122     virtual uint32_t ComputeConstraints(void);
00123 
00124     // Returns a pointer to the constraint index; null if the index is not valid or
00125     // the user did not previously call 'ComputeConstraints' 
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             // build kernels
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             // Release kernels
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
Copyright © 2015-2017 NVIDIA Corporation, 2701 San Tomas Expressway, Santa Clara, CA 95050 U.S.A. All rights reserved. www.nvidia.com