00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "core/simul/colision.h"
00024 #include "lista.cc"
00025
00026
00027
00028
00029
00030 static int COLOR_pareja = 0;
00031 static LISTA <CONTACTO *> contactos;
00032
00033 LISTA <MINMAX *> TMP_debug_visual;
00034 static BOOLEAN visual_debug = TRUE;
00035
00036 #define VERIFICAR(p) \
00037 if ( !p ) { \
00038 fprintf(stderr, "<COLISION> - ERROR: memoria insuficiente!\n"); \
00039 fflush(stderr); \
00040 return; \
00041 }
00042
00043
00044
00045
00046
00047 MINMAX::MINMAX()
00048 {
00049 Rayito = NULL;
00050 switch ( COLOR_pareja ) {
00051 case 0: color.r = 1; color.g = 1; color.b = 1; break;
00052 case 1: color.r = 1; color.g = 0; color.b = 0; break;
00053 case 2: color.r = 0; color.g = 1; color.b = 0; break;
00054 case 3: color.r = 0; color.g = 0; color.b = 1; break;
00055 case 4: color.r = 1; color.g = 1; color.b = 0; break;
00056 case 5: color.r = 0; color.g = 1; color.b = 1; break;
00057 case 6: color.r = 1; color.g = 0; color.b = 1; break;
00058 }
00059 if ( COLOR_pareja >= 7 ) COLOR_pareja = 0;
00060 }
00061
00062 MINMAX::~MINMAX()
00063 {
00064 if ( Rayito ) delete Rayito;
00065 }
00066
00067 #ifdef GL_ENABLED
00068 void
00069 MINMAX::pintar_gl(void)
00070 {
00071 glColor3f(color.r, color.g, color.b);
00072 pintar_paralelepipedo(min, max);
00073 if ( Rayito ) {
00074 Rayito->pintar_gl();
00075 }
00076 }
00077 #endif
00078
00079
00080
00081
00082
00083 CONTACTO::CONTACTO()
00084 {
00085 ;
00086 }
00087
00088 CONTACTO::~CONTACTO()
00089 {
00090 ;
00091 }
00092
00093
00094
00095
00096
00097 #define SWAP(a, b) temp = (a); (a) = (b); (b) = temp;
00098 #define TA A->tipo_de_cosa()
00099 #define TB B->tipo_de_cosa()
00100
00101 static void
00102 detector_colision_puntual_rigida(COSA *A, COSA *B,
00103 LISTA <CONTACTO *> *Colisiones, double udt, BOOLEAN visual_debug,
00104 MINMAX *m1, MINMAX *m2)
00123 {
00124 CONTACTO *Contacto = NULL;
00125 VECTOR nulo(0, 0, 0);
00126 VECTOR pos_actual, pos_anterior, punto_choque, normal_choque;
00127 RAYO rayo;
00128 double t;
00129
00130 pos_actual = A->posicion_absoluta(nulo);
00131 pos_anterior = pos_actual - A->velocidad_absoluta()*udt;
00132 rayo.origen = pos_anterior;
00133 rayo.direccion = pos_actual - pos_anterior;
00134 if ( visual_debug ) {
00135 m1->Rayito = new RAYO();
00136 *(m1->Rayito) = rayo;
00137 }
00138 rayo.direccion.normalizar();
00139
00140 t = B->interseccion(&rayo, &punto_choque, &normal_choque);
00141 punto_choque = punto_choque - rayo.direccion * (EPSILON * 4);
00142 if ( t < EPSILON || t > DISTANCIA_V(pos_actual, pos_anterior) ) {
00143
00144
00145
00146 return;
00147 }
00148 else {
00149
00150
00151
00152 if ( visual_debug ) {
00153 m2->Rayito = new RAYO();
00154 m2->Rayito->origen = punto_choque;
00155 m2->Rayito->direccion = normal_choque * (0.3);
00156 ((MASA_PUNTUAL *)A)->en_colision = TRUE;
00157 }
00158 A->set_posicion_absoluta(punto_choque);
00159 Contacto = new CONTACTO;
00160 VERIFICAR(Contacto);
00161 Contacto->A = A;
00162 Contacto->B = B;
00163 Contacto->p = punto_choque;
00164
00165 Contacto->n_a = normal_choque * -1.0;
00166 Contacto->n_b = normal_choque;
00167 Contacto->t = t;
00168 Colisiones->anx(Contacto);
00169 }
00170 }
00171
00172 static void
00173 detector_colision_tela_rigida(COSA *A, COSA *B,
00174 LISTA <CONTACTO *> *Colisiones, double udt, BOOLEAN visual_debug,
00175 MINMAX *m1, MINMAX *m2)
00183 {
00184 MASA_PUNTUAL *Mi;
00185 TELA *T = (TELA *)A;
00186 int i;
00187
00188 for ( i = 0; i < T->num_masas(); i++ ) {
00189 Mi = T->masa_puntual(i);
00190 detector_colision_puntual_rigida(Mi, B, Colisiones, udt,
00191 visual_debug, m1, m2);
00192 }
00193 }
00194
00195 static void
00196 detectar_par_colision(COSA *A, COSA *B, LISTA <CONTACTO *> *Colisiones,
00197 double udt, BOOLEAN visual_debug)
00219 {
00220
00221 if ( A->estoy_fijo() && B->estoy_fijo() ) return;
00222
00223
00224 MINMAX *m1, *m2;
00225
00226 m1 = new MINMAX;
00227 A->minmax(&(m1->min), &(m1->max));
00228 m2 = new MINMAX;
00229 B->minmax(&(m2->min), &(m2->max));
00230
00231 if ( ((m1->max.x >= m2->min.x) && (m1->min.x <= m2->max.x)) &&
00232 ((m1->max.y >= m2->min.y) && (m1->min.y <= m2->max.y)) &&
00233 ((m1->max.z >= m2->min.z) && (m1->min.z <= m2->max.z)) ) {
00234 if ( visual_debug ) {
00235 TMP_debug_visual.anx(m1);
00236 TMP_debug_visual.anx(m2);
00237 }
00238 else {
00239 delete m1;
00240 delete m2;
00241 }
00242 COLOR_pareja++;
00243 }
00244 else {
00245 delete m1;
00246 delete m2;
00247 return;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 COSA *temp;
00263
00264 if ( (TB == CC_MASA_PUNTUAL && TA == CC_COSA_RIGIDA) ||
00265 (TB == CC_TELA && TA == CC_COSA_RIGIDA)
00266 ) {
00267 SWAP(A, B);
00268 }
00269
00270
00271 if ( TA == CC_MASA_PUNTUAL && TB == CC_MASA_PUNTUAL ) {
00272
00273 return;
00274 }
00275 else if ( TA == CC_MASA_PUNTUAL && TB == CC_COSA_RIGIDA ) {
00276 detector_colision_puntual_rigida(A, B, Colisiones, udt, visual_debug,
00277 m1, m2);
00278 }
00279 else if ( TA == CC_TELA && TB == CC_COSA_RIGIDA ) {
00280 detector_colision_tela_rigida(A, B, Colisiones, udt, visual_debug,
00281 m1, m2);
00282 }
00283 ;
00284 }
00285
00286
00287
00288
00289
00290 MANEJADOR_CONFLICTOS_COLISION::MANEJADOR_CONFLICTOS_COLISION()
00291 {
00292 ;
00293 }
00294
00295 MANEJADOR_CONFLICTOS_COLISION::~MANEJADOR_CONFLICTOS_COLISION()
00296 {
00297 ;
00298 }
00299
00300
00301
00302 void
00303 MANEJADOR_CONFLICTOS_COLISION::detectar_conflictos(LISTA <COSA *> *Cosas,
00304 double udt)
00335 {
00336 int i, j;
00337
00338
00339 for ( i = 0; i < TMP_debug_visual.tam(); i++ ) delete TMP_debug_visual[i];
00340 TMP_debug_visual.elim();
00341
00342
00343 COLOR_pareja = 1;
00344
00345 for ( i = 0; i < Cosas->tam()-1; i++ ) {
00346 for ( j = i+1; j < Cosas->tam(); j++ ) {
00347 detectar_par_colision((*Cosas)[i],(*Cosas)[j], &contactos,
00348 udt,visual_debug);
00349 }
00350 }
00351 }
00352
00353
00354
00355 void
00356 MANEJADOR_CONFLICTOS_COLISION::resolver_conflictos(void)
00378 {
00379 int i;
00380
00381
00382 COSA *A, *B;
00383 CONTACTO *Contacto;
00384 VECTOR centro_de_masa(0, 0, 0);
00385 double numerator, term1, term2, term3, term4;
00386 VECTOR p;
00387 VECTOR n;
00388 VECTOR xa;
00389 VECTOR xb;
00390 VECTOR pa;
00391 VECTOR pb;
00392 VECTOR dot_pa;
00393 VECTOR dot_pb;
00394 double vrel;
00395 VECTOR J;
00396 double j;
00397 VECTOR torque_impulsivo_a;
00398 VECTOR torque_impulsivo_b;
00399 double epsilon;
00400 MATRIZ_4x4 Ia_i;
00401 MATRIZ_4x4 Ib_i;
00402
00403
00404 for ( i = 0; i < contactos.tam(); i++ ) {
00405
00406 Contacto = contactos[i];
00407 A = Contacto->A;
00408 B = Contacto->B;
00409
00410
00411 p = Contacto->p;
00412 xa = A->posicion_absoluta(centro_de_masa);
00413 dot_pa = A->velocidad_absoluta() +
00414 (A->velocidad_angular_absoluta().producto_cruz(p - xa));
00415
00416 xb = B->posicion_absoluta(centro_de_masa);
00417 dot_pb = B->velocidad_absoluta() +
00418 (B->velocidad_angular_absoluta().producto_cruz(p - xb));
00419
00420
00421
00422
00423 n = Contacto->n_b;
00424 n.normalizar();
00425 vrel = n.producto_punto(dot_pa - dot_pb);
00426 if ( vrel < -EPSILON ) {
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 epsilon = A->ke() * B->ke();
00439
00440
00441 if ( A->estoy_fijo() ) Ia_i = Ia_i * 0;
00442 else Ia_i = (A->tensor_de_inercia()).inversa();
00443 if ( B->estoy_fijo() ) Ib_i = Ib_i * 0;
00444 else Ib_i = (B->tensor_de_inercia()).inversa();
00445 numerator = -((1 + epsilon) * vrel);
00446 if ( A->estoy_fijo() ) term1 = 0;
00447 else term1 = 1/A->masa();
00448 if ( B->estoy_fijo() ) term2 = 0;
00449 else term2 = 1/B->masa();
00450
00451 pa = p - xa;
00452 pb = p - xb;
00453
00454 term3 = n.producto_punto(
00455 (Ia_i * (pa.producto_cruz(n))).producto_cruz(pa)
00456 );
00457 term4 = n.producto_punto(
00458 (Ib_i * (pb.producto_cruz(n))).producto_cruz(pb)
00459 );
00460 j = numerator / (term1 + term2 + term3 + term4);
00461 J = n * j;
00462
00463
00464 torque_impulsivo_a = pa.producto_cruz(J);
00465 torque_impulsivo_b = pb.producto_cruz(J*(-1));
00466
00467
00468 if ( !A->estoy_fijo() ) {
00469 A->set_velocidad_absoluta(
00470 A->velocidad_absoluta() + J * (1/A->masa()));
00471 A->set_velocidad_angular_absoluta(
00472 A->velocidad_angular_absoluta() + Ia_i*torque_impulsivo_a);
00473 }
00474 if ( !B->estoy_fijo() ) {
00475 B->set_velocidad_absoluta(
00476 B->velocidad_absoluta() - J * (1/B->masa()));
00477 B->set_velocidad_angular_absoluta(
00478 B->velocidad_angular_absoluta() + Ib_i*torque_impulsivo_b);
00479 }
00480
00481
00482
00483
00484
00485
00486 }
00487 else if ( vrel > EPSILON ) {
00488
00489 }
00490 else {
00491
00492 }
00493 ;
00494
00495
00496
00497
00498
00499 }
00500
00501
00502 for ( i = 0; i < contactos.tam(); i++ ) delete contactos[i];
00503 contactos.elim();
00504 }
00505
00506
00507
00508
00509