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.
25 #include <ode/collision.h>
26 #include <ode/matrix.h>
27 #include <ode/rotation.h>
28 #include <ode/odemath.h>
33 #include "collision_util.h"
34 #include "collision_trimesh_internal.h"
37 int dCollideRTL(dxGeom
* g1
, dxGeom
* RayGeom
, int Flags
, dContactGeom
* Contacts
, int Stride
){
38 dIASSERT (Stride
>= (int)sizeof(dContactGeom
));
39 dIASSERT (g1
->type
== dTriMeshClass
);
40 dIASSERT (RayGeom
->type
== dRayClass
);
41 dIASSERT ((Flags
& NUMC_MASK
) >= 1);
43 dxTriMesh
* TriMesh
= (dxTriMesh
*)g1
;
45 const dVector3
& TLPosition
= *(const dVector3
*)dGeomGetPosition(TriMesh
);
46 const dMatrix3
& TLRotation
= *(const dMatrix3
*)dGeomGetRotation(TriMesh
);
48 TrimeshCollidersCache
*pccColliderCache
= GetTrimeshCollidersCache();
49 RayCollider
& Collider
= pccColliderCache
->_RayCollider
;
51 dReal Length
= dGeomRayGetLength(RayGeom
);
53 int FirstContact
, BackfaceCull
;
54 dGeomRayGetParams(RayGeom
, &FirstContact
, &BackfaceCull
);
55 int ClosestHit
= dGeomRayGetClosestHit(RayGeom
);
57 Collider
.SetFirstContact(FirstContact
!= 0);
58 Collider
.SetClosestHit(ClosestHit
!= 0);
59 Collider
.SetCulling(BackfaceCull
!= 0);
60 Collider
.SetMaxDist(Length
);
62 dVector3 Origin
, Direction
;
63 dGeomRayGet(RayGeom
, Origin
, Direction
);
67 WorldRay
.mOrig
.x
= Origin
[0];
68 WorldRay
.mOrig
.y
= Origin
[1];
69 WorldRay
.mOrig
.z
= Origin
[2];
70 WorldRay
.mDir
.x
= Direction
[0];
71 WorldRay
.mDir
.y
= Direction
[1];
72 WorldRay
.mDir
.z
= Direction
[2];
77 if (Collider
.Collide(WorldRay
, TriMesh
->Data
->BVTree
, &MakeMatrix(TLPosition
, TLRotation
, amatrix
))) {
78 TriCount
= pccColliderCache
->Faces
.GetNbFaces();
85 const CollisionFace
* Faces
= pccColliderCache
->Faces
.GetFaces();
88 for (int i
= 0; i
< TriCount
; i
++) {
89 if (TriMesh
->RayCallback
== null
||
90 TriMesh
->RayCallback(TriMesh
, RayGeom
, Faces
[i
].mFaceID
,
91 Faces
[i
].mU
, Faces
[i
].mV
)) {
92 const int& TriIndex
= Faces
[i
].mFaceID
;
93 if (!Callback(TriMesh
, RayGeom
, TriIndex
)) {
97 dContactGeom
* Contact
= SAFECONTACT(Flags
, Contacts
, OutTriCount
, Stride
);
100 FetchTriangle(TriMesh
, TriIndex
, TLPosition
, TLRotation
, dv
);
103 vu
[0] = dv
[1][0] - dv
[0][0];
104 vu
[1] = dv
[1][1] - dv
[0][1];
105 vu
[2] = dv
[1][2] - dv
[0][2];
109 vv
[0] = dv
[2][0] - dv
[0][0];
110 vv
[1] = dv
[2][1] - dv
[0][1];
111 vv
[2] = dv
[2][2] - dv
[0][2];
114 dCROSS(Contact
->normal
, =, vv
, vu
); // Reversed
116 // Even though all triangles might be initially valid,
117 // a triangle may degenerate into a segment after applying
118 // space transformation.
119 if (dSafeNormalize3(Contact
->normal
))
121 // No sense to save on single type conversion in algorithm of this size.
122 // If there would be a custom typedef for distance type it could be used
123 // instead of dReal. However using float directly is the loss of abstraction
124 // and possible loss of precision in future.
125 /*float*/ dReal T
= Faces
[i
].mDistance
;
126 Contact
->pos
[0] = Origin
[0] + (Direction
[0] * T
);
127 Contact
->pos
[1] = Origin
[1] + (Direction
[1] * T
);
128 Contact
->pos
[2] = Origin
[2] + (Direction
[2] * T
);
129 Contact
->pos
[3] = REAL(0.0);
132 Contact
->g1
= TriMesh
;
133 Contact
->g2
= RayGeom
;
137 // Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
138 if (OutTriCount
>= (Flags
& NUMC_MASK
)) {
146 #endif // dTRIMESH_OPCODE
149 int dCollideRTL(dxGeom
* g1
, dxGeom
* RayGeom
, int Flags
, dContactGeom
* Contacts
, int Stride
)
151 dIASSERT (Stride
>= (int)sizeof(dContactGeom
));
152 dIASSERT (g1
->type
== dTriMeshClass
);
153 dIASSERT (RayGeom
->type
== dRayClass
);
154 dIASSERT ((Flags
& NUMC_MASK
) >= 1);
156 dxTriMesh
* TriMesh
= (dxTriMesh
*)g1
;
158 dReal Length
= dGeomRayGetLength(RayGeom
);
159 int FirstContact
, BackfaceCull
;
160 dGeomRayGetParams(RayGeom
, &FirstContact
, &BackfaceCull
);
161 int ClosestHit
= dGeomRayGetClosestHit(RayGeom
);
162 dVector3 Origin
, Direction
;
163 dGeomRayGet(RayGeom
, Origin
, Direction
);
166 GIM_TRIANGLE_RAY_CONTACT_DATA contact_data
;
170 intersect
= gim_trimesh_ray_closest_collisionODE(&TriMesh
->m_collision_trimesh
,Origin
,Direction
,Length
,&contact_data
);
174 intersect
= gim_trimesh_ray_collisionODE(&TriMesh
->m_collision_trimesh
,Origin
,Direction
,Length
,&contact_data
);
183 if(!TriMesh
->RayCallback
||
184 TriMesh
->RayCallback(TriMesh
, RayGeom
, contact_data
.m_face_id
, contact_data
.u
, contact_data
.v
))
186 dContactGeom
* Contact
= &( Contacts
[ 0 ] );
187 VEC_COPY(Contact
->pos
,contact_data
.m_point
);
188 VEC_COPY(Contact
->normal
,contact_data
.m_normal
);
189 Contact
->depth
= contact_data
.tparam
;
190 Contact
->g1
= TriMesh
;
191 Contact
->g2
= RayGeom
;
198 #endif // dTRIMESH_GIMPACT
200 #endif // dTRIMESH_ENABLED