]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
removed .axis_forward, .axis_left, .axis_up, .spinvelocity, now the only
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 20 Oct 2009 14:53:52 +0000 (14:53 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 20 Oct 2009 14:53:52 +0000 (14:53 +0000)
new field is .mass
implemented a "hands off" approach to entity->rigidbody property
transfer, it should only lose precision when the QC edits something

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@9365 d7cf8633-e32d-0410-b094-e92efae38249

model_shared.c
progs.h
progsvm.h
prvm_edict.c
sv_main.c
world.c

index 9389654b14823a587bdfddc24b69650f8f200d55..ac16b9acf0bc8600a6381dd09b550d85c8924932 100644 (file)
@@ -1345,6 +1345,86 @@ void Mod_ConstructTerrainPatchFromBGRA(const unsigned char *imagepixels, int ima
                        Mod_GetTerrainVertexFromBGRA(imagepixels, imagewidth, imageheight, ix, iy, vertex3f, texcoord2f, svector3f, tvector3f, normal3f, pixelstepmatrix, pixeltexturestepmatrix);
 }
 
+#if 0
+void Mod_Terrain_SurfaceRecurseChunk(dp_model_t *model, int stepsize, int x, int y)
+{
+       float mins[3];
+       float maxs[3];
+       float chunkwidth = min(stepsize, model->terrain.width - 1 - x);
+       float chunkheight = min(stepsize, model->terrain.height - 1 - y);
+       float viewvector[3];
+       unsigned int firstvertex;
+       unsigned int *e;
+       float *v;
+       if (chunkwidth < 2 || chunkheight < 2)
+               return;
+       VectorSet(mins, model->terrain.mins[0] +  x    * stepsize * model->terrain.scale[0], model->terrain.mins[1] +  y    * stepsize * model->terrain.scale[1], model->terrain.mins[2]);
+       VectorSet(maxs, model->terrain.mins[0] + (x+1) * stepsize * model->terrain.scale[0], model->terrain.mins[1] + (y+1) * stepsize * model->terrain.scale[1], model->terrain.maxs[2]);
+       viewvector[0] = bound(mins[0], modelorg, maxs[0]) - model->terrain.vieworigin[0];
+       viewvector[1] = bound(mins[1], modelorg, maxs[1]) - model->terrain.vieworigin[1];
+       viewvector[2] = bound(mins[2], modelorg, maxs[2]) - model->terrain.vieworigin[2];
+       if (stepsize > 1 && VectorLength(viewvector) < stepsize*model->terrain.scale[0]*r_terrain_lodscale.value)
+       {
+               // too close for this stepsize, emit as 4 chunks instead
+               stepsize /= 2;
+               Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x, y);
+               Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x+stepsize, y);
+               Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x, y+stepsize);
+               Mod_Terrain_SurfaceRecurseChunk(model, stepsize, x+stepsize, y+stepsize);
+               return;
+       }
+       // emit the geometry at stepsize into our vertex buffer / index buffer
+       // we add two columns and two rows for skirt
+       outwidth = chunkwidth+2;
+       outheight = chunkheight+2;
+       outwidth2 = outwidth-1;
+       outheight2 = outheight-1;
+       outwidth3 = outwidth+1;
+       outheight3 = outheight+1;
+       firstvertex = numvertices;
+       e = model->terrain.element3i + numtriangles;
+       numtriangles += chunkwidth*chunkheight*2+chunkwidth*2*2+chunkheight*2*2;
+       v = model->terrain.vertex3f + numvertices;
+       numvertices += (chunkwidth+1)*(chunkheight+1)+(chunkwidth+1)*2+(chunkheight+1)*2;
+       // emit the triangles (note: the skirt is treated as two extra rows and two extra columns)
+       for (ty = 0;ty < outheight;ty++)
+       {
+               for (tx = 0;tx < outwidth;tx++)
+               {
+                       *e++ = firstvertex + (ty  )*outwidth3+(tx  );
+                       *e++ = firstvertex + (ty  )*outwidth3+(tx+1);
+                       *e++ = firstvertex + (ty+1)*outwidth3+(tx+1);
+                       *e++ = firstvertex + (ty  )*outwidth3+(tx  );
+                       *e++ = firstvertex + (ty+1)*outwidth3+(tx+1);
+                       *e++ = firstvertex + (ty+1)*outwidth3+(tx  );
+               }
+       }
+       // TODO: emit surface vertices (x+tx*stepsize, y+ty*stepsize)
+       for (ty = 0;ty <= outheight;ty++)
+       {
+               skirtrow = ty == 0 || ty == outheight;
+               ry = y+bound(1, ty, outheight)*stepsize;
+               for (tx = 0;tx <= outwidth;tx++)
+               {
+                       skirt = skirtrow || tx == 0 || tx == outwidth;
+                       rx = x+bound(1, tx, outwidth)*stepsize;
+                       v[0] = rx*scale[0];
+                       v[1] = ry*scale[1];
+                       v[2] = heightmap[ry*terrainwidth+rx]*scale[2];
+                       v += 3;
+               }
+       }
+       // TODO: emit skirt vertices
+}
+
+void Mod_Terrain_UpdateSurfacesForViewOrigin(dp_model_t *model)
+{
+       for (y = 0;y < model->terrain.size[1];y += model->terrain.
+       Mod_Terrain_SurfaceRecurseChunk(model, model->terrain.maxstepsize, x, y);
+       Mod_Terrain_BuildChunk(model, 
+}
+#endif
+
 q3wavefunc_t Mod_LoadQ3Shaders_EnumerateWaveFunc(const char *s)
 {
        if (!strcasecmp(s, "sin"))             return Q3WAVEFUNC_SIN;
diff --git a/progs.h b/progs.h
index cf0239bfca46bb0ead7adc9241b8e698a8067f6e..34aa817444eb8c4feac576f95a973c3cf200c7da 100644 (file)
--- a/progs.h
+++ b/progs.h
@@ -80,6 +80,10 @@ typedef struct edict_engineprivate_s
        vec3_t ode_mins;
        vec3_t ode_maxs;
        vec_t ode_mass;
+       vec3_t ode_origin;
+       vec3_t ode_velocity;
+       vec3_t ode_angles;
+       vec3_t ode_avelocity;
        int ode_modelindex;
        vec_t ode_movelimit; // smallest component of (maxs[]-mins[])
        matrix4x4_t ode_offsetmatrix;
index f7ab5dfd2cf747e86d79932bdd3c310ffa0f3c7c..d5477892fd3a6247f250fe91faa46d38ca011527 100644 (file)
--- a/progsvm.h
+++ b/progsvm.h
@@ -239,13 +239,13 @@ typedef struct prvm_prog_fieldoffsets_s
        int maxs; // ssqc / csqc (physics)
        int mass; // ssqc / csqc (physics)
        int origin; // ssqc / csqc (physics)
-       int axis_forward; // ssqc / csqc (physics)
-       int axis_left; // ssqc / csqc (physics)
-       int axis_up; // ssqc / csqc (physics)
-       //int angles; // ssqc / csqc (physics)
        int velocity; // ssqc / csqc (physics)
+       //int axis_forward; // ssqc / csqc (physics)
+       //int axis_left; // ssqc / csqc (physics)
+       //int axis_up; // ssqc / csqc (physics)
+       //int spinvelocity; // ssqc / csqc (physics)
+       //int angles; // ssqc / csqc (physics)
        int avelocity; // ssqc / csqc (physics)
-       int spinvelocity; // ssqc / csqc (physics)
 }
 prvm_prog_fieldoffsets_t;
 
index 583ec19da51938b597a71bb4ad0a4f79f1a031e3..bbf7baed33d510ef9487f1c9c2c5bc5842a8270f 100644 (file)
@@ -1643,13 +1643,13 @@ void PRVM_FindOffsets(void)
        prog->fieldoffsets.maxs                           = PRVM_ED_FindFieldOffset("maxs");
        prog->fieldoffsets.mass                           = PRVM_ED_FindFieldOffset("mass");
        prog->fieldoffsets.origin                         = PRVM_ED_FindFieldOffset("origin");
-       prog->fieldoffsets.axis_forward                   = PRVM_ED_FindFieldOffset("axis_forward");
-       prog->fieldoffsets.axis_left                      = PRVM_ED_FindFieldOffset("axis_left");
-       prog->fieldoffsets.axis_up                        = PRVM_ED_FindFieldOffset("axis_up");
-       prog->fieldoffsets.angles                         = PRVM_ED_FindFieldOffset("angles");
        prog->fieldoffsets.velocity                       = PRVM_ED_FindFieldOffset("velocity");
+       //prog->fieldoffsets.axis_forward                   = PRVM_ED_FindFieldOffset("axis_forward");
+       //prog->fieldoffsets.axis_left                      = PRVM_ED_FindFieldOffset("axis_left");
+       //prog->fieldoffsets.axis_up                        = PRVM_ED_FindFieldOffset("axis_up");
+       //prog->fieldoffsets.spinvelocity                   = PRVM_ED_FindFieldOffset("spinvelocity");
+       prog->fieldoffsets.angles                         = PRVM_ED_FindFieldOffset("angles");
        prog->fieldoffsets.avelocity                      = PRVM_ED_FindFieldOffset("avelocity");
-       prog->fieldoffsets.spinvelocity                   = PRVM_ED_FindFieldOffset("spinvelocity");
 
        prog->funcoffsets.CSQC_ConsoleCommand             = PRVM_ED_FindFunctionOffset("CSQC_ConsoleCommand");
        prog->funcoffsets.CSQC_Ent_Remove                 = PRVM_ED_FindFunctionOffset("CSQC_Ent_Remove");
index 889b03aaa2873feb4e0194d8fc56083ce3e3aab8..7d951159cd7cd5d1c8f9821d5cfecd1933ef2b85 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -303,14 +303,13 @@ prvm_required_field_t reqfields[] =
        //{ev_float, "modelindex"},
        {ev_vector, "mass"},
        //{ev_vector, "origin"},
-       //{ev_vector, "angles"},
-       {ev_vector, "axis_forward"},
-       {ev_vector, "axis_left"},
-       {ev_vector, "axis_up"},
-       //{ev_vector, "angles"},
        //{ev_vector, "velocity"},
+       //{ev_vector, "axis_forward"},
+       //{ev_vector, "axis_left"},
+       //{ev_vector, "axis_up"},
+       //{ev_vector, "spinvelocity"},
+       //{ev_vector, "angles"},
        //{ev_vector, "avelocity"},
-       {ev_vector, "spinvelocity"},
 
 };
 
diff --git a/world.c b/world.c
index 946642e19d47bbf37db833cc5ee997b5f0cf810b..ae836a42d976d1b1265bbbe3eff7385f231adbeb 100644 (file)
--- a/world.c
+++ b/world.c
@@ -1545,6 +1545,8 @@ static void World_Physics_Frame_BodyToEntity(world_t *world, prvm_edict_t *ed)
        matrix4x4_t bodymatrix;
        matrix4x4_t entitymatrix;
        prvm_eval_t *val;
+       vec3_t angles;
+       vec3_t avelocity;
        vec3_t forward, left, up;
        vec3_t origin;
        vec3_t spinvelocity;
@@ -1575,13 +1577,24 @@ static void World_Physics_Frame_BodyToEntity(world_t *world, prvm_edict_t *ed)
        Matrix4x4_FromVectors(&bodymatrix, forward, left, up, origin);
        Matrix4x4_Concat(&entitymatrix, &bodymatrix, &ed->priv.server->ode_offsetimatrix);
        Matrix4x4_ToVectors(&entitymatrix, forward, left, up, origin);
+
+       AnglesFromVectors(angles, forward, up, true);
+       VectorSet(avelocity, RAD2DEG(spinvelocity[PITCH]), RAD2DEG(spinvelocity[YAW]), RAD2DEG(spinvelocity[ROLL]));
+
        val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.origin);if (val) VectorCopy(origin, val->vector);
-       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_forward);if (val) VectorCopy(forward, val->vector);
-       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_left);if (val) VectorCopy(left, val->vector);
-       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_up);if (val) VectorCopy(up, val->vector);
        val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.velocity);if (val) VectorCopy(velocity, val->vector);
-       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.spinvelocity);if (val) VectorCopy(spinvelocity, val->vector);
-       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.angles);if (val) AnglesFromVectors(val->vector, forward, up, true);
+       //val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_forward);if (val) VectorCopy(forward, val->vector);
+       //val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_left);if (val) VectorCopy(left, val->vector);
+       //val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_up);if (val) VectorCopy(up, val->vector);
+       //val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.spinvelocity);if (val) VectorCopy(spinvelocity, val->vector);
+       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.angles);if (val) VectorCopy(angles, val->vector);
+       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.avelocity);if (val) VectorCopy(avelocity, val->vector);
+
+       // 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);
+       VectorCopy(angles, ed->priv.server->ode_angles);
+       VectorCopy(avelocity, ed->priv.server->ode_avelocity);
 }
 
 static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
@@ -1598,14 +1611,15 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
        int *oe;
        int axisindex;
        int modelindex = 0;
-       int movetype;
+       int movetype = MOVETYPE_NONE;
        int numtriangles;
        int numvertices;
-       int solid;
+       int solid = SOLID_NOT;
        int triangleindex;
        int vertexindex;
        mempool_t *mempool;
        prvm_eval_t *val;
+       qboolean modified = false;
        vec3_t angles;
        vec3_t avelocity;
        vec3_t entmaxs;
@@ -1623,20 +1637,22 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
        vec_t massval = 1.0f;
        vec_t movelimit;
        vec_t radius;
+       vec_t scale = 1.0f;
        vec_t spinlimit;
 #ifdef ODE_DYNAMIC
        if (!ode_dll)
                return;
 #endif
-       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.solid);
-       solid = (int)val->_float;
-       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.movetype);
-       movetype = (int)val->_float;
+       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.solid);if (val) solid = (int)val->_float;
+       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.movetype);if (val) movetype = (int)val->_float;
+       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.movetype);if (val && val->_float) scale = val->_float;
+       modelindex = 0;
        switch(solid)
        {
        case SOLID_BSP:
                val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.modelindex);
-               modelindex = (int)val->_float;
+               if (val)
+                       modelindex = (int)val->_float;
                if (world == &sv.world && modelindex >= 1 && modelindex < MAX_MODELS)
                {
                        model = sv.models[modelindex];
@@ -1655,8 +1671,8 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
                }
                if (model)
                {
-                       VectorCopy(model->normalmins, entmins);
-                       VectorCopy(model->normalmaxs, entmaxs);
+                       VectorScale(model->normalmins, scale, entmins);
+                       VectorScale(model->normalmaxs, scale, entmaxs);
                        val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.mass);if (val) massval = val->_float;
                }
                else
@@ -1700,6 +1716,7 @@ 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)
        {
+               modified = true;
                World_Physics_RemoveFromEntity(world, ed);
                ed->priv.server->ode_physics = true;
                VectorCopy(entmins, ed->priv.server->ode_mins);
@@ -1825,29 +1842,29 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
 
        // get current data from entity
        VectorClear(origin);
-       VectorClear(forward);
-       VectorClear(left);
-       VectorClear(up);
        VectorClear(velocity);
-       VectorClear(spinvelocity);
+       //VectorClear(forward);
+       //VectorClear(left);
+       //VectorClear(up);
+       //VectorClear(spinvelocity);
+       VectorClear(angles);
+       VectorClear(avelocity);
        val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.origin);if (val) VectorCopy(val->vector, origin);
-       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_forward);if (val) VectorCopy(val->vector, forward);
-       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_left);if (val) VectorCopy(val->vector, left);
-       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_up);if (val) VectorCopy(val->vector, up);
        val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.velocity);if (val) VectorCopy(val->vector, velocity);
-       val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.spinvelocity);if (val) VectorCopy(val->vector, spinvelocity);
+       //val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_forward);if (val) VectorCopy(val->vector, forward);
+       //val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_left);if (val) VectorCopy(val->vector, left);
+       //val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.axis_up);if (val) VectorCopy(val->vector, up);
+       //val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.spinvelocity);if (val) VectorCopy(val->vector, spinvelocity);
+       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);
 
        // compatibility for legacy entities
-       if (!VectorLength2(forward) || solid == SOLID_BSP)
+       //if (!VectorLength2(forward) || solid == SOLID_BSP)
        {
-               VectorClear(angles);
-               VectorClear(avelocity);
-               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);
                AngleVectorsFLU(angles, forward, left, up);
                // convert single-axis rotations in avelocity to spinvelocity
                // FIXME: untested math - check signs
-               VectorSet(spinvelocity, avelocity[PITCH] * ((float)M_PI / 180.0f), avelocity[ROLL] * ((float)M_PI / 180.0f), avelocity[YAW] * ((float)M_PI / 180.0f));
+               VectorSet(spinvelocity, DEG2RAD(avelocity[PITCH]), DEG2RAD(avelocity[ROLL]), DEG2RAD(avelocity[YAW]));
        }
 
        // compatibility for legacy entities
@@ -1856,7 +1873,6 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
        case SOLID_BBOX:
        case SOLID_SLIDEBOX:
        case SOLID_CORPSE:
-               //VectorClear(velocity);
                VectorSet(forward, 1, 0, 0);
                VectorSet(left, 0, 1, 0);
                VectorSet(up, 0, 0, 1);
@@ -1864,17 +1880,21 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
                break;
        }
 
+
        // we must prevent NANs...
        test = VectorLength2(origin) + VectorLength2(forward) + VectorLength2(left) + VectorLength2(up) + VectorLength2(velocity) + VectorLength2(spinvelocity);
        if (IS_NAN(test))
        {
-               Con_Printf("Fixing NAN values on entity %i : .classname = \"%s\" .origin = '%f %f %f' .axis_forward = '%f %f %f' .axis_left = '%f %f %f' .axis_up = '%f %f %f' .velocity = '%f %f %f' .spinvelocity = '%f %f %f'\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.classname)->string), origin[0], origin[1], origin[2], forward[0], forward[1], forward[2], left[0], left[1], left[2], up[0], up[1], up[2], velocity[0], velocity[1], velocity[2], spinvelocity[0], spinvelocity[1], spinvelocity[2]);
+               modified = true;
+               //Con_Printf("Fixing NAN values on entity %i : .classname = \"%s\" .origin = '%f %f %f' .velocity = '%f %f %f' .axis_forward = '%f %f %f' .axis_left = '%f %f %f' .axis_up = %f %f %f' .spinvelocity = '%f %f %f'\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.classname)->string), origin[0], origin[1], origin[2], velocity[0], velocity[1], velocity[2], forward[0], forward[1], forward[2], left[0], left[1], left[2], up[0], up[1], up[2], spinvelocity[0], spinvelocity[1], spinvelocity[2]);
+               Con_Printf("Fixing NAN values on entity %i : .classname = \"%s\" .origin = '%f %f %f' .velocity = '%f %f %f' .angles = '%f %f %f' .avelocity = '%f %f %f'\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.classname)->string), origin[0], origin[1], origin[2], velocity[0], velocity[1], velocity[2], angles[0], angles[1], angles[2], avelocity[0], avelocity[1], avelocity[2]);
                test = VectorLength2(origin);
                if (IS_NAN(test))
                        VectorClear(origin);
                test = VectorLength2(forward) * VectorLength2(left) * VectorLength2(up);
                if (IS_NAN(test))
                {
+                       VectorSet(angles, 0, 0, 0);
                        VectorSet(forward, 1, 0, 0);
                        VectorSet(left, 0, 1, 0);
                        VectorSet(up, 0, 0, 1);
@@ -1885,6 +1905,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
                test = VectorLength2(spinvelocity);
                if (IS_NAN(test))
                {
+                       VectorClear(avelocity);
                        VectorClear(spinvelocity);
                }
        }
@@ -1894,10 +1915,12 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
        test = VectorLength2(velocity);
        if (test > movelimit*movelimit)
        {
+               modified = true;
                // scale down linear velocity to the movelimit
                // scale down angular velocity the same amount for consistency
                f = movelimit / sqrt(test);
                VectorScale(velocity, f, velocity);
+               VectorScale(avelocity, f, avelocity);
                VectorScale(spinvelocity, f, spinvelocity);
        }
 
@@ -1905,11 +1928,22 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
        spinlimit = physics_ode_spinlimit.value;
        test = VectorLength2(spinvelocity);
        if (test > spinlimit)
+       {
+               modified = true;
+               VectorClear(avelocity);
                VectorClear(spinvelocity);
+       }
+
+       // check if the qc edited any position data
+       if (!VectorCompare(origin, ed->priv.server->ode_origin)
+        || !VectorCompare(velocity, ed->priv.server->ode_velocity)
+        || !VectorCompare(angles, ed->priv.server->ode_angles)
+        || !VectorCompare(avelocity, ed->priv.server->ode_avelocity))
+               modified = true;
 
-       // store the values into the physics engine
+       // store the qc values into the physics engine
        body = ed->priv.server->ode_body;
-       if (body)
+       if (body && modified)
        {
                dVector3 r[3];
                matrix4x4_t entitymatrix;