From: divverent Date: Thu, 22 Oct 2009 06:42:34 +0000 (+0000) Subject: ODE: joints X-Git-Tag: xonotic-v0.1.0preview~1265 X-Git-Url: https://git.xonotic.org/?a=commitdiff_plain;h=556467b184719f636ebc0bea884afe808a238c4b;p=xonotic%2Fdarkplaces.git ODE: joints fields: jointtype, origin, angles, and depending on joint type, velocity as secondary axis also, clean up pitchsign code to make ODE work with bmodels git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9373 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cl_main.c b/cl_main.c index af8c3103..bf4d1d80 100644 --- a/cl_main.c +++ b/cl_main.c @@ -1001,6 +1001,7 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat // if model is alias or this is a tenebrae-like dlight, reverse pitch direction else if (e->state_current.lightpflags & PFLAGS_FULLDYNAMIC) angles[0] = -angles[0]; + // NOTE: this must be synced to SV_GetPitchSign! if ((e->render.effects & EF_ROTATE) && !(e->render.flags & RENDER_VIEWMODEL)) { diff --git a/clvm_cmds.c b/clvm_cmds.c index 77456632..959e043e 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -2232,12 +2232,19 @@ int CL_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, cons return 1; } +int CL_GetPitchSign(prvm_edict_t *ent) +{ + dp_model_t *model; + if ((model = CL_GetModelFromEdict(ent)) && model->type == mod_alias) + return -1; + return 1; +} + void CL_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatrix) { prvm_eval_t *val; float scale; float pitchsign = 1; - dp_model_t *model; scale = 1; val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale); @@ -2249,8 +2256,7 @@ void CL_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatri Matrix4x4_CreateFromQuakeEntity(out, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], scale * cl_viewmodel_scale.value); else { - if ((model = CL_GetModelFromEdict(ent)) && model->type == mod_alias) - pitchsign = -1; + pitchsign = CL_GetPitchSign(ent); Matrix4x4_CreateFromQuakeEntity(out, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], pitchsign * ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], scale); } } diff --git a/clvm_cmds.h b/clvm_cmds.h index f0813812..32aebeb8 100644 --- a/clvm_cmds.h +++ b/clvm_cmds.h @@ -1,6 +1,7 @@ #ifndef __CLVM_CMDS_H__ #define __CLVM_CMDS_H__ +int CL_GetPitchSign(prvm_edict_t *ent); int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex); /* These are VM built-ins that originate in the client-side programs support diff --git a/csprogs.c b/csprogs.c index 18d5c642..1f774fa4 100644 --- a/csprogs.c +++ b/csprogs.c @@ -732,6 +732,7 @@ void CL_VM_CB_FreeEdict(prvm_edict_t *ed) World_UnlinkEdict(ed); memset(ed->fields.client, 0, sizeof(*ed->fields.client)); World_Physics_RemoveFromEntity(&cl.world, ed); + World_Physics_RemoveJointFromEntity(&cl.world, ed); } void CL_VM_CB_CountEdicts(void) diff --git a/progs.h b/progs.h index 83270139..c3f3870e 100644 --- a/progs.h +++ b/progs.h @@ -25,6 +25,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define ENTITYGRIDAREAS 16 #define MAX_ENTITYCLUSTERS 16 +#define JOINTTYPE_POINT 1 +#define JOINTTYPE_HINGE 2 +#define JOINTTYPE_SLIDER 3 +#define JOINTTYPE_UNIVERSAL 4 +#define JOINTTYPE_HINGE2 5 +#define JOINTTYPE_PISTON 6 + typedef struct edict_engineprivate_s { // true if this edict is unused @@ -73,6 +80,7 @@ typedef struct edict_engineprivate_s qboolean ode_physics; void *ode_body; void *ode_geom; + void *ode_joint; float *ode_vertex3f; int *ode_element3i; int ode_numvertices; @@ -89,6 +97,12 @@ typedef struct edict_engineprivate_s vec_t ode_movelimit; // smallest component of (maxs[]-mins[]) matrix4x4_t ode_offsetmatrix; matrix4x4_t ode_offsetimatrix; + int ode_joint_type; + int ode_joint_enemy; + int ode_joint_aiment; + vec3_t ode_joint_origin; // joint anchor + vec3_t ode_joint_angles; // joint axis + vec3_t ode_joint_velocity; // second joint axis } edict_engineprivate_t; diff --git a/progsvm.h b/progsvm.h index d5477892..229e60ef 100644 --- a/progsvm.h +++ b/progsvm.h @@ -246,6 +246,9 @@ typedef struct prvm_prog_fieldoffsets_s //int spinvelocity; // ssqc / csqc (physics) //int angles; // ssqc / csqc (physics) int avelocity; // ssqc / csqc (physics) + int jointtype; // ssqc / csqc (physics) + int enemy; // ssqc / csqc (physics) + int aiment; // ssqc / csqc (physics) } prvm_prog_fieldoffsets_t; diff --git a/prvm_edict.c b/prvm_edict.c index bbf7baed..7b2b3e1a 100644 --- a/prvm_edict.c +++ b/prvm_edict.c @@ -1650,6 +1650,9 @@ void PRVM_FindOffsets(void) //prog->fieldoffsets.spinvelocity = PRVM_ED_FindFieldOffset("spinvelocity"); prog->fieldoffsets.angles = PRVM_ED_FindFieldOffset("angles"); prog->fieldoffsets.avelocity = PRVM_ED_FindFieldOffset("avelocity"); + prog->fieldoffsets.aiment = PRVM_ED_FindFieldOffset("aiment"); + prog->fieldoffsets.enemy = PRVM_ED_FindFieldOffset("enemy"); + prog->fieldoffsets.jointtype = PRVM_ED_FindFieldOffset("jointtype"); prog->funcoffsets.CSQC_ConsoleCommand = PRVM_ED_FindFunctionOffset("CSQC_ConsoleCommand"); prog->funcoffsets.CSQC_Ent_Remove = PRVM_ED_FindFunctionOffset("CSQC_Ent_Remove"); diff --git a/server.h b/server.h index d904c55a..38697488 100644 --- a/server.h +++ b/server.h @@ -555,5 +555,7 @@ void SV_VM_End(void); const char *Host_TimingReport(void); ///< for output in Host_Status_f +int SV_GetPitchSign(prvm_edict_t *ent); + #endif diff --git a/sv_main.c b/sv_main.c index 7d951159..ac717fab 100644 --- a/sv_main.c +++ b/sv_main.c @@ -1429,18 +1429,21 @@ qboolean SV_CanSeeBox(int numtraces, vec_t enlarge, vec3_t eye, vec3_t entboxmin { touch = touchedicts[touchindex]; modelindex = (unsigned int)touch->fields.server->modelindex; - model = sv.models[(int)touch->fields.server->modelindex]; - // get the entity matrix - pitchsign = (model->type == mod_alias) ? -1 : 1; - Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], pitchsign * touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1); - Matrix4x4_Invert_Simple(&imatrix, &matrix); - // see if the ray hits this entity - Matrix4x4_Transform(&imatrix, eye, starttransformed); - Matrix4x4_Transform(&imatrix, endpoints[traceindex], endtransformed); - if (!model->brush.TraceLineOfSight(model, starttransformed, endtransformed)) + model = (modelindex >= 1 && modelindex < MAX_MODELS) ? sv.models[(int)touch->fields.server->modelindex] : NULL; + if(model && model->brush.TraceLineOfSight) { - blocked++; - break; + // get the entity matrix + pitchsign = SV_GetPitchSign(touch); + Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], pitchsign * touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1); + Matrix4x4_Invert_Simple(&imatrix, &matrix); + // see if the ray hits this entity + Matrix4x4_Transform(&imatrix, eye, starttransformed); + Matrix4x4_Transform(&imatrix, endpoints[traceindex], endtransformed); + if (!model->brush.TraceLineOfSight(model, starttransformed, endtransformed)) + { + blocked++; + break; + } } } // check if the ray was blocked @@ -3290,6 +3293,7 @@ static void SV_VM_CB_FreeEdict(prvm_edict_t *ed) ed->fields.server->solid = 0; World_Physics_RemoveFromEntity(&sv.world, ed); + World_Physics_RemoveJointFromEntity(&sv.world, ed); // make sure csqc networking is aware of the removed entity e = PRVM_NUM_FOR_EDICT(ed); diff --git a/sv_phys.c b/sv_phys.c index e4292c1a..db221566 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -43,6 +43,25 @@ solid_edge items only clip against bsp models. void SV_Physics_Toss (prvm_edict_t *ent); +int SV_GetPitchSign(prvm_edict_t *ent) +{ + dp_model_t *model; + int modelindex; + if ( + ((modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[modelindex])) + ? + model->type == mod_alias + : + ( + (((unsigned char)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC) + || + ((gamemode == GAME_TENEBRAE) && ((unsigned int)ent->fields.server->effects & (16 | 32))) + ) + ) + return -1; + return 1; +} + /* =============================================================================== @@ -199,19 +218,7 @@ trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int // if the modelindex is 0, it shouldn't be SOLID_BSP! if (modelindex > 0 && modelindex < MAX_MODELS) model = sv.models[(int)touch->fields.server->modelindex]; - //pitchsign = 1; - if ( - ((modelindex = (int)touch->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)touch->fields.server->modelindex])) - ? - model->type == mod_alias - : - ( - (((unsigned char)PRVM_EDICTFIELDVALUE(touch, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC) - || - ((gamemode == GAME_TENEBRAE) && ((unsigned int)touch->fields.server->effects & (16 | 32))) - ) - ) - pitchsign = -1; + pitchsign = SV_GetPitchSign(touch); } if (model) Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], pitchsign * touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1); @@ -374,19 +381,7 @@ trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_ // if the modelindex is 0, it shouldn't be SOLID_BSP! if (modelindex > 0 && modelindex < MAX_MODELS) model = sv.models[(int)touch->fields.server->modelindex]; - //pitchsign = 1; - if ( - ((modelindex = (int)touch->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)touch->fields.server->modelindex])) - ? - model->type == mod_alias - : - ( - (((unsigned char)PRVM_EDICTFIELDVALUE(touch, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC) - || - ((gamemode == GAME_TENEBRAE) && ((unsigned int)touch->fields.server->effects & (16 | 32))) - ) - ) - pitchsign = -1; + pitchsign = SV_GetPitchSign(touch); } if (model) Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], pitchsign * touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1); @@ -587,18 +582,7 @@ trace_t SV_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co if (modelindex > 0 && modelindex < MAX_MODELS) model = sv.models[(int)touch->fields.server->modelindex]; //pitchsign = 1; - if ( - ((modelindex = (int)touch->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)touch->fields.server->modelindex])) - ? - model->type == mod_alias - : - ( - (((unsigned char)PRVM_EDICTFIELDVALUE(touch, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC) - || - ((gamemode == GAME_TENEBRAE) && ((unsigned int)touch->fields.server->effects & (16 | 32))) - ) - ) - pitchsign = -1; + pitchsign = SV_GetPitchSign(touch); } if (model) Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], pitchsign * touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1); diff --git a/svvm_cmds.c b/svvm_cmds.c index f1f15f64..57ef2eef 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -2620,8 +2620,6 @@ void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatri prvm_eval_t *val; float scale; float pitchsign = 1; - int modelindex; - dp_model_t *model; scale = 1; val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.scale); @@ -2632,18 +2630,7 @@ void SV_GetEntityMatrix (prvm_edict_t *ent, matrix4x4_t *out, qboolean viewmatri Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2] + ent->fields.server->view_ofs[2], ent->fields.server->v_angle[0], ent->fields.server->v_angle[1], ent->fields.server->v_angle[2], scale * cl_viewmodel_scale.value); else { - if ( - ((modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)ent->fields.server->modelindex])) - ? - model->type == mod_alias - : - ( - (((unsigned char)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC) - || - ((gamemode == GAME_TENEBRAE) && ((unsigned int)ent->fields.server->effects & (16 | 32))) - ) - ) - pitchsign = -1; + pitchsign = SV_GetPitchSign(ent); Matrix4x4_CreateFromQuakeEntity(out, ent->fields.server->origin[0], ent->fields.server->origin[1], ent->fields.server->origin[2], pitchsign * ent->fields.server->angles[0], ent->fields.server->angles[1], ent->fields.server->angles[2], scale); } } diff --git a/world.c b/world.c index 00135163..2f9118b0 100644 --- a/world.c +++ b/world.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // world.c -- world query functions #include "quakedef.h" +#include "clvm_cmds.h" /* @@ -1512,16 +1513,49 @@ static void World_Physics_End(world_t *world) #endif } +void World_Physics_RemoveJointFromEntity(world_t *world, prvm_edict_t *ed) +{ + ed->priv.server->ode_joint_type = 0; +#ifdef USEODE + if(ed->priv.server->ode_joint) + dJointDestroy((dJointID)ed->priv.server->ode_joint); + ed->priv.server->ode_joint = NULL; +#endif +} + void World_Physics_RemoveFromEntity(world_t *world, prvm_edict_t *ed) { // entity is not physics controlled, free any physics data + prvm_edict_t *ed2; ed->priv.server->ode_physics = false; #ifdef USEODE if (ed->priv.server->ode_geom) dGeomDestroy((dGeomID)ed->priv.server->ode_geom); ed->priv.server->ode_geom = NULL; if (ed->priv.server->ode_body) + { + dJointID j; + dBodyID b1, b2; + while(dBodyGetNumJoints((dBodyID)ed->priv.server->ode_body)) + { + j = dBodyGetJoint((dBodyID)ed->priv.server->ode_body, 0); + ed2 = (prvm_edict_t *) dJointGetData(j); + b1 = dJointGetBody(j, 0); + b2 = dJointGetBody(j, 1); + if(b1 == (dBodyID)ed->priv.server->ode_body) + { + b1 = 0; + ed2->priv.server->ode_joint_enemy = 0; + } + if(b2 == (dBodyID)ed->priv.server->ode_body) + { + b2 = 0; + ed2->priv.server->ode_joint_aiment = 0; + } + dJointAttach(j, b1, b2); + } dBodyDestroy((dBodyID)ed->priv.server->ode_body); + } ed->priv.server->ode_body = NULL; #endif if (ed->priv.server->ode_vertex3f) @@ -1552,12 +1586,32 @@ static void World_Physics_Frame_BodyToEntity(world_t *world, prvm_edict_t *ed) vec3_t origin; vec3_t spinvelocity; vec3_t velocity; + int jointtype; if (!body) return; val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.movetype); movetype = (int)val->_float; if (movetype != MOVETYPE_PHYSICS) + { + val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.jointtype);if (val) jointtype = (int)val->_float; + switch(jointtype) + { + // TODO feed back data from physics + case JOINTTYPE_POINT: + break; + case JOINTTYPE_HINGE: + break; + case JOINTTYPE_SLIDER: + break; + case JOINTTYPE_UNIVERSAL: + break; + case JOINTTYPE_HINGE2: + break; + case JOINTTYPE_PISTON: + break; + } return; + } // store the physics engine data into the entity o = dBodyGetPosition(body); r = dBodyGetRotation(body); @@ -1579,9 +1633,23 @@ static void World_Physics_Frame_BodyToEntity(world_t *world, prvm_edict_t *ed) Matrix4x4_Concat(&entitymatrix, &bodymatrix, &ed->priv.server->ode_offsetimatrix); Matrix4x4_ToVectors(&entitymatrix, forward, left, up, origin); - AnglesFromVectors(angles, forward, up, true); + AnglesFromVectors(angles, forward, up, false); VectorSet(avelocity, RAD2DEG(spinvelocity[PITCH]), RAD2DEG(spinvelocity[ROLL]), RAD2DEG(spinvelocity[YAW])); + { + float pitchsign = 1; + if(!strcmp(prog->name, "server")) // FIXME some better way? + { + pitchsign = SV_GetPitchSign(ed); + } + else if(!strcmp(prog->name, "client")) + { + pitchsign = CL_GetPitchSign(ed); + } + angles[PITCH] *= pitchsign; + avelocity[PITCH] *= pitchsign; + } + val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.origin);if (val) VectorCopy(origin, val->vector); val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.velocity);if (val) VectorCopy(velocity, val->vector); //val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_forward);if (val) VectorCopy(forward, val->vector); @@ -1599,6 +1667,109 @@ static void World_Physics_Frame_BodyToEntity(world_t *world, prvm_edict_t *ed) ed->priv.server->ode_gravity = dBodyGetGravityMode(body); } +static void World_Physics_Frame_JointFromEntity(world_t *world, prvm_edict_t *ed) +{ + dJointID j = 0; + dBodyID b1 = 0; + dBodyID b2 = 0; + int movetype = 0; + int jointtype = 0; + int enemy = 0, aiment = 0; + vec3_t origin, velocity, angles, forward, left, up; + prvm_eval_t *val; + VectorClear(origin); + VectorClear(velocity); + VectorClear(angles); + val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.movetype);if (val) movetype = (int)val->_float; + val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.jointtype);if (val) jointtype = (int)val->_float; + val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.enemy);if (val) enemy = val->_int; + val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.aiment);if (val) aiment = val->_int; + val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.origin);if (val) VectorCopy(val->vector, origin); + val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.velocity);if (val) VectorCopy(val->vector, velocity); + val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.angles);if (val) VectorCopy(val->vector, angles); + if(movetype == MOVETYPE_PHYSICS) + jointtype = 0; // can't have both + if(enemy <= 0 || enemy >= prog->num_edicts || prog->edicts[enemy].priv.required->free || prog->edicts[enemy].priv.server->ode_body == 0) + enemy = 0; + if(aiment <= 0 || aiment >= prog->num_edicts || prog->edicts[aiment].priv.required->free || prog->edicts[aiment].priv.server->ode_body == 0) + aiment = 0; + if(jointtype == ed->priv.server->ode_joint_type && VectorCompare(origin, ed->priv.server->ode_joint_origin) && VectorCompare(velocity, ed->priv.server->ode_joint_velocity) && VectorCompare(angles, ed->priv.server->ode_joint_angles) && enemy == ed->priv.server->ode_joint_enemy && aiment == ed->priv.server->ode_joint_aiment) + return; // nothing to do + AngleVectorsFLU(angles, forward, left, up); + switch(jointtype) + { + case JOINTTYPE_POINT: + j = dJointCreateBall(world->physics.ode_world, 0); + break; + case JOINTTYPE_HINGE: + j = dJointCreateHinge(world->physics.ode_world, 0); + break; + case JOINTTYPE_SLIDER: + j = dJointCreateSlider(world->physics.ode_world, 0); + break; + case JOINTTYPE_UNIVERSAL: + j = dJointCreateUniversal(world->physics.ode_world, 0); + break; + case JOINTTYPE_HINGE2: + j = dJointCreateHinge2(world->physics.ode_world, 0); + break; + case JOINTTYPE_PISTON: + j = dJointCreatePiston(world->physics.ode_world, 0); + break; + case 0: + default: + // no joint + j = 0; + break; + } + ed->priv.server->ode_joint = (void *) j; + ed->priv.server->ode_joint_type = jointtype; + ed->priv.server->ode_joint_enemy = enemy; + ed->priv.server->ode_joint_aiment = aiment; + VectorCopy(origin, ed->priv.server->ode_joint_origin); + VectorCopy(velocity, ed->priv.server->ode_joint_velocity); + VectorCopy(angles, ed->priv.server->ode_joint_angles); + if(j) + { + dJointSetData(j, (void *) ed); + if(enemy) + b1 = (dBodyID)prog->edicts[enemy].priv.server->ode_body; + if(aiment) + b2 = (dBodyID)prog->edicts[aiment].priv.server->ode_body; + dJointAttach(j, b1, b2); + switch(jointtype) + { + case JOINTTYPE_POINT: + dJointSetBallAnchor(j, origin[0], origin[1], origin[2]); + break; + case JOINTTYPE_HINGE: + dJointSetHingeAnchor(j, origin[0], origin[1], origin[2]); + dJointSetHingeAxis(j, forward[0], forward[1], forward[2]); + break; + case JOINTTYPE_SLIDER: + dJointSetSliderAxis(j, forward[0], forward[1], forward[2]); + break; + case JOINTTYPE_UNIVERSAL: + dJointSetUniversalAnchor(j, origin[0], origin[1], origin[2]); + dJointSetUniversalAxis1(j, forward[0], forward[1], forward[2]); + dJointSetUniversalAxis2(j, up[0], up[1], up[2]); + break; + case JOINTTYPE_HINGE2: + dJointSetHinge2Anchor(j, origin[0], origin[1], origin[2]); + dJointSetHinge2Axis1(j, forward[0], forward[1], forward[2]); + dJointSetHinge2Axis2(j, velocity[0], velocity[1], velocity[2]); + break; + case JOINTTYPE_PISTON: + dJointSetPistonAxis(j, forward[0], forward[1], forward[2]); + break; + case 0: + default: + Host_Error("what? but above the joint was valid...\n"); + break; + } + } +} + static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed) { const float *iv; @@ -1858,6 +2029,8 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed) val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.angles);if (val) VectorCopy(val->vector, angles); val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.avelocity);if (val) VectorCopy(val->vector, avelocity); val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.gravity);if (val) { if(val->_float != 0.0f && val->_float < 0.5f) gravity = false; } + if(ed == prog->edicts) + gravity = false; // compatibility for legacy entities //if (!VectorLength2(forward) || solid == SOLID_BSP) @@ -1950,6 +2123,21 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed) dVector3 r[3]; matrix4x4_t entitymatrix; matrix4x4_t bodymatrix; + + { + float pitchsign = 1; + if(!strcmp(prog->name, "server")) // FIXME some better way? + { + pitchsign = SV_GetPitchSign(ed); + } + else if(!strcmp(prog->name, "client")) + { + pitchsign = CL_GetPitchSign(ed); + } + angles[PITCH] *= pitchsign; + avelocity[PITCH] *= pitchsign; + } + Matrix4x4_FromVectors(&entitymatrix, forward, left, up, origin); Matrix4x4_Concat(&bodymatrix, &entitymatrix, &ed->priv.server->ode_offsetmatrix); Matrix4x4_ToVectors(&bodymatrix, forward, left, up, origin); @@ -2092,9 +2280,15 @@ void World_Physics_Frame(world_t *world, double frametime, double gravity) // copy physics properties from entities to physics engine if (prog) + { for (i = 0, ed = prog->edicts + i;i < prog->num_edicts;i++, ed++) if (!prog->edicts[i].priv.required->free) World_Physics_Frame_BodyFromEntity(world, ed); + // oh, and it must be called after all bodies were created + for (i = 0, ed = prog->edicts + i;i < prog->num_edicts;i++, ed++) + if (!prog->edicts[i].priv.required->free) + World_Physics_Frame_JointFromEntity(world, ed); + } world->physics.ode_iterations = bound(1, physics_ode_iterationsperframe.integer, 1000); world->physics.ode_step = frametime / world->physics.ode_iterations; diff --git a/world.h b/world.h index 7e3cf3a1..4dad70ba 100644 --- a/world.h +++ b/world.h @@ -119,6 +119,7 @@ void World_Physics_Frame(world_t *world, double frametime, double gravity); // this is called by entity removal struct prvm_edict_s; void World_Physics_RemoveFromEntity(world_t *world, struct prvm_edict_s *ed); +void World_Physics_RemoveJointFromEntity(world_t *world, struct prvm_edict_s *ed); #endif