collision_trimesh_plane.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*************************************************************************
  2. * *
  3. * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
  4. * All rights reserved. Email: [email protected] Web: www.q12.org *
  5. * *
  6. * This library is free software; you can redistribute it and/or *
  7. * modify it under the terms of EITHER: *
  8. * (1) The GNU Lesser General Public License as published by the Free *
  9. * Software Foundation; either version 2.1 of the License, or (at *
  10. * your option) any later version. The text of the GNU Lesser *
  11. * General Public License is included with this library in the *
  12. * file LICENSE.TXT. *
  13. * (2) The BSD-style license that is included with this library in *
  14. * the file LICENSE-BSD.TXT. *
  15. * *
  16. * This library is distributed in the hope that it will be useful, *
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
  19. * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
  20. * *
  21. *************************************************************************/
  22. // TriMesh - Plane collider by David Walters, July 2006
  23. #include <ode/collision.h>
  24. #include <ode/rotation.h>
  25. #include "config.h"
  26. #include "matrix.h"
  27. #include "odemath.h"
  28. #if dTRIMESH_ENABLED
  29. #include "collision_util.h"
  30. #include "collision_std.h"
  31. #include "collision_trimesh_internal.h"
  32. #if dTRIMESH_OPCODE
  33. int dCollideTrimeshPlane( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contacts, int skip )
  34. {
  35. dIASSERT( skip >= (int)sizeof( dContactGeom ) );
  36. dIASSERT( o1->type == dTriMeshClass );
  37. dIASSERT( o2->type == dPlaneClass );
  38. dIASSERT ((flags & NUMC_MASK) >= 1);
  39. // Alias pointers to the plane and trimesh
  40. dxTriMesh* trimesh = (dxTriMesh*)( o1 );
  41. dxPlane* plane = (dxPlane*)( o2 );
  42. int contact_count = 0;
  43. // Cache the maximum contact count.
  44. const int contact_max = ( flags & NUMC_MASK );
  45. // Cache trimesh position and rotation.
  46. const dVector3& trimesh_pos = *(const dVector3*)dGeomGetPosition( trimesh );
  47. const dMatrix3& trimesh_R = *(const dMatrix3*)dGeomGetRotation( trimesh );
  48. //
  49. // For all triangles.
  50. //
  51. VertexPointersEx VPE;
  52. VertexPointers &VP = VPE.vp;
  53. ConversionArea VC;
  54. dReal alpha;
  55. dVector3 vertex;
  56. #if !defined(dSINGLE) || 1
  57. dVector3 int_vertex; // Intermediate vertex for double precision mode.
  58. #endif // dSINGLE
  59. const unsigned uiTLSKind = trimesh->getParentSpaceTLSKind();
  60. dIASSERT(uiTLSKind == plane->getParentSpaceTLSKind()); // The colliding spaces must use matching cleanup method
  61. TrimeshCollidersCache *pccColliderCache = GetTrimeshCollidersCache(uiTLSKind);
  62. VertexUseCache &vertex_use_cache = pccColliderCache->m_VertexUses;
  63. // Reallocate vertex use cache if necessary
  64. const dxTriMeshData *meshData = trimesh->retrieveMeshData();
  65. const int vertex_count = meshData->m_Mesh.GetNbVertices();
  66. const bool cache_status = vertex_use_cache.resizeAndResetVertexUSEDFlags(vertex_count);
  67. // Cache the triangle count.
  68. const int tri_count = meshData->m_Mesh.GetNbTriangles();
  69. // For each triangle
  70. for ( int t = 0; t < tri_count; ++t )
  71. {
  72. // Get triangle, which should also use callback.
  73. bool ex_avail = meshData->m_Mesh.GetExTriangle( VPE, t, VC);
  74. // For each vertex.
  75. for ( int v = 0; v < 3; ++v )
  76. {
  77. // point already used ?
  78. if (cache_status && ex_avail)
  79. {
  80. unsigned VIndex = VPE.Index[v];
  81. if (vertex_use_cache.getVertexUSEDFlag(VIndex))
  82. continue;
  83. // mark this point as used
  84. vertex_use_cache.setVertexUSEDFlag(VIndex);
  85. }
  86. //
  87. // Get Vertex
  88. //
  89. #if defined(dSINGLE) && 0 // Always assign via intermediate array as otherwise it is an incapsulation violation
  90. dMultiply0_331( vertex, trimesh_R, (float*)( VP.Vertex[ v ] ) );
  91. #else // dDOUBLE || 1
  92. // OPCODE data is in single precision format.
  93. int_vertex[ 0 ] = VP.Vertex[ v ]->x;
  94. int_vertex[ 1 ] = VP.Vertex[ v ]->y;
  95. int_vertex[ 2 ] = VP.Vertex[ v ]->z;
  96. dMultiply0_331( vertex, trimesh_R, int_vertex );
  97. #endif // dSINGLE/dDOUBLE
  98. vertex[ 0 ] += trimesh_pos[ 0 ];
  99. vertex[ 1 ] += trimesh_pos[ 1 ];
  100. vertex[ 2 ] += trimesh_pos[ 2 ];
  101. //
  102. // Collision?
  103. //
  104. // If alpha < 0 then point is if front of plane. i.e. no contact
  105. // If alpha = 0 then the point is on the plane
  106. alpha = plane->p[ 3 ] - dCalcVectorDot3( plane->p, vertex );
  107. // If alpha > 0 the point is behind the plane. CONTACT!
  108. if ( alpha > 0 )
  109. {
  110. // Alias the contact
  111. dContactGeom* contact = SAFECONTACT( flags, contacts, contact_count, skip );
  112. contact->pos[ 0 ] = vertex[ 0 ];
  113. contact->pos[ 1 ] = vertex[ 1 ];
  114. contact->pos[ 2 ] = vertex[ 2 ];
  115. contact->normal[ 0 ] = plane->p[ 0 ];
  116. contact->normal[ 1 ] = plane->p[ 1 ];
  117. contact->normal[ 2 ] = plane->p[ 2 ];
  118. contact->depth = alpha;
  119. contact->g1 = trimesh;
  120. contact->g2 = plane;
  121. contact->side1 = t;
  122. contact->side2 = -1;
  123. ++contact_count;
  124. // All contact slots are full?
  125. if ( contact_count >= contact_max )
  126. return contact_count; // <=== STOP HERE
  127. }
  128. }
  129. }
  130. // Return contact count.
  131. return contact_count;
  132. }
  133. #endif // dTRIMESH_OPCODE
  134. #if dTRIMESH_GIMPACT
  135. #include "gimpact_contact_export_helper.h"
  136. #include "gimpact_plane_contact_accessor.h"
  137. int dCollideTrimeshPlane( dxGeom *o1, dxGeom *o2, int flags, dContactGeom* contacts, int skip )
  138. {
  139. dIASSERT( skip >= (int)sizeof( dContactGeom ) );
  140. dIASSERT( o1->type == dTriMeshClass );
  141. dIASSERT( o2->type == dPlaneClass );
  142. dIASSERT ((flags & NUMC_MASK) >= 1);
  143. // Alias pointers to the plane and trimesh
  144. dxTriMesh* trimesh = (dxTriMesh*)( o1 );
  145. dVector4 plane;
  146. dGeomPlaneGetParams(o2, plane);
  147. o1 -> recomputeAABB();
  148. o2 -> recomputeAABB();
  149. //Find collision
  150. GDYNAMIC_ARRAY collision_result;
  151. GIM_CREATE_TRIMESHPLANE_CONTACTS(collision_result);
  152. gim_trimesh_plane_collisionODE(&trimesh->m_collision_trimesh,plane,&collision_result);
  153. if(collision_result.m_size == 0 )
  154. {
  155. GIM_DYNARRAY_DESTROY(collision_result);
  156. return 0;
  157. }
  158. vec4f * planecontact_results = GIM_DYNARRAY_POINTER(vec4f, collision_result);
  159. unsigned int contactcount = collision_result.m_size;
  160. dxPlaneContactAccessor contactaccessor(planecontact_results, plane, o1, o2);
  161. contactcount = dxGImpactContactsExportHelper::ExportMaxDepthGImpactContacts(contactaccessor, contactcount, flags, contacts, skip);
  162. GIM_DYNARRAY_DESTROY(collision_result);
  163. return (int)contactcount;
  164. }
  165. #endif // dTRIMESH_GIMPACT
  166. #endif // dTRIMESH_ENABLED