ODE support works slightly better now. remember to force fixed-rate tics by setting sv_[min|max]tic to the same value.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3436 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2009-11-12 08:53:10 +00:00
parent b9baebe711
commit 67e90812c2
4 changed files with 175 additions and 93 deletions

View file

@ -42,10 +42,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
cvar_t physics_ode_quadtree_depth = CVARDP4(0, "physics_ode_quadtree_depth","5", "desired subdivision level of quadtree culling space"); cvar_t physics_ode_quadtree_depth = CVARDP4(0, "physics_ode_quadtree_depth","5", "desired subdivision level of quadtree culling space");
cvar_t physics_ode_contactsurfacelayer = CVARDP4(0, "physics_ode_contactsurfacelayer","0", "allows objects to overlap this many units to reduce jitter"); cvar_t physics_ode_contactsurfacelayer = CVARDP4(0, "physics_ode_contactsurfacelayer","0", "allows objects to overlap this many units to reduce jitter");
cvar_t physics_ode_worldquickstep = CVARDP4(0, "physics_ode_worldquickstep","1", "use dWorldQuickStep rather than dWorldStepFast1 or dWorldStep"); cvar_t physics_ode_worldquickstep = CVARDP4(0, "physics_ode_worldquickstep","1", "use dWorldQuickStep rather than dWorldStep");
cvar_t physics_ode_worldquickstep_iterations = CVARDP4(0, "physics_ode_worldquickstep_iterations","20", "parameter to dWorldQuickStep"); cvar_t physics_ode_worldquickstep_iterations = CVARDP4(0, "physics_ode_worldquickstep_iterations","20", "parameter to dWorldQuickStep");
cvar_t physics_ode_worldstepfast = CVARDP4(0, "physics_ode_worldstepfast","0", "use dWorldStepFast1 rather than dWorldStep"); //physics_ode_worldstepfast dWorldStepFast1 is not present in more recent versions of ODE. thus we don't use it ever.
cvar_t physics_ode_worldstepfast_iterations = CVARDP4(0, "physics_ode_worldstepfast_iterations","20", "parameter to dWorldStepFast1");
cvar_t physics_ode_contact_mu = CVARDP4(0, "physics_ode_contact_mu", "1", "contact solver mu parameter - friction pyramid approximation 1 (see ODE User Guide)"); cvar_t physics_ode_contact_mu = CVARDP4(0, "physics_ode_contact_mu", "1", "contact solver mu parameter - friction pyramid approximation 1 (see ODE User Guide)");
cvar_t physics_ode_contact_erp = CVARDP4(0, "physics_ode_contact_erp", "0.96", "contact solver erp parameter - Error Restitution Percent (see ODE User Guide)"); cvar_t physics_ode_contact_erp = CVARDP4(0, "physics_ode_contact_erp", "0.96", "contact solver erp parameter - Error Restitution Percent (see ODE User Guide)");
cvar_t physics_ode_contact_cfm = CVARDP4(0, "physics_ode_contact_cfm", "0", "contact solver cfm parameter - Constraint Force Mixing (see ODE User Guide)"); cvar_t physics_ode_contact_cfm = CVARDP4(0, "physics_ode_contact_cfm", "0", "contact solver cfm parameter - Constraint Force Mixing (see ODE User Guide)");
@ -234,7 +233,7 @@ typedef struct dContact
} }
dContact; dContact;
typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); typedef void VARGS dNearCallback (void *data, dGeomID o1, dGeomID o2);
// SAP // SAP
// Order XZY or ZXY usually works best, if your Y is up. // Order XZY or ZXY usually works best, if your Y is up.
@ -290,7 +289,7 @@ void (ODE_API *dWorldSetQuickStepNumIterations)(dWorldID, int num);
//dReal (ODE_API *dWorldGetContactMaxCorrectingVel)(dWorldID); //dReal (ODE_API *dWorldGetContactMaxCorrectingVel)(dWorldID);
void (ODE_API *dWorldSetContactSurfaceLayer)(dWorldID, dReal depth); void (ODE_API *dWorldSetContactSurfaceLayer)(dWorldID, dReal depth);
//dReal (ODE_API *dWorldGetContactSurfaceLayer)(dWorldID); //dReal (ODE_API *dWorldGetContactSurfaceLayer)(dWorldID);
void (ODE_API *dWorldStepFast1)(dWorldID, dReal stepsize, int maxiterations); //void (ODE_API *dWorldStepFast1)(dWorldID, dReal stepsize, int maxiterations);
//void (ODE_API *dWorldSetAutoEnableDepthSF1)(dWorldID, int autoEnableDepth); //void (ODE_API *dWorldSetAutoEnableDepthSF1)(dWorldID, int autoEnableDepth);
//int (ODE_API *dWorldGetAutoEnableDepthSF1)(dWorldID); //int (ODE_API *dWorldGetAutoEnableDepthSF1)(dWorldID);
//dReal (ODE_API *dWorldGetAutoDisableLinearThreshold)(dWorldID); //dReal (ODE_API *dWorldGetAutoDisableLinearThreshold)(dWorldID);
@ -755,7 +754,7 @@ static dllfunction_t odefuncs[] =
// {"dWorldGetContactMaxCorrectingVel", (void **) &dWorldGetContactMaxCorrectingVel}, // {"dWorldGetContactMaxCorrectingVel", (void **) &dWorldGetContactMaxCorrectingVel},
{(void **) &dWorldSetContactSurfaceLayer, "dWorldSetContactSurfaceLayer"}, {(void **) &dWorldSetContactSurfaceLayer, "dWorldSetContactSurfaceLayer"},
// {"dWorldGetContactSurfaceLayer", (void **) &dWorldGetContactSurfaceLayer}, // {"dWorldGetContactSurfaceLayer", (void **) &dWorldGetContactSurfaceLayer},
{(void **) &dWorldStepFast1, "dWorldStepFast1"}, // {(void **) &dWorldStepFast1, "dWorldStepFast1"},
// {"dWorldSetAutoEnableDepthSF1", (void **) &dWorldSetAutoEnableDepthSF1}, // {"dWorldSetAutoEnableDepthSF1", (void **) &dWorldSetAutoEnableDepthSF1},
// {"dWorldGetAutoEnableDepthSF1", (void **) &dWorldGetAutoEnableDepthSF1}, // {"dWorldGetAutoEnableDepthSF1", (void **) &dWorldGetAutoEnableDepthSF1},
// {"dWorldGetAutoDisableLinearThreshold", (void **) &dWorldGetAutoDisableLinearThreshold}, // {"dWorldGetAutoDisableLinearThreshold", (void **) &dWorldGetAutoDisableLinearThreshold},
@ -1183,8 +1182,6 @@ void World_Physics_Init(void)
Cvar_Register(&physics_ode_contactsurfacelayer, "ODE Physics Library"); Cvar_Register(&physics_ode_contactsurfacelayer, "ODE Physics Library");
Cvar_Register(&physics_ode_worldquickstep, "ODE Physics Library"); Cvar_Register(&physics_ode_worldquickstep, "ODE Physics Library");
Cvar_Register(&physics_ode_worldquickstep_iterations, "ODE Physics Library"); Cvar_Register(&physics_ode_worldquickstep_iterations, "ODE Physics Library");
Cvar_Register(&physics_ode_worldstepfast, "ODE Physics Library");
Cvar_Register(&physics_ode_worldstepfast_iterations, "ODE Physics Library");
Cvar_Register(&physics_ode_contact_mu, "ODE Physics Library"); Cvar_Register(&physics_ode_contact_mu, "ODE Physics Library");
Cvar_Register(&physics_ode_contact_erp, "ODE Physics Library"); Cvar_Register(&physics_ode_contact_erp, "ODE Physics Library");
Cvar_Register(&physics_ode_contact_cfm, "ODE Physics Library"); Cvar_Register(&physics_ode_contact_cfm, "ODE Physics Library");
@ -1284,6 +1281,9 @@ void World_Physics_RemoveJointFromEntity(world_t *world, wedict_t *ed)
void World_Physics_RemoveFromEntity(world_t *world, wedict_t *ed) void World_Physics_RemoveFromEntity(world_t *world, wedict_t *ed)
{ {
if (!ed->ode.ode_physics)
return;
// entity is not physics controlled, free any physics data // entity is not physics controlled, free any physics data
ed->ode.ode_physics = false; ed->ode.ode_physics = false;
if (ed->ode.ode_geom) if (ed->ode.ode_geom)
@ -1386,9 +1386,9 @@ static void World_Physics_Frame_BodyToEntity(world_t *world, wedict_t *ed)
up[2] = r[10]; up[2] = r[10];
VectorCopy(vel, velocity); VectorCopy(vel, velocity);
VectorCopy(avel, spinvelocity); VectorCopy(avel, spinvelocity);
Matrix4_FromVectors(bodymatrix, forward, left, up, origin); Matrix4Q_FromVectors(bodymatrix, forward, left, up, origin);
Matrix4_Multiply(entitymatrix, bodymatrix, ed->ode.ode_offsetimatrix); Matrix4_Multiply(bodymatrix, ed->ode.ode_offsetimatrix, entitymatrix);
Matrix4_ToVectors(entitymatrix, forward, left, up, origin); Matrix4Q_ToVectors(entitymatrix, forward, left, up, origin);
VectorAngles(forward, up, angles); VectorAngles(forward, up, angles);
avelocity[PITCH] = RAD2DEG(spinvelocity[PITCH]); avelocity[PITCH] = RAD2DEG(spinvelocity[PITCH]);
@ -1612,11 +1612,17 @@ static qboolean GenerateCollisionMesh(world_t *world, model_t *mod, wedict_t *ed
for (sno = 0; sno < mod->nummodelsurfaces; sno++) for (sno = 0; sno < mod->nummodelsurfaces; sno++)
{ {
surf = &mod->surfaces[sno+mod->firstmodelsurface]; surf = &mod->surfaces[sno+mod->firstmodelsurface];
mesh = surf->mesh; if (surf->mesh)
if (!mesh) {
continue; mesh = surf->mesh;
numverts += mesh->numvertexes; numverts += mesh->numvertexes;
numindexes += mesh->numindexes; numindexes += mesh->numindexes;
}
else
{
numverts += surf->numedges;
numindexes += (surf->numedges-2) * 3;
}
} }
if (!numindexes) if (!numindexes)
{ {
@ -1625,24 +1631,61 @@ static qboolean GenerateCollisionMesh(world_t *world, model_t *mod, wedict_t *ed
} }
ed->ode.ode_element3i = BZ_Malloc(numindexes*sizeof(index_t)); ed->ode.ode_element3i = BZ_Malloc(numindexes*sizeof(index_t));
ed->ode.ode_vertex3f = BZ_Malloc(numverts*sizeof(vec3_t)); ed->ode.ode_vertex3f = BZ_Malloc(numverts*sizeof(vec3_t));
numverts = 0;
numindexes = 0;
for (sno = 0; sno < mod->nummodelsurfaces; sno++) for (sno = 0; sno < mod->nummodelsurfaces; sno++)
{ {
surf = &mod->surfaces[sno+mod->firstmodelsurface]; surf = &mod->surfaces[sno+mod->firstmodelsurface];
mesh = surf->mesh; if (surf->mesh)
if (!mesh)
continue;
for (i = 0; i < mesh->numvertexes; i++)
VectorSubtract(mesh->xyz_array[i], geomcenter, (ed->ode.ode_vertex3f + numverts+i));
for (i = 0; i < mesh->numindexes; i+=3)
{ {
//flip the triangles as we go mesh = surf->mesh;
ed->ode.ode_element3i[numindexes+i+0] = mesh->indexes[i+2]; for (i = 0; i < mesh->numvertexes; i++)
ed->ode.ode_element3i[numindexes+i+1] = mesh->indexes[i+1]; VectorSubtract(mesh->xyz_array[i], geomcenter, (ed->ode.ode_vertex3f + 3*(numverts+i)));
ed->ode.ode_element3i[numindexes+i+2] = mesh->indexes[i+0]; for (i = 0; i < mesh->numindexes; i+=3)
{
//flip the triangles as we go
ed->ode.ode_element3i[numindexes+i+0] = numverts+mesh->indexes[i+2];
ed->ode.ode_element3i[numindexes+i+1] = numverts+mesh->indexes[i+1];
ed->ode.ode_element3i[numindexes+i+2] = numverts+mesh->indexes[i+0];
}
numverts += mesh->numvertexes;
numindexes += i;
}
else
{
float *vec;
medge_t *edge;
int lindex;
for (i = 0; i < surf->numedges; i++)
{
lindex = mod->surfedges[surf->firstedge + i];
if (lindex > 0)
{
edge = &mod->edges[lindex];
vec = mod->vertexes[edge->v[0]].position;
}
else
{
edge = &mod->edges[-lindex];
vec = mod->vertexes[edge->v[1]].position;
}
VectorSubtract(vec, geomcenter, (ed->ode.ode_vertex3f + 3*(numverts+i)));
}
for (i = 2; i < surf->numedges; i++)
{
//quake is backwards, not ode
ed->ode.ode_element3i[numindexes++] = numverts+i;
ed->ode.ode_element3i[numindexes++] = numverts+i-1;
ed->ode.ode_element3i[numindexes++] = numverts;
}
numverts += surf->numedges;
} }
numverts += mesh->numvertexes;
numindexes += mesh->numindexes;
} }
ed->ode.ode_numvertices = numverts;
ed->ode.ode_numtriangles = numindexes/3;
return true; return true;
} }
@ -1650,7 +1693,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
{ {
dBodyID body = (dBodyID)ed->ode.ode_body; dBodyID body = (dBodyID)ed->ode.ode_body;
dMass mass; dMass mass;
dReal test; float test;
void *dataID; void *dataID;
dVector3 capsulerot[3]; dVector3 capsulerot[3];
model_t *model; model_t *model;
@ -1676,7 +1719,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
vec_t massval = 1.0f; vec_t massval = 1.0f;
vec_t movelimit; vec_t movelimit;
vec_t radius; vec_t radius;
vec_t scale = 1.0f; vec_t scale;
vec_t spinlimit; vec_t spinlimit;
qboolean gravity; qboolean gravity;
#ifdef ODE_DYNAMIC #ifdef ODE_DYNAMIC
@ -1685,7 +1728,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
#endif #endif
solid = (int)ed->v->solid; solid = (int)ed->v->solid;
movetype = (int)ed->v->movetype; movetype = (int)ed->v->movetype;
scale = ed->xv->scale; scale = ed->xv->scale?ed->xv->scale:1;
modelindex = 0; modelindex = 0;
model = NULL; model = NULL;
@ -1698,7 +1741,8 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
{ {
VectorScale(model->mins, scale, entmins); VectorScale(model->mins, scale, entmins);
VectorScale(model->maxs, scale, entmaxs); VectorScale(model->maxs, scale, entmaxs);
massval = ed->xv->mass; if (ed->xv->mass)
massval = ed->xv->mass;
} }
else else
{ {
@ -1707,14 +1751,15 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
} }
break; break;
case SOLID_BBOX: case SOLID_BBOX:
//case SOLID_SLIDEBOX: case SOLID_SLIDEBOX:
case SOLID_CORPSE: case SOLID_CORPSE:
case SOLID_PHYSICS_BOX: case SOLID_PHYSICS_BOX:
case SOLID_PHYSICS_SPHERE: case SOLID_PHYSICS_SPHERE:
case SOLID_PHYSICS_CAPSULE: case SOLID_PHYSICS_CAPSULE:
VectorCopy(ed->v->mins, entmins); VectorCopy(ed->v->mins, entmins);
VectorCopy(ed->v->maxs, entmaxs); VectorCopy(ed->v->maxs, entmaxs);
massval = ed->xv->mass; if (ed->xv->mass)
massval = ed->xv->mass;
break; break;
default: default:
if (ed->ode.ode_physics) if (ed->ode.ode_physics)
@ -1771,7 +1816,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
if (!GenerateCollisionMesh(world, model, ed, geomcenter)) if (!GenerateCollisionMesh(world, model, ed, geomcenter))
break; break;
Matrix4_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]); Matrix4Q_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]);
// now create the geom // now create the geom
dataID = dGeomTriMeshDataCreate(); dataID = dGeomTriMeshDataCreate();
dGeomTriMeshDataBuildSingle(dataID, (void*)ed->ode.ode_vertex3f, sizeof(float[3]), ed->ode.ode_numvertices, ed->ode.ode_element3i, ed->ode.ode_numtriangles*3, sizeof(int[3])); dGeomTriMeshDataBuildSingle(dataID, (void*)ed->ode.ode_vertex3f, sizeof(float[3]), ed->ode.ode_numvertices, ed->ode.ode_element3i, ed->ode.ode_numtriangles*3, sizeof(int[3]));
@ -1782,12 +1827,12 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
case SOLID_SLIDEBOX: case SOLID_SLIDEBOX:
case SOLID_CORPSE: case SOLID_CORPSE:
case SOLID_PHYSICS_BOX: case SOLID_PHYSICS_BOX:
Matrix4_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]); Matrix4Q_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]);
ed->ode.ode_geom = (void *)dCreateBox(world->ode.ode_space, geomsize[0], geomsize[1], geomsize[2]); ed->ode.ode_geom = (void *)dCreateBox(world->ode.ode_space, geomsize[0], geomsize[1], geomsize[2]);
dMassSetBoxTotal(&mass, massval, geomsize[0], geomsize[1], geomsize[2]); dMassSetBoxTotal(&mass, massval, geomsize[0], geomsize[1], geomsize[2]);
break; break;
case SOLID_PHYSICS_SPHERE: case SOLID_PHYSICS_SPHERE:
Matrix4_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]); Matrix4Q_CreateTranslate(ed->ode.ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]);
ed->ode.ode_geom = (void *)dCreateSphere(world->ode.ode_space, geomsize[0] * 0.5f); ed->ode.ode_geom = (void *)dCreateSphere(world->ode.ode_space, geomsize[0] * 0.5f);
dMassSetSphereTotal(&mass, massval, geomsize[0] * 0.5f); dMassSetSphereTotal(&mass, massval, geomsize[0] * 0.5f);
break; break;
@ -1821,8 +1866,8 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
default: default:
Sys_Error("World_Physics_BodyFromEntity: unrecognized solid value %i was accepted by filter\n", solid); Sys_Error("World_Physics_BodyFromEntity: unrecognized solid value %i was accepted by filter\n", solid);
} }
Matrix4_Invert_Simple(ed->ode.ode_offsetmatrix, ed->ode.ode_offsetimatrix); Matrix4Q_Invert_Simple(ed->ode.ode_offsetmatrix, ed->ode.ode_offsetimatrix);
ed->ode.ode_massbuf = BZ_Malloc(sizeof(mass)); ed->ode.ode_massbuf = BZ_Malloc(sizeof(dMass));
memcpy(ed->ode.ode_massbuf, &mass, sizeof(dMass)); memcpy(ed->ode.ode_massbuf, &mass, sizeof(dMass));
} }
@ -1868,8 +1913,9 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
//val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_up);if (val) VectorCopy(val->vector, up); //val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_up);if (val) VectorCopy(val->vector, up);
//val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.spinvelocity);if (val) VectorCopy(val->vector, spinvelocity); //val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.spinvelocity);if (val) VectorCopy(val->vector, spinvelocity);
VectorCopy(ed->v->angles, angles); VectorCopy(ed->v->angles, angles);
angles[0] = 0;
VectorCopy(ed->v->avelocity, avelocity); VectorCopy(ed->v->avelocity, avelocity);
if (ed == world->edicts || (ed->xv->gravity && ed->xv->gravity < 0)) if (ed == world->edicts || (ed->xv->gravity && ed->xv->gravity <= 0.01))
gravity = false; gravity = false;
// compatibility for legacy entities // compatibility for legacy entities
@ -1966,9 +2012,9 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
VectorCopy(avelocity, ed->ode.ode_avelocity); VectorCopy(avelocity, ed->ode.ode_avelocity);
ed->ode.ode_gravity = gravity; ed->ode.ode_gravity = gravity;
Matrix4_FromVectors(entitymatrix, forward, left, up, origin); Matrix4Q_FromVectors(entitymatrix, forward, left, up, origin);
Matrix4_Multiply(bodymatrix, entitymatrix, ed->ode.ode_offsetmatrix); Matrix4_Multiply(entitymatrix, ed->ode.ode_offsetmatrix, bodymatrix);
Matrix4_ToVectors(bodymatrix, forward, left, up, origin); Matrix4Q_ToVectors(bodymatrix, forward, left, up, origin);
r[0][0] = forward[0]; r[0][0] = forward[0];
r[1][0] = forward[1]; r[1][0] = forward[1];
r[2][0] = forward[2]; r[2][0] = forward[2];
@ -2038,7 +2084,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
} }
#define MAX_CONTACTS 16 #define MAX_CONTACTS 16
static void nearCallback (void *data, dGeomID o1, dGeomID o2) static void VARGS nearCallback (void *data, dGeomID o1, dGeomID o2)
{ {
world_t *world = (world_t *)data; world_t *world = (world_t *)data;
dContact contact[MAX_CONTACTS]; // max contacts per collision pair dContact contact[MAX_CONTACTS]; // max contacts per collision pair
@ -2080,6 +2126,28 @@ static void nearCallback (void *data, dGeomID o1, dGeomID o2)
ed1 = (wedict_t *) dGeomGetData(o1); ed1 = (wedict_t *) dGeomGetData(o1);
if(ed1 && ed1->isfree) if(ed1 && ed1->isfree)
ed1 = NULL; ed1 = NULL;
ed2 = (wedict_t *) dGeomGetData(o2);
if(ed2 && ed2->isfree)
ed2 = NULL;
// generate contact points between the two non-space geoms
numcontacts = dCollide(o1, o2, MAX_CONTACTS, &(contact[0].geom), sizeof(contact[0]));
if (numcontacts)
{
if(ed1 && ed1->v->touch)
{
world->Event_Touch(world, ed1, ed2);
}
if(ed2 && ed2->v->touch)
{
world->Event_Touch(world, ed2, ed1);
}
/* if either ent killed itself, don't collide */
if ((ed1&&ed1->isfree) || (ed2&&ed2->isfree))
return;
}
if(ed1) if(ed1)
{ {
if (ed1->xv->bouncefactor) if (ed1->xv->bouncefactor)
@ -2089,9 +2157,6 @@ static void nearCallback (void *data, dGeomID o1, dGeomID o2)
bouncestop1 = ed1->xv->bouncestop; bouncestop1 = ed1->xv->bouncestop;
} }
ed2 = (wedict_t *) dGeomGetData(o2);
if(ed2 && ed2->isfree)
ed2 = NULL;
if(ed2) if(ed2)
{ {
if (ed2->xv->bouncefactor) if (ed2->xv->bouncefactor)
@ -2101,14 +2166,8 @@ static void nearCallback (void *data, dGeomID o1, dGeomID o2)
bouncestop2 = ed2->xv->bouncestop; bouncestop2 = ed2->xv->bouncestop;
} }
if(ed1 && ed1->v->touch) if (ed1->v->owner == ed2->entnum || ed2->v->owner == ed1->entnum)
{ return;
world->Event_Touch(world, ed1, ed2);
}
if(ed2 && ed2->v->touch)
{
world->Event_Touch(world, ed2, ed1);
}
// merge bounce factors and bounce stop // merge bounce factors and bounce stop
if(bouncefactor2 > 0) if(bouncefactor2 > 0)
@ -2130,12 +2189,13 @@ static void nearCallback (void *data, dGeomID o1, dGeomID o2)
dWorldGetGravity(world->ode.ode_world, grav); dWorldGetGravity(world->ode.ode_world, grav);
bouncestop1 *= fabs(grav[2]); bouncestop1 *= fabs(grav[2]);
// generate contact points between the two non-space geoms
numcontacts = dCollide(o1, o2, MAX_CONTACTS, &(contact[0].geom), sizeof(contact[0]));
// add these contact points to the simulation // add these contact points to the simulation
for (i = 0;i < numcontacts;i++) for (i = 0;i < numcontacts;i++)
{ {
contact[i].surface.mode = (physics_ode_contact_mu.value != -1 ? dContactApprox1 : 0) | (physics_ode_contact_erp.value != -1 ? dContactSoftERP : 0) | (physics_ode_contact_cfm.value != -1 ? dContactSoftCFM : 0) | (bouncefactor1 > 0 ? dContactBounce : 0); contact[i].surface.mode = (physics_ode_contact_mu.value != -1 ? dContactApprox1 : 0) |
(physics_ode_contact_erp.value != -1 ? dContactSoftERP : 0) |
(physics_ode_contact_cfm.value != -1 ? dContactSoftCFM : 0) |
(bouncefactor1 > 0 ? dContactBounce : 0);
contact[i].surface.mu = physics_ode_contact_mu.value; contact[i].surface.mu = physics_ode_contact_mu.value;
contact[i].surface.soft_erp = physics_ode_contact_erp.value; contact[i].surface.soft_erp = physics_ode_contact_erp.value;
contact[i].surface.soft_cfm = physics_ode_contact_cfm.value; contact[i].surface.soft_cfm = physics_ode_contact_cfm.value;
@ -2160,14 +2220,14 @@ void World_Physics_Frame(world_t *world, double frametime, double gravity)
// copy physics properties from entities to physics engine // copy physics properties from entities to physics engine
for (i = 0;i < world->num_edicts;i++) for (i = 0;i < world->num_edicts;i++)
{ {
ed = EDICT_NUM(world->progs, i); ed = (wedict_t*)EDICT_NUM(world->progs, i);
if (!ed->isfree) if (!ed->isfree)
World_Physics_Frame_BodyFromEntity(world, ed); World_Physics_Frame_BodyFromEntity(world, ed);
} }
// oh, and it must be called after all bodies were created // oh, and it must be called after all bodies were created
for (i = 0;i < world->num_edicts;i++) for (i = 0;i < world->num_edicts;i++)
{ {
ed = EDICT_NUM(world->progs, i); ed = (wedict_t*)EDICT_NUM(world->progs, i);
if (!ed->isfree) if (!ed->isfree)
World_Physics_Frame_JointFromEntity(world, ed); World_Physics_Frame_JointFromEntity(world, ed);
} }
@ -2188,8 +2248,6 @@ void World_Physics_Frame(world_t *world, double frametime, double gravity)
dWorldSetQuickStepNumIterations(world->ode.ode_world, bound(1, physics_ode_worldquickstep_iterations.ival, 200)); dWorldSetQuickStepNumIterations(world->ode.ode_world, bound(1, physics_ode_worldquickstep_iterations.ival, 200));
dWorldQuickStep(world->ode.ode_world, world->ode.ode_step); dWorldQuickStep(world->ode.ode_world, world->ode.ode_step);
} }
else if (physics_ode_worldstepfast.ival)
dWorldStepFast1(world->ode.ode_world, world->ode.ode_step, bound(1, physics_ode_worldstepfast_iterations.ival, 200));
else else
dWorldStep(world->ode.ode_world, world->ode.ode_step); dWorldStep(world->ode.ode_world, world->ode.ode_step);
@ -2200,7 +2258,7 @@ void World_Physics_Frame(world_t *world, double frametime, double gravity)
// copy physics properties from physics engine to entities // copy physics properties from physics engine to entities
for (i = 1;i < world->num_edicts;i++) for (i = 1;i < world->num_edicts;i++)
{ {
ed = EDICT_NUM(world->progs, i); ed = (wedict_t*)EDICT_NUM(world->progs, i);
if (!ed->isfree) if (!ed->isfree)
World_Physics_Frame_BodyToEntity(world, ed); World_Physics_Frame_BodyToEntity(world, ed);
} }

View file

@ -23,7 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <math.h> #include <math.h>
vec3_t vec3_origin = {0,0,0}; vec3_t vec3_origin = {0,0,0};
int nanmask = 255<<23;
/*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/
@ -877,7 +876,7 @@ float *Matrix4_NewTranslation(float x, float y, float z)
} }
//be aware that this generates two sorts of matricies depending on order of a+b //be aware that this generates two sorts of matricies depending on order of a+b
void Matrix4_Multiply(float *a, float *b, float *out) void Matrix4_Multiply(const float *a, const float *b, float *out)
{ {
out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3]; out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3];
out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3]; out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3];
@ -901,7 +900,7 @@ void Matrix4_Multiply(float *a, float *b, float *out)
} }
//transform 4d vector by a 4d matrix. //transform 4d vector by a 4d matrix.
void Matrix4_Transform4(float *matrix, float *vector, float *product) void Matrix4_Transform4(const float *matrix, const float *vector, float *product)
{ {
product[0] = matrix[0]*vector[0] + matrix[4]*vector[1] + matrix[8]*vector[2] + matrix[12]*vector[3]; product[0] = matrix[0]*vector[0] + matrix[4]*vector[1] + matrix[8]*vector[2] + matrix[12]*vector[3];
product[1] = matrix[1]*vector[0] + matrix[5]*vector[1] + matrix[9]*vector[2] + matrix[13]*vector[3]; product[1] = matrix[1]*vector[0] + matrix[5]*vector[1] + matrix[9]*vector[2] + matrix[13]*vector[3];
@ -909,7 +908,7 @@ void Matrix4_Transform4(float *matrix, float *vector, float *product)
product[3] = matrix[3]*vector[0] + matrix[7]*vector[1] + matrix[11]*vector[2] + matrix[15]*vector[3]; product[3] = matrix[3]*vector[0] + matrix[7]*vector[1] + matrix[11]*vector[2] + matrix[15]*vector[3];
} }
void Matrix4_Transform3(float *matrix, float *vector, float *product) void Matrix4_Transform3(const float *matrix, const float *vector, float *product)
{ {
product[0] = matrix[0]*vector[0] + matrix[4]*vector[1] + matrix[8]*vector[2] + matrix[12]; product[0] = matrix[0]*vector[0] + matrix[4]*vector[1] + matrix[8]*vector[2] + matrix[12];
product[1] = matrix[1]*vector[0] + matrix[5]*vector[1] + matrix[9]*vector[2] + matrix[13]; product[1] = matrix[1]*vector[0] + matrix[5]*vector[1] + matrix[9]*vector[2] + matrix[13];
@ -951,6 +950,29 @@ void Matrix4_CreateTranslate (float *out, float x, float y, float z)
memcpy(out, Matrix4_NewTranslation(x, y, z), 16*sizeof(float)); memcpy(out, Matrix4_NewTranslation(x, y, z), 16*sizeof(float));
} }
void Matrix4Q_CreateTranslate (float *out, float x, float y, float z)
{
out[0] = 1;
out[4] = 0;
out[8] = 0;
out[12] = 0;
out[1] = 0;
out[5] = 1;
out[9] = 0;
out[13] = 0;
out[2] = 0;
out[6] = 0;
out[10] = 1;
out[14] = 0;
out[3] = x;
out[7] = y;
out[11] = z;
out[15] = 1;
}
void Matrix4_ModelViewMatrixFromAxis(float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg) void Matrix4_ModelViewMatrixFromAxis(float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg)
{ {
float tempmat[16]; float tempmat[16];
@ -976,7 +998,7 @@ void Matrix4_ModelViewMatrixFromAxis(float *modelview, const vec3_t pn, const ve
} }
void Matrix4_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]) void Matrix4Q_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3])
{ {
vx[0] = in[0]; vx[0] = in[0];
vx[1] = in[4]; vx[1] = in[4];
@ -995,23 +1017,23 @@ void Matrix4_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], f
t [2] = in[11]; t [2] = in[11];
} }
void Matrix4_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]) void Matrix4Q_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3])
{ {
out[0] = vx[0]; out[0] = vx[0];
out[4] = vy[0]; out[1] = vy[0];
out[8] = vz[0]; out[2] = vz[0];
out[12] = t[0]; out[3] = t[0];
out[1] = vx[1]; out[4] = vx[1];
out[5] = vy[1]; out[5] = vy[1];
out[9] = vz[1]; out[6] = vz[1];
out[13] = t[1]; out[7] = t[1];
out[2] = vx[2]; out[8] = vx[2];
out[6] = vy[2]; out[9] = vy[2];
out[10] = vz[2]; out[10] = vz[2];
out[14] = t[2]; out[11] = t[2];
out[3] = 0.0f; out[12] = 0.0f;
out[7] = 0.0f; out[13] = 0.0f;
out[11] = 0.0f; out[14] = 0.0f;
out[15] = 1.0f; out[15] = 1.0f;
} }
@ -1397,7 +1419,7 @@ qboolean Matrix4_Invert(const float *m, float *out)
#undef SWAP_ROWS #undef SWAP_ROWS
} }
void Matrix4_Invert_Simple (const float *in1, float *out) void Matrix4Q_Invert_Simple (const float *in1, float *out)
{ {
// we only support uniform scaling, so assume the first row is enough // we only support uniform scaling, so assume the first row is enough
// (note the lack of sqrt here, because we're trying to undo the scaling, // (note the lack of sqrt here, because we're trying to undo the scaling,

View file

@ -55,10 +55,10 @@ typedef int fixed16_t;
struct mplane_s; struct mplane_s;
extern vec3_t vec3_origin; extern vec3_t vec3_origin;
extern int nanmask;
#define bound(min,num,max) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min)) #define bound(min,num,max) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min))
#define nanmask (255<<23)
#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask) #define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]) #define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
@ -131,19 +131,20 @@ float Q_rsqrt(float number);
void Matrix3_Multiply (vec3_t *in1, vec3_t *in2, vec3_t *out); void Matrix3_Multiply (vec3_t *in1, vec3_t *in2, vec3_t *out);
void Matrix4_Identity(float *outm); void Matrix4_Identity(float *outm);
qboolean Matrix4_Invert(const float *m, float *out); qboolean Matrix4_Invert(const float *m, float *out);
void Matrix4_Invert_Simple (const float *in1, float *out); void Matrix4Q_Invert_Simple (const float *in1, float *out);
void Matrix4_CreateTranslate (float *out, float x, float y, float z); void Matrix4_CreateTranslate (float *out, float x, float y, float z);
void Matrix4Q_CreateTranslate (float *out, float x, float y, float z);
void Matrix4_ModelMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg); void Matrix4_ModelMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg);
void Matrix4_ModelViewMatrix (float *modelview, const vec3_t viewangles, const vec3_t vieworg); void Matrix4_ModelViewMatrix (float *modelview, const vec3_t viewangles, const vec3_t vieworg);
void Matrix4_ModelViewMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg); void Matrix4_ModelViewMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg);
void Matrix4_CreateFromQuakeEntity (float *matrix, float x, float y, float z, float pitch, float yaw, float roll, float scale); void Matrix4_CreateFromQuakeEntity (float *matrix, float x, float y, float z, float pitch, float yaw, float roll, float scale);
void Matrix4_Multiply (float *a, float *b, float *out); void Matrix4_Multiply (const float *a, const float *b, float *out);
void Matrix4_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy); void Matrix4_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy);
void Matrix4_Transform3 (float *matrix, float *vector, float *product); void Matrix4_Transform3 (const float *matrix, const float *vector, float *product);
void Matrix4_Transform4 (float *matrix, float *vector, float *product); void Matrix4_Transform4 (const float *matrix, const float *vector, float *product);
void Matrix4_UnProject (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy); void Matrix4_UnProject (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy);
void Matrix4_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]); void Matrix4Q_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]);
void Matrix4_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]); void Matrix4Q_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]);
#define AngleVectorsFLU(a,f,l,u) do{AngleVectors(a,f,l,u);VectorNegate(l,l);}while(0) #define AngleVectorsFLU(a,f,l,u) do{AngleVectors(a,f,l,u);VectorNegate(l,l);}while(0)

View file

@ -690,6 +690,10 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
} }
} }
#ifdef USEODE
World_Physics_End(&sv.world);
#endif
// wipe the entire per-level structure // wipe the entire per-level structure
memset (&sv, 0, sizeof(sv)); memset (&sv, 0, sizeof(sv));
@ -826,7 +830,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
Info_SetValueForStarKey(svs.info, "*startspot", "", MAX_SERVERINFO_STRING); Info_SetValueForStarKey(svs.info, "*startspot", "", MAX_SERVERINFO_STRING);
// //
// clear physics interaction links // init physics interaction links
// //
World_ClearWorld (&sv.world); World_ClearWorld (&sv.world);
@ -864,9 +868,6 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
Info_RemoveKey(svs.info, "*csqcdebug"); Info_RemoveKey(svs.info, "*csqcdebug");
#endif #endif
if (svs.gametype == GT_PROGS) if (svs.gametype == GT_PROGS)
{ {
if (svprogfuncs) //we don't want the q1 stuff anymore. if (svprogfuncs) //we don't want the q1 stuff anymore.