make ODE entities call touch functions
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 23 Oct 2009 09:11:54 +0000 (09:11 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 23 Oct 2009 09:11:54 +0000 (09:11 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9387 d7cf8633-e32d-0410-b094-e92efae38249

server.h
sv_phys.c
world.c

index 3869748..53ada65 100644 (file)
--- a/server.h
+++ b/server.h
@@ -520,6 +520,7 @@ qboolean SV_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean
  */
 void SV_LinkEdict(prvm_edict_t *ent);
 void SV_LinkEdict_TouchAreaGrid(prvm_edict_t *ent);
+void SV_LinkEdict_TouchAreaGrid_Call(prvm_edict_t *touch, prvm_edict_t *ent); // if we detected a touch from another source
 
 /*! move an entity that is stuck by small amounts in various directions to try to nudge it back into the collision hull
  * returns true if it found a better place
index db22156..e189ee9 100644 (file)
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -690,6 +690,32 @@ Linking entities into the world culling system
 ===============================================================================
 */
 
+void SV_LinkEdict_TouchAreaGrid_Call(prvm_edict_t *touch, prvm_edict_t *ent)
+{
+       prvm_eval_t *val;
+       prog->globals.server->self = PRVM_EDICT_TO_PROG(touch);
+       prog->globals.server->other = PRVM_EDICT_TO_PROG(ent);
+       prog->globals.server->time = sv.time;
+       prog->globals.server->trace_allsolid = false;
+       prog->globals.server->trace_startsolid = false;
+       prog->globals.server->trace_fraction = 1;
+       prog->globals.server->trace_inwater = false;
+       prog->globals.server->trace_inopen = true;
+       VectorCopy (touch->fields.server->origin, prog->globals.server->trace_endpos);
+       VectorSet (prog->globals.server->trace_plane_normal, 0, 0, 1);
+       prog->globals.server->trace_plane_dist = 0;
+       prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(ent);
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents)))
+               val->_float = 0;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents)))
+               val->_float = 0;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags)))
+               val->_float = 0;
+       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename)))
+               val->string = 0;
+       PRVM_ExecuteProgram (touch->fields.server->touch, "QC function self.touch is missing");
+}
+
 void SV_LinkEdict_TouchAreaGrid(prvm_edict_t *ent)
 {
        int i, numtouchedicts, old_self, old_other;
@@ -721,34 +747,44 @@ void SV_LinkEdict_TouchAreaGrid(prvm_edict_t *ent)
                touch = touchedicts[i];
                if (touch != ent && (int)touch->fields.server->solid == SOLID_TRIGGER && touch->fields.server->touch)
                {
-                       prvm_eval_t *val;
-                       prog->globals.server->self = PRVM_EDICT_TO_PROG(touch);
-                       prog->globals.server->other = PRVM_EDICT_TO_PROG(ent);
-                       prog->globals.server->time = sv.time;
-                       prog->globals.server->trace_allsolid = false;
-                       prog->globals.server->trace_startsolid = false;
-                       prog->globals.server->trace_fraction = 1;
-                       prog->globals.server->trace_inwater = false;
-                       prog->globals.server->trace_inopen = true;
-                       VectorCopy (touch->fields.server->origin, prog->globals.server->trace_endpos);
-                       VectorSet (prog->globals.server->trace_plane_normal, 0, 0, 1);
-                       prog->globals.server->trace_plane_dist = 0;
-                       prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(ent);
-                       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents)))
-                               val->_float = 0;
-                       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents)))
-                               val->_float = 0;
-                       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags)))
-                               val->_float = 0;
-                       if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename)))
-                               val->string = 0;
-                       PRVM_ExecuteProgram (touch->fields.server->touch, "QC function self.touch is missing");
+                       SV_LinkEdict_TouchAreaGrid_Call(touch, ent);
                }
        }
        prog->globals.server->self = old_self;
        prog->globals.server->other = old_other;
 }
 
+static void RotateBBox(const vec3_t mins, const vec3_t maxs, const vec3_t angles, vec3_t rotatedmins, vec3_t rotatedmaxs)
+{
+       vec3_t v, u;
+       matrix4x4_t m;
+       Matrix4x4_CreateFromQuakeEntity(&m, 0, 0, 0, angles[PITCH], angles[YAW], angles[ROLL], 1.0);
+
+       v[0] = mins[0]; v[1] = mins[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+               VectorCopy(u, rotatedmins); VectorCopy(u, rotatedmaxs);
+       v[0] = maxs[0]; v[1] = mins[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+               if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+               if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+       v[0] = mins[0]; v[1] = maxs[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+               if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+               if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+       v[0] = maxs[0]; v[1] = maxs[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+               if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+               if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+       v[0] = mins[0]; v[1] = mins[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+               if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+               if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+       v[0] = maxs[0]; v[1] = mins[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+               if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+               if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+       v[0] = mins[0]; v[1] = maxs[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+               if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+               if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+       v[0] = maxs[0]; v[1] = maxs[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+               if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+               if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+}
+
 /*
 ===============
 SV_LinkEdict
@@ -768,7 +804,15 @@ void SV_LinkEdict (prvm_edict_t *ent)
 
 // set the abs box
 
-       if (ent->fields.server->solid == SOLID_BSP)
+       if (ent->fields.server->movetype == MOVETYPE_PHYSICS)
+       {
+               // TODO maybe should do this for rotating SOLID_BSP too? Would behave better with rotating doors
+               // TODO special handling for spheres?
+               RotateBBox(ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->angles, mins, maxs);
+               VectorAdd(ent->fields.server->origin, mins, mins);
+               VectorAdd(ent->fields.server->origin, maxs, maxs);
+       }
+       else if (ent->fields.server->solid == SOLID_BSP)
        {
                int modelindex = (int)ent->fields.server->modelindex;
                if (modelindex < 0 || modelindex >= MAX_MODELS)
diff --git a/world.c b/world.c
index 39d985d..42fd70d 100644 (file)
--- a/world.c
+++ b/world.c
@@ -863,8 +863,8 @@ void            (ODE_API *dSpaceDestroy)(dSpaceID);
 //int             (ODE_API *dSpaceGetClass)(dSpaceID space);
 //
 void            (ODE_API *dGeomDestroy)(dGeomID geom);
-//void            (ODE_API *dGeomSetData)(dGeomID geom, void* data);
-//void *          (ODE_API *dGeomGetData)(dGeomID geom);
+void            (ODE_API *dGeomSetData)(dGeomID geom, void* data);
+void *          (ODE_API *dGeomGetData)(dGeomID geom);
 void            (ODE_API *dGeomSetBody)(dGeomID geom, dBodyID body);
 dBodyID         (ODE_API *dGeomGetBody)(dGeomID geom);
 void            (ODE_API *dGeomSetPosition)(dGeomID geom, dReal x, dReal y, dReal z);
@@ -1713,6 +1713,12 @@ static void World_Physics_Frame_BodyToEntity(world_t *world, prvm_edict_t *ed)
        VectorCopy(angles, ed->priv.server->ode_angles);
        VectorCopy(avelocity, ed->priv.server->ode_avelocity);
        ed->priv.server->ode_gravity = dBodyGetGravityMode(body);
+
+       if(!strcmp(prog->name, "server")) // FIXME some better way?
+       {
+               SV_LinkEdict(ed);
+               SV_LinkEdict_TouchAreaGrid(ed);
+       }
 }
 
 static void World_Physics_Frame_JointFromEntity(world_t *world, prvm_edict_t *ed)
@@ -2080,6 +2086,8 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
                Matrix4x4_Invert_Simple(&ed->priv.server->ode_offsetimatrix, &ed->priv.server->ode_offsetmatrix);
        }
 
+       if(ed->priv.server->ode_geom)
+               dGeomSetData(ed->priv.server->ode_geom, (void*)ed);
        if (movetype == MOVETYPE_PHYSICS && ed->priv.server->ode_geom)
        {
                if (ed->priv.server->ode_body == NULL)
@@ -2185,6 +2193,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
                matrix4x4_t entitymatrix;
                matrix4x4_t bodymatrix;
 
+#if 0
                Con_Printf("entity %i got changed by QC\n", (int) (ed - prog->edicts));
                if(!VectorCompare(origin, ed->priv.server->ode_origin))
                        Con_Printf("  origin: %f %f %f -> %f %f %f\n", ed->priv.server->ode_origin[0], ed->priv.server->ode_origin[1], ed->priv.server->ode_origin[2], origin[0], origin[1], origin[2]);
@@ -2196,6 +2205,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
                        Con_Printf("  avelocity: %f %f %f -> %f %f %f\n", ed->priv.server->ode_avelocity[0], ed->priv.server->ode_avelocity[1], ed->priv.server->ode_avelocity[2], avelocity[0], avelocity[1], avelocity[2]);
                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);
@@ -2301,7 +2311,7 @@ static void nearCallback (void *data, dGeomID o1, dGeomID o2)
        float bouncefactor2 = 0.0f;
        float bouncestop2 = 60.0f / 800.0f;
        dVector3 grav;
-       prvm_edict_t *ed;
+       prvm_edict_t *ed1, *ed2;
 
        if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
        {
@@ -2325,33 +2335,43 @@ static void nearCallback (void *data, dGeomID o1, dGeomID o2)
        if (b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact))
                return;
 
-       if(b1)
+       ed1 = (prvm_edict_t *) dGeomGetData(o1);
+       if(ed1 && ed1->priv.server->free)
+               ed1 = NULL;
+       if(ed1)
        {
-               ed = (prvm_edict_t *) dBodyGetData(b1);
-               if(ed)
-               {
-                       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.bouncefactor);
-                       if (val!=0 && val->_float)
-                               bouncefactor1 = val->_float;
+               val = PRVM_EDICTFIELDVALUE(ed1, prog->fieldoffsets.bouncefactor);
+               if (val!=0 && val->_float)
+                       bouncefactor1 = val->_float;
 
-                       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.bouncestop);
-                       if (val!=0 && val->_float)
-                               bouncestop1 = val->_float;
-               }
+               val = PRVM_EDICTFIELDVALUE(ed1, prog->fieldoffsets.bouncestop);
+               if (val!=0 && val->_float)
+                       bouncestop1 = val->_float;
        }
 
-       if(b2)
+       ed2 = (prvm_edict_t *) dGeomGetData(o2);
+       if(ed2 && ed2->priv.server->free)
+               ed2 = NULL;
+       if(ed2)
        {
-               ed = (prvm_edict_t *) dBodyGetData(b2);
-               if(ed)
-               {
-                       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.bouncefactor);
-                       if (val!=0 && val->_float)
-                               bouncefactor2 = val->_float;
+               val = PRVM_EDICTFIELDVALUE(ed2, prog->fieldoffsets.bouncefactor);
+               if (val!=0 && val->_float)
+                       bouncefactor2 = val->_float;
 
-                       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.bouncestop);
-                       if (val!=0 && val->_float)
-                               bouncestop2 = val->_float;
+               val = PRVM_EDICTFIELDVALUE(ed2, prog->fieldoffsets.bouncestop);
+               if (val!=0 && val->_float)
+                       bouncestop2 = val->_float;
+       }
+
+       if(!strcmp(prog->name, "server"))
+       {
+               if(ed1 && ed1->fields.server->touch)
+               {
+                       SV_LinkEdict_TouchAreaGrid_Call(ed1, ed2 ? ed2 : prog->edicts);
+               }
+               if(ed2 && ed2->fields.server->touch)
+               {
+                       SV_LinkEdict_TouchAreaGrid_Call(ed2, ed1 ? ed1 : prog->edicts);
                }
        }