1 /*************************************************************************
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
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 *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
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. *
21 *************************************************************************/
23 // TriMesh code by Erwin de Vries.
24 // Modified for FreeSOLID Compatibility by Rodrigo Hernandez
25 // Trimesh caches separation by Oleh Derevenko
26 // TriMesh storage classes refactoring and face angle computation code by Oleh Derevenko (C) 2016-2022
29 #ifndef _ODE_COLLISION_TRIMESH_GIMPACT_H_
30 #define _ODE_COLLISION_TRIMESH_GIMPACT_H_
33 #if dTRIMESH_ENABLED && dTRIMESH_GIMPACT
36 //****************************************************************************
40 #include "collision_kernel.h"
41 #include "collision_trimesh_colliders.h"
42 #include "collision_util.h"
43 #include <ode/collision_trimesh.h>
45 #include "collision_trimesh_internal.h"
46 #include <GIMPACT/gimpact.h>
49 struct TrimeshCollidersCache
// Required for compatibility with OPCODE
54 typedef dxTriDataBase dxTriMeshData_Parent
;
56 public dxTriMeshData_Parent
60 dxTriMeshData_Parent()
64 ~dxTriMeshData() { /* Do nothing */ }
66 using dxTriMeshData_Parent::buildData
;
68 /* Setup the UseFlags array and/or build face angles*/
69 bool preprocessData(bool buildUseFlags
/*=false*/, FaceAngleStorageMethod faceAndgesRequirement
/*=ASM__INVALID*/);
72 bool meaningfulPreprocessData(FaceAngleStorageMethod faceAndgesRequirement
/*=ASM__INVALID*/);
75 /* For when app changes the vertices */
76 void updateData() { /* Do nothing */ }
79 const vec3f
*retrieveVertexInstances() const { return (const vec3f
*)dxTriMeshData_Parent::retrieveVertexInstances(); }
80 const GUINT32
*retrieveTriangleVertexIndices() const { return (const GUINT32
*)dxTriMeshData_Parent::retrieveTriangleVertexIndices(); }
83 void assignNormals(const dReal
*normals
) { dxTriMeshData_Parent::assignNormals(normals
); }
84 const dReal
*retrieveNormals() const { return (const dReal
*)dxTriMeshData_Parent::retrieveNormals(); }
85 sizeint
calculateNormalsMemoryRequirement() const { return retrieveTriangleCount() * (sizeof(dReal
) * dSA__MAX
); }
91 // To use GIMPACT with doubles, we need to patch a couple of the GIMPACT functions to
92 // convert arguments to floats before sending them in
95 /// Convert an gimpact vec3f to a ODE dVector3d: dVector3[i] = vec3f[i]
96 #define dVECTOR3_VEC3F_COPY(b,a) { \
104 void gim_trimesh_get_triangle_verticesODE(GIM_TRIMESH
* trimesh
, GUINT32 triangle_index
, dVector3 v1
, dVector3 v2
, dVector3 v3
)
106 vec3f src1
, src2
, src3
;
107 GREAL
*psrc1
= v1
!= NULL
? src1
: NULL
;
108 GREAL
*psrc2
= v2
!= NULL
? src2
: NULL
;
109 GREAL
*psrc3
= v3
!= NULL
? src3
: NULL
;
110 gim_trimesh_get_triangle_vertices(trimesh
, triangle_index
, psrc1
, psrc2
, psrc3
);
114 dVECTOR3_VEC3F_COPY(v1
, src1
);
119 dVECTOR3_VEC3F_COPY(v2
, src2
);
124 dVECTOR3_VEC3F_COPY(v3
, src3
);
128 // Anything calling gim_trimesh_get_triangle_vertices from within ODE
129 // should be patched through to the dDOUBLE version above
131 #define gim_trimesh_get_triangle_vertices gim_trimesh_get_triangle_verticesODE
134 int gim_trimesh_ray_closest_collisionODE( GIM_TRIMESH
*mesh
, dVector3 origin
, dVector3 dir
, dReal tmax
, GIM_TRIANGLE_RAY_CONTACT_DATA
*contact
)
136 vec3f dir_vec3f
= { (GREAL
)dir
[ 0 ], (GREAL
)dir
[ 1 ], (GREAL
)dir
[ 2 ] };
137 vec3f origin_vec3f
= { (GREAL
)origin
[ 0 ], (GREAL
)origin
[ 1 ], (GREAL
)origin
[ 2 ] };
139 return gim_trimesh_ray_closest_collision( mesh
, origin_vec3f
, dir_vec3f
, (GREAL
)tmax
, contact
);
143 int gim_trimesh_ray_collisionODE( GIM_TRIMESH
*mesh
, const dVector3 origin
, const dVector3 dir
, dReal tmax
, GIM_TRIANGLE_RAY_CONTACT_DATA
*contact
)
145 vec3f dir_vec3f
= { (GREAL
)dir
[ 0 ], (GREAL
)dir
[ 1 ], (GREAL
)dir
[ 2 ] };
146 vec3f origin_vec3f
= { (GREAL
)origin
[ 0 ], (GREAL
)origin
[ 1 ], (GREAL
)origin
[ 2 ] };
148 return gim_trimesh_ray_collision( mesh
, origin_vec3f
, dir_vec3f
, (GREAL
)tmax
, contact
);
152 void gim_trimesh_sphere_collisionODE( GIM_TRIMESH
*mesh
, const dVector3 Position
, dReal Radius
, GDYNAMIC_ARRAY
*contact
)
154 vec3f pos_vec3f
= { (GREAL
)Position
[ 0 ], (GREAL
)Position
[ 1 ], (GREAL
)Position
[ 2 ] };
155 gim_trimesh_sphere_collision( mesh
, pos_vec3f
, (GREAL
)Radius
, contact
);
159 void gim_trimesh_plane_collisionODE( GIM_TRIMESH
*mesh
, const dVector4 plane
, GDYNAMIC_ARRAY
*contact
)
161 vec4f plane_vec4f
= { (GREAL
)plane
[ 0 ], (GREAL
)plane
[ 1 ], (GREAL
)plane
[ 2 ], (GREAL
)plane
[ 3 ] }; \
162 gim_trimesh_plane_collision( mesh
, plane_vec4f
, contact
); \
165 #define GIM_AABB_COPY( src, dst ) { \
166 (dst)[ 0 ]= (src) -> minX; \
167 (dst)[ 1 ]= (src) -> maxX; \
168 (dst)[ 2 ]= (src) -> minY; \
169 (dst)[ 3 ]= (src) -> maxY; \
170 (dst)[ 4 ]= (src) -> minZ; \
171 (dst)[ 5 ]= (src) -> maxZ; \
175 #else // #ifdef !dDOUBLE
177 // With single precision, we can pass native ODE vectors directly to GIMPACT
179 #define gim_trimesh_ray_closest_collisionODE gim_trimesh_ray_closest_collision
180 #define gim_trimesh_ray_collisionODE gim_trimesh_ray_collision
181 #define gim_trimesh_sphere_collisionODE gim_trimesh_sphere_collision
182 #define gim_trimesh_plane_collisionODE gim_trimesh_plane_collision
184 #define GIM_AABB_COPY( src, dst ) memcpy( dst, src, 6 * sizeof( GREAL ) )
187 #endif // #ifdef !dDOUBLE
190 typedef dxMeshBase dxTriMesh_Parent
;
192 public dxTriMesh_Parent
196 dxTriMesh(dxSpace
*Space
, dxTriMeshData
*Data
,
197 dTriCallback
*Callback
, dTriArrayCallback
*ArrayCallback
, dTriRayCallback
*RayCallback
):
198 dxTriMesh_Parent(Space
, NULL
, Callback
, ArrayCallback
, RayCallback
, true) // TC has speed/space 'issues' that don't make it a clear win by default on spheres/boxes.
200 gim_init_buffer_managers(m_buffer_managers
);
201 assignMeshData(Data
);
206 void clearTCCache() { /* do nothing */ }
208 virtual void computeAABB();
211 dxTriMeshData
*retrieveMeshData() const { return getMeshData(); }
213 unsigned getMeshTriangleCount() const { return gim_trimesh_get_triangle_count(const_cast<GIM_TRIMESH
*>(&m_collision_trimesh
)); }
215 void fetchMeshTransformedTriangle(dVector3
*const pout_triangle
[3], unsigned index
)
217 gim_trimesh_locks_work_data(&m_collision_trimesh
);
218 gim_trimesh_get_triangle_vertices(&m_collision_trimesh
, (GUINT32
)index
, *pout_triangle
[0], *pout_triangle
[1], *pout_triangle
[2]);
219 gim_trimesh_unlocks_work_data(&m_collision_trimesh
);
222 void fetchMeshTransformedTriangle(dVector3 out_triangle
[3], unsigned index
)
224 gim_trimesh_locks_work_data(&m_collision_trimesh
);
225 gim_trimesh_get_triangle_vertices(&m_collision_trimesh
, (GUINT32
)index
, out_triangle
[0], out_triangle
[1], out_triangle
[2]);
226 gim_trimesh_unlocks_work_data(&m_collision_trimesh
);
230 dxTriMeshData
*getMeshData() const { return static_cast<dxTriMeshData
*>(dxTriMesh_Parent::getMeshData()); }
235 VERTEXINSTANCE_STRIDE
= sizeof(vec3f
),
236 TRIANGLEINDEX_STRIDE
= sizeof(GUINT32
) * dMTV__MAX
,
239 void assignMeshData(dxTriMeshData
*Data
);
242 GIM_TRIMESH m_collision_trimesh
;
243 GBUFFER_MANAGER_DATA m_buffer_managers
[G_BUFFER_MANAGER__MAX
];
248 void MakeMatrix(const dVector3 position
, const dMatrix3 rotation
, mat4f m
)
250 m
[0][0] = (GREAL
)rotation
[dM3E_XX
];
251 m
[0][1] = (GREAL
)rotation
[dM3E_XY
];
252 m
[0][2] = (GREAL
)rotation
[dM3E_XZ
];
254 m
[1][0] = (GREAL
)rotation
[dM3E_YX
];
255 m
[1][1] = (GREAL
)rotation
[dM3E_YY
];
256 m
[1][2] = (GREAL
)rotation
[dM3E_YZ
];
258 m
[2][0] = (GREAL
)rotation
[dM3E_ZX
];
259 m
[2][1] = (GREAL
)rotation
[dM3E_ZY
];
260 m
[2][2] = (GREAL
)rotation
[dM3E_ZZ
];
262 m
[0][3] = (GREAL
)position
[dV3E_X
];
263 m
[1][3] = (GREAL
)position
[dV3E_Y
];
264 m
[2][3] = (GREAL
)position
[dV3E_Z
];
268 void MakeMatrix(dxGeom
*g
, mat4f m
)
270 const dVector3
&position
= g
->buildUpdatedPosition();
271 const dMatrix3
&rotation
= g
->buildUpdatedRotation();
272 MakeMatrix(position
, rotation
, m
);
276 #endif // #if dTRIMESH_ENABLED && dTRIMESH_GIMPACT
278 #endif //_ODE_COLLISION_TRIMESH_GIMPACT_H_