From cbc820e3534a6dea25645c8242df02cf02e48679 Mon Sep 17 00:00:00 2001 From: divverent Date: Fri, 23 Oct 2009 09:11:54 +0000 Subject: [PATCH] make ODE entities call touch functions git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9387 d7cf8633-e32d-0410-b094-e92efae38249 --- server.h | 1 + sv_phys.c | 90 +++++++++++++++++++++++++++++++++++++++++-------------- world.c | 68 ++++++++++++++++++++++++++--------------- 3 files changed, 112 insertions(+), 47 deletions(-) diff --git a/server.h b/server.h index 38697488..53ada655 100644 --- 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 diff --git a/sv_phys.c b/sv_phys.c index db221566..e189ee92 100644 --- 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 39d985d0..42fd70de 100644 --- 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); } } -- 2.39.2