NvConcavityVolume.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. NvConcavityVolume.cpp : This is a code snippet that computes the volume of concavity of a traingle mesh.
  3. */
  4. /*!
  5. **
  6. ** Copyright (c) 2009 by John W. Ratcliff mailto:[email protected]
  7. **
  8. ** Portions of this source has been released with the PhysXViewer application, as well as
  9. ** Rocket, CreateDynamics, ODF, and as a number of sample code snippets.
  10. **
  11. ** If you find this code useful or you are feeling particularily generous I would
  12. ** ask that you please go to http://www.amillionpixels.us and make a donation
  13. ** to Troy DeMolay.
  14. **
  15. ** DeMolay is a youth group for young men between the ages of 12 and 21.
  16. ** It teaches strong moral principles, as well as leadership skills and
  17. ** public speaking. The donations page uses the 'pay for pixels' paradigm
  18. ** where, in this case, a pixel is only a single penny. Donations can be
  19. ** made for as small as $4 or as high as a $100 block. Each person who donates
  20. ** will get a link to their own site as well as acknowledgement on the
  21. ** donations blog located here http://www.amillionpixels.blogspot.com/
  22. **
  23. ** If you wish to contact me you can use the following methods:
  24. **
  25. ** Skype ID: jratcliff63367
  26. ** Yahoo: jratcliff63367
  27. ** AOL: jratcliff1961
  28. ** email: [email protected]
  29. **
  30. **
  31. ** The MIT license:
  32. **
  33. ** Permission is hereby granted, free of charge, to any person obtaining a copy
  34. ** of this software and associated documentation files (the "Software"), to deal
  35. ** in the Software without restriction, including without limitation the rights
  36. ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  37. ** copies of the Software, and to permit persons to whom the Software is furnished
  38. ** to do so, subject to the following conditions:
  39. **
  40. ** The above copyright notice and this permission notice shall be included in all
  41. ** copies or substantial portions of the Software.
  42. ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  43. ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  44. ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  45. ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  46. ** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  47. ** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  48. */
  49. #define SHOW_DEBUG 0
  50. #if SHOW_DEBUG
  51. #include "RenderDebug.h"
  52. #endif
  53. #include "NvConcavityVolume.h"
  54. #include "NvFloatMath.h"
  55. #include "NvRayCast.h"
  56. #include <stdio.h>
  57. #pragma warning(disable:4100 4189 4505 4127 4101)
  58. namespace CONVEX_DECOMPOSITION
  59. {
  60. bool raycast(const NxF32 *p1,const NxF32 *normal,NxF32 *dest,iRayCast *cast_hull,iRayCast *cast_mesh)
  61. {
  62. bool ret = true;
  63. NxF32 hit_hull[3];
  64. NxF32 hit_hullNormal[3];
  65. NxF32 hit_mesh[3];
  66. NxF32 hit_meshNormal[3];
  67. bool hitHull = cast_hull->castRay(p1,normal,hit_hull,hit_hullNormal);
  68. bool hitMesh = cast_mesh->castRay(p1,normal,hit_mesh,hit_meshNormal);
  69. if ( hitMesh )
  70. {
  71. float dot = fm_dot(normal,hit_meshNormal);
  72. if ( dot < 0 ) // skip if we hit an internal face of the mesh when projection out towards the convex hull.
  73. {
  74. ret = false;
  75. }
  76. else
  77. {
  78. NxF32 d1 = fm_distanceSquared(p1,hit_mesh);
  79. NxF32 d2 = fm_distanceSquared(p1,hit_hull);
  80. if ( d1 < d2 )
  81. {
  82. dest[0] = hit_mesh[0];
  83. dest[1] = hit_mesh[1];
  84. dest[2] = hit_mesh[2];
  85. }
  86. else
  87. {
  88. dest[0] = hit_hull[0];
  89. dest[1] = hit_hull[1];
  90. dest[2] = hit_hull[2];
  91. }
  92. }
  93. }
  94. else if ( hitHull )
  95. {
  96. dest[0] = hit_hull[0];
  97. dest[1] = hit_hull[1];
  98. dest[2] = hit_hull[2];
  99. }
  100. else
  101. {
  102. ret = false;
  103. }
  104. return ret;
  105. }
  106. void addTri(NxU32 *indices,NxU32 i1,NxU32 i2,NxU32 i3,NxU32 &tcount)
  107. {
  108. indices[tcount*3+0] = i1;
  109. indices[tcount*3+1] = i2;
  110. indices[tcount*3+2] = i3;
  111. tcount++;
  112. }
  113. NxF32 computeConcavityVolume(NxU32 vcount_hull,
  114. const NxF32 *vertices_hull,
  115. NxU32 tcount_hull,
  116. const NxU32 *indices_hull,
  117. NxU32 vcount_mesh,
  118. const NxF32 *vertices_mesh,
  119. NxU32 tcount_mesh,
  120. const NxU32 *indices_mesh)
  121. {
  122. NxF32 total_volume = 0;
  123. #if SHOW_DEBUG
  124. NVSHARE::gRenderDebug->pushRenderState();
  125. NVSHARE::gRenderDebug->setCurrentDisplayTime(150.0f);
  126. #endif
  127. iRayCast *cast_hull = createRayCast(vertices_hull,tcount_hull,indices_hull);
  128. iRayCast *cast_mesh = createRayCast(vertices_mesh,tcount_mesh,indices_mesh);
  129. const NxU32 *indices = indices_mesh;
  130. #if 0
  131. static NxU32 index = 0;
  132. NxU32 i = index++;
  133. indices = &indices[i*3];
  134. #else
  135. for (NxU32 i=0; i<tcount_mesh; i++)
  136. #endif
  137. {
  138. NxU32 i1 = indices[0];
  139. NxU32 i2 = indices[1];
  140. NxU32 i3 = indices[2];
  141. const NxF32 *p1 = &vertices_mesh[i1*3];
  142. const NxF32 *p2 = &vertices_mesh[i2*3];
  143. const NxF32 *p3 = &vertices_mesh[i3*3];
  144. NxF32 normal[3];
  145. NxF32 d = fm_computePlane(p3,p2,p1,normal);
  146. NxF32 vertices[6*3];
  147. vertices[0] = p1[0];
  148. vertices[1] = p1[1];
  149. vertices[2] = p1[2];
  150. vertices[3] = p2[0];
  151. vertices[4] = p2[1];
  152. vertices[5] = p2[2];
  153. vertices[6] = p3[0];
  154. vertices[7] = p3[1];
  155. vertices[8] = p3[2];
  156. NxF32 midPoint[3];
  157. midPoint[0] = (p1[0]+p2[0]+p3[0])/3;
  158. midPoint[1] = (p1[1]+p2[1]+p3[1])/3;
  159. midPoint[2] = (p1[2]+p2[2]+p3[2])/3;
  160. fm_lerp(midPoint,p1,&vertices[0],0.9999f);
  161. fm_lerp(midPoint,p2,&vertices[3],0.9999f);
  162. fm_lerp(midPoint,p3,&vertices[6],0.9999f);
  163. NxF32 *_p1 = &vertices[3*3];
  164. NxF32 *_p2 = &vertices[4*3];
  165. NxF32 *_p3 = &vertices[5*3];
  166. NxU32 hitCount = 0;
  167. if ( raycast(&vertices[0],normal, _p1,cast_hull,cast_mesh) ) hitCount++;
  168. if ( raycast(&vertices[3],normal, _p2,cast_hull,cast_mesh) ) hitCount++;
  169. if ( raycast(&vertices[6],normal, _p3,cast_hull,cast_mesh) ) hitCount++;
  170. // form triangle mesh!
  171. if ( hitCount == 3 )
  172. {
  173. NxU32 tcount = 0;
  174. NxU32 tindices[8*3];
  175. addTri(tindices,2,1,0,tcount);
  176. addTri(tindices,3,4,5,tcount);
  177. addTri(tindices,0,3,2,tcount);
  178. addTri(tindices,2,3,5,tcount);
  179. addTri(tindices,1,3,0,tcount);
  180. addTri(tindices,4,3,1,tcount);
  181. addTri(tindices,5,4,1,tcount);
  182. addTri(tindices,2,5,1,tcount);
  183. NxF32 volume = fm_computeMeshVolume(vertices,tcount,tindices);
  184. total_volume+=volume;
  185. #if SHOW_DEBUG
  186. NVSHARE::gRenderDebug->setCurrentColor(0x0000FF,0xFFFFFF);
  187. NVSHARE::gRenderDebug->addToCurrentState(NVSHARE::DebugRenderState::SolidWireShaded);
  188. for (NxU32 i=0; i<tcount; i++)
  189. {
  190. NxU32 i1 = tindices[i*3+0];
  191. NxU32 i2 = tindices[i*3+1];
  192. NxU32 i3 = tindices[i*3+2];
  193. const NxF32 *p1 = &vertices[i1*3];
  194. const NxF32 *p2 = &vertices[i2*3];
  195. const NxF32 *p3 = &vertices[i3*3];
  196. NVSHARE::gRenderDebug->DebugTri(p1,p2,p3);
  197. }
  198. #endif
  199. }
  200. indices+=3;
  201. }
  202. #if SHOW_DEBUG
  203. NVSHARE::gRenderDebug->popRenderState();
  204. #endif
  205. releaseRayCast(cast_hull);
  206. releaseRayCast(cast_mesh);
  207. return total_volume;
  208. }
  209. }; // end of namespace