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;
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;
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)
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;
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];
}
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
|| 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);
// 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
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);
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);
test = VectorLength2(spinvelocity);
if (IS_NAN(test))
{
+ VectorClear(avelocity);
VectorClear(spinvelocity);
}
}
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);
}
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;