DP_PHYSICS_ODE: new SOLID_PHYSICS_CYLINDER. New "massofs" vector field (shifts center...
authorvortex <vortex@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 25 Sep 2011 02:08:56 +0000 (02:08 +0000)
committervortex <vortex@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 25 Sep 2011 02:08:56 +0000 (02:08 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11368 d7cf8633-e32d-0410-b094-e92efae38249

dpdefs/dpextensions.qc
progs.h
prvm_offsets.h
server.h
world.c

index 889e283..f88283b 100644 (file)
@@ -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 3021914..72813bb 100644 (file)
--- 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;
index 3293081..3e6dc0e 100644 (file)
@@ -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)
index a83e6f3..34c68e2 100644 (file)
--- 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 3a6503d..f228ec5 100644 (file)
--- 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;