From 61f44ced2c1db2784bcdb2fe4151fc6f5342248a Mon Sep 17 00:00:00 2001 From: vortex Date: Sun, 25 Sep 2011 02:08:56 +0000 Subject: [PATCH] DP_PHYSICS_ODE: new SOLID_PHYSICS_CYLINDER. New "massofs" vector field (shifts center-of-mass from model center, replaces default 'center of mins/maxs' approach). New "friction" field. Contact friction = cvar:physics_ode_contact_mu * object1.friction * object2.friction. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11368 d7cf8633-e32d-0410-b094-e92efae38249 --- dpdefs/dpextensions.qc | 4 +++- progs.h | 1 + prvm_offsets.h | 6 ++++++ server.h | 1 + world.c | 37 +++++++++++++++++++++++++++---------- 5 files changed, 38 insertions(+), 11 deletions(-) diff --git a/dpdefs/dpextensions.qc b/dpdefs/dpextensions.qc index 889e2839..f88283b5 100644 --- a/dpdefs/dpextensions.qc +++ b/dpdefs/dpextensions.qc @@ -1617,6 +1617,7 @@ const float SOLID_PHYSICS_BOX = 32; const float SOLID_PHYSICS_SPHERE = 33; const float SOLID_PHYSICS_CAPSULE = 34; const float SOLID_PHYSICS_TRIMESH = 35; +const float SOLID_PHYSICS_CYLINDER = 36; //SOLID_BSP; //joint types: const float JOINTTYPE_POINT = 1; @@ -1639,6 +1640,8 @@ const float JOINTTYPE_FIXED = -1; // note that ODE does not support both in one anyway //field definitions: .float mass; // ODE mass, standart value is 1 +.vector massofs; // offsets a mass center out of object center, if not set a center of model bounds is used +.float friction; .float bouncefactor; .float bouncestop; .float jointtype; @@ -1649,7 +1652,6 @@ void(entity e, vector torque) physics_addtorque = #542; // add relative torque //description: provides Open Dynamics Engine support, requires extenal dll to be present or engine compiled with statical link option //be sure to checkextension for it to know if library is loaded and ready, also to enable physics set "physics_ode" cvar to 1 //note: this extension is highly experimental and may be unstable -//note: use SOLID_BSP on entities to get a trimesh collision models on them //DP_SV_PRINT //idea: id Software (QuakeWorld Server) diff --git a/progs.h b/progs.h index 30219148..72813bbf 100644 --- a/progs.h +++ b/progs.h @@ -106,6 +106,7 @@ typedef struct edict_engineprivate_s vec3_t ode_mins; vec3_t ode_maxs; vec_t ode_mass; + float ode_friction; vec3_t ode_origin; vec3_t ode_velocity; vec3_t ode_angles; diff --git a/prvm_offsets.h b/prvm_offsets.h index 3293081a..3e6dc0ea 100644 --- a/prvm_offsets.h +++ b/prvm_offsets.h @@ -29,6 +29,8 @@ PRVM_DECLARE_clientfieldfloat(lerpfrac) PRVM_DECLARE_clientfieldfloat(lerpfrac3) PRVM_DECLARE_clientfieldfloat(lerpfrac4) PRVM_DECLARE_clientfieldfloat(mass) +PRVM_DECLARE_clientfieldvector(massofs) +PRVM_DECLARE_clientfieldfloat(friction) PRVM_DECLARE_clientfieldfloat(modelindex) PRVM_DECLARE_clientfieldfloat(movetype) PRVM_DECLARE_clientfieldfloat(nextthink) @@ -305,6 +307,8 @@ PRVM_DECLARE_field(lerpfrac4) PRVM_DECLARE_field(light_lev) PRVM_DECLARE_field(ltime) PRVM_DECLARE_field(mass) +PRVM_DECLARE_field(massofs) +PRVM_DECLARE_field(friction) PRVM_DECLARE_field(max_health) PRVM_DECLARE_field(maxs) PRVM_DECLARE_field(message) @@ -661,6 +665,8 @@ PRVM_DECLARE_serverfieldfloat(lerpfrac4) PRVM_DECLARE_serverfieldfloat(light_lev) PRVM_DECLARE_serverfieldfloat(ltime) PRVM_DECLARE_serverfieldfloat(mass) +PRVM_DECLARE_serverfieldvector(massofs) +PRVM_DECLARE_serverfieldfloat(friction) PRVM_DECLARE_serverfieldfloat(max_health) PRVM_DECLARE_serverfieldfloat(modelflags) PRVM_DECLARE_serverfieldfloat(modelindex) diff --git a/server.h b/server.h index a83e6f30..34c68e2d 100644 --- a/server.h +++ b/server.h @@ -332,6 +332,7 @@ typedef struct client_s #define SOLID_PHYSICS_SPHERE 33 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity) #define SOLID_PHYSICS_CAPSULE 34 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity) #define SOLID_PHYSICS_TRIMESH 35 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity) +#define SOLID_PHYSICS_CYLINDER 36 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity) // edict->deadflag values #define DEAD_NO 0 diff --git a/world.c b/world.c index 3a6503d7..f228ec55 100644 --- a/world.c +++ b/world.c @@ -559,7 +559,7 @@ void (ODE_API *dMassSetSphereTotal)(dMass *, dReal total_mass, dReal //void (ODE_API *dMassSetCapsule)(dMass *, dReal density, int direction, dReal radius, dReal length); void (ODE_API *dMassSetCapsuleTotal)(dMass *, dReal total_mass, int direction, dReal radius, dReal length); //void (ODE_API *dMassSetCylinder)(dMass *, dReal density, int direction, dReal radius, dReal length); -//void (ODE_API *dMassSetCylinderTotal)(dMass *, dReal total_mass, int direction, dReal radius, dReal length); +void (ODE_API *dMassSetCylinderTotal)(dMass *, dReal total_mass, int direction, dReal radius, dReal length); //void (ODE_API *dMassSetBox)(dMass *, dReal density, dReal lx, dReal ly, dReal lz); void (ODE_API *dMassSetBoxTotal)(dMass *, dReal total_mass, dReal lx, dReal ly, dReal lz); //void (ODE_API *dMassSetTrimesh)(dMass *, dReal density, dGeomID g); @@ -950,7 +950,7 @@ dGeomID (ODE_API *dCreateCapsule)(dSpaceID space, dReal radius, dReal le //void (ODE_API *dGeomCapsuleGetParams)(dGeomID ccylinder, dReal *radius, dReal *length); //dReal (ODE_API *dGeomCapsulePointDepth)(dGeomID ccylinder, dReal x, dReal y, dReal z); // -//dGeomID (ODE_API *dCreateCylinder)(dSpaceID space, dReal radius, dReal length); +dGeomID (ODE_API *dCreateCylinder)(dSpaceID space, dReal radius, dReal length); //void (ODE_API *dGeomCylinderSetParams)(dGeomID cylinder, dReal radius, dReal length); //void (ODE_API *dGeomCylinderGetParams)(dGeomID cylinder, dReal *radius, dReal *length); // @@ -1026,7 +1026,7 @@ static dllfunction_t odefuncs[] = // {"dMassSetCapsule", (void **) &dMassSetCapsule}, {"dMassSetCapsuleTotal", (void **) &dMassSetCapsuleTotal}, // {"dMassSetCylinder", (void **) &dMassSetCylinder}, -// {"dMassSetCylinderTotal", (void **) &dMassSetCylinderTotal}, + {"dMassSetCylinderTotal", (void **) &dMassSetCylinderTotal}, // {"dMassSetBox", (void **) &dMassSetBox}, {"dMassSetBoxTotal", (void **) &dMassSetBoxTotal}, // {"dMassSetTrimesh", (void **) &dMassSetTrimesh}, @@ -1408,7 +1408,7 @@ static dllfunction_t odefuncs[] = // {"dGeomCapsuleSetParams", (void **) &dGeomCapsuleSetParams}, // {"dGeomCapsuleGetParams", (void **) &dGeomCapsuleGetParams}, // {"dGeomCapsulePointDepth", (void **) &dGeomCapsulePointDepth}, -// {"dCreateCylinder", (void **) &dCreateCylinder}, + {"dCreateCylinder", (void **) &dCreateCylinder}, // {"dGeomCylinderSetParams", (void **) &dGeomCylinderSetParams}, // {"dGeomCylinderGetParams", (void **) &dGeomCylinderGetParams}, // {"dCreateRay", (void **) &dCreateRay}, @@ -2134,6 +2134,12 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed) if (movetype != MOVETYPE_PHYSICS) massval = 1.0f; + // get friction from entity + if (PRVM_gameedictfloat(ed, friction)) + ed->priv.server->ode_friction = PRVM_gameedictfloat(ed, friction); + else + ed->priv.server->ode_friction = 1.0; + // check if we need to create or replace the geom if (!ed->priv.server->ode_physics || !VectorCompare(ed->priv.server->ode_mins, entmins) @@ -2149,8 +2155,11 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed) ed->priv.server->ode_mass = massval; ed->priv.server->ode_modelindex = modelindex; VectorMAM(0.5f, entmins, 0.5f, entmaxs, geomcenter); + if (PRVM_gameedictvector(ed, massofs)) + VectorCopy(geomcenter, PRVM_gameedictvector(ed, massofs)); + else + VectorMAM(0.5f, entmins, 0.5f, entmaxs, geomcenter); ed->priv.server->ode_movelimit = min(geomsize[0], min(geomsize[1], geomsize[2])); - if (massval * geomsize[0] * geomsize[1] * geomsize[2] == 0) { if (movetype == MOVETYPE_PHYSICS) @@ -2221,6 +2230,7 @@ treatasbox: dMassSetSphereTotal(&mass, massval, geomsize[0] * 0.5f); break; case SOLID_PHYSICS_CAPSULE: + case SOLID_PHYSICS_CYLINDER: axisindex = 0; if (geomsize[axisindex] < geomsize[1]) axisindex = 1; @@ -2242,8 +2252,16 @@ treatasbox: // because we want to support more than one axisindex, we have to // create a transform, and turn on its cleanup setting (which will // cause the child to be destroyed when it is destroyed) - ed->priv.server->ode_geom = (void *)dCreateCapsule((dSpaceID)world->physics.ode_space, radius, length); - dMassSetCapsuleTotal(&mass, massval, axisindex+1, radius, length); + if (solid == SOLID_PHYSICS_CAPSULE) + { + ed->priv.server->ode_geom = (void *)dCreateCapsule((dSpaceID)world->physics.ode_space, radius, length); + dMassSetCapsuleTotal(&mass, massval, axisindex+1, radius, length); + } + else + { + ed->priv.server->ode_geom = (void *)dCreateCylinder((dSpaceID)world->physics.ode_space, radius, length); + dMassSetCylinderTotal(&mass, massval, axisindex+1, radius, length); + } break; default: Sys_Error("World_Physics_BodyFromEntity: unrecognized solid value %i was accepted by filter\n", solid); @@ -2257,7 +2275,7 @@ treatasbox: memcpy(ed->priv.server->ode_massbuf, &mass, sizeof(dMass)); } - if(ed->priv.server->ode_geom) + if (ed->priv.server->ode_geom) dGeomSetData((dGeomID)ed->priv.server->ode_geom, (void*)ed); if (movetype == MOVETYPE_PHYSICS && ed->priv.server->ode_geom) { @@ -2405,7 +2423,6 @@ treatasbox: if(gravity != ed->priv.server->ode_gravity) Con_Printf(" gravity: %i -> %i\n", ed->priv.server->ode_gravity, gravity); #endif - // values for BodyFromEntity to check if the qc modified anything later VectorCopy(origin, ed->priv.server->ode_origin); VectorCopy(velocity, ed->priv.server->ode_velocity); @@ -2593,7 +2610,7 @@ static void nearCallback (void *data, dGeomID o1, dGeomID o2) 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.mu = physics_ode_contact_mu.value; + contact[i].surface.mu = physics_ode_contact_mu.value * ed1->priv.server->ode_friction * ed2->priv.server->ode_friction; contact[i].surface.soft_erp = physics_ode_contact_erp.value; contact[i].surface.soft_cfm = physics_ode_contact_cfm.value; contact[i].surface.bounce = bouncefactor1; -- 2.39.2