From 62838fb8a4d27654998b6b304d1c485e497bfa4c Mon Sep 17 00:00:00 2001 From: taw27 Date: Tue, 8 Jul 2008 23:49:48 +0000 Subject: Restructuring of collision detection git-svn-id: svn://cook.msm.cam.ac.uk:745/thrust3d/thrust3d@134 84d2e878-0bd5-11dd-ad15-13eda11d74c5 --- src/physics.c | 114 +++++++++++++++++++++++++++++----------------------------- src/types.h | 14 ++++++++ 2 files changed, 70 insertions(+), 58 deletions(-) diff --git a/src/physics.c b/src/physics.c index 7677a02..34e07da 100644 --- a/src/physics.c +++ b/src/physics.c @@ -142,7 +142,7 @@ int physics_will_collide_face(double sx, double sy, double sz, double vx, double /* Check for collision with all faces in a primitive */ static int physics_check_collide_all_faces(ModelInstance *obj, ModelInstance *other, Uint32 dt, int a, double sx, double sy, double sz, double vx, double vy, double vz, - double *ttc_lowest, double *nxc, double *nyc, double *nzc) { + CollisionSpec *coll) { switch ( other->model->primitives[a]->type ) { @@ -172,12 +172,12 @@ static int physics_check_collide_all_faces(ModelInstance *obj, ModelInstance *ot if ( physics_will_collide_face(sx, sy, sz, vx, vy, vz, nx, ny, nz, face, 4, dt, other, &ttc) != 0 ) { - if ( ttc < *ttc_lowest ) { + if ( ttc < coll->ttc ) { printf("PH: collides with %s/%p in %5.2f ms\n", other->model->name, other, ttc); - *ttc_lowest = ttc; - *nxc = nx; - *nyc = ny; - *nzc = nz; + coll->ttc = ttc; + coll->nx = nx; + coll->ny = ny; + coll->nz = nz; } } @@ -193,7 +193,7 @@ static int physics_check_collide_all_faces(ModelInstance *obj, ModelInstance *ot } /* Return non-zero if 'obj' will collide with 'other' with 'dt' milliseconds */ -static int physics_check_collide(ModelInstance *obj, ModelInstance *other, Uint32 dt) { +static int physics_check_collide(ModelInstance *obj, ModelInstance *other, double dt, CollisionSpec *coll) { int i; @@ -202,13 +202,6 @@ static int physics_check_collide(ModelInstance *obj, ModelInstance *other, Uint3 const double vz = obj->vz; double ttc_lowest = +INFINITY; - double nxc = 0.0; - double nyc = 0.0; - double nzc = 0.0; - - if ( strcmp(other->model->name, "platform") ) { -// printf("Checking against platform\n"); - } /* Consider all the primitives in 'obj' */ for ( i=0; imodel->num_primitives; i++ ) { @@ -225,8 +218,7 @@ static int physics_check_collide(ModelInstance *obj, ModelInstance *other, Uint3 /* Consider all the primitives in 'other' */ for ( a=0; amodel->num_primitives; a++ ) { - // printf("Primitive %i\n", a); - physics_check_collide_all_faces(obj, other, dt, a, sx, sy, sz, vx, vy, vz, &ttc_lowest, &nxc, &nyc, &nzc); + physics_check_collide_all_faces(obj, other, dt, a, sx, sy, sz, vx, vy, vz, coll); } } @@ -239,49 +231,37 @@ static int physics_check_collide(ModelInstance *obj, ModelInstance *other, Uint3 return 0; } - if ( (nxc == 0.0) && (nyc == 0.0) && (nzc == 1.0) ) { - obj->x += obj->vx * ttc_lowest; - obj->y += obj->vy * ttc_lowest; - obj->z += obj->vz * ttc_lowest; - obj->vz = 0.0; - obj->landed = 1; - printf("PH: Landed!\n"); - } else { - obj->vx = -obj->vx; - obj->vy = -obj->vy; - obj->vz = -obj->vz; - obj->yawspeed = 0.0; - printf("PH: Bounce!\n"); - } - return 1; } -/* Called once for each object which isn't just "scenery" */ -static void physics_process(ModelInstance *obj, Uint32 dt, Game *game) { - - int collided = 0; - do { +static int physics_find_earliest_collision(ModelInstance *obj, Game *game, double dt, CollisionSpec *coll) { + + Room *room; - Room *room; + /* Consider only the current room, for now */ + room = game_find_room(game, game->cur_room_x, game->cur_room_y, game->cur_room_z); + if ( room != NULL ) { - collided = 0; - - /* Consider only the current room */ - room = game_find_room(game, game->cur_room_x, game->cur_room_y, game->cur_room_z); - if ( room != NULL ) { - /* Consider all the objects in this room */ - int j; - for ( j=0; jnum_objects; j++ ) { - if ( physics_check_collide(obj, room->objects[j], dt) ) { /* Should be dt - ttc */ - collided = 1; - audio_play(game->audio, "clang", 0.7, 0); - } + /* Consider all the objects in this room */ + int j; + + for ( j=0; jnum_objects; j++ ) { + if ( physics_check_collide(obj, room->objects[j], dt, coll) ) { + return 1; } } + + } + + return 0; + +} + +/* Called once for each object which isn't just "scenery" */ +static void physics_process(ModelInstance *obj, Uint32 dt, Game *game) { - } while ( collided ); + int collided = 0; /* Air friction */ if ( obj->vx > 0.0 ) { @@ -321,13 +301,32 @@ static void physics_process(ModelInstance *obj, Uint32 dt, Game *game) { obj->vz -= GRAVITY * dt; } - /* Take a step */ - if ( !obj->landed ) { - obj->x += obj->vx * dt; - obj->y += obj->vy * dt; - obj->z += obj->vz * dt; - obj->yaw += obj->yawspeed * dt; - } + /* Take a step, allowing for collisions and landing */ + double sttc = 0.0; + do { + + CollisionSpec coll; + collided = physics_find_earliest_collision(obj, game, dt, &coll); + + if ( collided ) { + + if ( (coll.nx==0) && (coll.ny==0) && (coll.nz==1.0) ) { + obj->landed = 1; + obj->vx = 0.0; + obj->vy = 0.0; + obj->vz = 0.0; + } + + } else { + + obj->x += obj->vx * (dt-sttc); + obj->y += obj->vy * (dt-sttc); + obj->z += obj->vz * (dt-sttc); + obj->yaw += obj->yawspeed * (dt-sttc); + + } + + } while ( collided && !obj->landed ); if ( obj->yaw < -M_PI ) obj->yaw += 2*M_PI; if ( obj->yaw > M_PI ) obj->yaw -= 2*M_PI; @@ -362,7 +361,6 @@ void physics_step(Game *game, Uint32 t) { game->lander->yawspeed += YAWTHRUST *dt; /* +ve yaw is "right" */ } - /* The number of rooms to consider for physics purposes can probably be further reduced */ physics_process(game->lander, dt, game); game_check_handoff(game); diff --git a/src/types.h b/src/types.h index d489be7..dcbc097 100644 --- a/src/types.h +++ b/src/types.h @@ -255,5 +255,19 @@ typedef struct { } Game; +typedef struct { + + double nx; + double ny; + double nz; /* Normal of face being collided with */ + + double cx; + double cy; + double cz; /* Coordinates of object at the moment when it collides */ + + double ttc; + +} CollisionSpec; + #endif /* TYPES_H */ -- cgit v1.2.3