36static void World_Physics_Init(
void);
47static void World_Physics_Shutdown(
void);
52 World_Physics_Shutdown();
62 World_Physics_Start(
world);
72 World_Physics_End(
world);
106 Con_Printf(
"%s areagrid check stats: %d calls %d nodes (%f per call) %d entities (%f per call)\n", worldname,
world->areagrid_stats_calls,
world->areagrid_stats_nodechecks, (
double)
world->areagrid_stats_nodechecks / (
double)
world->areagrid_stats_calls,
world->areagrid_stats_entitychecks, (
double)
world->areagrid_stats_entitychecks / (
double)
world->areagrid_stats_calls);
107 world->areagrid_stats_calls = 0;
108 world->areagrid_stats_nodechecks = 0;
109 world->areagrid_stats_entitychecks = 0;
128 if (
world->areagrid_marknumber < 1)
129 world->areagrid_marknumber = 1;
150 Con_DPrintf(
"areagrid settings: divisions %ix%ix1 : box %f %f %f : %f %f %f size %f %f %f grid %f %f %f (mingrid %f)\n",
AREA_GRID,
AREA_GRID,
world->areagrid_mins[0],
world->areagrid_mins[1],
world->areagrid_mins[2],
world->areagrid_maxs[0],
world->areagrid_maxs[1],
world->areagrid_maxs[2],
world->areagrid_size[0],
world->areagrid_size[1],
world->areagrid_size[2], 1.0f /
world->areagrid_scale[0], 1.0f /
world->areagrid_scale[1], 1.0f /
world->areagrid_scale[2],
sv_areagrid_mingridsize.
value);
165 grid = &
world->areagrid_outside;
195 vec3_t paddedmins, paddedmaxs;
196 int igrid[3], igridmins[3], igridmaxs[3];
210 world->areagrid_stats_calls++;
211 world->areagrid_marknumber++;
212 igridmins[0] = (
int)
floor((paddedmins[0] +
world->areagrid_bias[0]) *
world->areagrid_scale[0]);
213 igridmins[1] = (
int)
floor((paddedmins[1] +
world->areagrid_bias[1]) *
world->areagrid_scale[1]);
215 igridmaxs[0] = (
int)
floor((paddedmaxs[0] +
world->areagrid_bias[0]) *
world->areagrid_scale[0]) + 1;
216 igridmaxs[1] = (
int)
floor((paddedmaxs[1] +
world->areagrid_bias[1]) *
world->areagrid_scale[1]) + 1;
218 igridmins[0] =
max(0, igridmins[0]);
219 igridmins[1] =
max(0, igridmins[1]);
231 if (
world->areagrid_outside.list.next)
233 grid = &
world->areagrid_outside;
237 if (ent->
priv.
server->areagridmarknumber !=
world->areagrid_marknumber)
242 if (numlist < maxlist)
246 world->areagrid_stats_entitychecks++;
251 for (igrid[1] = igridmins[1];igrid[1] < igridmaxs[1];igrid[1]++)
254 for (igrid[0] = igridmins[0];igrid[0] < igridmaxs[0];igrid[0]++, grid++)
261 if (ent->
priv.
server->areagridmarknumber !=
world->areagrid_marknumber)
266 if (numlist < maxlist)
272 world->areagrid_stats_entitychecks++;
284 int igrid[3], igridmins[3], igridmaxs[3], gridnum, entitynumber =
PRVM_NUM_FOR_EDICT(ent);
288 Con_Printf (
"World_LinkEdict_AreaGrid: invalid edict %p (edicts is %p, edict compared to prog->edicts is %i)\n", (
void *)ent, (
void *)prog->
edicts, entitynumber);
298 if (igridmins[0] < 0 || igridmaxs[0] >
AREA_GRID || igridmins[1] < 0 || igridmaxs[1] >
AREA_GRID || ((igridmaxs[0] - igridmins[0]) * (igridmaxs[1] - igridmins[1])) >
ENTITYGRIDAREAS)
306 for (igrid[1] = igridmins[1];igrid[1] < igridmaxs[1];igrid[1]++)
309 for (igrid[0] = igridmins[0];igrid[0] < igridmaxs[0];igrid[0]++, grid++, gridnum++)
352cvar_t physics_ode_quadtree_depth = {
CF_CLIENT |
CF_SERVER,
"physics_ode_quadtree_depth",
"5",
"desired subdivision level of quadtree culling space"};
353cvar_t physics_ode_allowconvex = {
CF_CLIENT |
CF_SERVER,
"physics_ode_allowconvex",
"0",
"allow usage of Convex Hull primitive type on trimeshes that have custom 'collisionconvex' mesh. If disabled, trimesh primitive type are used."};
354cvar_t physics_ode_contactsurfacelayer = {
CF_CLIENT |
CF_SERVER,
"physics_ode_contactsurfacelayer",
"1",
"allows objects to overlap this many units to reduce jitter"};
355cvar_t physics_ode_worldstep_iterations = {
CF_CLIENT |
CF_SERVER,
"physics_ode_worldstep_iterations",
"20",
"parameter to dWorldQuickStep"};
356cvar_t physics_ode_contact_mu = {
CF_CLIENT |
CF_SERVER,
"physics_ode_contact_mu",
"1",
"contact solver mu parameter - friction pyramid approximation 1 (see ODE User Guide)"};
357cvar_t physics_ode_contact_erp = {
CF_CLIENT |
CF_SERVER,
"physics_ode_contact_erp",
"0.96",
"contact solver erp parameter - Error Restitution Percent (see ODE User Guide)"};
358cvar_t physics_ode_contact_cfm = {
CF_CLIENT |
CF_SERVER,
"physics_ode_contact_cfm",
"0",
"contact solver cfm parameter - Constraint Force Mixing (see ODE User Guide)"};
359cvar_t physics_ode_contact_maxpoints = {
CF_CLIENT |
CF_SERVER,
"physics_ode_contact_maxpoints",
"16",
"maximal number of contact points between 2 objects, higher = stable (and slower), can be up to 32"};
360cvar_t physics_ode_world_erp = {
CF_CLIENT |
CF_SERVER,
"physics_ode_world_erp",
"-1",
"world solver erp parameter - Error Restitution Percent (see ODE User Guide); use defaults when set to -1"};
361cvar_t physics_ode_world_cfm = {
CF_CLIENT |
CF_SERVER,
"physics_ode_world_cfm",
"-1",
"world solver cfm parameter - Constraint Force Mixing (see ODE User Guide); not touched when -1"};
362cvar_t physics_ode_world_damping = {
CF_CLIENT |
CF_SERVER,
"physics_ode_world_damping",
"1",
"enabled damping scale (see ODE User Guide), this scales all damping values, be aware that behavior depends of step type"};
363cvar_t physics_ode_world_damping_linear = {
CF_CLIENT |
CF_SERVER,
"physics_ode_world_damping_linear",
"0.01",
"world linear damping scale (see ODE User Guide); use defaults when set to -1"};
364cvar_t physics_ode_world_damping_linear_threshold = {
CF_CLIENT |
CF_SERVER,
"physics_ode_world_damping_linear_threshold",
"0.1",
"world linear damping threshold (see ODE User Guide); use defaults when set to -1"};
365cvar_t physics_ode_world_damping_angular = {
CF_CLIENT |
CF_SERVER,
"physics_ode_world_damping_angular",
"0.05",
"world angular damping scale (see ODE User Guide); use defaults when set to -1"};
366cvar_t physics_ode_world_damping_angular_threshold = {
CF_CLIENT |
CF_SERVER,
"physics_ode_world_damping_angular_threshold",
"0.1",
"world angular damping threshold (see ODE User Guide); use defaults when set to -1"};
367cvar_t physics_ode_world_gravitymod = {
CF_CLIENT |
CF_SERVER,
"physics_ode_world_gravitymod",
"1",
"multiplies gravity got from sv_gravity, this may be needed to tweak if strong damping is used"};
368cvar_t physics_ode_iterationsperframe = {
CF_CLIENT |
CF_SERVER,
"physics_ode_iterationsperframe",
"1",
"divisor for time step, runs multiple physics steps per frame"};
369cvar_t physics_ode_constantstep = {
CF_CLIENT |
CF_SERVER,
"physics_ode_constantstep",
"0",
"use constant step instead of variable step which tends to increase stability, if set to 1 uses sys_ticrate, instead uses it's own value"};
370cvar_t physics_ode_autodisable = {
CF_CLIENT |
CF_SERVER,
"physics_ode_autodisable",
"1",
"automatic disabling of objects which dont move for long period of time, makes object stacking a lot faster"};
371cvar_t physics_ode_autodisable_steps = {
CF_CLIENT |
CF_SERVER,
"physics_ode_autodisable_steps",
"10",
"how many steps object should be dormant to be autodisabled"};
372cvar_t physics_ode_autodisable_time = {
CF_CLIENT |
CF_SERVER,
"physics_ode_autodisable_time",
"0",
"how many seconds object should be dormant to be autodisabled"};
373cvar_t physics_ode_autodisable_threshold_linear = {
CF_CLIENT |
CF_SERVER,
"physics_ode_autodisable_threshold_linear",
"0.6",
"body will be disabled if it's linear move below this value"};
374cvar_t physics_ode_autodisable_threshold_angular = {
CF_CLIENT |
CF_SERVER,
"physics_ode_autodisable_threshold_angular",
"6",
"body will be disabled if it's angular move below this value"};
375cvar_t physics_ode_autodisable_threshold_samples = {
CF_CLIENT |
CF_SERVER,
"physics_ode_autodisable_threshold_samples",
"5",
"average threshold with this number of samples"};
376cvar_t physics_ode_movelimit = {
CF_CLIENT |
CF_SERVER,
"physics_ode_movelimit",
"0.5",
"clamp velocity if a single move would exceed this percentage of object thickness, to prevent flying through walls, be aware that behavior depends of step type"};
377cvar_t physics_ode_spinlimit = {
CF_CLIENT |
CF_SERVER,
"physics_ode_spinlimit",
"10000",
"reset spin velocity if it gets too large"};
378cvar_t physics_ode_trick_fixnan = {
CF_CLIENT |
CF_SERVER,
"physics_ode_trick_fixnan",
"1",
"engine trick that checks and fixes NaN velocity/origin/angles on objects, a value of 2 makes console prints on each fix"};
379cvar_t physics_ode_printstats = {
CF_CLIENT |
CF_SERVER,
"physics_ode_printstats",
"0",
"print ODE stats each frame"};
381cvar_t physics_ode = {
CF_CLIENT |
CF_SERVER,
"physics_ode",
"0",
"run ODE physics (VERY experimental and potentially buggy)"};
400typedef dReal dVector3[4];
401typedef dReal dVector4[4];
402typedef dReal dMatrix3[4*3];
403typedef dReal dMatrix4[4*4];
404typedef dReal dMatrix6[8*6];
405typedef dReal dQuaternion[4];
416#define dInfinity 3.402823466e+38f
418typedef struct dxWorld *dWorldID;
419typedef struct dxSpace *dSpaceID;
420typedef struct dxBody *dBodyID;
421typedef struct dxGeom *dGeomID;
422typedef struct dxJoint *dJointID;
423typedef struct dxJointGroup *dJointGroupID;
424typedef struct dxTriMeshData *dTriMeshDataID;
426typedef struct dJointFeedback
435typedef enum dJointType
455#define D_ALL_PARAM_NAMES(start) \
457 dParamLoStop = start, \
467 dParamSuspensionERP, \
468 dParamSuspensionCFM, \
471#define D_ALL_PARAM_NAMES_X(start,x) \
473 dParamLoStop ## x = start, \
477 dParamFudgeFactor ## x, \
480 dParamStopERP ## x, \
481 dParamStopCFM ## x, \
483 dParamSuspensionERP ## x, \
484 dParamSuspensionCFM ## x, \
489 D_ALL_PARAM_NAMES_X(0x100,2)
490 D_ALL_PARAM_NAMES_X(0x200,3)
509 dContactFDir1 = 0x002,
510 dContactBounce = 0x004,
511 dContactSoftERP = 0x008,
512 dContactSoftCFM = 0x010,
513 dContactMotion1 = 0x020,
514 dContactMotion2 = 0x040,
515 dContactMotionN = 0x080,
516 dContactSlip1 = 0x100,
517 dContactSlip2 = 0x200,
519 dContactApprox0 = 0x0000,
520 dContactApprox1_1 = 0x1000,
521 dContactApprox1_2 = 0x2000,
522 dContactApprox1 = 0x3000
525typedef struct dSurfaceParameters
537 dReal motion1,motion2,motionN;
541typedef struct dContactGeom
551typedef struct dContact
553 dSurfaceParameters surface;
559typedef void dNearCallback (
void *
data, dGeomID o1, dGeomID o2);
563#define dSAP_AXES_XYZ ((0)|(1<<2)|(2<<4))
564#define dSAP_AXES_XZY ((0)|(2<<2)|(1<<4))
565#define dSAP_AXES_YXZ ((1)|(0<<2)|(2<<4))
566#define dSAP_AXES_YZX ((1)|(2<<2)|(0<<4))
567#define dSAP_AXES_ZXY ((2)|(0<<2)|(1<<4))
568#define dSAP_AXES_ZYX ((2)|(1<<2)|(0<<4))
570const char* (ODE_API *dGetConfiguration)(
void);
571int (ODE_API *dCheckConfiguration)(
const char* token );
582void (ODE_API *dMassSetSphereTotal)(dMass *, dReal total_mass, dReal radius);
584void (ODE_API *dMassSetCapsuleTotal)(dMass *, dReal total_mass,
int direction, dReal radius, dReal
length);
586void (ODE_API *dMassSetCylinderTotal)(dMass *, dReal total_mass,
int direction, dReal radius, dReal
length);
588void (ODE_API *dMassSetBoxTotal)(dMass *, dReal total_mass, dReal lx, dReal ly, dReal lz);
596dWorldID (ODE_API *dWorldCreate)(
void);
597void (ODE_API *dWorldDestroy)(dWorldID
world);
598void (ODE_API *dWorldSetGravity)(dWorldID, dReal
x, dReal
y, dReal
z);
599void (ODE_API *dWorldGetGravity)(dWorldID, dVector3 gravity);
600void (ODE_API *dWorldSetERP)(dWorldID, dReal
erp);
602void (ODE_API *dWorldSetCFM)(dWorldID, dReal cfm);
606void (ODE_API *dWorldQuickStep)(dWorldID
w, dReal stepsize);
607void (ODE_API *dWorldSetQuickStepNumIterations)(dWorldID,
int num);
613void (ODE_API *dWorldSetContactSurfaceLayer)(dWorldID, dReal
depth);
619void (ODE_API *dWorldSetAutoDisableLinearThreshold)(dWorldID, dReal linear_threshold);
621void (ODE_API *dWorldSetAutoDisableAngularThreshold)(dWorldID, dReal angular_threshold);
627void (ODE_API *dWorldSetAutoDisableAverageSamplesCount)(dWorldID,
unsigned int average_samples_count );
629void (ODE_API *dWorldSetAutoDisableSteps)(dWorldID,
int steps);
631void (ODE_API *dWorldSetAutoDisableTime)(dWorldID, dReal
time);
633void (ODE_API *dWorldSetAutoDisableFlag)(dWorldID,
int do_auto_disable);
635void (ODE_API *dWorldSetLinearDampingThreshold)(dWorldID
w, dReal threshold);
637void (ODE_API *dWorldSetAngularDampingThreshold)(dWorldID
w, dReal threshold);
639void (ODE_API *dWorldSetLinearDamping)(dWorldID
w, dReal
scale);
641void (ODE_API *dWorldSetAngularDamping)(dWorldID
w, dReal
scale);
659dBodyID (ODE_API *dBodyCreate)(dWorldID);
660void (ODE_API *dBodyDestroy)(dBodyID);
661void (ODE_API *dBodySetData)(dBodyID,
void *
data);
662void * (ODE_API *dBodyGetData)(dBodyID);
663void (ODE_API *dBodySetPosition)(dBodyID, dReal
x, dReal
y, dReal
z);
664void (ODE_API *dBodySetRotation)(dBodyID,
const dMatrix3 R);
666void (ODE_API *dBodySetLinearVel)(dBodyID, dReal
x, dReal
y, dReal
z);
667void (ODE_API *dBodySetAngularVel)(dBodyID, dReal
x, dReal
y, dReal
z);
668const dReal * (ODE_API *dBodyGetPosition)(dBodyID);
670const dReal * (ODE_API *dBodyGetRotation)(dBodyID);
674const dReal * (ODE_API *dBodyGetLinearVel)(dBodyID);
675const dReal * (ODE_API *dBodyGetAngularVel)(dBodyID);
676void (ODE_API *dBodySetMass)(dBodyID,
const dMass *
mass);
678void (ODE_API *dBodyAddForce)(dBodyID, dReal fx, dReal fy, dReal fz);
679void (ODE_API *dBodyAddTorque)(dBodyID, dReal fx, dReal fy, dReal fz);
682void (ODE_API *dBodyAddForceAtPos)(dBodyID, dReal fx, dReal fy, dReal fz, dReal
px, dReal py, dReal pz);
700int (ODE_API *dBodyGetNumJoints)(dBodyID
b);
701dJointID (ODE_API *dBodyGetJoint)(dBodyID,
int index);
705void (ODE_API *dBodyEnable)(dBodyID);
706void (ODE_API *dBodyDisable)(dBodyID);
707int (ODE_API *dBodyIsEnabled)(dBodyID);
708void (ODE_API *dBodySetGravityMode)(dBodyID
b,
int mode);
709int (ODE_API *dBodyGetGravityMode)(dBodyID
b);
727dJointID (ODE_API *dJointCreateBall)(dWorldID, dJointGroupID);
728dJointID (ODE_API *dJointCreateHinge)(dWorldID, dJointGroupID);
729dJointID (ODE_API *dJointCreateSlider)(dWorldID, dJointGroupID);
730dJointID (ODE_API *dJointCreateContact)(dWorldID, dJointGroupID,
const dContact *);
731dJointID (ODE_API *dJointCreateHinge2)(dWorldID, dJointGroupID);
732dJointID (ODE_API *dJointCreateUniversal)(dWorldID, dJointGroupID);
736dJointID (ODE_API *dJointCreateFixed)(dWorldID, dJointGroupID);
741void (ODE_API *dJointDestroy)(dJointID);
742dJointGroupID (ODE_API *dJointGroupCreate)(
int max_size);
743void (ODE_API *dJointGroupDestroy)(dJointGroupID);
744void (ODE_API *dJointGroupEmpty)(dJointGroupID);
746void (ODE_API *dJointAttach)(dJointID, dBodyID body1, dBodyID body2);
750void (ODE_API *dJointSetData)(dJointID,
void *
data);
751void * (ODE_API *dJointGetData)(dJointID);
753dBodyID (ODE_API *dJointGetBody)(dJointID,
int index);
756void (ODE_API *dJointSetBallAnchor)(dJointID, dReal
x, dReal
y, dReal
z);
758void (ODE_API *dJointSetBallParam)(dJointID,
int parameter, dReal
value);
759void (ODE_API *dJointSetHingeAnchor)(dJointID, dReal
x, dReal
y, dReal
z);
761void (ODE_API *dJointSetHingeAxis)(dJointID, dReal
x, dReal
y, dReal
z);
763void (ODE_API *dJointSetHingeParam)(dJointID,
int parameter, dReal
value);
765void (ODE_API *dJointSetSliderAxis)(dJointID, dReal
x, dReal
y, dReal
z);
767void (ODE_API *dJointSetSliderParam)(dJointID,
int parameter, dReal
value);
769void (ODE_API *dJointSetHinge2Anchor)(dJointID, dReal
x, dReal
y, dReal
z);
770void (ODE_API *dJointSetHinge2Axis1)(dJointID, dReal
x, dReal
y, dReal
z);
771void (ODE_API *dJointSetHinge2Axis2)(dJointID, dReal
x, dReal
y, dReal
z);
772void (ODE_API *dJointSetHinge2Param)(dJointID,
int parameter, dReal
value);
774void (ODE_API *dJointSetUniversalAnchor)(dJointID, dReal
x, dReal
y, dReal
z);
775void (ODE_API *dJointSetUniversalAxis1)(dJointID, dReal
x, dReal
y, dReal
z);
777void (ODE_API *dJointSetUniversalAxis2)(dJointID, dReal
x, dReal
y, dReal
z);
779void (ODE_API *dJointSetUniversalParam)(dJointID,
int parameter, dReal
value);
885int (ODE_API *dAreConnected)(dBodyID, dBodyID);
886int (ODE_API *dAreConnectedExcluding)(dBodyID body1, dBodyID body2,
int joint_type);
888dSpaceID (ODE_API *dSimpleSpaceCreate)(dSpaceID space);
889dSpaceID (ODE_API *dHashSpaceCreate)(dSpaceID space);
890dSpaceID (ODE_API *dQuadTreeSpaceCreate)(dSpaceID space,
const dVector3 Center,
const dVector3 Extents,
int Depth);
892void (ODE_API *dSpaceDestroy)(dSpaceID);
909void (ODE_API *dGeomDestroy)(dGeomID geom);
910void (ODE_API *dGeomSetData)(dGeomID geom,
void*
data);
911void * (ODE_API *dGeomGetData)(dGeomID geom);
912void (ODE_API *dGeomSetBody)(dGeomID geom, dBodyID body);
913dBodyID (ODE_API *dGeomGetBody)(dGeomID geom);
914void (ODE_API *dGeomSetPosition)(dGeomID geom, dReal
x, dReal
y, dReal
z);
915void (ODE_API *dGeomSetRotation)(dGeomID geom,
const dMatrix3 R);
923int (ODE_API *dGeomIsSpace)(dGeomID geom);
946int (ODE_API *dCollide)(dGeomID o1, dGeomID o2,
int flags, dContactGeom *contact,
int skip);
948void (ODE_API *dSpaceCollide)(dSpaceID space,
void *
data, dNearCallback *callback);
949void (ODE_API *dSpaceCollide2)(dGeomID space1, dGeomID space2,
void *
data, dNearCallback *callback);
951dGeomID (ODE_API *dCreateSphere)(dSpaceID space, dReal radius);
956dGeomID (ODE_API *dCreateConvex)(dSpaceID space, dReal *_planes,
unsigned int _planecount, dReal *_points,
unsigned int _pointcount,
unsigned int *_polygons);
959dGeomID (ODE_API *dCreateBox)(dSpaceID space, dReal lx, dReal ly, dReal lz);
970dGeomID (ODE_API *dCreateCapsule)(dSpaceID space, dReal radius, dReal
length);
975dGeomID (ODE_API *dCreateCylinder)(dSpaceID space, dReal radius, dReal
length);
985dGeomID (ODE_API *dCreateGeomTransform)(dSpaceID space);
986void (ODE_API *dGeomTransformSetGeom)(dGeomID
g, dGeomID
obj);
988void (ODE_API *dGeomTransformSetCleanup)(dGeomID
g,
int mode);
993enum { TRIMESH_FACE_NORMALS };
994typedef int dTriCallback(dGeomID TriMesh, dGeomID RefObject,
int TriangleIndex);
995typedef void dTriArrayCallback(dGeomID TriMesh, dGeomID RefObject,
const int* TriIndices,
int TriCount);
996typedef int dTriRayCallback(dGeomID TriMesh, dGeomID Ray,
int TriangleIndex, dReal u, dReal
v);
997typedef int dTriTriMergeCallback(dGeomID TriMesh,
int FirstTriangleIndex,
int SecondTriangleIndex);
999dTriMeshDataID (ODE_API *dGeomTriMeshDataCreate)(
void);
1000void (ODE_API *dGeomTriMeshDataDestroy)(dTriMeshDataID
g);
1005void (ODE_API *dGeomTriMeshDataBuildSingle)(dTriMeshDataID
g,
const void* Vertices,
int VertexStride,
int VertexCount,
const void* Indices,
int IndexCount,
int TriStride);
1022dGeomID (ODE_API *dCreateTriMesh)(dSpaceID space, dTriMeshDataID
Data, dTriCallback* Callback, dTriArrayCallback* ArrayCallback, dTriRayCallback* RayCallback);
1036 {
"dGetConfiguration", (
void **) &dGetConfiguration},
1037 {
"dCheckConfiguration", (
void **) &dCheckConfiguration},
1038 {
"dInitODE", (
void **) &dInitODE},
1042 {
"dCloseODE", (
void **) &dCloseODE},
1047 {
"dMassSetSphereTotal", (
void **) &dMassSetSphereTotal},
1049 {
"dMassSetCapsuleTotal", (
void **) &dMassSetCapsuleTotal},
1051 {
"dMassSetCylinderTotal", (
void **) &dMassSetCylinderTotal},
1053 {
"dMassSetBoxTotal", (
void **) &dMassSetBoxTotal},
1061 {
"dWorldCreate", (
void **) &dWorldCreate},
1062 {
"dWorldDestroy", (
void **) &dWorldDestroy},
1063 {
"dWorldSetGravity", (
void **) &dWorldSetGravity},
1064 {
"dWorldGetGravity", (
void **) &dWorldGetGravity},
1065 {
"dWorldSetERP", (
void **) &dWorldSetERP},
1067 {
"dWorldSetCFM", (
void **) &dWorldSetCFM},
1071 {
"dWorldQuickStep", (
void **) &dWorldQuickStep},
1072 {
"dWorldSetQuickStepNumIterations", (
void **) &dWorldSetQuickStepNumIterations},
1078 {
"dWorldSetContactSurfaceLayer", (
void **) &dWorldSetContactSurfaceLayer},
1084 {
"dWorldSetAutoDisableLinearThreshold", (
void **) &dWorldSetAutoDisableLinearThreshold},
1086 {
"dWorldSetAutoDisableAngularThreshold", (
void **) &dWorldSetAutoDisableAngularThreshold},
1092 {
"dWorldSetAutoDisableAverageSamplesCount", (
void **) &dWorldSetAutoDisableAverageSamplesCount},
1094 {
"dWorldSetAutoDisableSteps", (
void **) &dWorldSetAutoDisableSteps},
1096 {
"dWorldSetAutoDisableTime", (
void **) &dWorldSetAutoDisableTime},
1098 {
"dWorldSetAutoDisableFlag", (
void **) &dWorldSetAutoDisableFlag},
1100 {
"dWorldSetLinearDampingThreshold", (
void **) &dWorldSetLinearDampingThreshold},
1102 {
"dWorldSetAngularDampingThreshold", (
void **) &dWorldSetAngularDampingThreshold},
1104 {
"dWorldSetLinearDamping", (
void **) &dWorldSetLinearDamping},
1106 {
"dWorldSetAngularDamping", (
void **) &dWorldSetAngularDamping},
1124 {
"dBodyCreate", (
void **) &dBodyCreate},
1125 {
"dBodyDestroy", (
void **) &dBodyDestroy},
1126 {
"dBodySetData", (
void **) &dBodySetData},
1127 {
"dBodyGetData", (
void **) &dBodyGetData},
1128 {
"dBodySetPosition", (
void **) &dBodySetPosition},
1129 {
"dBodySetRotation", (
void **) &dBodySetRotation},
1131 {
"dBodySetLinearVel", (
void **) &dBodySetLinearVel},
1132 {
"dBodySetAngularVel", (
void **) &dBodySetAngularVel},
1133 {
"dBodyGetPosition", (
void **) &dBodyGetPosition},
1135 {
"dBodyGetRotation", (
void **) &dBodyGetRotation},
1139 {
"dBodyGetLinearVel", (
void **) &dBodyGetLinearVel},
1140 {
"dBodyGetAngularVel", (
void **) &dBodyGetAngularVel},
1141 {
"dBodySetMass", (
void **) &dBodySetMass},
1143 {
"dBodyAddForce", (
void **) &dBodyAddForce},
1144 {
"dBodyAddTorque", (
void **) &dBodyAddTorque},
1147 {
"dBodyAddForceAtPos", (
void **) &dBodyAddForceAtPos},
1165 {
"dBodyGetNumJoints", (
void **) &dBodyGetNumJoints},
1166 {
"dBodyGetJoint", (
void **) &dBodyGetJoint},
1170 {
"dBodyEnable", (
void **) &dBodyEnable},
1171 {
"dBodyDisable", (
void **) &dBodyDisable},
1172 {
"dBodyIsEnabled", (
void **) &dBodyIsEnabled},
1173 {
"dBodySetGravityMode", (
void **) &dBodySetGravityMode},
1174 {
"dBodyGetGravityMode", (
void **) &dBodyGetGravityMode},
1192 {
"dJointCreateBall", (
void **) &dJointCreateBall},
1193 {
"dJointCreateHinge", (
void **) &dJointCreateHinge},
1194 {
"dJointCreateSlider", (
void **) &dJointCreateSlider},
1195 {
"dJointCreateContact", (
void **) &dJointCreateContact},
1196 {
"dJointCreateHinge2", (
void **) &dJointCreateHinge2},
1197 {
"dJointCreateUniversal", (
void **) &dJointCreateUniversal},
1201 {
"dJointCreateFixed", (
void **) &dJointCreateFixed},
1206 {
"dJointDestroy", (
void **) &dJointDestroy},
1207 {
"dJointGroupCreate", (
void **) &dJointGroupCreate},
1208 {
"dJointGroupDestroy", (
void **) &dJointGroupDestroy},
1209 {
"dJointGroupEmpty", (
void **) &dJointGroupEmpty},
1211 {
"dJointAttach", (
void **) &dJointAttach},
1215 {
"dJointSetData", (
void **) &dJointSetData},
1216 {
"dJointGetData", (
void **) &dJointGetData},
1218 {
"dJointGetBody", (
void **) &dJointGetBody},
1221 {
"dJointSetBallAnchor", (
void **) &dJointSetBallAnchor},
1223 {
"dJointSetBallParam", (
void **) &dJointSetBallParam},
1224 {
"dJointSetHingeAnchor", (
void **) &dJointSetHingeAnchor},
1226 {
"dJointSetHingeAxis", (
void **) &dJointSetHingeAxis},
1228 {
"dJointSetHingeParam", (
void **) &dJointSetHingeParam},
1230 {
"dJointSetSliderAxis", (
void **) &dJointSetSliderAxis},
1232 {
"dJointSetSliderParam", (
void **) &dJointSetSliderParam},
1234 {
"dJointSetHinge2Anchor", (
void **) &dJointSetHinge2Anchor},
1235 {
"dJointSetHinge2Axis1", (
void **) &dJointSetHinge2Axis1},
1236 {
"dJointSetHinge2Axis2", (
void **) &dJointSetHinge2Axis2},
1237 {
"dJointSetHinge2Param", (
void **) &dJointSetHinge2Param},
1239 {
"dJointSetUniversalAnchor", (
void **) &dJointSetUniversalAnchor},
1240 {
"dJointSetUniversalAxis1", (
void **) &dJointSetUniversalAxis1},
1242 {
"dJointSetUniversalAxis2", (
void **) &dJointSetUniversalAxis2},
1244 {
"dJointSetUniversalParam", (
void **) &dJointSetUniversalParam},
1350 {
"dAreConnected", (
void **) &dAreConnected},
1351 {
"dAreConnectedExcluding", (
void **) &dAreConnectedExcluding},
1352 {
"dSimpleSpaceCreate", (
void **) &dSimpleSpaceCreate},
1353 {
"dHashSpaceCreate", (
void **) &dHashSpaceCreate},
1354 {
"dQuadTreeSpaceCreate", (
void **) &dQuadTreeSpaceCreate},
1356 {
"dSpaceDestroy", (
void **) &dSpaceDestroy},
1372 {
"dGeomDestroy", (
void **) &dGeomDestroy},
1373 {
"dGeomSetData", (
void **) &dGeomSetData},
1374 {
"dGeomGetData", (
void **) &dGeomGetData},
1375 {
"dGeomSetBody", (
void **) &dGeomSetBody},
1376 {
"dGeomGetBody", (
void **) &dGeomGetBody},
1377 {
"dGeomSetPosition", (
void **) &dGeomSetPosition},
1378 {
"dGeomSetRotation", (
void **) &dGeomSetRotation},
1386 {
"dGeomIsSpace", (
void **) &dGeomIsSpace},
1409 {
"dCollide", (
void **) &dCollide},
1410 {
"dSpaceCollide", (
void **) &dSpaceCollide},
1411 {
"dSpaceCollide2", (
void **) &dSpaceCollide2},
1412 {
"dCreateSphere", (
void **) &dCreateSphere},
1416 {
"dCreateConvex", (
void **) &dCreateConvex},
1418 {
"dCreateBox", (
void **) &dCreateBox},
1427 {
"dCreateCapsule", (
void **) &dCreateCapsule},
1431 {
"dCreateCylinder", (
void **) &dCreateCylinder},
1439 {
"dCreateGeomTransform", (
void **) &dCreateGeomTransform},
1440 {
"dGeomTransformSetGeom", (
void **) &dGeomTransformSetGeom},
1442 {
"dGeomTransformSetCleanup", (
void **) &dGeomTransformSetCleanup},
1446 {
"dGeomTriMeshDataCreate", (
void **) &dGeomTriMeshDataCreate},
1447 {
"dGeomTriMeshDataDestroy", (
void **) &dGeomTriMeshDataDestroy},
1452 {
"dGeomTriMeshDataBuildSingle", (
void **) &dGeomTriMeshDataBuildSingle},
1469 {
"dCreateTriMesh", (
void **) &dCreateTriMesh},
1486static void World_Physics_Init(
void)
1488#ifndef LINK_TO_LIBODE
1489 const char* dllnames [] =
1495# elif defined(MACOSX)
1538#ifndef LINK_TO_LIBODE
1545#ifndef LINK_TO_LIBODE
1547 if (!dCheckConfiguration(
"ODE_single_precision"))
1549 if (!dCheckConfiguration(
"ODE_double_precision"))
1553 Con_Printf(
"ODE library not compiled for single precision - incompatible! Not using ODE physics.\n");
1555 Con_Printf(
"ODE library not compiled for double precision - incompatible! Not using ODE physics.\n");
1563 Con_Printf(
"ODE library loaded with single precision.\n");
1565 Con_Printf(
"ODE library loaded with double precision.\n");
1567 Con_Printf(
"ODE configuration list: %s\n", dGetConfiguration());
1572static void World_Physics_Shutdown(
void)
1574#ifndef LINK_TO_LIBODE
1579#ifndef LINK_TO_LIBODE
1590 odeworld = (dWorldID)
world->physics.ode_world;
1593 if (physics_ode_world_erp.
value >= 0)
1594 dWorldSetERP(odeworld, physics_ode_world_erp.
value);
1595 if (physics_ode_world_cfm.
value >= 0)
1596 dWorldSetCFM(odeworld, physics_ode_world_cfm.
value);
1598 if (physics_ode_world_damping.
integer)
1600 dWorldSetLinearDamping(odeworld, (physics_ode_world_damping_linear.
value >= 0) ? (physics_ode_world_damping_linear.
value * physics_ode_world_damping.
value) : 0);
1601 dWorldSetLinearDampingThreshold(odeworld, (physics_ode_world_damping_linear_threshold.
value >= 0) ? (physics_ode_world_damping_linear_threshold.
value * physics_ode_world_damping.
value) : 0);
1602 dWorldSetAngularDamping(odeworld, (physics_ode_world_damping_angular.
value >= 0) ? (physics_ode_world_damping_angular.
value * physics_ode_world_damping.
value) : 0);
1603 dWorldSetAngularDampingThreshold(odeworld, (physics_ode_world_damping_angular_threshold.
value >= 0) ? (physics_ode_world_damping_angular_threshold.
value * physics_ode_world_damping.
value) : 0);
1607 dWorldSetLinearDamping(odeworld, 0);
1608 dWorldSetLinearDampingThreshold(odeworld, 0);
1609 dWorldSetAngularDamping(odeworld, 0);
1610 dWorldSetAngularDampingThreshold(odeworld, 0);
1613 dWorldSetAutoDisableFlag(odeworld, (physics_ode_autodisable.
integer) ? 1 : 0);
1614 if (physics_ode_autodisable.
integer)
1616 dWorldSetAutoDisableSteps(odeworld,
bound(1, physics_ode_autodisable_steps.
integer, 100));
1617 dWorldSetAutoDisableTime(odeworld, physics_ode_autodisable_time.
value);
1618 dWorldSetAutoDisableAverageSamplesCount(odeworld,
bound(1, physics_ode_autodisable_threshold_samples.
integer, 100));
1619 dWorldSetAutoDisableLinearThreshold(odeworld, physics_ode_autodisable_threshold_linear.
value);
1620 dWorldSetAutoDisableAngularThreshold(odeworld, physics_ode_autodisable_threshold_angular.
value);
1626 dVector3 center, extents;
1627 if (
world->physics.ode)
1629#ifndef LINK_TO_LIBODE
1633 world->physics.ode =
true;
1636 world->physics.ode_world = dWorldCreate();
1637 world->physics.ode_space = dQuadTreeSpaceCreate(
NULL, center, extents,
bound(1, physics_ode_quadtree_depth.
integer, 10));
1638 world->physics.ode_contactgroup = dJointGroupCreate(0);
1640 World_Physics_UpdateODE(
world);
1645 if (
world->physics.ode)
1647 World_Physics_EnableODE(
world);
1652 if (
world->physics.ode)
1654 dWorldDestroy((dWorldID)
world->physics.ode_world);
1655 dSpaceDestroy((dSpaceID)
world->physics.ode_space);
1656 dJointGroupDestroy((dJointGroupID)
world->physics.ode_contactgroup);
1657 world->physics.ode =
false;
1665 dJointDestroy((dJointID)ed->
priv.
server->ode_joint);
1671 edict_odefunc_t *
f, *nf;
1676 dGeomDestroy((dGeomID)ed->
priv.
server->ode_geom);
1683 while(dBodyGetNumJoints((dBodyID)ed->
priv.
server->ode_body))
1685 j = dBodyGetJoint((dBodyID)ed->
priv.
server->ode_body, 0);
1687 b1 = dJointGetBody(j, 0);
1688 b2 = dJointGetBody(j, 1);
1699 dJointAttach(j, b1, b2);
1701 dBodyDestroy((dBodyID)ed->
priv.
server->ode_body);
1726 dBodyID body = (dBodyID)ed->
priv.
server->ode_body;
1730 case ODEFUNC_ENABLE:
1733 case ODEFUNC_DISABLE:
1738 dBodyAddForceAtPos(body,
f->v1[0],
f->v1[1],
f->v1[2],
f->v2[0],
f->v2[1],
f->v2[2]);
1740 case ODEFUNC_TORQUE:
1742 dBodyAddTorque(body,
f->v1[0],
f->v1[1],
f->v1[2]);
1756 dBodyID body = (dBodyID)ed->
priv.
server->ode_body;
1792 o = dBodyGetPosition(body);
1793 r = dBodyGetRotation(body);
1794 vel = dBodyGetLinearVel(body);
1795 avel = dBodyGetAngularVel(body);
1816 float pitchsign = 1;
1843 ed->
priv.
server->ode_gravity = dBodyGetGravityMode(body) != 0;
1901 vec_t CFM, ERP, FMax, Stop, Vel;
1928 float R = 2.0 * D *
sqrt(K);
1929 CFM = 1.0 / (
world->physics.ode_step * K + R);
1930 ERP =
world->physics.ode_step * K * CFM;
1957 j = dJointCreateBall((dWorldID)
world->physics.ode_world, 0);
1960 j = dJointCreateHinge((dWorldID)
world->physics.ode_world, 0);
1963 j = dJointCreateSlider((dWorldID)
world->physics.ode_world, 0);
1966 j = dJointCreateUniversal((dWorldID)
world->physics.ode_world, 0);
1969 j = dJointCreateHinge2((dWorldID)
world->physics.ode_world, 0);
1972 j = dJointCreateFixed((dWorldID)
world->physics.ode_world, 0);
1983 dJointAttach((dJointID)ed->
priv.
server->ode_joint, 0, 0);
1984 dJointDestroy((dJointID)ed->
priv.
server->ode_joint);
1997 dJointSetData(j, (
void *) ed);
2002 dJointAttach(j, b1, b2);
2012 dJointSetHingeParam(j, dParamFMax, FMax);
2013 dJointSetHingeParam(j, dParamHiStop, Stop);
2014 dJointSetHingeParam(j, dParamLoStop, -Stop);
2015 dJointSetHingeParam(j, dParamStopCFM, CFM);
2016 dJointSetHingeParam(j, dParamStopERP, ERP);
2017 dJointSetHingeParam(j, dParamVel, Vel);
2021 dJointSetSliderParam(j, dParamFMax, FMax);
2022 dJointSetSliderParam(j, dParamHiStop, Stop);
2023 dJointSetSliderParam(j, dParamLoStop, -Stop);
2024 dJointSetSliderParam(j, dParamStopCFM, CFM);
2025 dJointSetSliderParam(j, dParamStopERP, ERP);
2026 dJointSetSliderParam(j, dParamVel, Vel);
2031 dJointSetUniversalAxis2(j,
up[0],
up[1],
up[2]);
2032 dJointSetUniversalParam(j, dParamFMax, FMax);
2033 dJointSetUniversalParam(j, dParamHiStop, Stop);
2034 dJointSetUniversalParam(j, dParamLoStop, -Stop);
2035 dJointSetUniversalParam(j, dParamStopCFM, CFM);
2036 dJointSetUniversalParam(j, dParamStopERP, ERP);
2037 dJointSetUniversalParam(j, dParamVel, Vel);
2038 dJointSetUniversalParam(j, dParamFMax2, FMax);
2039 dJointSetUniversalParam(j, dParamHiStop2, Stop);
2040 dJointSetUniversalParam(j, dParamLoStop2, -Stop);
2041 dJointSetUniversalParam(j, dParamStopCFM2, CFM);
2042 dJointSetUniversalParam(j, dParamStopERP2, ERP);
2043 dJointSetUniversalParam(j, dParamVel2, Vel);
2049 dJointSetHinge2Param(j, dParamFMax, FMax);
2050 dJointSetHinge2Param(j, dParamHiStop, Stop);
2051 dJointSetHinge2Param(j, dParamLoStop, -Stop);
2052 dJointSetHinge2Param(j, dParamStopCFM, CFM);
2053 dJointSetHinge2Param(j, dParamStopERP, ERP);
2054 dJointSetHinge2Param(j, dParamVel, Vel);
2055 dJointSetHinge2Param(j, dParamFMax2, FMax);
2056 dJointSetHinge2Param(j, dParamHiStop2, Stop);
2057 dJointSetHinge2Param(j, dParamLoStop2, -Stop);
2058 dJointSetHinge2Param(j, dParamStopCFM2, CFM);
2059 dJointSetHinge2Param(j, dParamStopERP2, ERP);
2060 dJointSetHinge2Param(j, dParamVel2, Vel);
2066 Sys_Error(
"what? but above the joint was valid...\n");
2076dReal test_convex_planes[] =
2078 1.0f ,0.0f ,0.0f ,2.25f,
2079 0.0f ,1.0f ,0.0f ,2.25f,
2080 0.0f ,0.0f ,1.0f ,2.25f,
2081 -1.0f,0.0f ,0.0f ,2.25f,
2082 0.0f ,-1.0f,0.0f ,2.25f,
2083 0.0f ,0.0f ,-1.0f,2.25f
2085const unsigned int test_convex_planecount = 6;
2087dReal test_convex_points[] =
2092 -2.25f,-2.25f,2.25f,
2094 -2.25f,2.25f,-2.25f,
2095 2.25f,-2.25f,-2.25f,
2096 -2.25f,-2.25f,-2.25f,
2098const unsigned int test_convex_pointcount = 8;
2100unsigned int test_convex_polygons[] =
2117 const dReal *ovelocity, *ospinvelocity;
2131 qbool modified =
false;
2146 vec_t massval = 1.0f;
2153 qbool geom_modified =
false;
2154 edict_odefunc_t *func, *nextf;
2156 dReal *planes, *planesData, *pointsData;
2157 unsigned int *polygons, *polygonsData, polyvert;
2158 qbool *mapped, *used, convex_compatible;
2159 int numplanes = 0, numpoints = 0,
i;
2161#ifndef LINK_TO_LIBODE
2214 entmins[0] =
model->normalmins[0] *
scale[0];
2215 entmins[1] =
model->normalmins[1] *
scale[1];
2216 entmins[2] =
model->normalmins[2] *
scale[2];
2217 entmaxs[0] =
model->normalmaxs[0] *
scale[0];
2218 entmaxs[1] =
model->normalmaxs[1] *
scale[1];
2219 entmaxs[2] =
model->normalmaxs[2] *
scale[2];
2264 VectorMAM(0.5f, entmins, 0.5f, entmaxs, geomcenter);
2269 if (geomsize[0] * geomsize[1] * geomsize[2] == 0)
2281 if (!
model->brush.collisionmesh)
2283 if (!
model->brush.collisionmesh)
2290 convex_compatible =
false;
2293 if (!strcmp(
model->data_surfaces[
i].texture->name,
"collisionconvex"))
2295 convex_compatible =
true;
2305 ed->
priv.
server->ode_numvertices = numvertices =
model->brush.collisionmesh->numverts;
2306 ed->
priv.
server->ode_vertex3f = (
float *)
Mem_Alloc(mempool, numvertices *
sizeof(
float[3]));
2311 for (vertexindex = 0, ov = ed->
priv.
server->ode_vertex3f, iv =
model->brush.collisionmesh->vertex3f;vertexindex < numvertices;vertexindex++, ov += 3, iv += 3)
2313 ov[0] = iv[0] *
scale[0];
2314 ov[1] = iv[1] *
scale[1];
2315 ov[2] = iv[2] *
scale[2];
2316 entmins[0] =
min(entmins[0], ov[0]);
2317 entmins[1] =
min(entmins[1], ov[1]);
2318 entmins[2] =
min(entmins[2], ov[2]);
2319 entmaxs[0] =
max(entmaxs[0], ov[0]);
2320 entmaxs[1] =
max(entmaxs[1], ov[1]);
2321 entmaxs[2] =
max(entmaxs[2], ov[2]);
2324 VectorMAM(0.5f, entmins, 0.5f, entmaxs, geomcenter);
2325 for (vertexindex = 0, ov = ed->
priv.
server->ode_vertex3f, iv =
model->brush.collisionmesh->vertex3f;vertexindex < numvertices;vertexindex++, ov += 3, iv += 3)
2327 ov[0] = ov[0] - geomcenter[0];
2328 ov[1] = ov[1] - geomcenter[1];
2329 ov[2] = ov[2] - geomcenter[2];
2338 ed->
priv.
server->ode_numtriangles = numtriangles =
model->brush.collisionmesh->numtriangles;
2339 ed->
priv.
server->ode_element3i = (
int *)
Mem_Alloc(mempool, numtriangles *
sizeof(
int[3]));
2341 for (triangleindex = 0, oe = ed->
priv.
server->ode_element3i, ie =
model->brush.collisionmesh->element3i;triangleindex < numtriangles;triangleindex++, oe += 3, ie += 3)
2349 if (!convex_compatible || !physics_ode_allowconvex.
integer)
2352 dataID = dGeomTriMeshDataCreate();
2353 dGeomTriMeshDataBuildSingle((dTriMeshDataID)dataID, (
void*)ed->
priv.
server->ode_vertex3f,
sizeof(
float[3]), ed->
priv.
server->ode_numvertices, ed->
priv.
server->ode_element3i, ed->
priv.
server->ode_numtriangles*3,
sizeof(
int[3]));
2355 dMassSetBoxTotal(&
mass, massval, geomsize[0], geomsize[1], geomsize[2]);
2373 polygonsData = polygons = (
unsigned int *)
Mem_Alloc(mempool, numtriangles*
sizeof(
int)*4);
2374 planesData = planes = (dReal *)
Mem_Alloc(mempool, numtriangles*
sizeof(dReal)*4);
2377 memset(mapped, 0, numvertices*
sizeof(
qbool));
2378 memset(used, 0, numtriangles*
sizeof(
qbool));
2379 numplanes = numpoints = polyvert = 0;
2384 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
2387 if (used[triangleindex])
2391 ie = &
model->brush.collisionmesh->element3i[triangleindex*3];
2392 used[triangleindex] =
true;
2393 TriangleNormal(&iv[ie[0]*3], &iv[ie[1]*3], &iv[ie[2]*3], planes);
2396 polygons[3] = (
unsigned int)ie[0]; mapped[polygons[3]] =
true;
2397 polygons[2] = (
unsigned int)ie[1]; mapped[polygons[2]] =
true;
2398 polygons[1] = (
unsigned int)ie[2]; mapped[polygons[1]] =
true;
2401 for (
i = triangleindex;
i < numtriangles;
i++)
2406 for (polyvert = 1; polyvert <= polygons[0]; polyvert++)
2413 planes[3] =
DotProduct(&iv[polygons[1]*3], planes);
2414 polygons += (polygons[0]+1);
2420 for (vertexindex = 0, numpoints = 0; vertexindex < numvertices; vertexindex++)
2421 if (mapped[vertexindex])
2423 pointsData = (dReal *)
Mem_Alloc(mempool, numpoints*
sizeof(dReal)*3 + numplanes*
sizeof(dReal)*4);
2424 for (vertexindex = 0, numpoints = 0; vertexindex < numvertices; vertexindex++)
2426 if (mapped[vertexindex])
2428 VectorCopy(&iv[vertexindex*3], &pointsData[numpoints*3]);
2434 for (
i = 0;
i < (
int)numpoints;
i++)
2435 Con_Printf(
"%3i: %3.1f %3.1f %3.1f\n",
i, pointsData[
i*3], pointsData[
i*3+1], pointsData[
i*3+2]);
2437 planes = planesData;
2438 planesData = pointsData + numpoints*3;
2439 memcpy(planesData, planes, numplanes*
sizeof(dReal)*4);
2442 for (
i = 0;
i < numplanes;
i++)
2443 Con_Printf(
"%3i: %1.1f %1.1f %1.1f %1.1f\n",
i, planesData[
i*4], planesData[
i*4 + 1], planesData[
i*4 + 2], planesData[
i*4 + 3]);
2445 polyvert = polygons - polygonsData;
2446 polygons = polygonsData;
2447 polygonsData = (
unsigned int *)
Mem_Alloc(mempool, polyvert*
sizeof(
int));
2448 memcpy(polygonsData, polygons, polyvert*
sizeof(
int));
2451 polygons = polygonsData;
2452 for (
i = 0;
i < numplanes;
i++)
2455 for (triangleindex = 1; triangleindex <= (
int)polygons[0]; triangleindex++)
2457 polygons += (polygons[0]+1);
2461 ed->
priv.
server->ode_element3i = (
int *)polygonsData;
2463 ed->
priv.
server->ode_vertex3f = (
float *)pointsData;
2467 polygons = polygonsData;
2468 for (
i = 0;
i < numplanes;
i++)
2470 if((pointsData[(polygons[1]*3)+0]*pointsData[(polygons[2]*3)+1]*pointsData[(polygons[3]*3)+2] +
2471 pointsData[(polygons[1]*3)+1]*pointsData[(polygons[2]*3)+2]*pointsData[(polygons[3]*3)+0] +
2472 pointsData[(polygons[1]*3)+2]*pointsData[(polygons[2]*3)+0]*pointsData[(polygons[3]*3)+1] -
2473 pointsData[(polygons[1]*3)+2]*pointsData[(polygons[2]*3)+1]*pointsData[(polygons[3]*3)+0] -
2474 pointsData[(polygons[1]*3)+1]*pointsData[(polygons[2]*3)+0]*pointsData[(polygons[3]*3)+2] -
2475 pointsData[(polygons[1]*3)+0]*pointsData[(polygons[2]*3)+2]*pointsData[(polygons[3]*3)+1]) < 0)
2477 if (planesData[(
i*4)+3] < 0)
2479 polygons += (*polygons + 1);
2483 ed->
priv.
server->ode_geom = (
void *)dCreateConvex((dSpaceID)
world->physics.ode_space, planesData, numplanes, pointsData, numpoints, polygonsData);
2484 dMassSetBoxTotal(&
mass, massval, geomsize[0], geomsize[1], geomsize[2]);
2491 ed->
priv.
server->ode_geom = (
void *)dCreateBox((dSpaceID)
world->physics.ode_space, geomsize[0], geomsize[1], geomsize[2]);
2492 dMassSetBoxTotal(&
mass, massval, geomsize[0], geomsize[1], geomsize[2]);
2496 ed->
priv.
server->ode_geom = (
void *)dCreateSphere((dSpaceID)
world->physics.ode_space, geomsize[0] * 0.5f);
2497 dMassSetSphereTotal(&
mass, massval, geomsize[0] * 0.5f);
2501 if (geomsize[axisindex] < geomsize[1])
2503 if (geomsize[axisindex] < geomsize[2])
2512 radius =
min(geomsize[1], geomsize[2]) * 0.5f;
2514 else if (axisindex == 1)
2517 radius =
min(geomsize[0], geomsize[2]) * 0.5f;
2522 radius =
min(geomsize[0], geomsize[1]) * 0.5f;
2524 length = geomsize[axisindex] - radius*2;
2528 ed->
priv.
server->ode_geom = (
void *)dCreateCapsule((dSpaceID)
world->physics.ode_space, radius,
length);
2529 dMassSetCapsuleTotal(&
mass, massval, axisindex+1, radius,
length);
2533 radius =
min(geomsize[1], geomsize[2]) * 0.5f;
2534 length = geomsize[0] - radius*2;
2538 radius -= (1 -
length)*0.5;
2541 ed->
priv.
server->ode_geom = (
void *)dCreateCapsule((dSpaceID)
world->physics.ode_space, radius,
length);
2542 dMassSetCapsuleTotal(&
mass, massval, 1, radius,
length);
2546 radius =
min(geomsize[0], geomsize[2]) * 0.5f;
2547 length = geomsize[1] - radius*2;
2551 radius -= (1 -
length)*0.5;
2554 ed->
priv.
server->ode_geom = (
void *)dCreateCapsule((dSpaceID)
world->physics.ode_space, radius,
length);
2555 dMassSetCapsuleTotal(&
mass, massval, 2, radius,
length);
2559 radius =
min(geomsize[1], geomsize[0]) * 0.5f;
2560 length = geomsize[2] - radius*2;
2564 radius -= (1 -
length)*0.5;
2567 ed->
priv.
server->ode_geom = (
void *)dCreateCapsule((dSpaceID)
world->physics.ode_space, radius,
length);
2568 dMassSetCapsuleTotal(&
mass, massval, 3, radius,
length);
2572 if (geomsize[axisindex] < geomsize[1])
2574 if (geomsize[axisindex] < geomsize[2])
2583 radius =
min(geomsize[1], geomsize[2]) * 0.5f;
2585 else if (axisindex == 1)
2588 radius =
min(geomsize[0], geomsize[2]) * 0.5f;
2593 radius =
min(geomsize[0], geomsize[1]) * 0.5f;
2595 length = geomsize[axisindex];
2599 radius -= (1 -
length)*0.5;
2602 ed->
priv.
server->ode_geom = (
void *)dCreateCylinder((dSpaceID)
world->physics.ode_space, radius,
length);
2603 dMassSetCylinderTotal(&
mass, massval, axisindex+1, radius,
length);
2607 radius =
min(geomsize[1], geomsize[2]) * 0.5f;
2609 ed->
priv.
server->ode_geom = (
void *)dCreateCylinder((dSpaceID)
world->physics.ode_space, radius,
length);
2610 dMassSetCylinderTotal(&
mass, massval, 1, radius,
length);
2614 radius =
min(geomsize[0], geomsize[2]) * 0.5f;
2616 ed->
priv.
server->ode_geom = (
void *)dCreateCylinder((dSpaceID)
world->physics.ode_space, radius,
length);
2617 dMassSetCylinderTotal(&
mass, massval, 2, radius,
length);
2621 radius =
min(geomsize[0], geomsize[1]) * 0.5f;
2623 ed->
priv.
server->ode_geom = (
void *)dCreateCylinder((dSpaceID)
world->physics.ode_space, radius,
length);
2624 dMassSetCylinderTotal(&
mass, massval, 3, radius,
length);
2627 Sys_Error(
"World_Physics_BodyFromEntity: unrecognized geomtype value %i was accepted by filter\n",
solid);
2638 ed->
priv.
server->ode_movelimit =
min(geomsize[0],
min(geomsize[1], geomsize[2]));
2645 dGeomSetData((dGeomID)ed->
priv.
server->ode_geom, (
void*)ed);
2651 ed->
priv.
server->ode_body = (
void *)(body = dBodyCreate((dWorldID)
world->physics.ode_world));
2652 dGeomSetBody((dGeomID)ed->
priv.
server->ode_geom, body);
2653 dBodySetData(body, (
void*)ed);
2654 dBodySetMass(body, (dMass *) ed->
priv.
server->ode_massbuf);
2664 dGeomSetBody((dGeomID)ed->
priv.
server->ode_geom, 0);
2665 dBodyDestroy((dBodyID) ed->
priv.
server->ode_body);
2696 float pitchsign = 1;
2697 vec3_t qangles, qavelocity;
2709 qangles[
PITCH] *= pitchsign;
2710 qavelocity[
PITCH] *= pitchsign;
2733 if (physics_ode_trick_fixnan.
integer)
2740 if (physics_ode_trick_fixnan.
integer >= 2)
2741 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(prog,
PRVM_gameedictstring(ed,
classname)),
origin[0],
origin[1],
origin[2],
velocity[0],
velocity[1],
velocity[2],
angles[0],
angles[1],
angles[2],
avelocity[0],
avelocity[1],
avelocity[2]);
2817 dGeomSetBody((dGeomID)ed->
priv.
server->ode_geom, body);
2819 dBodySetRotation(body,
r[0]);
2821 dBodySetAngularVel(body, spinvelocity[0], spinvelocity[1], spinvelocity[2]);
2822 dBodySetGravityMode(body, gravity);
2826 dGeomSetBody((dGeomID)ed->
priv.
server->ode_geom, body);
2828 dBodySetRotation(body,
r[0]);
2830 dBodySetAngularVel(body, spinvelocity[0], spinvelocity[1], spinvelocity[2]);
2831 dBodySetGravityMode(body, gravity);
2832 dGeomSetBody((dGeomID)ed->
priv.
server->ode_geom, 0);
2838 dGeomSetBody((dGeomID)ed->
priv.
server->ode_geom, 0);
2840 dGeomSetRotation((dGeomID)ed->
priv.
server->ode_geom,
r[0]);
2848 ovelocity = dBodyGetLinearVel(body);
2849 ospinvelocity = dBodyGetAngularVel(body);
2850 movelimit = ed->
priv.
server->ode_movelimit *
world->physics.ode_movelimit;
2852 if (test > movelimit*movelimit)
2856 f = movelimit /
sqrt(test);
2860 dBodySetAngularVel(body, spinvelocity[0], spinvelocity[1], spinvelocity[2]);
2864 spinlimit = physics_ode_spinlimit.
value;
2866 if (test > spinlimit)
2868 dBodySetAngularVel(body, 0, 0, 0);
2872 for(func = ed->
priv.
server->ode_func; func; func = nextf)
2882#define MAX_CONTACTS 32
2883static void nearCallback (
void *
data, dGeomID o1, dGeomID o2)
2887 dContact contact[MAX_CONTACTS];
2888 int b1enabled = 0, b2enabled = 0;
2893 float bouncefactor1 = 0.0f;
2894 float bouncestop1 = 60.0f / 800.0f;
2895 float bouncefactor2 = 0.0f;
2896 float bouncestop2 = 60.0f / 800.0f;
2901 if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
2904 dSpaceCollide2(o1, o2,
data, &nearCallback);
2912 b1 = dGeomGetBody(o1);
2914 b1enabled = dBodyIsEnabled(b1);
2915 b2 = dGeomGetBody(o2);
2917 b2enabled = dBodyIsEnabled(b2);
2920 if (!b1enabled && !b2enabled)
2924 if (b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact))
2928 if(ed1 && ed1->
free)
2935 bouncestop1 = 60.0f / 800.0f;
2939 if(ed2 && ed2->
free)
2946 bouncestop2 = 60.0f / 800.0f;
2962 if(bouncefactor2 > 0)
2964 if(bouncefactor1 > 0)
2967 if(bouncestop2 < bouncestop1)
2968 bouncestop1 = bouncestop2;
2969 if(bouncefactor2 > bouncefactor1)
2970 bouncefactor1 = bouncefactor2;
2974 bouncestop1 = bouncestop2;
2975 bouncefactor1 = bouncefactor2;
2978 dWorldGetGravity((dWorldID)
world->physics.ode_world, grav);
2979 bouncestop1 *=
fabs(grav[2]);
2988 numcontacts = physics_ode_contact_maxpoints.
integer;
2992 numcontacts =
max(numcontacts, physics_ode_contact_maxpoints.
integer);
2995 numcontacts = dCollide(o1, o2,
min(MAX_CONTACTS, numcontacts), &(contact[0].geom),
sizeof(contact[0]));
2997 for (
i = 0;
i < numcontacts;
i++)
2999 contact[
i].surface.mode = (physics_ode_contact_mu.
value != -1 ? dContactApprox1 : 0) | (physics_ode_contact_erp.
value != -1 ? dContactSoftERP : 0) | (physics_ode_contact_cfm.
value != -1 ? dContactSoftCFM : 0) | (bouncefactor1 > 0 ? dContactBounce : 0);
3001 contact[
i].surface.soft_erp = physics_ode_contact_erp.
value +
erp;
3002 contact[
i].surface.soft_cfm = physics_ode_contact_cfm.
value;
3003 contact[
i].surface.bounce = bouncefactor1;
3004 contact[
i].surface.bounce_vel = bouncestop1;
3005 c = dJointCreateContact((dWorldID)
world->physics.ode_world, (dJointGroupID)
world->physics.ode_contactgroup, contact +
i);
3006 dJointAttach(c, b1, b2);
3013 double tdelta, tdelta2, tdelta3, simulationtime, collisiontime;
3021 if (!physics_ode_constantstep.
value)
3023 world->physics.ode_iterations =
bound(1, physics_ode_iterationsperframe.
integer, 1000);
3030 if (physics_ode_constantstep.
value > 0 && physics_ode_constantstep.
value < 1)
3031 world->physics.ode_step = physics_ode_constantstep.
value;
3034 if (
world->physics.ode_time > 0.2f)
3035 world->physics.ode_time =
world->physics.ode_step;
3037 world->physics.ode_iterations = 0;
3038 while(
world->physics.ode_time >=
world->physics.ode_step)
3040 world->physics.ode_iterations++;
3041 world->physics.ode_time -=
world->physics.ode_step;
3044 world->physics.ode_movelimit = physics_ode_movelimit.
value /
world->physics.ode_step;
3045 World_Physics_UpdateODE(
world);
3052 World_Physics_Frame_BodyFromEntity(
world, ed);
3056 World_Physics_Frame_JointFromEntity(
world, ed);
3061 for (
i = 0;
i <
world->physics.ode_iterations;
i++)
3064 dWorldSetGravity((dWorldID)
world->physics.ode_world, 0, 0, -gravity * physics_ode_world_gravitymod.
value);
3066 dWorldSetContactSurfaceLayer((dWorldID)
world->physics.ode_world,
max(0, physics_ode_contactsurfacelayer.
value));
3069 dSpaceCollide((dSpaceID)
world->physics.ode_space, (
void *)
world, nearCallback);
3075 for (j = 0, ed = prog->
edicts + j;j < prog->num_edicts;j++, ed++)
3077 World_Physics_Frame_ForceFromEntity(
world, ed);
3081 dWorldSetQuickStepNumIterations((dWorldID)
world->physics.ode_world,
bound(1, physics_ode_worldstep_iterations.
integer, 200));
3082 if (
world->physics.ode_step > 0)
3083 dWorldQuickStep((dWorldID)
world->physics.ode_world,
world->physics.ode_step);
3085 dJointGroupEmpty((dJointGroupID)
world->physics.ode_contactgroup);
3094 World_Physics_Frame_BodyToEntity(
world, ed);
3097 if (physics_ode_printstats.
integer)
3101 world->physics.ode_numobjects = 0;
3102 world->physics.ode_activeovjects = 0;
3110 world->physics.ode_numobjects++;
3111 if (dBodyIsEnabled(body))
3112 world->physics.ode_activeovjects++;
3114 Con_Printf(
"ODE Stats(%s): %i iterations, %3.01f (%3.01f collision) %3.01f total : %i objects %i active %i disabled\n", prog->
name,
world->physics.ode_iterations, simulationtime, collisiontime, (
Sys_DirtyTime() - tdelta)*10000,
world->physics.ode_numobjects,
world->physics.ode_activeovjects, (
world->physics.ode_numobjects -
world->physics.ode_activeovjects));
model_t * CL_GetModelByIndex(int modelindex)
int CL_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent)
#define CF_SERVER
cvar/command that only the server can change/execute
#define CF_CLIENT
cvar/command that only the client can change/execute
void Collision_Init(void)
#define List_Entry(ptr, type, member)
static void List_Add_Tail(llist_t *node, llist_t *head)
static void List_Delete(llist_t *node)
#define List_For_Each_Entry(pos, head, type, member)
#define dp_strlcpy(dst, src, dsize)
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
const float GEOMTYPE_TRIMESH
const float JOINTTYPE_SLIDER
const float JOINTTYPE_NONE
const float JOINTTYPE_FIXED
const float GEOMTYPE_CYLINDER_Y
const float GEOMTYPE_CAPSULE_Y
const float FORCETYPE_FORCE
const float GEOMTYPE_CYLINDER_Z
const float FORCETYPE_NONE
const float JOINTTYPE_UNIVERSAL
const float FORCETYPE_TORQUE
const float JOINTTYPE_POINT
const float GEOMTYPE_CAPSULE_X
const float GEOMTYPE_SPHERE
const float JOINTTYPE_HINGE
const float FORCETYPE_FORCEATPOS
const float GEOMTYPE_NONE
const float GEOMTYPE_CYLINDER_X
const float JOINTTYPE_HINGE2
const float GEOMTYPE_CAPSULE_Z
const float GEOMTYPE_CAPSULE
const float GEOMTYPE_CYLINDER
static int(ZEXPORT *qz_inflate)(z_stream *strm
GLubyte GLubyte GLubyte z
GLubyte GLubyte GLubyte GLubyte w
GLsizei const GLfloat * value
GLenum GLuint GLenum GLsizei length
GLint GLenum GLint GLint y
GLint GLenum GLsizei GLsizei GLsizei depth
GLsizeiptr const GLvoid * data
void AnglesFromVectors(vec3_t angles, const vec3_t forward, const vec3_t up, qbool flippitch)
LadyHavoc: calculates pitch/yaw/roll angles from forward and up vectors.
void AngleVectorsFLU(const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up)
LadyHavoc: proper matrix version of AngleVectors.
#define VectorNegate(a, b)
#define BoxesOverlap(a, b, c, d)
#define VectorNormalize(v)
#define bound(min, num, max)
#define VectorSet(vec, x, y, z)
#define VectorSubtract(a, b, out)
#define VectorCompare(a, b)
#define TriangleNormal(a, b, c, n)
#define VectorCopy(in, out)
#define VectorScale(in, scale, out)
#define VectorMAM(scale1, b1, scale2, b2, out)
void Matrix4x4_Concat(matrix4x4_t *out, const matrix4x4_t *in1, const matrix4x4_t *in2)
void Matrix4x4_CreateTranslate(matrix4x4_t *out, double x, double y, double z)
void Matrix4x4_CreateFromQuakeEntity(matrix4x4_t *out, double x, double y, double z, double pitch, double yaw, double roll, double scale)
void Matrix4x4_Invert_Simple(matrix4x4_t *out, const matrix4x4_t *in1)
void Matrix4x4_FromVectors(matrix4x4_t *out, const float vx[3], const float vy[3], const float vz[3], const float t[3])
void Matrix4x4_ToVectors(const matrix4x4_t *in, float vx[3], float vy[3], float vz[3], float t[3])
void Mod_CreateCollisionMesh(model_t *mod)
#define PRVM_gameedictvector(ed, fieldname)
#define PRVM_gameedictfloat(ed, fieldname)
#define PRVM_gameedictedict(ed, fieldname)
#define PRVM_gameedictstring(ed, fieldname)
#define PRVM_EDICT_NUM(n)
const char * PRVM_GetString(prvm_prog_t *prog, int num)
#define PRVM_NUM_FOR_EDICT(e)
#define PRVM_serveredictfloat(ed, fieldname)
#define PRVM_serveredictfunction(ed, fieldname)
#define MOVETYPE_PHYSICS
indicates this object is physics controlled
#define SOLID_BBOX
touch on edge, block
#define SOLID_SLIDEBOX
touch on edge, but not an onground
#define SOLID_PHYSICS_BOX
physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity,...
#define SOLID_PHYSICS_SPHERE
physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity,...
#define SOLID_CORPSE
same as SOLID_BBOX, except it behaves as SOLID_NOT against SOLID_SLIDEBOX objects (players/monsters)
void SV_LinkEdict_TouchAreaGrid_Call(prvm_edict_t *touch, prvm_edict_t *ent)
model_t * SV_GetModelByIndex(int modelindex)
#define MOVETYPE_NONE
never moves
#define SOLID_PHYSICS_CAPSULE
physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity,...
void SV_LinkEdict(prvm_edict_t *ent)
#define SOLID_NOT
no interaction with other objects
cvar_t sv_areagrid_mingridsize
int SV_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent)
#define SOLID_PHYSICS_CYLINDER
physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity,...
#define SOLID_TRIGGER
touch on edge, but not blocking
#define SOLID_PHYSICS_TRIMESH
physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity,...
#define SOLID_BSP
bsp clip, touch on edge, block
void SV_LinkEdict_TouchAreaGrid(prvm_edict_t *ent)
dp_varying highp float Depth
qbool free
true if this edict is unused
union prvm_edict_t::@29 priv
struct edict_engineprivate_s * server
FIXME: this server pointer really means world, not server (it is used by both server qc and client qc...
const char * name
name of the prog, e.g. "Server", "Client" or "Menu" (used for text output)
int num_edicts
copies of some vars that were former read from sv
mempool_t * progs_mempool
all memory allocations related to this vm_prog (code, edicts, strings)
int max_edicts
number of edicts for which space has been (should be) allocated
world_t world
collision culling data
void Sys_Error(const char *error,...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN
Causes the entire program to exit ASAP.
qbool Sys_LoadDependency(const char **dllnames, dllhandle_t *handle, const dllfunction_t *fcts)
double Sys_DirtyTime(void)
void Sys_FreeLibrary(dllhandle_t *handle)
static void World_LinkEdict_AreaGrid(world_t *world, prvm_edict_t *ent)
int World_EntitiesInBox(world_t *world, const vec3_t requestmins, const vec3_t requestmaxs, int maxlist, prvm_edict_t **list)
void World_PrintAreaStats(world_t *world, const char *worldname)
void World_InsertLinkBefore(link_t *l, link_t *before, int entitynumber)
void World_ClearLink(link_t *l)
World_ClearLink is used for new headnodes.
void World_SetSize(world_t *world, const char *filename, const vec3_t mins, const vec3_t maxs, prvm_prog_t *prog)
void World_UnlinkAll(world_t *world)
unlinks all entities (used before reallocation of edicts)
void World_UnlinkEdict(prvm_edict_t *ent)
void World_RemoveLink(link_t *l)
void World_LinkEdict(world_t *world, prvm_edict_t *ent, const vec3_t mins, const vec3_t maxs, qbool link_solid_not)
void World_Start(world_t *world)
void World_End(world_t *world)
void World_Shutdown(void)
void World_Physics_ApplyCmd(struct prvm_edict_s *ed, struct edict_odefunc_s *f)
void World_Physics_RemoveJointFromEntity(world_t *world, struct prvm_edict_s *ed)
void World_Physics_Frame(world_t *world, double frametime, double gravity)
void World_Physics_RemoveFromEntity(world_t *world, struct prvm_edict_s *ed)
#define Mem_Alloc(pool, size)