From e96f90ea4e19b54c7fa21be2a21341c5f6908067 Mon Sep 17 00:00:00 2001 From: havoc Date: Tue, 20 Oct 2009 14:53:52 +0000 Subject: [PATCH] removed .axis_forward, .axis_left, .axis_up, .spinvelocity, now the only 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 | 80 +++++++++++++++++++++++++++++++++++++++++ progs.h | 4 +++ progsvm.h | 10 +++--- prvm_edict.c | 10 +++--- sv_main.c | 11 +++--- world.c | 98 +++++++++++++++++++++++++++++++++----------------- 6 files changed, 165 insertions(+), 48 deletions(-) diff --git a/model_shared.c b/model_shared.c index 9389654b..ac16b9ac 100644 --- a/model_shared.c +++ b/model_shared.c @@ -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 cf0239bf..34aa8174 100644 --- 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; diff --git a/progsvm.h b/progsvm.h index f7ab5dfd..d5477892 100644 --- 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; diff --git a/prvm_edict.c b/prvm_edict.c index 583ec19d..bbf7baed 100644 --- a/prvm_edict.c +++ b/prvm_edict.c @@ -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"); diff --git a/sv_main.c b/sv_main.c index 889b03aa..7d951159 100644 --- 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 946642e1..ae836a42 100644 --- 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; -- 2.39.2