aboutsummaryrefslogtreecommitdiff
path: root/src/physics.c
diff options
context:
space:
mode:
authortaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-07-17 23:00:50 +0000
committertaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-07-17 23:00:50 +0000
commit55b4d0487c9222dd9bdc76dda0fd990d188d7e32 (patch)
treea2c1afea093356969c49eb634631b53597d8f428 /src/physics.c
parentea00365953dac518b388817261430d0efd451aa3 (diff)
Restore collision detection, apparently fixing the 'drop through floors' problem
git-svn-id: svn://cook.msm.cam.ac.uk:745/thrust3d/thrust3d@138 84d2e878-0bd5-11dd-ad15-13eda11d74c5
Diffstat (limited to 'src/physics.c')
-rw-r--r--src/physics.c101
1 files changed, 49 insertions, 52 deletions
diff --git a/src/physics.c b/src/physics.c
index 39a3e09..c6d4dd9 100644
--- a/src/physics.c
+++ b/src/physics.c
@@ -89,7 +89,7 @@ int physics_point_is_inside_hull(double cx, double cy, double cz, double *fvert,
int physics_will_collide_face(double sx, double sy, double sz, double vx, double vy, double vz,
double nx, double ny, double nz, double *fvert, int nfvert, Uint32 dt,
- ModelInstance *obj, double *ttc) {
+ double *ttc) {
double px, py, pz;
double pdotn, sdotn, vdotn;
@@ -115,24 +115,8 @@ int physics_will_collide_face(double sx, double sy, double sz, double vx, double
cy = sy + vy * t;
cz = sz + vz * t;
if ( physics_point_is_inside_hull(cx, cy, cz, fvert, nfvert, nx, ny, nz) == 1 ) {
-
- char *name;
-
- if ( obj == NULL ) {
- name = "unknown";
- } else {
- name = obj->model->name;
- }
-
- // printf("Testing vertex %8f %8f %8f, velocity %8f %8f %8f against face %8f %8f %8f (%s/%p)\n",
- // sx, sy, sz, vx, vy, vz, px, py, pz, name, obj);
- // printf("(%f - %f) / %f\n", pdotn, sdotn, vdotn);
- // printf("Collision happens at t + %f\n", t);
- // exit(0);
-
*ttc = t;
return 1;
-
}
return 0;
@@ -141,9 +125,10 @@ 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,
- CollisionSpec *coll) {
+ double sx, double sy, double sz, CollisionSpec *coll) {
+ int found = 0;
+
switch ( other->model->primitives[a]->type ) {
case PRIMITIVE_QUADS : {
@@ -162,7 +147,7 @@ static int physics_check_collide_all_faces(ModelInstance *obj, ModelInstance *ot
const double nz = other->model->primitives[a]->normals[3*(4*f)+2];
/* Skip if moving from the back to the front of this quad */
- if ( nx*vx + ny*vy + nz*vz > 0.0 ) continue;
+ if ( nx*obj->vx + ny*obj->vy + nz*obj->vz > 0.0 ) continue;
for ( q=0; q<4; q++ ) {
face[3*q + 0] = other->x + other->model->primitives[a]->vertices[3*((4*f)+q) + 0];
@@ -170,14 +155,19 @@ static int physics_check_collide_all_faces(ModelInstance *obj, ModelInstance *ot
face[3*q + 2] = other->z + other->model->primitives[a]->vertices[3*((4*f)+q) + 2];
}
- if ( physics_will_collide_face(sx, sy, sz, vx, vy, vz, nx, ny, nz, face, 4, dt, other, &ttc) != 0 ) {
+ if ( physics_will_collide_face(obj->x+sx, obj->y+sy, obj->z+sz, obj->vx, obj->vy, obj->vz,
+ nx, ny, nz, face, 4, dt, &ttc) != 0 ) {
+ /* Update 'coll' if this collision happens sooner than the current best */
if ( ttc < coll->ttc ) {
- printf("PH: collides with %s/%p in %5.2f ms\n", other->model->name, other, ttc);
coll->ttc = ttc;
coll->nx = nx;
coll->ny = ny;
coll->nz = nz;
+ coll->cx = obj->x + ttc*obj->vx;
+ coll->cy = obj->y + ttc*obj->vy;
+ coll->cz = obj->z + ttc*obj->vz;
+ found = 1;
}
}
@@ -188,73 +178,61 @@ static int physics_check_collide_all_faces(ModelInstance *obj, ModelInstance *ot
}
- return 0;
+ return found;
}
-/* Return non-zero if 'obj' will collide with 'other' with 'dt' milliseconds */
+/* Return non-zero if 'obj' will collide with 'other' within 'dt' milliseconds */
static int physics_check_collide(ModelInstance *obj, ModelInstance *other, double dt, CollisionSpec *coll) {
int i;
+ int found = 0;
- const double vx = obj->vx;
- const double vy = obj->vy;
- const double vz = obj->vz;
-
- double ttc_lowest = +INFINITY;
-
- /* Consider all the primitives in 'obj' */
+ /* Check all the vertices in the moving object... */
for ( i=0; i<obj->model->num_primitives; i++ ) {
-
int j;
-
- /* Consider all the vertices in this primitive */
for ( j=0; j<obj->model->primitives[i]->num_vertices; j++ ) {
int a;
- const double sx = obj->x + obj->model->primitives[i]->vertices[3*j+0];
- const double sy = obj->y + obj->model->primitives[i]->vertices[3*j+1];
- const double sz = obj->z + obj->model->primitives[i]->vertices[3*j+2];
+ const double sx = obj->model->primitives[i]->vertices[3*j+0];
+ const double sy = obj->model->primitives[i]->vertices[3*j+1];
+ const double sz = obj->model->primitives[i]->vertices[3*j+2];
- /* Consider all the primitives in 'other' */
+ /* ...against all primitives in the static object */
for ( a=0; a<other->model->num_primitives; a++ ) {
- physics_check_collide_all_faces(obj, other, dt, a, sx, sy, sz, vx, vy, vz, coll);
+ if ( physics_check_collide_all_faces(obj, other, dt, a, sx, sy, sz, coll) ) {
+ found = 1;
+ }
}
}
}
- if ( ttc_lowest == +INFINITY ) return 0;
-
- if ( ttc_lowest > dt ) {
- printf("PH: will collide with %s/%8p, but too far in the future at %5.2f ms\n", other->model->name, other, ttc_lowest);
- return 0;
- }
-
- return 1;
+ return found;
}
+/* Find the earliest collision for 'obj'. Fill out 'coll' and return 1 if any */
static int physics_find_earliest_collision(ModelInstance *obj, Game *game, double dt, CollisionSpec *coll) {
Room *room;
+ int found = 0;
/* 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 ) {
- /* Consider all the objects in this room */
+ /* Check for collision of this object with all other objects in the room */
int j;
-
for ( j=0; j<room->num_objects; j++ ) {
if ( physics_check_collide(obj, room->objects[j], dt, coll) ) {
- return 1;
+ found = 1;
}
}
}
- return 0;
+ return found;
}
@@ -306,19 +284,38 @@ static void physics_process(ModelInstance *obj, Uint32 dt, Game *game) {
do {
CollisionSpec coll;
- collided = physics_find_earliest_collision(obj, game, dt, &coll);
+ coll.ttc = +HUGE_VAL;
+ coll.nx = 0.0; coll.ny = 0.0; coll.nz = 0.0;
+ coll.cx = 0.0; coll.cy = 0.0; coll.cz = 0.0;
+ collided = physics_find_earliest_collision(obj, game, dt-sttc, &coll);
if ( collided ) {
+ /* Step forward to the point of collision */
+ obj->x = coll.cx;
+ obj->y = coll.cy;
+ obj->z = coll.cz;
+
+ sttc += coll.ttc;
+
+ /* Can we land here? */
if ( (coll.nx==0) && (coll.ny==0) && (coll.nz==1.0) ) {
+ /* Yes - land (already moved to this position */
obj->landed = 1;
obj->vx = 0.0;
obj->vy = 0.0;
obj->vz = 0.0;
+ } else {
+ /* No - bounce */
+ audio_play(game->audio, "clang", 1.0, 0);
+ obj->vx = -obj->vx;
+ obj->vy = -obj->vy;
+ obj->vz = -obj->vz;
}
} else {
+ /* No further collision - perform the 'end step' */
obj->x += obj->vx * (dt-sttc);
obj->y += obj->vy * (dt-sttc);
obj->z += obj->vz * (dt-sttc);