33 const bool COLLIDE_DEBUG =
false;
36 const double MAX_DEPTH = 0.1;
39 const int CD_ALL_CONTACTS = 1;
40 const int CD_FIRST_CONTACT = 2;
41 const int CD_ERR_COLLIDE_OUT_OF_MEMORY = 2;
51 CollisionPairInserter::CollisionPairInserter()
57 CollisionPairInserter::~CollisionPairInserter()
63 void CollisionPairInserter::copy_tri(
col_tri* t1,
tri* t2)
77 if(t2->
n[0] && t2->
n[1] && t2->
n[2]){
83 void CollisionPairInserter::calc_normal_vector(
col_tri* t)
88 t->
n = e1.cross(e2).normalized();
96 const double EPS = 1.0e-12;
98 calc_normal_vector(t2);
109 if(t2->
n.dot(vec1) <
EPS && t2->
n.dot(vec2) <
EPS && t2->
n.dot(vec3) <
EPS){
117 IceMaths::IndexedTriangle indextriangle = model->
triangles[id];
118 IceMaths::Point point0 = model->
vertices[indextriangle.mVRef[0]];
119 IceMaths::Point point1 = model->
vertices[indextriangle.mVRef[1]];
120 IceMaths::Point point2 = model->
vertices[indextriangle.mVRef[2]];
126 void CollisionPairInserter::get_triangles_in_convex_neighbor(
ColdetModelSharedDataSet* model,
int id,
col_tri* tri_convex_neighbor, std::vector<int>& foundTriangles,
int& count){
128 for(
unsigned int i=0;
i<foundTriangles.size();
i++)
129 if(foundTriangles[
i] ==
id){
134 for(
int i=0;
i<3;
i++){
135 int nei = model->
neighbor[id].triangles[
i];
139 for(; j<foundTriangles.size(); j++)
140 if(foundTriangles[j] == nei)
142 if(j<foundTriangles.size())
146 triangleIndexToPoint(model, nei, tri_nei);
148 if(is_convex_neighbor( &tri_nei, &tri_convex_neighbor[k])){
150 Vector3 p1 = tri_nei.
p1 - tri_convex_neighbor[0].
p1;
151 if(p1.dot(tri_convex_neighbor[0].
n) > 0)
153 Vector3 p2 = tri_nei.
p2 - tri_convex_neighbor[0].
p1;
154 if(p2.dot(tri_convex_neighbor[0].
n) > 0)
156 Vector3 p3 = tri_nei.
p3 - tri_convex_neighbor[0].
p1;
157 if(p3.dot(tri_convex_neighbor[0].
n) > 0)
160 foundTriangles.push_back(nei);
161 tri_convex_neighbor[count].
status = 0;
162 copy_tri(&tri_convex_neighbor[count++], &tri_nei);
169 std::vector<int> foundTriangles;
171 triangleIndexToPoint(model,
id, tri_convex_neighbor[count++]);
172 tri_convex_neighbor[0].
status = 0;
173 foundTriangles.push_back(
id);
179 while(count < min_num && j<2){
181 get_triangles_in_convex_neighbor(model, foundTriangles[
i], tri_convex_neighbor, foundTriangles, count);
191 void CollisionPairInserter::examine_normal_vector(
int id1,
int id2,
int ctype)
193 check_separability(id1, id2, ctype);
196 void CollisionPairInserter::check_separability(
int id1,
int id2,
int ctype){
197 int contactIndex = cdContact.size() - 1;
199 Vector3 signed_distance1(99999999.0,99999999.0,99999999.0);
200 Vector3 signed_distance2(-99999999.0,-99999999.0,-99999999.0);
204 find_signed_distance(signed_distance1, model0, id1, contactIndex, ctype, 1);
205 find_signed_distance(signed_distance2, model1, id2, contactIndex, ctype, 2);
207 int max = (2 < ctype) ? ctype : 2;
209 for(
int i=0;
i <
max; ++
i){
210 signed_distance[
i] = signed_distance1[
i] - signed_distance2[
i];
211 if(COLLIDE_DEBUG) printf(
"signed distance %d = %f\n",
i, signed_distance[
i]);
217 if(signed_distance[0] < signed_distance[1]){
218 cdContact[contactIndex].n_vector = cdContact[contactIndex].m;
219 cdContact[contactIndex].depth = fabs(signed_distance[1]);
220 if(COLLIDE_DEBUG) printf(
"normal replaced\n");
222 cdContact[contactIndex].depth = fabs(signed_distance[0]);
227 if(signed_distance[0] < signed_distance[1]){
228 cdContact[contactIndex].n_vector = - cdContact[contactIndex].n;
229 cdContact[contactIndex].depth = fabs(signed_distance[1]);
230 if(COLLIDE_DEBUG) printf(
"normal replaced\n");
232 cdContact[contactIndex].depth = fabs(signed_distance[0]);
237 cdContact[contactIndex].num_of_i_points = 1;
238 if(signed_distance[0] < signed_distance[1] && signed_distance[2] <= signed_distance[1]){
239 cdContact[contactIndex].n_vector = cdContact[contactIndex].m;
240 cdContact[contactIndex].depth = fabs(signed_distance[1]);
241 if(COLLIDE_DEBUG) printf(
"normal replaced\n");
242 }
else if(signed_distance[0] < signed_distance[2] && signed_distance[1] < signed_distance[2]){
243 cdContact[contactIndex].n_vector = - cdContact[contactIndex].n;
244 cdContact[contactIndex].depth = fabs(signed_distance[2]);
245 if(COLLIDE_DEBUG) printf(
"normal replaced\n");
247 cdContact[contactIndex].depth = fabs(signed_distance[0]);
250 cdContact[contactIndex].i_points[0] += cdContact[contactIndex].i_points[1];
251 cdContact[contactIndex].i_points[0] *= 0.5;
256 printf(
"final normal = %f %f %f\n", cdContact[contactIndex].n_vector[0],
257 cdContact[contactIndex].n_vector[1], cdContact[contactIndex].n_vector[2]);
260 for(
int i=0;
i < cdContact[contactIndex].num_of_i_points; ++
i){
261 cout <<
"final depth = " << cdContact[contactIndex].depth << endl;
262 cout <<
"final i_point = " << cdContact[contactIndex].i_points[
i][0] <<
" "
263 << cdContact[contactIndex].i_points[
i][1] <<
" " << cdContact[contactIndex].i_points[
i][2]
268 if(COLLIDE_DEBUG) cout << endl;
271 void CollisionPairInserter::find_signed_distance(
274 find_signed_distance(signed_distance, trp->
p1, nth, ctype,
obj);
275 find_signed_distance(signed_distance, trp->
p2, nth, ctype,
obj);
276 find_signed_distance(signed_distance, trp->
p3, nth, ctype,
obj);
279 void CollisionPairInserter::find_signed_distance(
284 vert_w = CD_s1 * (CD_Rot1 * vert + CD_Trans1);
286 vert_w = CD_s2 * (CD_Rot2 * vert + CD_Trans2);
289 if(COLLIDE_DEBUG) printf(
"vertex = %f %f %f\n", vert_w[0], vert_w[1], vert_w[2]);
292 const Vector3 vec(vert_w - cdContact[nth].i_points[0]);
294 cdContact[nth].n_vector.normalize();
296 double dis0 = cdContact[nth].n_vector.dot(vec);
301 if(
dot(cdContact[nth].n_vector, cdContact[nth].
n) > 0.0) dis0 = - dis0;
304 if(
dot(cdContact[nth].n_vector, cdContact[nth].m) < 0.0) dis0 = - dis0;
307 if(
dot(cdContact[nth].n_vector, cdContact[nth].
n) > 0.0 ||
308 dot(cdContact[nth].n_vector, cdContact[nth].m) < 0.0)
313 if(COLLIDE_DEBUG) printf(
"dis0 = %f\n", dis0);
320 dis1 = cdContact[nth].m.dot(vec);
321 if(COLLIDE_DEBUG) printf(
"dis1 = %f\n", dis1);
324 dis1 = - cdContact[nth].n.dot(vec);
325 if(COLLIDE_DEBUG) printf(
"dis1 = %f\n", dis1);
328 dis1 = cdContact[nth].m.dot(vec);
329 dis2 = - cdContact[nth].n.dot(vec);
331 printf(
"dis1 = %f\n", dis1);
332 printf(
"dis2 = %f\n", dis2);
336 if(COLLIDE_DEBUG) printf(
"obj = %d\n",
obj);
338 if(dis0 < signed_distance[0]) signed_distance[0] = dis0;
339 if(dis1 < signed_distance[1]) signed_distance[1] = dis1;
341 if(dis2 < signed_distance[2]) signed_distance[2] = dis2;
344 if(signed_distance[0] < dis0) signed_distance[0] = dis0;
345 if(signed_distance[1] < dis1) signed_distance[1] = dis1;
347 if(signed_distance[2] < dis2) signed_distance[2] = dis2;
351 void CollisionPairInserter::find_signed_distance(
359 const int MIN_NUM_NEIGHBOR = 10;
361 int num = get_triangles_in_convex_neighbor(model,
id, tri_convex_neighbor, MIN_NUM_NEIGHBOR);
364 find_signed_distance(signed_distance, &tri_convex_neighbor[
i], contactIndex, ctype,
obj);
367 delete [] tri_convex_neighbor;
370 int CollisionPairInserter::new_point_test(
int k)
372 const double eps = 1.0e-12;
374 int last = cdContact.size()-1;
376 for(
int i=0;
i < last; ++
i){
377 for(
int j=0; j < cdContact[
i].num_of_i_points; ++j){
378 Vector3 dv(cdContact[
i].i_points[j] - cdContact[last].i_points[k]);
379 double d = cdContact[
i].depth - cdContact[last].depth;
380 if(dv.dot(dv) <
eps && d*d <
eps)
return 0;
390 int CollisionPairInserter::apply(
391 const Opcode::AABBCollisionNode* b1,
392 const Opcode::AABBCollisionNode* b2,
401 Opcode::MeshInterface* mesh1,
402 Opcode::MeshInterface* mesh2)
408 contact.
depth = depth;
411 if(COLLIDE_DEBUG) printf(
"num_of_i_points = %d\n", num_of_i_points);
413 for(
int i=0;
i < num_of_i_points; ++
i){
414 contact.
i_points[
i].noalias() = CD_s2 * ((CD_Rot2 * i_points[
i]) + CD_Trans2);
417 contact.
n_vector.noalias() = CD_Rot2 * n_vector;
418 contact.
n.noalias() = CD_Rot2 * n1;
419 contact.
m.noalias() = CD_Rot2 * m1;
420 if (normalVectorCorrection){
421 examine_normal_vector(id1, id2, ctype);
427 if(fabs(contact.
depth) < MAX_DEPTH){
428 for(
int i=0;
i < num_of_i_points; ++
i){
432 for(
int i=0;
i < num_of_i_points; ++
i){
437 for(
int i=0;
i < num_of_i_points; ++
i){
446 int CollisionPairInserter::detectTriTriOverlap(