DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
world.c
Go to the documentation of this file.
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20// world.c -- world query functions
21
22#include "quakedef.h"
23#include "clvm_cmds.h"
24#include "cl_collision.h"
25#include "com_list.h"
26
27/*
28
29entities never clip against themselves, or their owner
30
31line of sight checks trace->inopen and trace->inwater, but bullets don't
32
33*/
34
35#ifdef USEODE
36static void World_Physics_Init(void);
37#endif
38void World_Init(void)
39{
41#ifdef USEODE
42 World_Physics_Init();
43#endif
44}
45
46#ifdef USEODE
47static void World_Physics_Shutdown(void);
48#endif
50{
51#ifdef USEODE
52 World_Physics_Shutdown();
53#endif
54}
55
56#ifdef USEODE
57static void World_Physics_Start(world_t *world);
58#endif
60{
61#ifdef USEODE
62 World_Physics_Start(world);
63#endif
64}
65
66#ifdef USEODE
67static void World_Physics_End(world_t *world);
68#endif
70{
71#ifdef USEODE
72 World_Physics_End(world);
73#endif
74}
75
76//============================================================================
77
80{
81 l->entitynumber = 0;
82 l->list.prev = l->list.next = &l->list;
83}
84
86{
87 List_Delete(&l->list);
88}
89
90void World_InsertLinkBefore (link_t *l, link_t *before, int entitynumber)
91{
92 l->entitynumber = entitynumber;
93 List_Add_Tail(&l->list, &before->list);
94}
95
96/*
97===============================================================================
98
99ENTITY AREA CHECKING
100
101===============================================================================
102*/
103
104void World_PrintAreaStats(world_t *world, const char *worldname)
105{
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;
110}
111
112/*
113===============
114World_SetSize
115
116===============
117*/
118void World_SetSize(world_t *world, const char *filename, const vec3_t mins, const vec3_t maxs, prvm_prog_t *prog)
119{
120 int i;
121
122 dp_strlcpy(world->filename, filename, sizeof(world->filename));
123 VectorCopy(mins, world->mins);
124 VectorCopy(maxs, world->maxs);
125 world->prog = prog;
126
127 // the areagrid_marknumber is not allowed to be 0
128 if (world->areagrid_marknumber < 1)
129 world->areagrid_marknumber = 1;
130 // choose either the world box size, or a larger box to ensure the grid isn't too fine
131 world->areagrid_size[0] = max(world->maxs[0] - world->mins[0], AREA_GRID * sv_areagrid_mingridsize.value);
132 world->areagrid_size[1] = max(world->maxs[1] - world->mins[1], AREA_GRID * sv_areagrid_mingridsize.value);
133 world->areagrid_size[2] = max(world->maxs[2] - world->mins[2], AREA_GRID * sv_areagrid_mingridsize.value);
134 // figure out the corners of such a box, centered at the center of the world box
135 world->areagrid_mins[0] = (world->mins[0] + world->maxs[0] - world->areagrid_size[0]) * 0.5f;
136 world->areagrid_mins[1] = (world->mins[1] + world->maxs[1] - world->areagrid_size[1]) * 0.5f;
137 world->areagrid_mins[2] = (world->mins[2] + world->maxs[2] - world->areagrid_size[2]) * 0.5f;
138 world->areagrid_maxs[0] = (world->mins[0] + world->maxs[0] + world->areagrid_size[0]) * 0.5f;
139 world->areagrid_maxs[1] = (world->mins[1] + world->maxs[1] + world->areagrid_size[1]) * 0.5f;
140 world->areagrid_maxs[2] = (world->mins[2] + world->maxs[2] + world->areagrid_size[2]) * 0.5f;
141 // now calculate the actual useful info from that
142 VectorNegate(world->areagrid_mins, world->areagrid_bias);
143 world->areagrid_scale[0] = AREA_GRID / world->areagrid_size[0];
144 world->areagrid_scale[1] = AREA_GRID / world->areagrid_size[1];
145 world->areagrid_scale[2] = AREA_GRID / world->areagrid_size[2];
146 World_ClearLink(&world->areagrid_outside);
147 for (i = 0;i < AREA_GRIDNODES;i++)
148 World_ClearLink(&world->areagrid[i]);
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);
151}
152
153/*
154===============
155World_UnlinkAll
156
157===============
158*/
160{
161 prvm_prog_t *prog = world->prog;
162 int i;
163 link_t *grid;
164 // unlink all entities one by one
165 grid = &world->areagrid_outside;
166 while (grid->list.next != &grid->list)
167 World_UnlinkEdict(PRVM_EDICT_NUM(List_Entry(grid->list.next, link_t, list)->entitynumber));
168 for (i = 0, grid = world->areagrid;i < AREA_GRIDNODES;i++, grid++)
169 while (grid->list.next != &grid->list)
170 World_UnlinkEdict(PRVM_EDICT_NUM(List_Entry(grid->list.next, link_t, list)->entitynumber));
171}
172
173/*
174===============
175
176===============
177*/
179{
180 int i;
181 for (i = 0;i < ENTITYGRIDAREAS;i++)
182 {
183 if (ent->priv.server->areagrid[i].list.prev)
184 World_RemoveLink (&ent->priv.server->areagrid[i]);
185 }
186}
187
188int World_EntitiesInBox(world_t *world, const vec3_t requestmins, const vec3_t requestmaxs, int maxlist, prvm_edict_t **list)
189{
190 prvm_prog_t *prog = world->prog;
191 int numlist;
192 link_t *grid;
193 link_t *l;
194 prvm_edict_t *ent;
195 vec3_t paddedmins, paddedmaxs;
196 int igrid[3], igridmins[3], igridmaxs[3];
197
198 // avoid crash in showtex code on level change
199 if (prog == NULL || prog->num_edicts < 1)
200 return 0;
201
202 // LadyHavoc: discovered this actually causes its own bugs (dm6 teleporters being too close to info_teleport_destination)
203 //VectorSet(paddedmins, requestmins[0] - 1.0f, requestmins[1] - 1.0f, requestmins[2] - 1.0f);
204 //VectorSet(paddedmaxs, requestmaxs[0] + 1.0f, requestmaxs[1] + 1.0f, requestmaxs[2] + 1.0f);
205 VectorCopy(requestmins, paddedmins);
206 VectorCopy(requestmaxs, paddedmaxs);
207
208 // FIXME: if areagrid_marknumber wraps, all entities need their
209 // ent->priv.server->areagridmarknumber reset
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]);
214 //igridmins[2] = (int) ((paddedmins[2] + world->areagrid_bias[2]) * world->areagrid_scale[2]);
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;
217 //igridmaxs[2] = (int) ((paddedmaxs[2] + world->areagrid_bias[2]) * world->areagrid_scale[2]) + 1;
218 igridmins[0] = max(0, igridmins[0]);
219 igridmins[1] = max(0, igridmins[1]);
220 //igridmins[2] = max(0, igridmins[2]);
221 igridmaxs[0] = min(AREA_GRID, igridmaxs[0]);
222 igridmaxs[1] = min(AREA_GRID, igridmaxs[1]);
223 //igridmaxs[2] = min(AREA_GRID, igridmaxs[2]);
224
225 // paranoid debugging
226 //VectorSet(igridmins, 0, 0, 0);VectorSet(igridmaxs, AREA_GRID, AREA_GRID, AREA_GRID);
227
228 numlist = 0;
229 // add entities not linked into areagrid because they are too big or
230 // outside the grid bounds
231 if (world->areagrid_outside.list.next)
232 {
233 grid = &world->areagrid_outside;
234 List_For_Each_Entry(l, &grid->list, link_t, list)
235 {
237 if (ent->priv.server->areagridmarknumber != world->areagrid_marknumber)
238 {
239 ent->priv.server->areagridmarknumber = world->areagrid_marknumber;
240 if (!ent->free && BoxesOverlap(paddedmins, paddedmaxs, ent->priv.server->areamins, ent->priv.server->areamaxs))
241 {
242 if (numlist < maxlist)
243 list[numlist] = ent;
244 numlist++;
245 }
246 world->areagrid_stats_entitychecks++;
247 }
248 }
249 }
250 // add grid linked entities
251 for (igrid[1] = igridmins[1];igrid[1] < igridmaxs[1];igrid[1]++)
252 {
253 grid = world->areagrid + igrid[1] * AREA_GRID + igridmins[0];
254 for (igrid[0] = igridmins[0];igrid[0] < igridmaxs[0];igrid[0]++, grid++)
255 {
256 if (grid->list.next)
257 {
258 List_For_Each_Entry(l, &grid->list, link_t, list)
259 {
261 if (ent->priv.server->areagridmarknumber != world->areagrid_marknumber)
262 {
263 ent->priv.server->areagridmarknumber = world->areagrid_marknumber;
264 if (!ent->free && BoxesOverlap(paddedmins, paddedmaxs, ent->priv.server->areamins, ent->priv.server->areamaxs))
265 {
266 if (numlist < maxlist)
267 list[numlist] = ent;
268 numlist++;
269 }
270 //Con_Printf("%d %f %f %f %f %f %f : %d : %f %f %f %f %f %f\n", BoxesOverlap(mins, maxs, ent->priv.server->areamins, ent->priv.server->areamaxs), ent->priv.server->areamins[0], ent->priv.server->areamins[1], ent->priv.server->areamins[2], ent->priv.server->areamaxs[0], ent->priv.server->areamaxs[1], ent->priv.server->areamaxs[2], PRVM_NUM_FOR_EDICT(ent), mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2]);
271 }
272 world->areagrid_stats_entitychecks++;
273 }
274 }
275 }
276 }
277 return numlist;
278}
279
281{
282 prvm_prog_t *prog = world->prog;
283 link_t *grid;
284 int igrid[3], igridmins[3], igridmaxs[3], gridnum, entitynumber = PRVM_NUM_FOR_EDICT(ent);
285
286 if (entitynumber <= 0 || entitynumber >= prog->max_edicts || PRVM_EDICT_NUM(entitynumber) != ent)
287 {
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);
289 return;
290 }
291
292 igridmins[0] = (int) floor((ent->priv.server->areamins[0] + world->areagrid_bias[0]) * world->areagrid_scale[0]);
293 igridmins[1] = (int) floor((ent->priv.server->areamins[1] + world->areagrid_bias[1]) * world->areagrid_scale[1]);
294 //igridmins[2] = (int) floor((ent->priv.server->areamins[2] + world->areagrid_bias[2]) * world->areagrid_scale[2]);
295 igridmaxs[0] = (int) floor((ent->priv.server->areamaxs[0] + world->areagrid_bias[0]) * world->areagrid_scale[0]) + 1;
296 igridmaxs[1] = (int) floor((ent->priv.server->areamaxs[1] + world->areagrid_bias[1]) * world->areagrid_scale[1]) + 1;
297 //igridmaxs[2] = (int) floor((ent->priv.server->areamaxs[2] + world->areagrid_bias[2]) * world->areagrid_scale[2]) + 1;
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)
299 {
300 // wow, something outside the grid, store it as such
301 World_InsertLinkBefore (&ent->priv.server->areagrid[0], &world->areagrid_outside, entitynumber);
302 return;
303 }
304
305 gridnum = 0;
306 for (igrid[1] = igridmins[1];igrid[1] < igridmaxs[1];igrid[1]++)
307 {
308 grid = world->areagrid + igrid[1] * AREA_GRID + igridmins[0];
309 for (igrid[0] = igridmins[0];igrid[0] < igridmaxs[0];igrid[0]++, grid++, gridnum++)
310 World_InsertLinkBefore (&ent->priv.server->areagrid[gridnum], grid, entitynumber);
311 }
312}
313
314/*
315===============
316World_LinkEdict
317
318===============
319*/
320void World_LinkEdict(world_t *world, prvm_edict_t *ent, const vec3_t mins, const vec3_t maxs, qbool link_solid_not)
321{
322 prvm_prog_t *prog = world->prog;
323 // unlink from old position first
324 if (ent->priv.server->areagrid[0].list.prev)
326
327 // some games don't want SOLID_NOT entities linked
328 if (!link_solid_not && PRVM_serveredictfloat(ent, solid) == SOLID_NOT)
329 return;
330
331 // don't add the world
332 if (ent == prog->edicts)
333 return;
334
335 // don't add free entities
336 if (ent->free)
337 return;
338
339 VectorCopy(mins, ent->priv.server->areamins);
340 VectorCopy(maxs, ent->priv.server->areamaxs);
342}
343
344
345
346
347//============================================================================
348// physics engine support
349//============================================================================
350
351#ifdef USEODE
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"};
380
381cvar_t physics_ode = {CF_CLIENT | CF_SERVER, "physics_ode", "0", "run ODE physics (VERY experimental and potentially buggy)"};
382
383// LadyHavoc: this large chunk of definitions comes from the ODE library
384// include files.
385
386#ifdef LINK_TO_LIBODE
387#include "ode/ode.h"
388#else
389#ifdef WINAPI
390// ODE does not use WINAPI
391#define ODE_API
392#else
393#define ODE_API
394#endif
395
396// note: dynamic builds of ODE tend to be double precision, this is not used
397// for static builds
398typedef double dReal;
399
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];
406
407struct dxWorld; /* dynamics world */
408struct dxSpace; /* collision space */
409struct dxBody; /* rigid body (dynamics object) */
410struct dxGeom; /* geometry (collision object) */
411struct dxJoint;
412struct dxJointNode;
413struct dxJointGroup;
414struct dxTriMeshData;
415
416#define dInfinity 3.402823466e+38f
417
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;
425
426typedef struct dJointFeedback
427{
428 dVector3 f1; /* force applied to body 1 */
429 dVector3 t1; /* torque applied to body 1 */
430 dVector3 f2; /* force applied to body 2 */
431 dVector3 t2; /* torque applied to body 2 */
432}
433dJointFeedback;
434
435typedef enum dJointType
436{
437 dJointTypeNone = 0,
438 dJointTypeBall,
439 dJointTypeHinge,
440 dJointTypeSlider,
441 dJointTypeContact,
442 dJointTypeUniversal,
443 dJointTypeHinge2,
444 dJointTypeFixed,
445 dJointTypeNull,
446 dJointTypeAMotor,
447 dJointTypeLMotor,
448 dJointTypePlane2D,
449 dJointTypePR,
450 dJointTypePU,
451 dJointTypePiston
452}
453dJointType;
454
455#define D_ALL_PARAM_NAMES(start) \
456 /* parameters for limits and motors */ \
457 dParamLoStop = start, \
458 dParamHiStop, \
459 dParamVel, \
460 dParamFMax, \
461 dParamFudgeFactor, \
462 dParamBounce, \
463 dParamCFM, \
464 dParamStopERP, \
465 dParamStopCFM, \
466 /* parameters for suspension */ \
467 dParamSuspensionERP, \
468 dParamSuspensionCFM, \
469 dParamERP, \
470
471#define D_ALL_PARAM_NAMES_X(start,x) \
472 /* parameters for limits and motors */ \
473 dParamLoStop ## x = start, \
474 dParamHiStop ## x, \
475 dParamVel ## x, \
476 dParamFMax ## x, \
477 dParamFudgeFactor ## x, \
478 dParamBounce ## x, \
479 dParamCFM ## x, \
480 dParamStopERP ## x, \
481 dParamStopCFM ## x, \
482 /* parameters for suspension */ \
483 dParamSuspensionERP ## x, \
484 dParamSuspensionCFM ## x, \
485 dParamERP ## x,
486
487enum {
488 D_ALL_PARAM_NAMES(0)
489 D_ALL_PARAM_NAMES_X(0x100,2)
490 D_ALL_PARAM_NAMES_X(0x200,3)
491
492 /* add a multiple of this constant to the basic parameter numbers to get
493 * the parameters for the second, third etc axes.
494 */
495 dParamGroup=0x100
496};
497
498typedef struct dMass
499{
500 dReal mass;
501 dVector3 c;
502 dMatrix3 I;
503}
504dMass;
505
506enum
507{
508 dContactMu2 = 0x001,
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,
518
519 dContactApprox0 = 0x0000,
520 dContactApprox1_1 = 0x1000,
521 dContactApprox1_2 = 0x2000,
522 dContactApprox1 = 0x3000
523};
524
525typedef struct dSurfaceParameters
526{
527 /* must always be defined */
528 int mode;
529 dReal mu;
530
531 /* only defined if the corresponding flag is set in mode */
532 dReal mu2;
533 dReal bounce;
534 dReal bounce_vel;
535 dReal soft_erp;
536 dReal soft_cfm;
537 dReal motion1,motion2,motionN;
538 dReal slip1,slip2;
539} dSurfaceParameters;
540
541typedef struct dContactGeom
542{
543 dVector3 pos;
544 dVector3 normal;
545 dReal depth;
546 dGeomID g1,g2;
547 int side1,side2;
548}
549dContactGeom;
550
551typedef struct dContact
552{
553 dSurfaceParameters surface;
554 dContactGeom geom;
555 dVector3 fdir1;
556}
557dContact;
558
559typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2);
560
561// SAP
562// Order XZY or ZXY usually works best, if your Y is up.
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))
569
570const char* (ODE_API *dGetConfiguration)(void);
571int (ODE_API *dCheckConfiguration)( const char* token );
572int (ODE_API *dInitODE)(void);
573//int (ODE_API *dInitODE2)(unsigned int uiInitFlags);
574//int (ODE_API *dAllocateODEDataForThread)(unsigned int uiAllocateFlags);
575//void (ODE_API *dCleanupODEAllDataForThread)(void);
576void (ODE_API *dCloseODE)(void);
577
578//int (ODE_API *dMassCheck)(const dMass *m);
579//void (ODE_API *dMassSetZero)(dMass *);
580//void (ODE_API *dMassSetParameters)(dMass *, dReal themass, dReal cgx, dReal cgy, dReal cgz, dReal I11, dReal I22, dReal I33, dReal I12, dReal I13, dReal I23);
581//void (ODE_API *dMassSetSphere)(dMass *, dReal density, dReal radius);
582void (ODE_API *dMassSetSphereTotal)(dMass *, dReal total_mass, dReal radius);
583//void (ODE_API *dMassSetCapsule)(dMass *, dReal density, int direction, dReal radius, dReal length);
584void (ODE_API *dMassSetCapsuleTotal)(dMass *, dReal total_mass, int direction, dReal radius, dReal length);
585//void (ODE_API *dMassSetCylinder)(dMass *, dReal density, int direction, dReal radius, dReal length);
586void (ODE_API *dMassSetCylinderTotal)(dMass *, dReal total_mass, int direction, dReal radius, dReal length);
587//void (ODE_API *dMassSetBox)(dMass *, dReal density, dReal lx, dReal ly, dReal lz);
588void (ODE_API *dMassSetBoxTotal)(dMass *, dReal total_mass, dReal lx, dReal ly, dReal lz);
589//void (ODE_API *dMassSetTrimesh)(dMass *, dReal density, dGeomID g);
590//void (ODE_API *dMassSetTrimeshTotal)(dMass *m, dReal total_mass, dGeomID g);
591//void (ODE_API *dMassAdjust)(dMass *, dReal newmass);
592//void (ODE_API *dMassTranslate)(dMass *, dReal x, dReal y, dReal z);
593//void (ODE_API *dMassRotate)(dMass *, const dMatrix3 R);
594//void (ODE_API *dMassAdd)(dMass *a, const dMass *b);
595//
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);
601//dReal (ODE_API *dWorldGetERP)(dWorldID);
602void (ODE_API *dWorldSetCFM)(dWorldID, dReal cfm);
603//dReal (ODE_API *dWorldGetCFM)(dWorldID);
604//void (ODE_API *dWorldStep)(dWorldID, dReal stepsize);
605//void (ODE_API *dWorldImpulseToForce)(dWorldID, dReal stepsize, dReal ix, dReal iy, dReal iz, dVector3 force);
606void (ODE_API *dWorldQuickStep)(dWorldID w, dReal stepsize);
607void (ODE_API *dWorldSetQuickStepNumIterations)(dWorldID, int num);
608//int (ODE_API *dWorldGetQuickStepNumIterations)(dWorldID);
609//void (ODE_API *dWorldSetQuickStepW)(dWorldID, dReal over_relaxation);
610//dReal (ODE_API *dWorldGetQuickStepW)(dWorldID);
611//void (ODE_API *dWorldSetContactMaxCorrectingVel)(dWorldID, dReal vel);
612//dReal (ODE_API *dWorldGetContactMaxCorrectingVel)(dWorldID);
613void (ODE_API *dWorldSetContactSurfaceLayer)(dWorldID, dReal depth);
614//dReal (ODE_API *dWorldGetContactSurfaceLayer)(dWorldID);
615//void (ODE_API *dWorldStepFast1)(dWorldID, dReal stepsize, int maxiterations);
616//void (ODE_API *dWorldSetAutoEnableDepthSF1)(dWorldID, int autoEnableDepth);
617//int (ODE_API *dWorldGetAutoEnableDepthSF1)(dWorldID);
618//dReal (ODE_API *dWorldGetAutoDisableLinearThreshold)(dWorldID);
619void (ODE_API *dWorldSetAutoDisableLinearThreshold)(dWorldID, dReal linear_threshold);
620//dReal (ODE_API *dWorldGetAutoDisableAngularThreshold)(dWorldID);
621void (ODE_API *dWorldSetAutoDisableAngularThreshold)(dWorldID, dReal angular_threshold);
622//dReal (ODE_API *dWorldGetAutoDisableLinearAverageThreshold)(dWorldID);
623//void (ODE_API *dWorldSetAutoDisableLinearAverageThreshold)(dWorldID, dReal linear_average_threshold);
624//dReal (ODE_API *dWorldGetAutoDisableAngularAverageThreshold)(dWorldID);
625//void (ODE_API *dWorldSetAutoDisableAngularAverageThreshold)(dWorldID, dReal angular_average_threshold);
626//int (ODE_API *dWorldGetAutoDisableAverageSamplesCount)(dWorldID);
627void (ODE_API *dWorldSetAutoDisableAverageSamplesCount)(dWorldID, unsigned int average_samples_count );
628//int (ODE_API *dWorldGetAutoDisableSteps)(dWorldID);
629void (ODE_API *dWorldSetAutoDisableSteps)(dWorldID, int steps);
630//dReal (ODE_API *dWorldGetAutoDisableTime)(dWorldID);
631void (ODE_API *dWorldSetAutoDisableTime)(dWorldID, dReal time);
632//int (ODE_API *dWorldGetAutoDisableFlag)(dWorldID);
633void (ODE_API *dWorldSetAutoDisableFlag)(dWorldID, int do_auto_disable);
634//dReal (ODE_API *dWorldGetLinearDampingThreshold)(dWorldID w);
635void (ODE_API *dWorldSetLinearDampingThreshold)(dWorldID w, dReal threshold);
636//dReal (ODE_API *dWorldGetAngularDampingThreshold)(dWorldID w);
637void (ODE_API *dWorldSetAngularDampingThreshold)(dWorldID w, dReal threshold);
638//dReal (ODE_API *dWorldGetLinearDamping)(dWorldID w);
639void (ODE_API *dWorldSetLinearDamping)(dWorldID w, dReal scale);
640//dReal (ODE_API *dWorldGetAngularDamping)(dWorldID w);
641void (ODE_API *dWorldSetAngularDamping)(dWorldID w, dReal scale);
642//void (ODE_API *dWorldSetDamping)(dWorldID w, dReal linear_scale, dReal angular_scale);
643//dReal (ODE_API *dWorldGetMaxAngularSpeed)(dWorldID w);
644//void (ODE_API *dWorldSetMaxAngularSpeed)(dWorldID w, dReal max_speed);
645//dReal (ODE_API *dBodyGetAutoDisableLinearThreshold)(dBodyID);
646//void (ODE_API *dBodySetAutoDisableLinearThreshold)(dBodyID, dReal linear_average_threshold);
647//dReal (ODE_API *dBodyGetAutoDisableAngularThreshold)(dBodyID);
648//void (ODE_API *dBodySetAutoDisableAngularThreshold)(dBodyID, dReal angular_average_threshold);
649//int (ODE_API *dBodyGetAutoDisableAverageSamplesCount)(dBodyID);
650//void (ODE_API *dBodySetAutoDisableAverageSamplesCount)(dBodyID, unsigned int average_samples_count);
651//int (ODE_API *dBodyGetAutoDisableSteps)(dBodyID);
652//void (ODE_API *dBodySetAutoDisableSteps)(dBodyID, int steps);
653//dReal (ODE_API *dBodyGetAutoDisableTime)(dBodyID);
654//void (ODE_API *dBodySetAutoDisableTime)(dBodyID, dReal time);
655//int (ODE_API *dBodyGetAutoDisableFlag)(dBodyID);
656//void (ODE_API *dBodySetAutoDisableFlag)(dBodyID, int do_auto_disable);
657//void (ODE_API *dBodySetAutoDisableDefaults)(dBodyID);
658//dWorldID (ODE_API *dBodyGetWorld)(dBodyID);
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);
665//void (ODE_API *dBodySetQuaternion)(dBodyID, const dQuaternion q);
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);
669//void (ODE_API *dBodyCopyPosition)(dBodyID body, dVector3 pos);
670const dReal * (ODE_API *dBodyGetRotation)(dBodyID);
671//void (ODE_API *dBodyCopyRotation)(dBodyID, dMatrix3 R);
672//const dReal * (ODE_API *dBodyGetQuaternion)(dBodyID);
673//void (ODE_API *dBodyCopyQuaternion)(dBodyID body, dQuaternion quat);
674const dReal * (ODE_API *dBodyGetLinearVel)(dBodyID);
675const dReal * (ODE_API *dBodyGetAngularVel)(dBodyID);
676void (ODE_API *dBodySetMass)(dBodyID, const dMass *mass);
677//void (ODE_API *dBodyGetMass)(dBodyID, dMass *mass);
678void (ODE_API *dBodyAddForce)(dBodyID, dReal fx, dReal fy, dReal fz);
679void (ODE_API *dBodyAddTorque)(dBodyID, dReal fx, dReal fy, dReal fz);
680//void (ODE_API *dBodyAddRelForce)(dBodyID, dReal fx, dReal fy, dReal fz);
681//void (ODE_API *dBodyAddRelTorque)(dBodyID, dReal fx, dReal fy, dReal fz);
682void (ODE_API *dBodyAddForceAtPos)(dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
683//void (ODE_API *dBodyAddForceAtRelPos)(dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
684//void (ODE_API *dBodyAddRelForceAtPos)(dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
685//void (ODE_API *dBodyAddRelForceAtRelPos)(dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
686//const dReal * (ODE_API *dBodyGetForce)(dBodyID);
687//const dReal * (ODE_API *dBodyGetTorque)(dBodyID);
688//void (ODE_API *dBodySetForce)(dBodyID b, dReal x, dReal y, dReal z);
689//void (ODE_API *dBodySetTorque)(dBodyID b, dReal x, dReal y, dReal z);
690//void (ODE_API *dBodyGetRelPointPos)(dBodyID, dReal px, dReal py, dReal pz, dVector3 result);
691//void (ODE_API *dBodyGetRelPointVel)(dBodyID, dReal px, dReal py, dReal pz, dVector3 result);
692//void (ODE_API *dBodyGetPointVel)(dBodyID, dReal px, dReal py, dReal pz, dVector3 result);
693//void (ODE_API *dBodyGetPosRelPoint)(dBodyID, dReal px, dReal py, dReal pz, dVector3 result);
694//void (ODE_API *dBodyVectorToWorld)(dBodyID, dReal px, dReal py, dReal pz, dVector3 result);
695//void (ODE_API *dBodyVectorFromWorld)(dBodyID, dReal px, dReal py, dReal pz, dVector3 result);
696//void (ODE_API *dBodySetFiniteRotationMode)(dBodyID, int mode);
697//void (ODE_API *dBodySetFiniteRotationAxis)(dBodyID, dReal x, dReal y, dReal z);
698//int (ODE_API *dBodyGetFiniteRotationMode)(dBodyID);
699//void (ODE_API *dBodyGetFiniteRotationAxis)(dBodyID, dVector3 result);
700int (ODE_API *dBodyGetNumJoints)(dBodyID b);
701dJointID (ODE_API *dBodyGetJoint)(dBodyID, int index);
702//void (ODE_API *dBodySetDynamic)(dBodyID);
703//void (ODE_API *dBodySetKinematic)(dBodyID);
704//int (ODE_API *dBodyIsKinematic)(dBodyID);
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);
710//void (*dBodySetMovedCallback)(dBodyID b, void(ODE_API *callback)(dBodyID));
711//dGeomID (ODE_API *dBodyGetFirstGeom)(dBodyID b);
712//dGeomID (ODE_API *dBodyGetNextGeom)(dGeomID g);
713//void (ODE_API *dBodySetDampingDefaults)(dBodyID b);
714//dReal (ODE_API *dBodyGetLinearDamping)(dBodyID b);
715//void (ODE_API *dBodySetLinearDamping)(dBodyID b, dReal scale);
716//dReal (ODE_API *dBodyGetAngularDamping)(dBodyID b);
717//void (ODE_API *dBodySetAngularDamping)(dBodyID b, dReal scale);
718//void (ODE_API *dBodySetDamping)(dBodyID b, dReal linear_scale, dReal angular_scale);
719//dReal (ODE_API *dBodyGetLinearDampingThreshold)(dBodyID b);
720//void (ODE_API *dBodySetLinearDampingThreshold)(dBodyID b, dReal threshold);
721//dReal (ODE_API *dBodyGetAngularDampingThreshold)(dBodyID b);
722//void (ODE_API *dBodySetAngularDampingThreshold)(dBodyID b, dReal threshold);
723//dReal (ODE_API *dBodyGetMaxAngularSpeed)(dBodyID b);
724//void (ODE_API *dBodySetMaxAngularSpeed)(dBodyID b, dReal max_speed);
725//int (ODE_API *dBodyGetGyroscopicMode)(dBodyID b);
726//void (ODE_API *dBodySetGyroscopicMode)(dBodyID b, int enabled);
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);
733//dJointID (ODE_API *dJointCreatePR)(dWorldID, dJointGroupID);
734//dJointID (ODE_API *dJointCreatePU)(dWorldID, dJointGroupID);
735//dJointID (ODE_API *dJointCreatePiston)(dWorldID, dJointGroupID);
736dJointID (ODE_API *dJointCreateFixed)(dWorldID, dJointGroupID);
737//dJointID (ODE_API *dJointCreateNull)(dWorldID, dJointGroupID);
738//dJointID (ODE_API *dJointCreateAMotor)(dWorldID, dJointGroupID);
739//dJointID (ODE_API *dJointCreateLMotor)(dWorldID, dJointGroupID);
740//dJointID (ODE_API *dJointCreatePlane2D)(dWorldID, dJointGroupID);
741void (ODE_API *dJointDestroy)(dJointID);
742dJointGroupID (ODE_API *dJointGroupCreate)(int max_size);
743void (ODE_API *dJointGroupDestroy)(dJointGroupID);
744void (ODE_API *dJointGroupEmpty)(dJointGroupID);
745//int (ODE_API *dJointGetNumBodies)(dJointID);
746void (ODE_API *dJointAttach)(dJointID, dBodyID body1, dBodyID body2);
747//void (ODE_API *dJointEnable)(dJointID);
748//void (ODE_API *dJointDisable)(dJointID);
749//int (ODE_API *dJointIsEnabled)(dJointID);
750void (ODE_API *dJointSetData)(dJointID, void *data);
751void * (ODE_API *dJointGetData)(dJointID);
752//dJointType (ODE_API *dJointGetType)(dJointID);
753dBodyID (ODE_API *dJointGetBody)(dJointID, int index);
754//void (ODE_API *dJointSetFeedback)(dJointID, dJointFeedback *);
755//dJointFeedback *(ODE_API *dJointGetFeedback)(dJointID);
756void (ODE_API *dJointSetBallAnchor)(dJointID, dReal x, dReal y, dReal z);
757//void (ODE_API *dJointSetBallAnchor2)(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);
760//void (ODE_API *dJointSetHingeAnchorDelta)(dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
761void (ODE_API *dJointSetHingeAxis)(dJointID, dReal x, dReal y, dReal z);
762//void (ODE_API *dJointSetHingeAxisOffset)(dJointID j, dReal x, dReal y, dReal z, dReal angle);
763void (ODE_API *dJointSetHingeParam)(dJointID, int parameter, dReal value);
764//void (ODE_API *dJointAddHingeTorque)(dJointID joint, dReal torque);
765void (ODE_API *dJointSetSliderAxis)(dJointID, dReal x, dReal y, dReal z);
766//void (ODE_API *dJointSetSliderAxisDelta)(dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
767void (ODE_API *dJointSetSliderParam)(dJointID, int parameter, dReal value);
768//void (ODE_API *dJointAddSliderForce)(dJointID joint, dReal force);
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);
773//void (ODE_API *dJointAddHinge2Torques)(dJointID joint, dReal torque1, dReal torque2);
774void (ODE_API *dJointSetUniversalAnchor)(dJointID, dReal x, dReal y, dReal z);
775void (ODE_API *dJointSetUniversalAxis1)(dJointID, dReal x, dReal y, dReal z);
776//void (ODE_API *dJointSetUniversalAxis1Offset)(dJointID, dReal x, dReal y, dReal z, dReal offset1, dReal offset2);
777void (ODE_API *dJointSetUniversalAxis2)(dJointID, dReal x, dReal y, dReal z);
778//void (ODE_API *dJointSetUniversalAxis2Offset)(dJointID, dReal x, dReal y, dReal z, dReal offset1, dReal offset2);
779void (ODE_API *dJointSetUniversalParam)(dJointID, int parameter, dReal value);
780//void (ODE_API *dJointAddUniversalTorques)(dJointID joint, dReal torque1, dReal torque2);
781//void (ODE_API *dJointSetPRAnchor)(dJointID, dReal x, dReal y, dReal z);
782//void (ODE_API *dJointSetPRAxis1)(dJointID, dReal x, dReal y, dReal z);
783//void (ODE_API *dJointSetPRAxis2)(dJointID, dReal x, dReal y, dReal z);
784//void (ODE_API *dJointSetPRParam)(dJointID, int parameter, dReal value);
785//void (ODE_API *dJointAddPRTorque)(dJointID j, dReal torque);
786//void (ODE_API *dJointSetPUAnchor)(dJointID, dReal x, dReal y, dReal z);
787//void (ODE_API *dJointSetPUAnchorOffset)(dJointID, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz);
788//void (ODE_API *dJointSetPUAxis1)(dJointID, dReal x, dReal y, dReal z);
789//void (ODE_API *dJointSetPUAxis2)(dJointID, dReal x, dReal y, dReal z);
790//void (ODE_API *dJointSetPUAxis3)(dJointID, dReal x, dReal y, dReal z);
791//void (ODE_API *dJointSetPUAxisP)(dJointID id, dReal x, dReal y, dReal z);
792//void (ODE_API *dJointSetPUParam)(dJointID, int parameter, dReal value);
793//void (ODE_API *dJointAddPUTorque)(dJointID j, dReal torque);
794//void (ODE_API *dJointSetPistonAnchor)(dJointID, dReal x, dReal y, dReal z);
795//void (ODE_API *dJointSetPistonAnchorOffset)(dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz);
796//void (ODE_API *dJointSetPistonParam)(dJointID, int parameter, dReal value);
797//void (ODE_API *dJointAddPistonForce)(dJointID joint, dReal force);
798//void (ODE_API *dJointSetFixed)(dJointID);
799//void (ODE_API *dJointSetFixedParam)(dJointID, int parameter, dReal value);
800//void (ODE_API *dJointSetAMotorNumAxes)(dJointID, int num);
801//void (ODE_API *dJointSetAMotorAxis)(dJointID, int anum, int rel, dReal x, dReal y, dReal z);
802//void (ODE_API *dJointSetAMotorAngle)(dJointID, int anum, dReal angle);
803//void (ODE_API *dJointSetAMotorParam)(dJointID, int parameter, dReal value);
804//void (ODE_API *dJointSetAMotorMode)(dJointID, int mode);
805//void (ODE_API *dJointAddAMotorTorques)(dJointID, dReal torque1, dReal torque2, dReal torque3);
806//void (ODE_API *dJointSetLMotorNumAxes)(dJointID, int num);
807//void (ODE_API *dJointSetLMotorAxis)(dJointID, int anum, int rel, dReal x, dReal y, dReal z);
808//void (ODE_API *dJointSetLMotorParam)(dJointID, int parameter, dReal value);
809//void (ODE_API *dJointSetPlane2DXParam)(dJointID, int parameter, dReal value);
810//void (ODE_API *dJointSetPlane2DYParam)(dJointID, int parameter, dReal value);
811//void (ODE_API *dJointSetPlane2DAngleParam)(dJointID, int parameter, dReal value);
812//void (ODE_API *dJointGetBallAnchor)(dJointID, dVector3 result);
813//void (ODE_API *dJointGetBallAnchor2)(dJointID, dVector3 result);
814//dReal (ODE_API *dJointGetBallParam)(dJointID, int parameter);
815//void (ODE_API *dJointGetHingeAnchor)(dJointID, dVector3 result);
816//void (ODE_API *dJointGetHingeAnchor2)(dJointID, dVector3 result);
817//void (ODE_API *dJointGetHingeAxis)(dJointID, dVector3 result);
818//dReal (ODE_API *dJointGetHingeParam)(dJointID, int parameter);
819//dReal (ODE_API *dJointGetHingeAngle)(dJointID);
820//dReal (ODE_API *dJointGetHingeAngleRate)(dJointID);
821//dReal (ODE_API *dJointGetSliderPosition)(dJointID);
822//dReal (ODE_API *dJointGetSliderPositionRate)(dJointID);
823//void (ODE_API *dJointGetSliderAxis)(dJointID, dVector3 result);
824//dReal (ODE_API *dJointGetSliderParam)(dJointID, int parameter);
825//void (ODE_API *dJointGetHinge2Anchor)(dJointID, dVector3 result);
826//void (ODE_API *dJointGetHinge2Anchor2)(dJointID, dVector3 result);
827//void (ODE_API *dJointGetHinge2Axis1)(dJointID, dVector3 result);
828//void (ODE_API *dJointGetHinge2Axis2)(dJointID, dVector3 result);
829//dReal (ODE_API *dJointGetHinge2Param)(dJointID, int parameter);
830//dReal (ODE_API *dJointGetHinge2Angle1)(dJointID);
831//dReal (ODE_API *dJointGetHinge2Angle1Rate)(dJointID);
832//dReal (ODE_API *dJointGetHinge2Angle2Rate)(dJointID);
833//void (ODE_API *dJointGetUniversalAnchor)(dJointID, dVector3 result);
834//void (ODE_API *dJointGetUniversalAnchor2)(dJointID, dVector3 result);
835//void (ODE_API *dJointGetUniversalAxis1)(dJointID, dVector3 result);
836//void (ODE_API *dJointGetUniversalAxis2)(dJointID, dVector3 result);
837//dReal (ODE_API *dJointGetUniversalParam)(dJointID, int parameter);
838//void (ODE_API *dJointGetUniversalAngles)(dJointID, dReal *angle1, dReal *angle2);
839//dReal (ODE_API *dJointGetUniversalAngle1)(dJointID);
840//dReal (ODE_API *dJointGetUniversalAngle2)(dJointID);
841//dReal (ODE_API *dJointGetUniversalAngle1Rate)(dJointID);
842//dReal (ODE_API *dJointGetUniversalAngle2Rate)(dJointID);
843//void (ODE_API *dJointGetPRAnchor)(dJointID, dVector3 result);
844//dReal (ODE_API *dJointGetPRPosition)(dJointID);
845//dReal (ODE_API *dJointGetPRPositionRate)(dJointID);
846//dReal (ODE_API *dJointGetPRAngle)(dJointID);
847//dReal (ODE_API *dJointGetPRAngleRate)(dJointID);
848//void (ODE_API *dJointGetPRAxis1)(dJointID, dVector3 result);
849//void (ODE_API *dJointGetPRAxis2)(dJointID, dVector3 result);
850//dReal (ODE_API *dJointGetPRParam)(dJointID, int parameter);
851//void (ODE_API *dJointGetPUAnchor)(dJointID, dVector3 result);
852//dReal (ODE_API *dJointGetPUPosition)(dJointID);
853//dReal (ODE_API *dJointGetPUPositionRate)(dJointID);
854//void (ODE_API *dJointGetPUAxis1)(dJointID, dVector3 result);
855//void (ODE_API *dJointGetPUAxis2)(dJointID, dVector3 result);
856//void (ODE_API *dJointGetPUAxis3)(dJointID, dVector3 result);
857//void (ODE_API *dJointGetPUAxisP)(dJointID id, dVector3 result);
858//void (ODE_API *dJointGetPUAngles)(dJointID, dReal *angle1, dReal *angle2);
859//dReal (ODE_API *dJointGetPUAngle1)(dJointID);
860//dReal (ODE_API *dJointGetPUAngle1Rate)(dJointID);
861//dReal (ODE_API *dJointGetPUAngle2)(dJointID);
862//dReal (ODE_API *dJointGetPUAngle2Rate)(dJointID);
863//dReal (ODE_API *dJointGetPUParam)(dJointID, int parameter);
864//dReal (ODE_API *dJointGetPistonPosition)(dJointID);
865//dReal (ODE_API *dJointGetPistonPositionRate)(dJointID);
866//dReal (ODE_API *dJointGetPistonAngle)(dJointID);
867//dReal (ODE_API *dJointGetPistonAngleRate)(dJointID);
868//void (ODE_API *dJointGetPistonAnchor)(dJointID, dVector3 result);
869//void (ODE_API *dJointGetPistonAnchor2)(dJointID, dVector3 result);
870//void (ODE_API *dJointGetPistonAxis)(dJointID, dVector3 result);
871//dReal (ODE_API *dJointGetPistonParam)(dJointID, int parameter);
872//int (ODE_API *dJointGetAMotorNumAxes)(dJointID);
873//void (ODE_API *dJointGetAMotorAxis)(dJointID, int anum, dVector3 result);
874//int (ODE_API *dJointGetAMotorAxisRel)(dJointID, int anum);
875//dReal (ODE_API *dJointGetAMotorAngle)(dJointID, int anum);
876//dReal (ODE_API *dJointGetAMotorAngleRate)(dJointID, int anum);
877//dReal (ODE_API *dJointGetAMotorParam)(dJointID, int parameter);
878//int (ODE_API *dJointGetAMotorMode)(dJointID);
879//int (ODE_API *dJointGetLMotorNumAxes)(dJointID);
880//void (ODE_API *dJointGetLMotorAxis)(dJointID, int anum, dVector3 result);
881//dReal (ODE_API *dJointGetLMotorParam)(dJointID, int parameter);
882//dReal (ODE_API *dJointGetFixedParam)(dJointID, int parameter);
883//dJointID (ODE_API *dConnectingJoint)(dBodyID, dBodyID);
884//int (ODE_API *dConnectingJointList)(dBodyID, dBodyID, dJointID*);
885int (ODE_API *dAreConnected)(dBodyID, dBodyID);
886int (ODE_API *dAreConnectedExcluding)(dBodyID body1, dBodyID body2, int joint_type);
887//
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);
891//dSpaceID (ODE_API *dSweepAndPruneSpaceCreate)( dSpaceID space, int axisorder );
892void (ODE_API *dSpaceDestroy)(dSpaceID);
893//void (ODE_API *dHashSpaceSetLevels)(dSpaceID space, int minlevel, int maxlevel);
894//void (ODE_API *dHashSpaceGetLevels)(dSpaceID space, int *minlevel, int *maxlevel);
895//void (ODE_API *dSpaceSetCleanup)(dSpaceID space, int mode);
896//int (ODE_API *dSpaceGetCleanup)(dSpaceID space);
897//void (ODE_API *dSpaceSetSublevel)(dSpaceID space, int sublevel);
898//int (ODE_API *dSpaceGetSublevel)(dSpaceID space);
899//void (ODE_API *dSpaceSetManualCleanup)(dSpaceID space, int mode);
900//int (ODE_API *dSpaceGetManualCleanup)(dSpaceID space);
901//void (ODE_API *dSpaceAdd)(dSpaceID, dGeomID);
902//void (ODE_API *dSpaceRemove)(dSpaceID, dGeomID);
903//int (ODE_API *dSpaceQuery)(dSpaceID, dGeomID);
904//void (ODE_API *dSpaceClean)(dSpaceID);
905//int (ODE_API *dSpaceGetNumGeoms)(dSpaceID);
906//dGeomID (ODE_API *dSpaceGetGeom)(dSpaceID, int i);
907//int (ODE_API *dSpaceGetClass)(dSpaceID space);
908//
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);
916//void (ODE_API *dGeomSetQuaternion)(dGeomID geom, const dQuaternion Q);
917//const dReal * (ODE_API *dGeomGetPosition)(dGeomID geom);
918//void (ODE_API *dGeomCopyPosition)(dGeomID geom, dVector3 pos);
919//const dReal * (ODE_API *dGeomGetRotation)(dGeomID geom);
920//void (ODE_API *dGeomCopyRotation)(dGeomID geom, dMatrix3 R);
921//void (ODE_API *dGeomGetQuaternion)(dGeomID geom, dQuaternion result);
922//void (ODE_API *dGeomGetAABB)(dGeomID geom, dReal aabb[6]);
923int (ODE_API *dGeomIsSpace)(dGeomID geom);
924//dSpaceID (ODE_API *dGeomGetSpace)(dGeomID);
925//int (ODE_API *dGeomGetClass)(dGeomID geom);
926//void (ODE_API *dGeomSetCategoryBits)(dGeomID geom, unsigned long bits);
927//void (ODE_API *dGeomSetCollideBits)(dGeomID geom, unsigned long bits);
928//unsigned long (ODE_API *dGeomGetCategoryBits)(dGeomID);
929//unsigned long (ODE_API *dGeomGetCollideBits)(dGeomID);
930//void (ODE_API *dGeomEnable)(dGeomID geom);
931//void (ODE_API *dGeomDisable)(dGeomID geom);
932//int (ODE_API *dGeomIsEnabled)(dGeomID geom);
933//void (ODE_API *dGeomSetOffsetPosition)(dGeomID geom, dReal x, dReal y, dReal z);
934//void (ODE_API *dGeomSetOffsetRotation)(dGeomID geom, const dMatrix3 R);
935//void (ODE_API *dGeomSetOffsetQuaternion)(dGeomID geom, const dQuaternion Q);
936//void (ODE_API *dGeomSetOffsetWorldPosition)(dGeomID geom, dReal x, dReal y, dReal z);
937//void (ODE_API *dGeomSetOffsetWorldRotation)(dGeomID geom, const dMatrix3 R);
938//void (ODE_API *dGeomSetOffsetWorldQuaternion)(dGeomID geom, const dQuaternion);
939//void (ODE_API *dGeomClearOffset)(dGeomID geom);
940//int (ODE_API *dGeomIsOffset)(dGeomID geom);
941//const dReal * (ODE_API *dGeomGetOffsetPosition)(dGeomID geom);
942//void (ODE_API *dGeomCopyOffsetPosition)(dGeomID geom, dVector3 pos);
943//const dReal * (ODE_API *dGeomGetOffsetRotation)(dGeomID geom);
944//void (ODE_API *dGeomCopyOffsetRotation)(dGeomID geom, dMatrix3 R);
945//void (ODE_API *dGeomGetOffsetQuaternion)(dGeomID geom, dQuaternion result);
946int (ODE_API *dCollide)(dGeomID o1, dGeomID o2, int flags, dContactGeom *contact, int skip);
947//
948void (ODE_API *dSpaceCollide)(dSpaceID space, void *data, dNearCallback *callback);
949void (ODE_API *dSpaceCollide2)(dGeomID space1, dGeomID space2, void *data, dNearCallback *callback);
950//
951dGeomID (ODE_API *dCreateSphere)(dSpaceID space, dReal radius);
952//void (ODE_API *dGeomSphereSetRadius)(dGeomID sphere, dReal radius);
953//dReal (ODE_API *dGeomSphereGetRadius)(dGeomID sphere);
954//dReal (ODE_API *dGeomSpherePointDepth)(dGeomID sphere, dReal x, dReal y, dReal z);
955//
956dGeomID (ODE_API *dCreateConvex)(dSpaceID space, dReal *_planes, unsigned int _planecount, dReal *_points, unsigned int _pointcount,unsigned int *_polygons);
957//void (ODE_API *dGeomSetConvex)(dGeomID g, dReal *_planes, unsigned int _count, dReal *_points, unsigned int _pointcount,unsigned int *_polygons);
958//
959dGeomID (ODE_API *dCreateBox)(dSpaceID space, dReal lx, dReal ly, dReal lz);
960//void (ODE_API *dGeomBoxSetLengths)(dGeomID box, dReal lx, dReal ly, dReal lz);
961//void (ODE_API *dGeomBoxGetLengths)(dGeomID box, dVector3 result);
962//dReal (ODE_API *dGeomBoxPointDepth)(dGeomID box, dReal x, dReal y, dReal z);
963//dReal (ODE_API *dGeomBoxPointDepth)(dGeomID box, dReal x, dReal y, dReal z);
964//
965//dGeomID (ODE_API *dCreatePlane)(dSpaceID space, dReal a, dReal b, dReal c, dReal d);
966//void (ODE_API *dGeomPlaneSetParams)(dGeomID plane, dReal a, dReal b, dReal c, dReal d);
967//void (ODE_API *dGeomPlaneGetParams)(dGeomID plane, dVector4 result);
968//dReal (ODE_API *dGeomPlanePointDepth)(dGeomID plane, dReal x, dReal y, dReal z);
969//
970dGeomID (ODE_API *dCreateCapsule)(dSpaceID space, dReal radius, dReal length);
971//void (ODE_API *dGeomCapsuleSetParams)(dGeomID ccylinder, dReal radius, dReal length);
972//void (ODE_API *dGeomCapsuleGetParams)(dGeomID ccylinder, dReal *radius, dReal *length);
973//dReal (ODE_API *dGeomCapsulePointDepth)(dGeomID ccylinder, dReal x, dReal y, dReal z);
974//
975dGeomID (ODE_API *dCreateCylinder)(dSpaceID space, dReal radius, dReal length);
976//void (ODE_API *dGeomCylinderSetParams)(dGeomID cylinder, dReal radius, dReal length);
977//void (ODE_API *dGeomCylinderGetParams)(dGeomID cylinder, dReal *radius, dReal *length);
978//
979//dGeomID (ODE_API *dCreateRay)(dSpaceID space, dReal length);
980//void (ODE_API *dGeomRaySetLength)(dGeomID ray, dReal length);
981//dReal (ODE_API *dGeomRayGetLength)(dGeomID ray);
982//void (ODE_API *dGeomRaySet)(dGeomID ray, dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz);
983//void (ODE_API *dGeomRayGet)(dGeomID ray, dVector3 start, dVector3 dir);
984//
985dGeomID (ODE_API *dCreateGeomTransform)(dSpaceID space);
986void (ODE_API *dGeomTransformSetGeom)(dGeomID g, dGeomID obj);
987//dGeomID (ODE_API *dGeomTransformGetGeom)(dGeomID g);
988void (ODE_API *dGeomTransformSetCleanup)(dGeomID g, int mode);
989//int (ODE_API *dGeomTransformGetCleanup)(dGeomID g);
990//void (ODE_API *dGeomTransformSetInfo)(dGeomID g, int mode);
991//int (ODE_API *dGeomTransformGetInfo)(dGeomID g);
992
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);
998
999dTriMeshDataID (ODE_API *dGeomTriMeshDataCreate)(void);
1000void (ODE_API *dGeomTriMeshDataDestroy)(dTriMeshDataID g);
1001//void (ODE_API *dGeomTriMeshDataSet)(dTriMeshDataID g, int data_id, void* in_data);
1002//void* (ODE_API *dGeomTriMeshDataGet)(dTriMeshDataID g, int data_id);
1003//void (*dGeomTriMeshSetLastTransform)( (ODE_API *dGeomID g, dMatrix4 last_trans );
1004//dReal* (*dGeomTriMeshGetLastTransform)( (ODE_API *dGeomID g );
1005void (ODE_API *dGeomTriMeshDataBuildSingle)(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride);
1006//void (ODE_API *dGeomTriMeshDataBuildSingle1)(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride, const void* Normals);
1007//void (ODE_API *dGeomTriMeshDataBuildDouble)(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride);
1008//void (ODE_API *dGeomTriMeshDataBuildDouble1)(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount, const void* Indices, int IndexCount, int TriStride, const void* Normals);
1009//void (ODE_API *dGeomTriMeshDataBuildSimple)(dTriMeshDataID g, const dReal* Vertices, int VertexCount, const dTriIndex* Indices, int IndexCount);
1010//void (ODE_API *dGeomTriMeshDataBuildSimple1)(dTriMeshDataID g, const dReal* Vertices, int VertexCount, const dTriIndex* Indices, int IndexCount, const int* Normals);
1011//void (ODE_API *dGeomTriMeshDataPreprocess)(dTriMeshDataID g);
1012//void (ODE_API *dGeomTriMeshDataGetBuffer)(dTriMeshDataID g, unsigned char** buf, int* bufLen);
1013//void (ODE_API *dGeomTriMeshDataSetBuffer)(dTriMeshDataID g, unsigned char* buf);
1014//void (ODE_API *dGeomTriMeshSetCallback)(dGeomID g, dTriCallback* Callback);
1015//dTriCallback* (ODE_API *dGeomTriMeshGetCallback)(dGeomID g);
1016//void (ODE_API *dGeomTriMeshSetArrayCallback)(dGeomID g, dTriArrayCallback* ArrayCallback);
1017//dTriArrayCallback* (ODE_API *dGeomTriMeshGetArrayCallback)(dGeomID g);
1018//void (ODE_API *dGeomTriMeshSetRayCallback)(dGeomID g, dTriRayCallback* Callback);
1019//dTriRayCallback* (ODE_API *dGeomTriMeshGetRayCallback)(dGeomID g);
1020//void (ODE_API *dGeomTriMeshSetTriMergeCallback)(dGeomID g, dTriTriMergeCallback* Callback);
1021//dTriTriMergeCallback* (ODE_API *dGeomTriMeshGetTriMergeCallback)(dGeomID g);
1022dGeomID (ODE_API *dCreateTriMesh)(dSpaceID space, dTriMeshDataID Data, dTriCallback* Callback, dTriArrayCallback* ArrayCallback, dTriRayCallback* RayCallback);
1023//void (ODE_API *dGeomTriMeshSetData)(dGeomID g, dTriMeshDataID Data);
1024//dTriMeshDataID (ODE_API *dGeomTriMeshGetData)(dGeomID g);
1025//void (ODE_API *dGeomTriMeshEnableTC)(dGeomID g, int geomClass, int enable);
1026//int (ODE_API *dGeomTriMeshIsTCEnabled)(dGeomID g, int geomClass);
1027//void (ODE_API *dGeomTriMeshClearTCCache)(dGeomID g);
1028//dTriMeshDataID (ODE_API *dGeomTriMeshGetTriMeshDataID)(dGeomID g);
1029//void (ODE_API *dGeomTriMeshGetTriangle)(dGeomID g, int Index, dVector3* v0, dVector3* v1, dVector3* v2);
1030//void (ODE_API *dGeomTriMeshGetPoint)(dGeomID g, int Index, dReal u, dReal v, dVector3 Out);
1031//int (ODE_API *dGeomTriMeshGetTriangleCount )(dGeomID g);
1032//void (ODE_API *dGeomTriMeshDataUpdate)(dTriMeshDataID g);
1033
1034static dllfunction_t odefuncs[] =
1035{
1036 {"dGetConfiguration", (void **) &dGetConfiguration},
1037 {"dCheckConfiguration", (void **) &dCheckConfiguration},
1038 {"dInitODE", (void **) &dInitODE},
1039// {"dInitODE2", (void **) &dInitODE2},
1040// {"dAllocateODEDataForThread", (void **) &dAllocateODEDataForThread},
1041// {"dCleanupODEAllDataForThread", (void **) &dCleanupODEAllDataForThread},
1042 {"dCloseODE", (void **) &dCloseODE},
1043// {"dMassCheck", (void **) &dMassCheck},
1044// {"dMassSetZero", (void **) &dMassSetZero},
1045// {"dMassSetParameters", (void **) &dMassSetParameters},
1046// {"dMassSetSphere", (void **) &dMassSetSphere},
1047 {"dMassSetSphereTotal", (void **) &dMassSetSphereTotal},
1048// {"dMassSetCapsule", (void **) &dMassSetCapsule},
1049 {"dMassSetCapsuleTotal", (void **) &dMassSetCapsuleTotal},
1050// {"dMassSetCylinder", (void **) &dMassSetCylinder},
1051 {"dMassSetCylinderTotal", (void **) &dMassSetCylinderTotal},
1052// {"dMassSetBox", (void **) &dMassSetBox},
1053 {"dMassSetBoxTotal", (void **) &dMassSetBoxTotal},
1054// {"dMassSetTrimesh", (void **) &dMassSetTrimesh},
1055// {"dMassSetTrimeshTotal", (void **) &dMassSetTrimeshTotal},
1056// {"dMassAdjust", (void **) &dMassAdjust},
1057// {"dMassTranslate", (void **) &dMassTranslate},
1058// {"dMassRotate", (void **) &dMassRotate},
1059// {"dMassAdd", (void **) &dMassAdd},
1060
1061 {"dWorldCreate", (void **) &dWorldCreate},
1062 {"dWorldDestroy", (void **) &dWorldDestroy},
1063 {"dWorldSetGravity", (void **) &dWorldSetGravity},
1064 {"dWorldGetGravity", (void **) &dWorldGetGravity},
1065 {"dWorldSetERP", (void **) &dWorldSetERP},
1066// {"dWorldGetERP", (void **) &dWorldGetERP},
1067 {"dWorldSetCFM", (void **) &dWorldSetCFM},
1068// {"dWorldGetCFM", (void **) &dWorldGetCFM},
1069// {"dWorldStep", (void **) &dWorldStep},
1070// {"dWorldImpulseToForce", (void **) &dWorldImpulseToForce},
1071 {"dWorldQuickStep", (void **) &dWorldQuickStep},
1072 {"dWorldSetQuickStepNumIterations", (void **) &dWorldSetQuickStepNumIterations},
1073// {"dWorldGetQuickStepNumIterations", (void **) &dWorldGetQuickStepNumIterations},
1074// {"dWorldSetQuickStepW", (void **) &dWorldSetQuickStepW},
1075// {"dWorldGetQuickStepW", (void **) &dWorldGetQuickStepW},
1076// {"dWorldSetContactMaxCorrectingVel", (void **) &dWorldSetContactMaxCorrectingVel},
1077// {"dWorldGetContactMaxCorrectingVel", (void **) &dWorldGetContactMaxCorrectingVel},
1078 {"dWorldSetContactSurfaceLayer", (void **) &dWorldSetContactSurfaceLayer},
1079// {"dWorldGetContactSurfaceLayer", (void **) &dWorldGetContactSurfaceLayer},
1080// {"dWorldStepFast1", (void **) &dWorldStepFast1},
1081// {"dWorldSetAutoEnableDepthSF1", (void **) &dWorldSetAutoEnableDepthSF1},
1082// {"dWorldGetAutoEnableDepthSF1", (void **) &dWorldGetAutoEnableDepthSF1},
1083// {"dWorldGetAutoDisableLinearThreshold", (void **) &dWorldGetAutoDisableLinearThreshold},
1084 {"dWorldSetAutoDisableLinearThreshold", (void **) &dWorldSetAutoDisableLinearThreshold},
1085// {"dWorldGetAutoDisableAngularThreshold", (void **) &dWorldGetAutoDisableAngularThreshold},
1086 {"dWorldSetAutoDisableAngularThreshold", (void **) &dWorldSetAutoDisableAngularThreshold},
1087// {"dWorldGetAutoDisableLinearAverageThreshold", (void **) &dWorldGetAutoDisableLinearAverageThreshold},
1088// {"dWorldSetAutoDisableLinearAverageThreshold", (void **) &dWorldSetAutoDisableLinearAverageThreshold},
1089// {"dWorldGetAutoDisableAngularAverageThreshold", (void **) &dWorldGetAutoDisableAngularAverageThreshold},
1090// {"dWorldSetAutoDisableAngularAverageThreshold", (void **) &dWorldSetAutoDisableAngularAverageThreshold},
1091// {"dWorldGetAutoDisableAverageSamplesCount", (void **) &dWorldGetAutoDisableAverageSamplesCount},
1092 {"dWorldSetAutoDisableAverageSamplesCount", (void **) &dWorldSetAutoDisableAverageSamplesCount},
1093// {"dWorldGetAutoDisableSteps", (void **) &dWorldGetAutoDisableSteps},
1094 {"dWorldSetAutoDisableSteps", (void **) &dWorldSetAutoDisableSteps},
1095// {"dWorldGetAutoDisableTime", (void **) &dWorldGetAutoDisableTime},
1096 {"dWorldSetAutoDisableTime", (void **) &dWorldSetAutoDisableTime},
1097// {"dWorldGetAutoDisableFlag", (void **) &dWorldGetAutoDisableFlag},
1098 {"dWorldSetAutoDisableFlag", (void **) &dWorldSetAutoDisableFlag},
1099// {"dWorldGetLinearDampingThreshold", (void **) &dWorldGetLinearDampingThreshold},
1100 {"dWorldSetLinearDampingThreshold", (void **) &dWorldSetLinearDampingThreshold},
1101// {"dWorldGetAngularDampingThreshold", (void **) &dWorldGetAngularDampingThreshold},
1102 {"dWorldSetAngularDampingThreshold", (void **) &dWorldSetAngularDampingThreshold},
1103// {"dWorldGetLinearDamping", (void **) &dWorldGetLinearDamping},
1104 {"dWorldSetLinearDamping", (void **) &dWorldSetLinearDamping},
1105// {"dWorldGetAngularDamping", (void **) &dWorldGetAngularDamping},
1106 {"dWorldSetAngularDamping", (void **) &dWorldSetAngularDamping},
1107// {"dWorldSetDamping", (void **) &dWorldSetDamping},
1108// {"dWorldGetMaxAngularSpeed", (void **) &dWorldGetMaxAngularSpeed},
1109// {"dWorldSetMaxAngularSpeed", (void **) &dWorldSetMaxAngularSpeed},
1110// {"dBodyGetAutoDisableLinearThreshold", (void **) &dBodyGetAutoDisableLinearThreshold},
1111// {"dBodySetAutoDisableLinearThreshold", (void **) &dBodySetAutoDisableLinearThreshold},
1112// {"dBodyGetAutoDisableAngularThreshold", (void **) &dBodyGetAutoDisableAngularThreshold},
1113// {"dBodySetAutoDisableAngularThreshold", (void **) &dBodySetAutoDisableAngularThreshold},
1114// {"dBodyGetAutoDisableAverageSamplesCount", (void **) &dBodyGetAutoDisableAverageSamplesCount},
1115// {"dBodySetAutoDisableAverageSamplesCount", (void **) &dBodySetAutoDisableAverageSamplesCount},
1116// {"dBodyGetAutoDisableSteps", (void **) &dBodyGetAutoDisableSteps},
1117// {"dBodySetAutoDisableSteps", (void **) &dBodySetAutoDisableSteps},
1118// {"dBodyGetAutoDisableTime", (void **) &dBodyGetAutoDisableTime},
1119// {"dBodySetAutoDisableTime", (void **) &dBodySetAutoDisableTime},
1120// {"dBodyGetAutoDisableFlag", (void **) &dBodyGetAutoDisableFlag},
1121// {"dBodySetAutoDisableFlag", (void **) &dBodySetAutoDisableFlag},
1122// {"dBodySetAutoDisableDefaults", (void **) &dBodySetAutoDisableDefaults},
1123// {"dBodyGetWorld", (void **) &dBodyGetWorld},
1124 {"dBodyCreate", (void **) &dBodyCreate},
1125 {"dBodyDestroy", (void **) &dBodyDestroy},
1126 {"dBodySetData", (void **) &dBodySetData},
1127 {"dBodyGetData", (void **) &dBodyGetData},
1128 {"dBodySetPosition", (void **) &dBodySetPosition},
1129 {"dBodySetRotation", (void **) &dBodySetRotation},
1130// {"dBodySetQuaternion", (void **) &dBodySetQuaternion},
1131 {"dBodySetLinearVel", (void **) &dBodySetLinearVel},
1132 {"dBodySetAngularVel", (void **) &dBodySetAngularVel},
1133 {"dBodyGetPosition", (void **) &dBodyGetPosition},
1134// {"dBodyCopyPosition", (void **) &dBodyCopyPosition},
1135 {"dBodyGetRotation", (void **) &dBodyGetRotation},
1136// {"dBodyCopyRotation", (void **) &dBodyCopyRotation},
1137// {"dBodyGetQuaternion", (void **) &dBodyGetQuaternion},
1138// {"dBodyCopyQuaternion", (void **) &dBodyCopyQuaternion},
1139 {"dBodyGetLinearVel", (void **) &dBodyGetLinearVel},
1140 {"dBodyGetAngularVel", (void **) &dBodyGetAngularVel},
1141 {"dBodySetMass", (void **) &dBodySetMass},
1142// {"dBodyGetMass", (void **) &dBodyGetMass},
1143 {"dBodyAddForce", (void **) &dBodyAddForce},
1144 {"dBodyAddTorque", (void **) &dBodyAddTorque},
1145// {"dBodyAddRelForce", (void **) &dBodyAddRelForce},
1146// {"dBodyAddRelTorque", (void **) &dBodyAddRelTorque},
1147 {"dBodyAddForceAtPos", (void **) &dBodyAddForceAtPos},
1148// {"dBodyAddForceAtRelPos", (void **) &dBodyAddForceAtRelPos},
1149// {"dBodyAddRelForceAtPos", (void **) &dBodyAddRelForceAtPos},
1150// {"dBodyAddRelForceAtRelPos", (void **) &dBodyAddRelForceAtRelPos},
1151// {"dBodyGetForce", (void **) &dBodyGetForce},
1152// {"dBodyGetTorque", (void **) &dBodyGetTorque},
1153// {"dBodySetForce", (void **) &dBodySetForce},
1154// {"dBodySetTorque", (void **) &dBodySetTorque},
1155// {"dBodyGetRelPointPos", (void **) &dBodyGetRelPointPos},
1156// {"dBodyGetRelPointVel", (void **) &dBodyGetRelPointVel},
1157// {"dBodyGetPointVel", (void **) &dBodyGetPointVel},
1158// {"dBodyGetPosRelPoint", (void **) &dBodyGetPosRelPoint},
1159// {"dBodyVectorToWorld", (void **) &dBodyVectorToWorld},
1160// {"dBodyVectorFromWorld", (void **) &dBodyVectorFromWorld},
1161// {"dBodySetFiniteRotationMode", (void **) &dBodySetFiniteRotationMode},
1162// {"dBodySetFiniteRotationAxis", (void **) &dBodySetFiniteRotationAxis},
1163// {"dBodyGetFiniteRotationMode", (void **) &dBodyGetFiniteRotationMode},
1164// {"dBodyGetFiniteRotationAxis", (void **) &dBodyGetFiniteRotationAxis},
1165 {"dBodyGetNumJoints", (void **) &dBodyGetNumJoints},
1166 {"dBodyGetJoint", (void **) &dBodyGetJoint},
1167// {"dBodySetDynamic", (void **) &dBodySetDynamic},
1168// {"dBodySetKinematic", (void **) &dBodySetKinematic},
1169// {"dBodyIsKinematic", (void **) &dBodyIsKinematic},
1170 {"dBodyEnable", (void **) &dBodyEnable},
1171 {"dBodyDisable", (void **) &dBodyDisable},
1172 {"dBodyIsEnabled", (void **) &dBodyIsEnabled},
1173 {"dBodySetGravityMode", (void **) &dBodySetGravityMode},
1174 {"dBodyGetGravityMode", (void **) &dBodyGetGravityMode},
1175// {"dBodySetMovedCallback", (void **) &dBodySetMovedCallback},
1176// {"dBodyGetFirstGeom", (void **) &dBodyGetFirstGeom},
1177// {"dBodyGetNextGeom", (void **) &dBodyGetNextGeom},
1178// {"dBodySetDampingDefaults", (void **) &dBodySetDampingDefaults},
1179// {"dBodyGetLinearDamping", (void **) &dBodyGetLinearDamping},
1180// {"dBodySetLinearDamping", (void **) &dBodySetLinearDamping},
1181// {"dBodyGetAngularDamping", (void **) &dBodyGetAngularDamping},
1182// {"dBodySetAngularDamping", (void **) &dBodySetAngularDamping},
1183// {"dBodySetDamping", (void **) &dBodySetDamping},
1184// {"dBodyGetLinearDampingThreshold", (void **) &dBodyGetLinearDampingThreshold},
1185// {"dBodySetLinearDampingThreshold", (void **) &dBodySetLinearDampingThreshold},
1186// {"dBodyGetAngularDampingThreshold", (void **) &dBodyGetAngularDampingThreshold},
1187// {"dBodySetAngularDampingThreshold", (void **) &dBodySetAngularDampingThreshold},
1188// {"dBodyGetMaxAngularSpeed", (void **) &dBodyGetMaxAngularSpeed},
1189// {"dBodySetMaxAngularSpeed", (void **) &dBodySetMaxAngularSpeed},
1190// {"dBodyGetGyroscopicMode", (void **) &dBodyGetGyroscopicMode},
1191// {"dBodySetGyroscopicMode", (void **) &dBodySetGyroscopicMode},
1192 {"dJointCreateBall", (void **) &dJointCreateBall},
1193 {"dJointCreateHinge", (void **) &dJointCreateHinge},
1194 {"dJointCreateSlider", (void **) &dJointCreateSlider},
1195 {"dJointCreateContact", (void **) &dJointCreateContact},
1196 {"dJointCreateHinge2", (void **) &dJointCreateHinge2},
1197 {"dJointCreateUniversal", (void **) &dJointCreateUniversal},
1198// {"dJointCreatePR", (void **) &dJointCreatePR},
1199// {"dJointCreatePU", (void **) &dJointCreatePU},
1200// {"dJointCreatePiston", (void **) &dJointCreatePiston},
1201 {"dJointCreateFixed", (void **) &dJointCreateFixed},
1202// {"dJointCreateNull", (void **) &dJointCreateNull},
1203// {"dJointCreateAMotor", (void **) &dJointCreateAMotor},
1204// {"dJointCreateLMotor", (void **) &dJointCreateLMotor},
1205// {"dJointCreatePlane2D", (void **) &dJointCreatePlane2D},
1206 {"dJointDestroy", (void **) &dJointDestroy},
1207 {"dJointGroupCreate", (void **) &dJointGroupCreate},
1208 {"dJointGroupDestroy", (void **) &dJointGroupDestroy},
1209 {"dJointGroupEmpty", (void **) &dJointGroupEmpty},
1210// {"dJointGetNumBodies", (void **) &dJointGetNumBodies},
1211 {"dJointAttach", (void **) &dJointAttach},
1212// {"dJointEnable", (void **) &dJointEnable},
1213// {"dJointDisable", (void **) &dJointDisable},
1214// {"dJointIsEnabled", (void **) &dJointIsEnabled},
1215 {"dJointSetData", (void **) &dJointSetData},
1216 {"dJointGetData", (void **) &dJointGetData},
1217// {"dJointGetType", (void **) &dJointGetType},
1218 {"dJointGetBody", (void **) &dJointGetBody},
1219// {"dJointSetFeedback", (void **) &dJointSetFeedback},
1220// {"dJointGetFeedback", (void **) &dJointGetFeedback},
1221 {"dJointSetBallAnchor", (void **) &dJointSetBallAnchor},
1222// {"dJointSetBallAnchor2", (void **) &dJointSetBallAnchor2},
1223 {"dJointSetBallParam", (void **) &dJointSetBallParam},
1224 {"dJointSetHingeAnchor", (void **) &dJointSetHingeAnchor},
1225// {"dJointSetHingeAnchorDelta", (void **) &dJointSetHingeAnchorDelta},
1226 {"dJointSetHingeAxis", (void **) &dJointSetHingeAxis},
1227// {"dJointSetHingeAxisOffset", (void **) &dJointSetHingeAxisOffset},
1228 {"dJointSetHingeParam", (void **) &dJointSetHingeParam},
1229// {"dJointAddHingeTorque", (void **) &dJointAddHingeTorque},
1230 {"dJointSetSliderAxis", (void **) &dJointSetSliderAxis},
1231// {"dJointSetSliderAxisDelta", (void **) &dJointSetSliderAxisDelta},
1232 {"dJointSetSliderParam", (void **) &dJointSetSliderParam},
1233// {"dJointAddSliderForce", (void **) &dJointAddSliderForce},
1234 {"dJointSetHinge2Anchor", (void **) &dJointSetHinge2Anchor},
1235 {"dJointSetHinge2Axis1", (void **) &dJointSetHinge2Axis1},
1236 {"dJointSetHinge2Axis2", (void **) &dJointSetHinge2Axis2},
1237 {"dJointSetHinge2Param", (void **) &dJointSetHinge2Param},
1238// {"dJointAddHinge2Torques", (void **) &dJointAddHinge2Torques},
1239 {"dJointSetUniversalAnchor", (void **) &dJointSetUniversalAnchor},
1240 {"dJointSetUniversalAxis1", (void **) &dJointSetUniversalAxis1},
1241// {"dJointSetUniversalAxis1Offset", (void **) &dJointSetUniversalAxis1Offset},
1242 {"dJointSetUniversalAxis2", (void **) &dJointSetUniversalAxis2},
1243// {"dJointSetUniversalAxis2Offset", (void **) &dJointSetUniversalAxis2Offset},
1244 {"dJointSetUniversalParam", (void **) &dJointSetUniversalParam},
1245// {"dJointAddUniversalTorques", (void **) &dJointAddUniversalTorques},
1246// {"dJointSetPRAnchor", (void **) &dJointSetPRAnchor},
1247// {"dJointSetPRAxis1", (void **) &dJointSetPRAxis1},
1248// {"dJointSetPRAxis2", (void **) &dJointSetPRAxis2},
1249// {"dJointSetPRParam", (void **) &dJointSetPRParam},
1250// {"dJointAddPRTorque", (void **) &dJointAddPRTorque},
1251// {"dJointSetPUAnchor", (void **) &dJointSetPUAnchor},
1252// {"dJointSetPUAnchorOffset", (void **) &dJointSetPUAnchorOffset},
1253// {"dJointSetPUAxis1", (void **) &dJointSetPUAxis1},
1254// {"dJointSetPUAxis2", (void **) &dJointSetPUAxis2},
1255// {"dJointSetPUAxis3", (void **) &dJointSetPUAxis3},
1256// {"dJointSetPUAxisP", (void **) &dJointSetPUAxisP},
1257// {"dJointSetPUParam", (void **) &dJointSetPUParam},
1258// {"dJointAddPUTorque", (void **) &dJointAddPUTorque},
1259// {"dJointSetPistonAnchor", (void **) &dJointSetPistonAnchor},
1260// {"dJointSetPistonAnchorOffset", (void **) &dJointSetPistonAnchorOffset},
1261// {"dJointSetPistonParam", (void **) &dJointSetPistonParam},
1262// {"dJointAddPistonForce", (void **) &dJointAddPistonForce},
1263// {"dJointSetFixed", (void **) &dJointSetFixed},
1264// {"dJointSetFixedParam", (void **) &dJointSetFixedParam},
1265// {"dJointSetAMotorNumAxes", (void **) &dJointSetAMotorNumAxes},
1266// {"dJointSetAMotorAxis", (void **) &dJointSetAMotorAxis},
1267// {"dJointSetAMotorAngle", (void **) &dJointSetAMotorAngle},
1268// {"dJointSetAMotorParam", (void **) &dJointSetAMotorParam},
1269// {"dJointSetAMotorMode", (void **) &dJointSetAMotorMode},
1270// {"dJointAddAMotorTorques", (void **) &dJointAddAMotorTorques},
1271// {"dJointSetLMotorNumAxes", (void **) &dJointSetLMotorNumAxes},
1272// {"dJointSetLMotorAxis", (void **) &dJointSetLMotorAxis},
1273// {"dJointSetLMotorParam", (void **) &dJointSetLMotorParam},
1274// {"dJointSetPlane2DXParam", (void **) &dJointSetPlane2DXParam},
1275// {"dJointSetPlane2DYParam", (void **) &dJointSetPlane2DYParam},
1276// {"dJointSetPlane2DAngleParam", (void **) &dJointSetPlane2DAngleParam},
1277// {"dJointGetBallAnchor", (void **) &dJointGetBallAnchor},
1278// {"dJointGetBallAnchor2", (void **) &dJointGetBallAnchor2},
1279// {"dJointGetBallParam", (void **) &dJointGetBallParam},
1280// {"dJointGetHingeAnchor", (void **) &dJointGetHingeAnchor},
1281// {"dJointGetHingeAnchor2", (void **) &dJointGetHingeAnchor2},
1282// {"dJointGetHingeAxis", (void **) &dJointGetHingeAxis},
1283// {"dJointGetHingeParam", (void **) &dJointGetHingeParam},
1284// {"dJointGetHingeAngle", (void **) &dJointGetHingeAngle},
1285// {"dJointGetHingeAngleRate", (void **) &dJointGetHingeAngleRate},
1286// {"dJointGetSliderPosition", (void **) &dJointGetSliderPosition},
1287// {"dJointGetSliderPositionRate", (void **) &dJointGetSliderPositionRate},
1288// {"dJointGetSliderAxis", (void **) &dJointGetSliderAxis},
1289// {"dJointGetSliderParam", (void **) &dJointGetSliderParam},
1290// {"dJointGetHinge2Anchor", (void **) &dJointGetHinge2Anchor},
1291// {"dJointGetHinge2Anchor2", (void **) &dJointGetHinge2Anchor2},
1292// {"dJointGetHinge2Axis1", (void **) &dJointGetHinge2Axis1},
1293// {"dJointGetHinge2Axis2", (void **) &dJointGetHinge2Axis2},
1294// {"dJointGetHinge2Param", (void **) &dJointGetHinge2Param},
1295// {"dJointGetHinge2Angle1", (void **) &dJointGetHinge2Angle1},
1296// {"dJointGetHinge2Angle1Rate", (void **) &dJointGetHinge2Angle1Rate},
1297// {"dJointGetHinge2Angle2Rate", (void **) &dJointGetHinge2Angle2Rate},
1298// {"dJointGetUniversalAnchor", (void **) &dJointGetUniversalAnchor},
1299// {"dJointGetUniversalAnchor2", (void **) &dJointGetUniversalAnchor2},
1300// {"dJointGetUniversalAxis1", (void **) &dJointGetUniversalAxis1},
1301// {"dJointGetUniversalAxis2", (void **) &dJointGetUniversalAxis2},
1302// {"dJointGetUniversalParam", (void **) &dJointGetUniversalParam},
1303// {"dJointGetUniversalAngles", (void **) &dJointGetUniversalAngles},
1304// {"dJointGetUniversalAngle1", (void **) &dJointGetUniversalAngle1},
1305// {"dJointGetUniversalAngle2", (void **) &dJointGetUniversalAngle2},
1306// {"dJointGetUniversalAngle1Rate", (void **) &dJointGetUniversalAngle1Rate},
1307// {"dJointGetUniversalAngle2Rate", (void **) &dJointGetUniversalAngle2Rate},
1308// {"dJointGetPRAnchor", (void **) &dJointGetPRAnchor},
1309// {"dJointGetPRPosition", (void **) &dJointGetPRPosition},
1310// {"dJointGetPRPositionRate", (void **) &dJointGetPRPositionRate},
1311// {"dJointGetPRAngle", (void **) &dJointGetPRAngle},
1312// {"dJointGetPRAngleRate", (void **) &dJointGetPRAngleRate},
1313// {"dJointGetPRAxis1", (void **) &dJointGetPRAxis1},
1314// {"dJointGetPRAxis2", (void **) &dJointGetPRAxis2},
1315// {"dJointGetPRParam", (void **) &dJointGetPRParam},
1316// {"dJointGetPUAnchor", (void **) &dJointGetPUAnchor},
1317// {"dJointGetPUPosition", (void **) &dJointGetPUPosition},
1318// {"dJointGetPUPositionRate", (void **) &dJointGetPUPositionRate},
1319// {"dJointGetPUAxis1", (void **) &dJointGetPUAxis1},
1320// {"dJointGetPUAxis2", (void **) &dJointGetPUAxis2},
1321// {"dJointGetPUAxis3", (void **) &dJointGetPUAxis3},
1322// {"dJointGetPUAxisP", (void **) &dJointGetPUAxisP},
1323// {"dJointGetPUAngles", (void **) &dJointGetPUAngles},
1324// {"dJointGetPUAngle1", (void **) &dJointGetPUAngle1},
1325// {"dJointGetPUAngle1Rate", (void **) &dJointGetPUAngle1Rate},
1326// {"dJointGetPUAngle2", (void **) &dJointGetPUAngle2},
1327// {"dJointGetPUAngle2Rate", (void **) &dJointGetPUAngle2Rate},
1328// {"dJointGetPUParam", (void **) &dJointGetPUParam},
1329// {"dJointGetPistonPosition", (void **) &dJointGetPistonPosition},
1330// {"dJointGetPistonPositionRate", (void **) &dJointGetPistonPositionRate},
1331// {"dJointGetPistonAngle", (void **) &dJointGetPistonAngle},
1332// {"dJointGetPistonAngleRate", (void **) &dJointGetPistonAngleRate},
1333// {"dJointGetPistonAnchor", (void **) &dJointGetPistonAnchor},
1334// {"dJointGetPistonAnchor2", (void **) &dJointGetPistonAnchor2},
1335// {"dJointGetPistonAxis", (void **) &dJointGetPistonAxis},
1336// {"dJointGetPistonParam", (void **) &dJointGetPistonParam},
1337// {"dJointGetAMotorNumAxes", (void **) &dJointGetAMotorNumAxes},
1338// {"dJointGetAMotorAxis", (void **) &dJointGetAMotorAxis},
1339// {"dJointGetAMotorAxisRel", (void **) &dJointGetAMotorAxisRel},
1340// {"dJointGetAMotorAngle", (void **) &dJointGetAMotorAngle},
1341// {"dJointGetAMotorAngleRate", (void **) &dJointGetAMotorAngleRate},
1342// {"dJointGetAMotorParam", (void **) &dJointGetAMotorParam},
1343// {"dJointGetAMotorMode", (void **) &dJointGetAMotorMode},
1344// {"dJointGetLMotorNumAxes", (void **) &dJointGetLMotorNumAxes},
1345// {"dJointGetLMotorAxis", (void **) &dJointGetLMotorAxis},
1346// {"dJointGetLMotorParam", (void **) &dJointGetLMotorParam},
1347// {"dJointGetFixedParam", (void **) &dJointGetFixedParam},
1348// {"dConnectingJoint", (void **) &dConnectingJoint},
1349// {"dConnectingJointList", (void **) &dConnectingJointList},
1350 {"dAreConnected", (void **) &dAreConnected},
1351 {"dAreConnectedExcluding", (void **) &dAreConnectedExcluding},
1352 {"dSimpleSpaceCreate", (void **) &dSimpleSpaceCreate},
1353 {"dHashSpaceCreate", (void **) &dHashSpaceCreate},
1354 {"dQuadTreeSpaceCreate", (void **) &dQuadTreeSpaceCreate},
1355// {"dSweepAndPruneSpaceCreate", (void **) &dSweepAndPruneSpaceCreate},
1356 {"dSpaceDestroy", (void **) &dSpaceDestroy},
1357// {"dHashSpaceSetLevels", (void **) &dHashSpaceSetLevels},
1358// {"dHashSpaceGetLevels", (void **) &dHashSpaceGetLevels},
1359// {"dSpaceSetCleanup", (void **) &dSpaceSetCleanup},
1360// {"dSpaceGetCleanup", (void **) &dSpaceGetCleanup},
1361// {"dSpaceSetSublevel", (void **) &dSpaceSetSublevel},
1362// {"dSpaceGetSublevel", (void **) &dSpaceGetSublevel},
1363// {"dSpaceSetManualCleanup", (void **) &dSpaceSetManualCleanup},
1364// {"dSpaceGetManualCleanup", (void **) &dSpaceGetManualCleanup},
1365// {"dSpaceAdd", (void **) &dSpaceAdd},
1366// {"dSpaceRemove", (void **) &dSpaceRemove},
1367// {"dSpaceQuery", (void **) &dSpaceQuery},
1368// {"dSpaceClean", (void **) &dSpaceClean},
1369// {"dSpaceGetNumGeoms", (void **) &dSpaceGetNumGeoms},
1370// {"dSpaceGetGeom", (void **) &dSpaceGetGeom},
1371// {"dSpaceGetClass", (void **) &dSpaceGetClass},
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},
1379// {"dGeomSetQuaternion", (void **) &dGeomSetQuaternion},
1380// {"dGeomGetPosition", (void **) &dGeomGetPosition},
1381// {"dGeomCopyPosition", (void **) &dGeomCopyPosition},
1382// {"dGeomGetRotation", (void **) &dGeomGetRotation},
1383// {"dGeomCopyRotation", (void **) &dGeomCopyRotation},
1384// {"dGeomGetQuaternion", (void **) &dGeomGetQuaternion},
1385// {"dGeomGetAABB", (void **) &dGeomGetAABB},
1386 {"dGeomIsSpace", (void **) &dGeomIsSpace},
1387// {"dGeomGetSpace", (void **) &dGeomGetSpace},
1388// {"dGeomGetClass", (void **) &dGeomGetClass},
1389// {"dGeomSetCategoryBits", (void **) &dGeomSetCategoryBits},
1390// {"dGeomSetCollideBits", (void **) &dGeomSetCollideBits},
1391// {"dGeomGetCategoryBits", (void **) &dGeomGetCategoryBits},
1392// {"dGeomGetCollideBits", (void **) &dGeomGetCollideBits},
1393// {"dGeomEnable", (void **) &dGeomEnable},
1394// {"dGeomDisable", (void **) &dGeomDisable},
1395// {"dGeomIsEnabled", (void **) &dGeomIsEnabled},
1396// {"dGeomSetOffsetPosition", (void **) &dGeomSetOffsetPosition},
1397// {"dGeomSetOffsetRotation", (void **) &dGeomSetOffsetRotation},
1398// {"dGeomSetOffsetQuaternion", (void **) &dGeomSetOffsetQuaternion},
1399// {"dGeomSetOffsetWorldPosition", (void **) &dGeomSetOffsetWorldPosition},
1400// {"dGeomSetOffsetWorldRotation", (void **) &dGeomSetOffsetWorldRotation},
1401// {"dGeomSetOffsetWorldQuaternion", (void **) &dGeomSetOffsetWorldQuaternion},
1402// {"dGeomClearOffset", (void **) &dGeomClearOffset},
1403// {"dGeomIsOffset", (void **) &dGeomIsOffset},
1404// {"dGeomGetOffsetPosition", (void **) &dGeomGetOffsetPosition},
1405// {"dGeomCopyOffsetPosition", (void **) &dGeomCopyOffsetPosition},
1406// {"dGeomGetOffsetRotation", (void **) &dGeomGetOffsetRotation},
1407// {"dGeomCopyOffsetRotation", (void **) &dGeomCopyOffsetRotation},
1408// {"dGeomGetOffsetQuaternion", (void **) &dGeomGetOffsetQuaternion},
1409 {"dCollide", (void **) &dCollide},
1410 {"dSpaceCollide", (void **) &dSpaceCollide},
1411 {"dSpaceCollide2", (void **) &dSpaceCollide2},
1412 {"dCreateSphere", (void **) &dCreateSphere},
1413// {"dGeomSphereSetRadius", (void **) &dGeomSphereSetRadius},
1414// {"dGeomSphereGetRadius", (void **) &dGeomSphereGetRadius},
1415// {"dGeomSpherePointDepth", (void **) &dGeomSpherePointDepth},
1416 {"dCreateConvex", (void **) &dCreateConvex},
1417// {"dGeomSetConvex", (void **) &dGeomSetConvex},
1418 {"dCreateBox", (void **) &dCreateBox},
1419// {"dGeomBoxSetLengths", (void **) &dGeomBoxSetLengths},
1420// {"dGeomBoxGetLengths", (void **) &dGeomBoxGetLengths},
1421// {"dGeomBoxPointDepth", (void **) &dGeomBoxPointDepth},
1422// {"dGeomBoxPointDepth", (void **) &dGeomBoxPointDepth},
1423// {"dCreatePlane", (void **) &dCreatePlane},
1424// {"dGeomPlaneSetParams", (void **) &dGeomPlaneSetParams},
1425// {"dGeomPlaneGetParams", (void **) &dGeomPlaneGetParams},
1426// {"dGeomPlanePointDepth", (void **) &dGeomPlanePointDepth},
1427 {"dCreateCapsule", (void **) &dCreateCapsule},
1428// {"dGeomCapsuleSetParams", (void **) &dGeomCapsuleSetParams},
1429// {"dGeomCapsuleGetParams", (void **) &dGeomCapsuleGetParams},
1430// {"dGeomCapsulePointDepth", (void **) &dGeomCapsulePointDepth},
1431 {"dCreateCylinder", (void **) &dCreateCylinder},
1432// {"dGeomCylinderSetParams", (void **) &dGeomCylinderSetParams},
1433// {"dGeomCylinderGetParams", (void **) &dGeomCylinderGetParams},
1434// {"dCreateRay", (void **) &dCreateRay},
1435// {"dGeomRaySetLength", (void **) &dGeomRaySetLength},
1436// {"dGeomRayGetLength", (void **) &dGeomRayGetLength},
1437// {"dGeomRaySet", (void **) &dGeomRaySet},
1438// {"dGeomRayGet", (void **) &dGeomRayGet},
1439 {"dCreateGeomTransform", (void **) &dCreateGeomTransform},
1440 {"dGeomTransformSetGeom", (void **) &dGeomTransformSetGeom},
1441// {"dGeomTransformGetGeom", (void **) &dGeomTransformGetGeom},
1442 {"dGeomTransformSetCleanup", (void **) &dGeomTransformSetCleanup},
1443// {"dGeomTransformGetCleanup", (void **) &dGeomTransformGetCleanup},
1444// {"dGeomTransformSetInfo", (void **) &dGeomTransformSetInfo},
1445// {"dGeomTransformGetInfo", (void **) &dGeomTransformGetInfo},
1446 {"dGeomTriMeshDataCreate", (void **) &dGeomTriMeshDataCreate},
1447 {"dGeomTriMeshDataDestroy", (void **) &dGeomTriMeshDataDestroy},
1448// {"dGeomTriMeshDataSet", (void **) &dGeomTriMeshDataSet},
1449// {"dGeomTriMeshDataGet", (void **) &dGeomTriMeshDataGet},
1450// {"dGeomTriMeshSetLastTransform", (void **) &dGeomTriMeshSetLastTransform},
1451// {"dGeomTriMeshGetLastTransform", (void **) &dGeomTriMeshGetLastTransform},
1452 {"dGeomTriMeshDataBuildSingle", (void **) &dGeomTriMeshDataBuildSingle},
1453// {"dGeomTriMeshDataBuildSingle1", (void **) &dGeomTriMeshDataBuildSingle1},
1454// {"dGeomTriMeshDataBuildDouble", (void **) &dGeomTriMeshDataBuildDouble},
1455// {"dGeomTriMeshDataBuildDouble1", (void **) &dGeomTriMeshDataBuildDouble1},
1456// {"dGeomTriMeshDataBuildSimple", (void **) &dGeomTriMeshDataBuildSimple},
1457// {"dGeomTriMeshDataBuildSimple1", (void **) &dGeomTriMeshDataBuildSimple1},
1458// {"dGeomTriMeshDataPreprocess", (void **) &dGeomTriMeshDataPreprocess},
1459// {"dGeomTriMeshDataGetBuffer", (void **) &dGeomTriMeshDataGetBuffer},
1460// {"dGeomTriMeshDataSetBuffer", (void **) &dGeomTriMeshDataSetBuffer},
1461// {"dGeomTriMeshSetCallback", (void **) &dGeomTriMeshSetCallback},
1462// {"dGeomTriMeshGetCallback", (void **) &dGeomTriMeshGetCallback},
1463// {"dGeomTriMeshSetArrayCallback", (void **) &dGeomTriMeshSetArrayCallback},
1464// {"dGeomTriMeshGetArrayCallback", (void **) &dGeomTriMeshGetArrayCallback},
1465// {"dGeomTriMeshSetRayCallback", (void **) &dGeomTriMeshSetRayCallback},
1466// {"dGeomTriMeshGetRayCallback", (void **) &dGeomTriMeshGetRayCallback},
1467// {"dGeomTriMeshSetTriMergeCallback", (void **) &dGeomTriMeshSetTriMergeCallback},
1468// {"dGeomTriMeshGetTriMergeCallback", (void **) &dGeomTriMeshGetTriMergeCallback},
1469 {"dCreateTriMesh", (void **) &dCreateTriMesh},
1470// {"dGeomTriMeshSetData", (void **) &dGeomTriMeshSetData},
1471// {"dGeomTriMeshGetData", (void **) &dGeomTriMeshGetData},
1472// {"dGeomTriMeshEnableTC", (void **) &dGeomTriMeshEnableTC},
1473// {"dGeomTriMeshIsTCEnabled", (void **) &dGeomTriMeshIsTCEnabled},
1474// {"dGeomTriMeshClearTCCache", (void **) &dGeomTriMeshClearTCCache},
1475// {"dGeomTriMeshGetTriMeshDataID", (void **) &dGeomTriMeshGetTriMeshDataID},
1476// {"dGeomTriMeshGetTriangle", (void **) &dGeomTriMeshGetTriangle},
1477// {"dGeomTriMeshGetPoint", (void **) &dGeomTriMeshGetPoint},
1478// {"dGeomTriMeshGetTriangleCount", (void **) &dGeomTriMeshGetTriangleCount},
1479// {"dGeomTriMeshDataUpdate", (void **) &dGeomTriMeshDataUpdate},
1480 {NULL, NULL}
1481};
1482// Handle for ODE DLL
1483dllhandle_t ode_dll = NULL;
1484#endif
1485
1486static void World_Physics_Init(void)
1487{
1488#ifndef LINK_TO_LIBODE
1489 const char* dllnames [] =
1490 {
1491# if defined(WIN32)
1492 "libode3.dll",
1493 "libode2.dll",
1494 "libode1.dll",
1495# elif defined(MACOSX)
1496 "libode.3.dylib",
1497 "libode.2.dylib",
1498 "libode.1.dylib",
1499# else
1500 "libode.so.3",
1501 "libode.so.2",
1502 "libode.so.1",
1503# endif
1504 NULL
1505 };
1506#endif
1507
1508 Cvar_RegisterVariable(&physics_ode_quadtree_depth);
1509 Cvar_RegisterVariable(&physics_ode_contactsurfacelayer);
1510 Cvar_RegisterVariable(&physics_ode_worldstep_iterations);
1511 Cvar_RegisterVariable(&physics_ode_contact_mu);
1512 Cvar_RegisterVariable(&physics_ode_contact_erp);
1513 Cvar_RegisterVariable(&physics_ode_contact_cfm);
1514 Cvar_RegisterVariable(&physics_ode_contact_maxpoints);
1515 Cvar_RegisterVariable(&physics_ode_world_erp);
1516 Cvar_RegisterVariable(&physics_ode_world_cfm);
1517 Cvar_RegisterVariable(&physics_ode_world_damping);
1518 Cvar_RegisterVariable(&physics_ode_world_damping_linear);
1519 Cvar_RegisterVariable(&physics_ode_world_damping_linear_threshold);
1520 Cvar_RegisterVariable(&physics_ode_world_damping_angular);
1521 Cvar_RegisterVariable(&physics_ode_world_damping_angular_threshold);
1522 Cvar_RegisterVariable(&physics_ode_world_gravitymod);
1523 Cvar_RegisterVariable(&physics_ode_iterationsperframe);
1524 Cvar_RegisterVariable(&physics_ode_constantstep);
1525 Cvar_RegisterVariable(&physics_ode_movelimit);
1526 Cvar_RegisterVariable(&physics_ode_spinlimit);
1527 Cvar_RegisterVariable(&physics_ode_trick_fixnan);
1528 Cvar_RegisterVariable(&physics_ode_autodisable);
1529 Cvar_RegisterVariable(&physics_ode_autodisable_steps);
1530 Cvar_RegisterVariable(&physics_ode_autodisable_time);
1531 Cvar_RegisterVariable(&physics_ode_autodisable_threshold_linear);
1532 Cvar_RegisterVariable(&physics_ode_autodisable_threshold_angular);
1533 Cvar_RegisterVariable(&physics_ode_autodisable_threshold_samples);
1534 Cvar_RegisterVariable(&physics_ode_printstats);
1535 Cvar_RegisterVariable(&physics_ode_allowconvex);
1536 Cvar_RegisterVariable(&physics_ode);
1537
1538#ifndef LINK_TO_LIBODE
1539 // Load the DLL
1540 if (Sys_LoadDependency (dllnames, &ode_dll, odefuncs))
1541#endif
1542 {
1543 dInitODE();
1544// dInitODE2(0);
1545#ifndef LINK_TO_LIBODE
1546# ifdef dSINGLE
1547 if (!dCheckConfiguration("ODE_single_precision"))
1548# else
1549 if (!dCheckConfiguration("ODE_double_precision"))
1550# endif
1551 {
1552# ifdef dSINGLE
1553 Con_Printf("ODE library not compiled for single precision - incompatible! Not using ODE physics.\n");
1554# else
1555 Con_Printf("ODE library not compiled for double precision - incompatible! Not using ODE physics.\n");
1556# endif
1557 Sys_FreeLibrary(&ode_dll);
1558 ode_dll = NULL;
1559 }
1560 else
1561 {
1562# ifdef dSINGLE
1563 Con_Printf("ODE library loaded with single precision.\n");
1564# else
1565 Con_Printf("ODE library loaded with double precision.\n");
1566# endif
1567 Con_Printf("ODE configuration list: %s\n", dGetConfiguration());
1568 }
1569#endif
1570 }
1571}
1572static void World_Physics_Shutdown(void)
1573{
1574#ifndef LINK_TO_LIBODE
1575 if (ode_dll)
1576#endif
1577 {
1578 dCloseODE();
1579#ifndef LINK_TO_LIBODE
1580 Sys_FreeLibrary(&ode_dll);
1581 ode_dll = NULL;
1582#endif
1583 }
1584}
1585
1586static void World_Physics_UpdateODE(world_t *world)
1587{
1588 dWorldID odeworld;
1589
1590 odeworld = (dWorldID)world->physics.ode_world;
1591
1592 // ERP and CFM
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);
1597 // Damping
1598 if (physics_ode_world_damping.integer)
1599 {
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);
1604 }
1605 else
1606 {
1607 dWorldSetLinearDamping(odeworld, 0);
1608 dWorldSetLinearDampingThreshold(odeworld, 0);
1609 dWorldSetAngularDamping(odeworld, 0);
1610 dWorldSetAngularDampingThreshold(odeworld, 0);
1611 }
1612 // Autodisable
1613 dWorldSetAutoDisableFlag(odeworld, (physics_ode_autodisable.integer) ? 1 : 0);
1614 if (physics_ode_autodisable.integer)
1615 {
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);
1621 }
1622}
1623
1624static void World_Physics_EnableODE(world_t *world)
1625{
1626 dVector3 center, extents;
1627 if (world->physics.ode)
1628 return;
1629#ifndef LINK_TO_LIBODE
1630 if (!ode_dll)
1631 return;
1632#endif
1633 world->physics.ode = true;
1634 VectorMAM(0.5f, world->mins, 0.5f, world->maxs, center);
1635 VectorSubtract(world->maxs, center, extents);
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);
1639
1640 World_Physics_UpdateODE(world);
1641}
1642
1643static void World_Physics_Start(world_t *world)
1644{
1645 if (world->physics.ode)
1646 return;
1647 World_Physics_EnableODE(world);
1648}
1649
1650static void World_Physics_End(world_t *world)
1651{
1652 if (world->physics.ode)
1653 {
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;
1658 }
1659}
1660
1662{
1663 ed->priv.server->ode_joint_type = 0;
1664 if(ed->priv.server->ode_joint)
1665 dJointDestroy((dJointID)ed->priv.server->ode_joint);
1666 ed->priv.server->ode_joint = NULL;
1667}
1668
1670{
1671 edict_odefunc_t *f, *nf;
1672
1673 // entity is not physics controlled, free any physics data
1674 ed->priv.server->ode_physics = false;
1675 if (ed->priv.server->ode_geom)
1676 dGeomDestroy((dGeomID)ed->priv.server->ode_geom);
1677 ed->priv.server->ode_geom = NULL;
1678 if (ed->priv.server->ode_body)
1679 {
1680 dJointID j;
1681 dBodyID b1, b2;
1682 prvm_edict_t *ed2;
1683 while(dBodyGetNumJoints((dBodyID)ed->priv.server->ode_body))
1684 {
1685 j = dBodyGetJoint((dBodyID)ed->priv.server->ode_body, 0);
1686 ed2 = (prvm_edict_t *) dJointGetData(j);
1687 b1 = dJointGetBody(j, 0);
1688 b2 = dJointGetBody(j, 1);
1689 if(b1 == (dBodyID)ed->priv.server->ode_body)
1690 {
1691 b1 = 0;
1692 ed2->priv.server->ode_joint_enemy = 0;
1693 }
1694 if(b2 == (dBodyID)ed->priv.server->ode_body)
1695 {
1696 b2 = 0;
1697 ed2->priv.server->ode_joint_aiment = 0;
1698 }
1699 dJointAttach(j, b1, b2);
1700 }
1701 dBodyDestroy((dBodyID)ed->priv.server->ode_body);
1702 }
1703 ed->priv.server->ode_body = NULL;
1704 if (ed->priv.server->ode_vertex3f)
1705 Mem_Free(ed->priv.server->ode_vertex3f);
1706 ed->priv.server->ode_vertex3f = NULL;
1707 ed->priv.server->ode_numvertices = 0;
1708 if (ed->priv.server->ode_element3i)
1709 Mem_Free(ed->priv.server->ode_element3i);
1710 ed->priv.server->ode_element3i = NULL;
1711 ed->priv.server->ode_numtriangles = 0;
1712 if(ed->priv.server->ode_massbuf)
1713 Mem_Free(ed->priv.server->ode_massbuf);
1714 ed->priv.server->ode_massbuf = NULL;
1715 // clear functions stack
1716 for(f = ed->priv.server->ode_func; f; f = nf)
1717 {
1718 nf = f->next;
1719 Mem_Free(f);
1720 }
1721 ed->priv.server->ode_func = NULL;
1722}
1723
1724void World_Physics_ApplyCmd(prvm_edict_t *ed, edict_odefunc_t *f)
1725{
1726 dBodyID body = (dBodyID)ed->priv.server->ode_body;
1727
1728 switch(f->type)
1729 {
1730 case ODEFUNC_ENABLE:
1731 dBodyEnable(body);
1732 break;
1733 case ODEFUNC_DISABLE:
1734 dBodyDisable(body);
1735 break;
1736 case ODEFUNC_FORCE:
1737 dBodyEnable(body);
1738 dBodyAddForceAtPos(body, f->v1[0], f->v1[1], f->v1[2], f->v2[0], f->v2[1], f->v2[2]);
1739 break;
1740 case ODEFUNC_TORQUE:
1741 dBodyEnable(body);
1742 dBodyAddTorque(body, f->v1[0], f->v1[1], f->v1[2]);
1743 break;
1744 default:
1745 break;
1746 }
1747}
1748
1749static void World_Physics_Frame_BodyToEntity(world_t *world, prvm_edict_t *ed)
1750{
1751 prvm_prog_t *prog = world->prog;
1752 const dReal *avel;
1753 const dReal *o;
1754 const dReal *r; // for some reason dBodyGetRotation returns a [3][4] matrix
1755 const dReal *vel;
1756 dBodyID body = (dBodyID)ed->priv.server->ode_body;
1757 int movetype;
1758 matrix4x4_t bodymatrix;
1759 matrix4x4_t entitymatrix;
1760 vec3_t angles;
1762 vec3_t forward, left, up;
1763 vec3_t origin;
1764 vec3_t spinvelocity;
1766 int jointtype;
1767 if (!body)
1768 return;
1771 {
1773 switch(jointtype)
1774 {
1775 // TODO feed back data from physics
1776 case JOINTTYPE_POINT:
1777 break;
1778 case JOINTTYPE_HINGE:
1779 break;
1780 case JOINTTYPE_SLIDER:
1781 break;
1783 break;
1784 case JOINTTYPE_HINGE2:
1785 break;
1786 case JOINTTYPE_FIXED:
1787 break;
1788 }
1789 return;
1790 }
1791 // store the physics engine data into the entity
1792 o = dBodyGetPosition(body);
1793 r = dBodyGetRotation(body);
1794 vel = dBodyGetLinearVel(body);
1795 avel = dBodyGetAngularVel(body);
1796 VectorCopy(o, origin);
1797 forward[0] = r[0];
1798 forward[1] = r[4];
1799 forward[2] = r[8];
1800 left[0] = r[1];
1801 left[1] = r[5];
1802 left[2] = r[9];
1803 up[0] = r[2];
1804 up[1] = r[6];
1805 up[2] = r[10];
1806 VectorCopy(vel, velocity);
1807 VectorCopy(avel, spinvelocity);
1808 Matrix4x4_FromVectors(&bodymatrix, forward, left, up, origin);
1809 Matrix4x4_Concat(&entitymatrix, &bodymatrix, &ed->priv.server->ode_offsetimatrix);
1810 Matrix4x4_ToVectors(&entitymatrix, forward, left, up, origin);
1811
1813 VectorSet(avelocity, RAD2DEG(spinvelocity[PITCH]), RAD2DEG(spinvelocity[ROLL]), RAD2DEG(spinvelocity[YAW]));
1814
1815 {
1816 float pitchsign = 1;
1817 if(prog == SVVM_prog) // FIXME some better way?
1818 {
1819 pitchsign = SV_GetPitchSign(prog, ed);
1820 }
1821 else if(prog == CLVM_prog)
1822 {
1823 pitchsign = CL_GetPitchSign(prog, ed);
1824 }
1825 angles[PITCH] *= pitchsign;
1826 avelocity[PITCH] *= pitchsign;
1827 }
1828
1831 //VectorCopy(forward, PRVM_gameedictvector(ed, axis_forward));
1832 //VectorCopy(left, PRVM_gameedictvector(ed, axis_left));
1833 //VectorCopy(up, PRVM_gameedictvector(ed, axis_up));
1834 //VectorCopy(spinvelocity, PRVM_gameedictvector(ed, spinvelocity));
1837
1838 // values for BodyFromEntity to check if the qc modified anything later
1839 VectorCopy(origin, ed->priv.server->ode_origin);
1840 VectorCopy(velocity, ed->priv.server->ode_velocity);
1841 VectorCopy(angles, ed->priv.server->ode_angles);
1842 VectorCopy(avelocity, ed->priv.server->ode_avelocity);
1843 ed->priv.server->ode_gravity = dBodyGetGravityMode(body) != 0;
1844
1845 if(prog == SVVM_prog) // FIXME some better way?
1846 {
1847 SV_LinkEdict(ed);
1849 }
1850}
1851
1852static void World_Physics_Frame_ForceFromEntity(world_t *world, prvm_edict_t *ed)
1853{
1854 prvm_prog_t *prog = world->prog;
1855 int forcetype = 0, movetype = 0, enemy = 0;
1857
1861 forcetype = FORCETYPE_NONE; // can't have both
1862 if (!forcetype)
1863 return;
1865 if (enemy <= 0 || enemy >= prog->num_edicts || prog->edicts[enemy].free || prog->edicts[enemy].priv.server->ode_body == 0)
1866 return;
1869 dBodyEnable((dBodyID)prog->edicts[enemy].priv.server->ode_body);
1870 switch(forcetype)
1871 {
1872 case FORCETYPE_FORCE:
1873 if (movedir[0] || movedir[1] || movedir[2])
1874 dBodyAddForce((dBodyID)prog->edicts[enemy].priv.server->ode_body, movedir[0], movedir[1], movedir[2]);
1875 break;
1877 if (movedir[0] || movedir[1] || movedir[2])
1878 dBodyAddForceAtPos((dBodyID)prog->edicts[enemy].priv.server->ode_body, movedir[0], movedir[1], movedir[2], origin[0], origin[1], origin[2]);
1879 break;
1880 case FORCETYPE_TORQUE:
1881 if (movedir[0] || movedir[1] || movedir[2])
1882 dBodyAddTorque((dBodyID)prog->edicts[enemy].priv.server->ode_body, movedir[0], movedir[1], movedir[2]);
1883 break;
1884 case FORCETYPE_NONE:
1885 default:
1886 // bad force
1887 break;
1888 }
1889}
1890
1891static void World_Physics_Frame_JointFromEntity(world_t *world, prvm_edict_t *ed)
1892{
1893 prvm_prog_t *prog = world->prog;
1894 dJointID j = 0;
1895 dBodyID b1 = 0;
1896 dBodyID b2 = 0;
1897 int movetype = 0;
1898 int jointtype = 0;
1899 int enemy = 0, aiment = 0;
1901 vec_t CFM, ERP, FMax, Stop, Vel;
1902
1916 jointtype = JOINTTYPE_NONE; // can't have both
1917 if(enemy <= 0 || enemy >= prog->num_edicts || prog->edicts[enemy].free || prog->edicts[enemy].priv.server->ode_body == 0)
1918 enemy = 0;
1919 if(aiment <= 0 || aiment >= prog->num_edicts || prog->edicts[aiment].free || prog->edicts[aiment].priv.server->ode_body == 0)
1920 aiment = 0;
1921 // see http://www.ode.org/old_list_archives/2006-January/017614.html
1922 // we want to set ERP? make it fps independent and work like a spring constant
1923 // note: if movedir[2] is 0, it becomes ERP = 1, CFM = 1.0 / (H * K)
1924 if(movedir[0] > 0 && movedir[1] > 0)
1925 {
1926 float K = movedir[0];
1927 float D = movedir[1];
1928 float R = 2.0 * D * sqrt(K); // we assume D is premultiplied by sqrt(sprungMass)
1929 CFM = 1.0 / (world->physics.ode_step * K + R); // always > 0
1930 ERP = world->physics.ode_step * K * CFM;
1931 Vel = 0;
1932 FMax = 0;
1933 Stop = movedir[2];
1934 }
1935 else if(movedir[1] < 0)
1936 {
1937 CFM = 0;
1938 ERP = 0;
1939 Vel = movedir[0];
1940 FMax = -movedir[1]; // TODO do we need to multiply with world.physics.ode_step?
1941 Stop = movedir[2] > 0 ? movedir[2] : dInfinity;
1942 }
1943 else // movedir[0] > 0, movedir[1] == 0 or movedir[0] < 0, movedir[1] >= 0
1944 {
1945 CFM = 0;
1946 ERP = 0;
1947 Vel = 0;
1948 FMax = 0;
1949 Stop = dInfinity;
1950 }
1951 if(jointtype == ed->priv.server->ode_joint_type && VectorCompare(origin, ed->priv.server->ode_joint_origin) && VectorCompare(velocity, ed->priv.server->ode_joint_velocity) && VectorCompare(angles, ed->priv.server->ode_joint_angles) && enemy == ed->priv.server->ode_joint_enemy && aiment == ed->priv.server->ode_joint_aiment && VectorCompare(movedir, ed->priv.server->ode_joint_movedir))
1952 return; // nothing to do
1954 switch(jointtype)
1955 {
1956 case JOINTTYPE_POINT:
1957 j = dJointCreateBall((dWorldID)world->physics.ode_world, 0);
1958 break;
1959 case JOINTTYPE_HINGE:
1960 j = dJointCreateHinge((dWorldID)world->physics.ode_world, 0);
1961 break;
1962 case JOINTTYPE_SLIDER:
1963 j = dJointCreateSlider((dWorldID)world->physics.ode_world, 0);
1964 break;
1966 j = dJointCreateUniversal((dWorldID)world->physics.ode_world, 0);
1967 break;
1968 case JOINTTYPE_HINGE2:
1969 j = dJointCreateHinge2((dWorldID)world->physics.ode_world, 0);
1970 break;
1971 case JOINTTYPE_FIXED:
1972 j = dJointCreateFixed((dWorldID)world->physics.ode_world, 0);
1973 break;
1974 case JOINTTYPE_NONE:
1975 default:
1976 // no joint
1977 j = 0;
1978 break;
1979 }
1980 if(ed->priv.server->ode_joint)
1981 {
1982 //Con_Printf("deleted old joint %i\n", (int) (ed - prog->edicts));
1983 dJointAttach((dJointID)ed->priv.server->ode_joint, 0, 0);
1984 dJointDestroy((dJointID)ed->priv.server->ode_joint);
1985 }
1986 ed->priv.server->ode_joint = (void *) j;
1987 ed->priv.server->ode_joint_type = jointtype;
1988 ed->priv.server->ode_joint_enemy = enemy;
1989 ed->priv.server->ode_joint_aiment = aiment;
1990 VectorCopy(origin, ed->priv.server->ode_joint_origin);
1991 VectorCopy(velocity, ed->priv.server->ode_joint_velocity);
1992 VectorCopy(angles, ed->priv.server->ode_joint_angles);
1993 VectorCopy(movedir, ed->priv.server->ode_joint_movedir);
1994 if(j)
1995 {
1996 //Con_Printf("made new joint %i\n", (int) (ed - prog->edicts));
1997 dJointSetData(j, (void *) ed);
1998 if(enemy)
1999 b1 = (dBodyID)prog->edicts[enemy].priv.server->ode_body;
2000 if(aiment)
2001 b2 = (dBodyID)prog->edicts[aiment].priv.server->ode_body;
2002 dJointAttach(j, b1, b2);
2003
2004 switch(jointtype)
2005 {
2006 case JOINTTYPE_POINT:
2007 dJointSetBallAnchor(j, origin[0], origin[1], origin[2]);
2008 break;
2009 case JOINTTYPE_HINGE:
2010 dJointSetHingeAnchor(j, origin[0], origin[1], origin[2]);
2011 dJointSetHingeAxis(j, forward[0], forward[1], forward[2]);
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);
2018 break;
2019 case JOINTTYPE_SLIDER:
2020 dJointSetSliderAxis(j, forward[0], forward[1], forward[2]);
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);
2027 break;
2029 dJointSetUniversalAnchor(j, origin[0], origin[1], origin[2]);
2030 dJointSetUniversalAxis1(j, forward[0], forward[1], forward[2]);
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);
2044 break;
2045 case JOINTTYPE_HINGE2:
2046 dJointSetHinge2Anchor(j, origin[0], origin[1], origin[2]);
2047 dJointSetHinge2Axis1(j, forward[0], forward[1], forward[2]);
2048 dJointSetHinge2Axis2(j, velocity[0], velocity[1], velocity[2]);
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);
2061 break;
2062 case JOINTTYPE_FIXED:
2063 break;
2064 case 0:
2065 default:
2066 Sys_Error("what? but above the joint was valid...\n");
2067 break;
2068 }
2069#undef SETPARAMS
2070
2071 }
2072}
2073
2074// test convex geometry data
2075// planes for a cube, these should coincide with the
2076dReal test_convex_planes[] =
2077{
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
2084};
2085const unsigned int test_convex_planecount = 6;
2086// points for a cube
2087dReal test_convex_points[] =
2088{
2089 2.25f,2.25f,2.25f, // point 0
2090 -2.25f,2.25f,2.25f, // point 1
2091 2.25f,-2.25f,2.25f, // point 2
2092 -2.25f,-2.25f,2.25f, // point 3
2093 2.25f,2.25f,-2.25f, // point 4
2094 -2.25f,2.25f,-2.25f, // point 5
2095 2.25f,-2.25f,-2.25f, // point 6
2096 -2.25f,-2.25f,-2.25f, // point 7
2097};
2098const unsigned int test_convex_pointcount = 8;
2099// polygons for a cube (6 squares), index
2100unsigned int test_convex_polygons[] =
2101{
2102 4,0,2,6,4, // positive X
2103 4,1,0,4,5, // positive Y
2104 4,0,1,3,2, // positive Z
2105 4,3,1,5,7, // negative X
2106 4,2,3,7,6, // negative Y
2107 4,5,4,6,7, // negative Z
2108};
2109
2110static void World_Physics_Frame_BodyFromEntity(world_t *world, prvm_edict_t *ed)
2111{
2112 prvm_prog_t *prog = world->prog;
2113 const float *iv;
2114 const int *ie;
2115 dBodyID body;
2116 dMass mass;
2117 const dReal *ovelocity, *ospinvelocity;
2118 void *dataID;
2119 model_t *model;
2120 float *ov;
2121 int *oe;
2122 int axisindex;
2123 int modelindex = 0;
2124 int movetype = MOVETYPE_NONE;
2125 int numtriangles;
2126 int numvertices;
2127 int solid = SOLID_NOT, geomtype = 0;
2128 int triangleindex;
2129 int vertexindex;
2130 mempool_t *mempool;
2131 qbool modified = false;
2132 vec3_t angles;
2134 vec3_t entmaxs;
2135 vec3_t entmins;
2137 vec3_t geomcenter;
2138 vec3_t geomsize;
2139 vec3_t left;
2140 vec3_t origin;
2141 vec3_t spinvelocity;
2142 vec3_t up;
2144 vec_t f;
2145 vec_t length;
2146 vec_t massval = 1.0f;
2147 vec_t movelimit;
2148 vec_t radius;
2149 vec3_t scale;
2150 vec_t spinlimit;
2151 vec_t test;
2152 qbool gravity;
2153 qbool geom_modified = false;
2154 edict_odefunc_t *func, *nextf;
2155
2156 dReal *planes, *planesData, *pointsData;
2157 unsigned int *polygons, *polygonsData, polyvert;
2158 qbool *mapped, *used, convex_compatible;
2159 int numplanes = 0, numpoints = 0, i;
2160
2161#ifndef LINK_TO_LIBODE
2162 if (!ode_dll)
2163 return;
2164#endif
2165 VectorClear(entmins);
2166 VectorClear(entmaxs);
2167
2171 // support scale and q3map/radiant's modelscale_vec
2172 if (PRVM_gameedictvector(ed, modelscale_vec)[0] != 0.0 || PRVM_gameedictvector(ed, modelscale_vec)[1] != 0.0 || PRVM_gameedictvector(ed, modelscale_vec)[2] != 0.0)
2173 VectorCopy(PRVM_gameedictvector(ed, modelscale_vec), scale);
2174 else if (PRVM_gameedictfloat(ed, scale))
2176 else
2177 VectorSet(scale, 1.0f, 1.0f, 1.0f);
2178 modelindex = 0;
2179 if (PRVM_gameedictfloat(ed, mass))
2180 massval = PRVM_gameedictfloat(ed, mass);
2182 massval = 1.0f;
2183 mempool = prog->progs_mempool;
2184 model = NULL;
2185 if (!geomtype)
2186 {
2187 // VorteX: keep support for deprecated solid fields to not break mods
2190 else if (solid == SOLID_NOT || solid == SOLID_TRIGGER)
2192 else if (solid == SOLID_PHYSICS_SPHERE)
2194 else if (solid == SOLID_PHYSICS_CAPSULE)
2196 else if (solid == SOLID_PHYSICS_CYLINDER)
2198 else if (solid == SOLID_PHYSICS_BOX)
2200 else
2202 }
2204 {
2206 if (world == &sv.world)
2208 else if (world == &cl.world)
2210 else
2211 model = NULL;
2212 if (model)
2213 {
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];
2220 geom_modified = !VectorCompare(ed->priv.server->ode_scale, scale) || ed->priv.server->ode_modelindex != modelindex;
2221 }
2222 else
2223 {
2224 Con_Printf("entity %i (classname %s) has no model\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(prog, PRVM_gameedictstring(ed, classname)));
2226 VectorCopy(PRVM_gameedictvector(ed, mins), entmins);
2227 VectorCopy(PRVM_gameedictvector(ed, maxs), entmaxs);
2228 modelindex = 0;
2229 geom_modified = !VectorCompare(ed->priv.server->ode_mins, entmins) || !VectorCompare(ed->priv.server->ode_maxs, entmaxs);
2230 }
2231 }
2232 else if (geomtype && geomtype != GEOMTYPE_NONE)
2233 {
2234 VectorCopy(PRVM_gameedictvector(ed, mins), entmins);
2235 VectorCopy(PRVM_gameedictvector(ed, maxs), entmaxs);
2236 geom_modified = !VectorCompare(ed->priv.server->ode_mins, entmins) || !VectorCompare(ed->priv.server->ode_maxs, entmaxs);
2237 }
2238 else
2239 {
2240 // geometry type not set, falling back
2241 if (ed->priv.server->ode_physics)
2243 return;
2244 }
2245
2246 VectorSubtract(entmaxs, entmins, geomsize);
2247 if (VectorLength2(geomsize) == 0)
2248 {
2249 // we don't allow point-size physics objects...
2250 if (ed->priv.server->ode_physics)
2252 return;
2253 }
2254
2255 // get friction
2256 ed->priv.server->ode_friction = PRVM_gameedictfloat(ed, friction) ? PRVM_gameedictfloat(ed, friction) : 1.0f;
2257
2258 // check if we need to create or replace the geom
2259 if (!ed->priv.server->ode_physics || ed->priv.server->ode_mass != massval || geom_modified)
2260 {
2261 modified = true;
2263 ed->priv.server->ode_physics = true;
2264 VectorMAM(0.5f, entmins, 0.5f, entmaxs, geomcenter);
2266 VectorCopy(geomcenter, PRVM_gameedictvector(ed, massofs));
2267
2268 // check geomsize
2269 if (geomsize[0] * geomsize[1] * geomsize[2] == 0)
2270 {
2272 Con_Printf("entity %i (classname %s) .mass * .size_x * .size_y * .size_z == 0\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(prog, PRVM_gameedictstring(ed, classname)));
2273 VectorSet(geomsize, 1.0f, 1.0f, 1.0f);
2274 }
2275
2276 // greate geom
2277 switch(geomtype)
2278 {
2279 case GEOMTYPE_TRIMESH:
2280 // add an optimized mesh to the model containing only the SUPERCONTENTS_SOLID surfaces
2281 if (!model->brush.collisionmesh)
2283 if (!model->brush.collisionmesh)
2284 {
2285 Con_Printf("entity %i (classname %s) has no geometry\n", PRVM_NUM_FOR_EDICT(ed), PRVM_GetString(prog, PRVM_gameedictstring(ed, classname)));
2286 goto treatasbox;
2287 }
2288
2289 // check if trimesh can be defined with convex
2290 convex_compatible = false;
2291 for (i = model->submodelsurfaces_start;i < model->submodelsurfaces_end;i++)
2292 {
2293 if (!strcmp(model->data_surfaces[i].texture->name, "collisionconvex"))
2294 {
2295 convex_compatible = true;
2296 break;
2297 }
2298 }
2299
2300 // ODE requires persistent mesh storage, so we need to copy out
2301 // the data from the model because renderer restarts could free it
2302 // during the game, additionally we need to flip the triangles...
2303 // note: ODE does preprocessing of the mesh for culling, removing
2304 // concave edges, etc., so this is not a lightweight operation
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]));
2307
2308 // VorteX: rebuild geomsize based on entity's collision mesh, honor scale
2309 VectorSet(entmins, 0, 0, 0);
2310 VectorSet(entmaxs, 0, 0, 0);
2311 for (vertexindex = 0, ov = ed->priv.server->ode_vertex3f, iv = model->brush.collisionmesh->vertex3f;vertexindex < numvertices;vertexindex++, ov += 3, iv += 3)
2312 {
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]);
2322 }
2323 if (!PRVM_gameedictvector(ed, massofs))
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)
2326 {
2327 ov[0] = ov[0] - geomcenter[0];
2328 ov[1] = ov[1] - geomcenter[1];
2329 ov[2] = ov[2] - geomcenter[2];
2330 }
2331 VectorSubtract(entmaxs, entmins, geomsize);
2332 if (VectorLength2(geomsize) == 0)
2333 {
2335 Con_Printf("entity %i collision mesh has null geomsize\n", PRVM_NUM_FOR_EDICT(ed));
2336 VectorSet(geomsize, 1.0f, 1.0f, 1.0f);
2337 }
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]));
2340 //memcpy(ed->priv.server->ode_element3i, model->brush.collisionmesh->element3i, ed->priv.server->ode_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)
2342 {
2343 oe[0] = ie[2];
2344 oe[1] = ie[1];
2345 oe[2] = ie[0];
2346 }
2347 // create geom
2348 Matrix4x4_CreateTranslate(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2]);
2349 if (!convex_compatible || !physics_ode_allowconvex.integer)
2350 {
2351 // trimesh
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]));
2354 ed->priv.server->ode_geom = (void *)dCreateTriMesh((dSpaceID)world->physics.ode_space, (dTriMeshDataID)dataID, NULL, NULL, NULL);
2355 dMassSetBoxTotal(&mass, massval, geomsize[0], geomsize[1], geomsize[2]);
2356 }
2357 else
2358 {
2359 // VorteX: this code is unfinished in two ways
2360 // - no duplicate vertex merging are done
2361 // - triangles that shares same edge and havee sam plane are not merget into poly
2362 // so, currently it only works for geosphere meshes with no UV
2363
2364 Con_Printf("Build convex hull for model %s...\n", model->name);
2365 // build convex geometry from trimesh data
2366 // this ensures that trimesh's triangles can form correct convex geometry
2367 // not many of error checking is performed
2368 // ODE's conve hull data consist of:
2369 // planes : an array of planes in the form: normal X, normal Y, normal Z, distance
2370 // points : an array of points X,Y,Z
2371 // polygons: an array of indices to the points of each polygon,it should be the number of vertices
2372 // followed by that amount of indices to "points" in counter clockwise order
2373 polygonsData = polygons = (unsigned int *)Mem_Alloc(mempool, numtriangles*sizeof(int)*4);
2374 planesData = planes = (dReal *)Mem_Alloc(mempool, numtriangles*sizeof(dReal)*4);
2375 mapped = (qbool *)Mem_Alloc(mempool, numvertices*sizeof(qbool));
2376 used = (qbool *)Mem_Alloc(mempool, numtriangles*sizeof(qbool));
2377 memset(mapped, 0, numvertices*sizeof(qbool));
2378 memset(used, 0, numtriangles*sizeof(qbool));
2379 numplanes = numpoints = polyvert = 0;
2380 // build convex hull
2381 // todo: merge duplicated verts here
2382 Con_Printf("Building...\n");
2383 iv = ed->priv.server->ode_vertex3f;
2384 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
2385 {
2386 // already formed a polygon?
2387 if (used[triangleindex])
2388 continue;
2389 // init polygon
2390 // switch clockwise->counterclockwise
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);
2394 VectorNormalize(planes);
2395 polygons[0] = 3;
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;
2399
2400 // now find and include concave triangles
2401 for (i = triangleindex; i < numtriangles; i++)
2402 {
2403 if (used[i])
2404 continue;
2405 // should share at least 2 vertexes
2406 for (polyvert = 1; polyvert <= polygons[0]; polyvert++)
2407 {
2408 // todo: merge in triangles that shares an edge and have same plane here
2409 }
2410 }
2411
2412 // add polygon to overall stats
2413 planes[3] = DotProduct(&iv[polygons[1]*3], planes);
2414 polygons += (polygons[0]+1);
2415 planes += 4;
2416 numplanes++;
2417 }
2418 Mem_Free(used);
2419 // save points
2420 for (vertexindex = 0, numpoints = 0; vertexindex < numvertices; vertexindex++)
2421 if (mapped[vertexindex])
2422 numpoints++;
2423 pointsData = (dReal *)Mem_Alloc(mempool, numpoints*sizeof(dReal)*3 + numplanes*sizeof(dReal)*4); // planes is appended
2424 for (vertexindex = 0, numpoints = 0; vertexindex < numvertices; vertexindex++)
2425 {
2426 if (mapped[vertexindex])
2427 {
2428 VectorCopy(&iv[vertexindex*3], &pointsData[numpoints*3]);
2429 numpoints++;
2430 }
2431 }
2432 Mem_Free(mapped);
2433 Con_Printf("Points: \n");
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]);
2436 // save planes
2437 planes = planesData;
2438 planesData = pointsData + numpoints*3;
2439 memcpy(planesData, planes, numplanes*sizeof(dReal)*4);
2440 Mem_Free(planes);
2441 Con_Printf("planes...\n");
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]);
2444 // save polygons
2445 polyvert = polygons - polygonsData;
2446 polygons = polygonsData;
2447 polygonsData = (unsigned int *)Mem_Alloc(mempool, polyvert*sizeof(int));
2448 memcpy(polygonsData, polygons, polyvert*sizeof(int));
2449 Mem_Free(polygons);
2450 Con_Printf("Polygons: \n");
2451 polygons = polygonsData;
2452 for (i = 0; i < numplanes; i++)
2453 {
2454 Con_Printf("%3i : %i ", i, polygons[0]);
2455 for (triangleindex = 1; triangleindex <= (int)polygons[0]; triangleindex++)
2456 Con_Printf("%3i ", polygons[triangleindex]);
2457 polygons += (polygons[0]+1);
2458 Con_Printf("\n");
2459 }
2460 Mem_Free(ed->priv.server->ode_element3i);
2461 ed->priv.server->ode_element3i = (int *)polygonsData;
2462 Mem_Free(ed->priv.server->ode_vertex3f);
2463 ed->priv.server->ode_vertex3f = (float *)pointsData;
2464 // check for properly build polygons by calculating the determinant of the 3x3 matrix composed of the first 3 points in the polygon
2465 // this code is picked from ODE Source
2466 Con_Printf("Check...\n");
2467 polygons = polygonsData;
2468 for (i = 0; i < numplanes; i++)
2469 {
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)
2476 Con_Printf(CON_WARN "WARNING: Polygon %d is not defined counterclockwise\n", i);
2477 if (planesData[(i*4)+3] < 0)
2478 Con_Printf(CON_WARN "WARNING: Plane %d does not contain the origin\n", i);
2479 polygons += (*polygons + 1);
2480 }
2481 // create geom
2482 Con_Printf("Create geom...\n");
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]);
2485 Con_Printf("Done!\n");
2486 }
2487 break;
2488 case GEOMTYPE_BOX:
2489treatasbox:
2490 Matrix4x4_CreateTranslate(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[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]);
2493 break;
2494 case GEOMTYPE_SPHERE:
2495 Matrix4x4_CreateTranslate(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[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);
2498 break;
2499 case GEOMTYPE_CAPSULE:
2500 axisindex = 0;
2501 if (geomsize[axisindex] < geomsize[1])
2502 axisindex = 1;
2503 if (geomsize[axisindex] < geomsize[2])
2504 axisindex = 2;
2505 // the qc gives us 3 axis radius, the longest axis is the capsule
2506 // axis, since ODE doesn't like this idea we have to create a
2507 // capsule which uses the standard orientation, and apply a
2508 // transform to it
2509 if (axisindex == 0)
2510 {
2511 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 90, 1);
2512 radius = min(geomsize[1], geomsize[2]) * 0.5f;
2513 }
2514 else if (axisindex == 1)
2515 {
2516 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 90, 0, 0, 1);
2517 radius = min(geomsize[0], geomsize[2]) * 0.5f;
2518 }
2519 else
2520 {
2521 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 0, 1);
2522 radius = min(geomsize[0], geomsize[1]) * 0.5f;
2523 }
2524 length = geomsize[axisindex] - radius*2;
2525 // because we want to support more than one axisindex, we have to
2526 // create a transform, and turn on its cleanup setting (which will
2527 // cause the child to be destroyed when it is destroyed)
2528 ed->priv.server->ode_geom = (void *)dCreateCapsule((dSpaceID)world->physics.ode_space, radius, length);
2529 dMassSetCapsuleTotal(&mass, massval, axisindex+1, radius, length);
2530 break;
2531 case GEOMTYPE_CAPSULE_X:
2532 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 90, 1);
2533 radius = min(geomsize[1], geomsize[2]) * 0.5f;
2534 length = geomsize[0] - radius*2;
2535 // check if length is not enough, reduce radius then
2536 if (length <= 0)
2537 {
2538 radius -= (1 - length)*0.5;
2539 length = 1;
2540 }
2541 ed->priv.server->ode_geom = (void *)dCreateCapsule((dSpaceID)world->physics.ode_space, radius, length);
2542 dMassSetCapsuleTotal(&mass, massval, 1, radius, length);
2543 break;
2544 case GEOMTYPE_CAPSULE_Y:
2545 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 90, 0, 0, 1);
2546 radius = min(geomsize[0], geomsize[2]) * 0.5f;
2547 length = geomsize[1] - radius*2;
2548 // check if length is not enough, reduce radius then
2549 if (length <= 0)
2550 {
2551 radius -= (1 - length)*0.5;
2552 length = 1;
2553 }
2554 ed->priv.server->ode_geom = (void *)dCreateCapsule((dSpaceID)world->physics.ode_space, radius, length);
2555 dMassSetCapsuleTotal(&mass, massval, 2, radius, length);
2556 break;
2557 case GEOMTYPE_CAPSULE_Z:
2558 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 0, 1);
2559 radius = min(geomsize[1], geomsize[0]) * 0.5f;
2560 length = geomsize[2] - radius*2;
2561 // check if length is not enough, reduce radius then
2562 if (length <= 0)
2563 {
2564 radius -= (1 - length)*0.5;
2565 length = 1;
2566 }
2567 ed->priv.server->ode_geom = (void *)dCreateCapsule((dSpaceID)world->physics.ode_space, radius, length);
2568 dMassSetCapsuleTotal(&mass, massval, 3, radius, length);
2569 break;
2570 case GEOMTYPE_CYLINDER:
2571 axisindex = 0;
2572 if (geomsize[axisindex] < geomsize[1])
2573 axisindex = 1;
2574 if (geomsize[axisindex] < geomsize[2])
2575 axisindex = 2;
2576 // the qc gives us 3 axis radius, the longest axis is the capsule
2577 // axis, since ODE doesn't like this idea we have to create a
2578 // capsule which uses the standard orientation, and apply a
2579 // transform to it
2580 if (axisindex == 0)
2581 {
2582 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 90, 1);
2583 radius = min(geomsize[1], geomsize[2]) * 0.5f;
2584 }
2585 else if (axisindex == 1)
2586 {
2587 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 90, 0, 0, 1);
2588 radius = min(geomsize[0], geomsize[2]) * 0.5f;
2589 }
2590 else
2591 {
2592 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 0, 1);
2593 radius = min(geomsize[0], geomsize[1]) * 0.5f;
2594 }
2595 length = geomsize[axisindex];
2596 // check if length is not enough, reduce radius then
2597 if (length <= 0)
2598 {
2599 radius -= (1 - length)*0.5;
2600 length = 1;
2601 }
2602 ed->priv.server->ode_geom = (void *)dCreateCylinder((dSpaceID)world->physics.ode_space, radius, length);
2603 dMassSetCylinderTotal(&mass, massval, axisindex+1, radius, length);
2604 break;
2606 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 90, 1);
2607 radius = min(geomsize[1], geomsize[2]) * 0.5f;
2608 length = geomsize[0];
2609 ed->priv.server->ode_geom = (void *)dCreateCylinder((dSpaceID)world->physics.ode_space, radius, length);
2610 dMassSetCylinderTotal(&mass, massval, 1, radius, length);
2611 break;
2613 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 90, 0, 0, 1);
2614 radius = min(geomsize[0], geomsize[2]) * 0.5f;
2615 length = geomsize[1];
2616 ed->priv.server->ode_geom = (void *)dCreateCylinder((dSpaceID)world->physics.ode_space, radius, length);
2617 dMassSetCylinderTotal(&mass, massval, 2, radius, length);
2618 break;
2620 Matrix4x4_CreateFromQuakeEntity(&ed->priv.server->ode_offsetmatrix, geomcenter[0], geomcenter[1], geomcenter[2], 0, 0, 0, 1);
2621 radius = min(geomsize[0], geomsize[1]) * 0.5f;
2622 length = geomsize[2];
2623 ed->priv.server->ode_geom = (void *)dCreateCylinder((dSpaceID)world->physics.ode_space, radius, length);
2624 dMassSetCylinderTotal(&mass, massval, 3, radius, length);
2625 break;
2626 default:
2627 Sys_Error("World_Physics_BodyFromEntity: unrecognized geomtype value %i was accepted by filter\n", solid);
2628 // this goto only exists to prevent warnings from the compiler
2629 // about uninitialized variables (mass), while allowing it to
2630 // catch legitimate uninitialized variable warnings
2631 goto treatasbox;
2632 }
2633 ed->priv.server->ode_mass = massval;
2634 ed->priv.server->ode_modelindex = modelindex;
2635 VectorCopy(entmins, ed->priv.server->ode_mins);
2636 VectorCopy(entmaxs, ed->priv.server->ode_maxs);
2637 VectorCopy(scale, ed->priv.server->ode_scale);
2638 ed->priv.server->ode_movelimit = min(geomsize[0], min(geomsize[1], geomsize[2]));
2639 Matrix4x4_Invert_Simple(&ed->priv.server->ode_offsetimatrix, &ed->priv.server->ode_offsetmatrix);
2640 ed->priv.server->ode_massbuf = Mem_Alloc(mempool, sizeof(mass));
2641 memcpy(ed->priv.server->ode_massbuf, &mass, sizeof(dMass));
2642 }
2643
2644 if (ed->priv.server->ode_geom)
2645 dGeomSetData((dGeomID)ed->priv.server->ode_geom, (void*)ed);
2646 if (movetype == MOVETYPE_PHYSICS && ed->priv.server->ode_geom)
2647 {
2648 // entity is dynamic
2649 if (ed->priv.server->ode_body == NULL)
2650 {
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);
2655 modified = true;
2656 }
2657 }
2658 else
2659 {
2660 // entity is deactivated
2661 if (ed->priv.server->ode_body != NULL)
2662 {
2663 if(ed->priv.server->ode_geom)
2664 dGeomSetBody((dGeomID)ed->priv.server->ode_geom, 0);
2665 dBodyDestroy((dBodyID) ed->priv.server->ode_body);
2666 ed->priv.server->ode_body = NULL;
2667 modified = true;
2668 }
2669 }
2670
2671 // get current data from entity
2674 //VectorClear(forward);
2675 //VectorClear(left);
2676 //VectorClear(up);
2677 //VectorClear(spinvelocity);
2680 gravity = true;
2683 //VectorCopy(PRVM_gameedictvector(ed, axis_forward), forward);
2684 //VectorCopy(PRVM_gameedictvector(ed, axis_left), left);
2685 //VectorCopy(PRVM_gameedictvector(ed, axis_up), up);
2686 //VectorCopy(PRVM_gameedictvector(ed, spinvelocity), spinvelocity);
2689 if (PRVM_gameedictfloat(ed, gravity) != 0.0f && PRVM_gameedictfloat(ed, gravity) < 0.5f) gravity = false;
2690 if (ed == prog->edicts)
2691 gravity = false;
2692
2693 // compatibility for legacy entities
2694 //if (!VectorLength2(forward) || solid == SOLID_BSP)
2695 {
2696 float pitchsign = 1;
2697 vec3_t qangles, qavelocity;
2698 VectorCopy(angles, qangles);
2699 VectorCopy(avelocity, qavelocity);
2700
2701 if(prog == SVVM_prog) // FIXME some better way?
2702 {
2703 pitchsign = SV_GetPitchSign(prog, ed);
2704 }
2705 else if(prog == CLVM_prog)
2706 {
2707 pitchsign = CL_GetPitchSign(prog, ed);
2708 }
2709 qangles[PITCH] *= pitchsign;
2710 qavelocity[PITCH] *= pitchsign;
2711
2712 AngleVectorsFLU(qangles, forward, left, up);
2713 // convert single-axis rotations in avelocity to spinvelocity
2714 // FIXME: untested math - check signs
2715 VectorSet(spinvelocity, DEG2RAD(qavelocity[PITCH]), DEG2RAD(qavelocity[ROLL]), DEG2RAD(qavelocity[YAW]));
2716 }
2717
2718 // compatibility for legacy entities
2719 switch (solid)
2720 {
2721 case SOLID_BBOX:
2722 case SOLID_SLIDEBOX:
2723 case SOLID_CORPSE:
2724 VectorSet(forward, 1, 0, 0);
2725 VectorSet(left, 0, 1, 0);
2726 VectorSet(up, 0, 0, 1);
2727 VectorSet(spinvelocity, 0, 0, 0);
2728 break;
2729 }
2730
2731
2732 // we must prevent NANs...
2733 if (physics_ode_trick_fixnan.integer)
2734 {
2736 if (isnan(test))
2737 {
2738 modified = true;
2739 //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_gameedictstring(ed, classname)), 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]);
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]);
2742 test = VectorLength2(origin);
2743 if (isnan(test))
2746 if (isnan(test))
2747 {
2748 VectorSet(angles, 0, 0, 0);
2749 VectorSet(forward, 1, 0, 0);
2750 VectorSet(left, 0, 1, 0);
2751 VectorSet(up, 0, 0, 1);
2752 }
2753 test = VectorLength2(velocity);
2754 if (isnan(test))
2756 test = VectorLength2(spinvelocity);
2757 if (isnan(test))
2758 {
2760 VectorClear(spinvelocity);
2761 }
2762 }
2763 }
2764
2765 // check if the qc edited any position data
2766 if (!VectorCompare(origin, ed->priv.server->ode_origin)
2767 || !VectorCompare(velocity, ed->priv.server->ode_velocity)
2768 || !VectorCompare(angles, ed->priv.server->ode_angles)
2769 || !VectorCompare(avelocity, ed->priv.server->ode_avelocity)
2770 || gravity != ed->priv.server->ode_gravity)
2771 modified = true;
2772
2773 // store the qc values into the physics engine
2774 body = (dBodyID)ed->priv.server->ode_body;
2775 if (modified && ed->priv.server->ode_geom)
2776 {
2777 dVector3 r[3];
2778 matrix4x4_t entitymatrix;
2779 matrix4x4_t bodymatrix;
2780
2781#if 0
2782 Con_Printf("entity %i got changed by QC\n", (int) (ed - prog->edicts));
2783 if(!VectorCompare(origin, ed->priv.server->ode_origin))
2784 Con_Printf(" origin: %f %f %f -> %f %f %f\n", ed->priv.server->ode_origin[0], ed->priv.server->ode_origin[1], ed->priv.server->ode_origin[2], origin[0], origin[1], origin[2]);
2785 if(!VectorCompare(velocity, ed->priv.server->ode_velocity))
2786 Con_Printf(" velocity: %f %f %f -> %f %f %f\n", ed->priv.server->ode_velocity[0], ed->priv.server->ode_velocity[1], ed->priv.server->ode_velocity[2], velocity[0], velocity[1], velocity[2]);
2787 if(!VectorCompare(angles, ed->priv.server->ode_angles))
2788 Con_Printf(" angles: %f %f %f -> %f %f %f\n", ed->priv.server->ode_angles[0], ed->priv.server->ode_angles[1], ed->priv.server->ode_angles[2], angles[0], angles[1], angles[2]);
2789 if(!VectorCompare(avelocity, ed->priv.server->ode_avelocity))
2790 Con_Printf(" avelocity: %f %f %f -> %f %f %f\n", ed->priv.server->ode_avelocity[0], ed->priv.server->ode_avelocity[1], ed->priv.server->ode_avelocity[2], avelocity[0], avelocity[1], avelocity[2]);
2791 if(gravity != ed->priv.server->ode_gravity)
2792 Con_Printf(" gravity: %i -> %i\n", ed->priv.server->ode_gravity, gravity);
2793#endif
2794 // values for BodyFromEntity to check if the qc modified anything later
2795 VectorCopy(origin, ed->priv.server->ode_origin);
2796 VectorCopy(velocity, ed->priv.server->ode_velocity);
2797 VectorCopy(angles, ed->priv.server->ode_angles);
2798 VectorCopy(avelocity, ed->priv.server->ode_avelocity);
2799 ed->priv.server->ode_gravity = gravity;
2800
2801 Matrix4x4_FromVectors(&entitymatrix, forward, left, up, origin);
2802 Matrix4x4_Concat(&bodymatrix, &entitymatrix, &ed->priv.server->ode_offsetmatrix);
2803 Matrix4x4_ToVectors(&bodymatrix, forward, left, up, origin);
2804 r[0][0] = forward[0];
2805 r[1][0] = forward[1];
2806 r[2][0] = forward[2];
2807 r[0][1] = left[0];
2808 r[1][1] = left[1];
2809 r[2][1] = left[2];
2810 r[0][2] = up[0];
2811 r[1][2] = up[1];
2812 r[2][2] = up[2];
2813 if (body)
2814 {
2816 {
2817 dGeomSetBody((dGeomID)ed->priv.server->ode_geom, body);
2818 dBodySetPosition(body, origin[0], origin[1], origin[2]);
2819 dBodySetRotation(body, r[0]);
2820 dBodySetLinearVel(body, velocity[0], velocity[1], velocity[2]);
2821 dBodySetAngularVel(body, spinvelocity[0], spinvelocity[1], spinvelocity[2]);
2822 dBodySetGravityMode(body, gravity);
2823 }
2824 else
2825 {
2826 dGeomSetBody((dGeomID)ed->priv.server->ode_geom, body);
2827 dBodySetPosition(body, origin[0], origin[1], origin[2]);
2828 dBodySetRotation(body, r[0]);
2829 dBodySetLinearVel(body, velocity[0], velocity[1], velocity[2]);
2830 dBodySetAngularVel(body, spinvelocity[0], spinvelocity[1], spinvelocity[2]);
2831 dBodySetGravityMode(body, gravity);
2832 dGeomSetBody((dGeomID)ed->priv.server->ode_geom, 0);
2833 }
2834 }
2835 else
2836 {
2837 // no body... then let's adjust the parameters of the geom directly
2838 dGeomSetBody((dGeomID)ed->priv.server->ode_geom, 0); // just in case we previously HAD a body (which should never happen)
2839 dGeomSetPosition((dGeomID)ed->priv.server->ode_geom, origin[0], origin[1], origin[2]);
2840 dGeomSetRotation((dGeomID)ed->priv.server->ode_geom, r[0]);
2841 }
2842 }
2843
2844 if (body)
2845 {
2846
2847 // limit movement speed to prevent missed collisions at high speed
2848 ovelocity = dBodyGetLinearVel(body);
2849 ospinvelocity = dBodyGetAngularVel(body);
2850 movelimit = ed->priv.server->ode_movelimit * world->physics.ode_movelimit;
2851 test = VectorLength2(ovelocity);
2852 if (test > movelimit*movelimit)
2853 {
2854 // scale down linear velocity to the movelimit
2855 // scale down angular velocity the same amount for consistency
2856 f = movelimit / sqrt(test);
2857 VectorScale(ovelocity, f, velocity);
2858 VectorScale(ospinvelocity, f, spinvelocity);
2859 dBodySetLinearVel(body, velocity[0], velocity[1], velocity[2]);
2860 dBodySetAngularVel(body, spinvelocity[0], spinvelocity[1], spinvelocity[2]);
2861 }
2862
2863 // make sure the angular velocity is not exploding
2864 spinlimit = physics_ode_spinlimit.value;
2865 test = VectorLength2(ospinvelocity);
2866 if (test > spinlimit)
2867 {
2868 dBodySetAngularVel(body, 0, 0, 0);
2869 }
2870
2871 // apply functions and clear stack
2872 for(func = ed->priv.server->ode_func; func; func = nextf)
2873 {
2874 nextf = func->next;
2875 World_Physics_ApplyCmd(ed, func);
2876 Mem_Free(func);
2877 }
2878 ed->priv.server->ode_func = NULL;
2879 }
2880}
2881
2882#define MAX_CONTACTS 32
2883static void nearCallback (void *data, dGeomID o1, dGeomID o2)
2884{
2885 world_t *world = (world_t *)data;
2886 prvm_prog_t *prog = world->prog;
2887 dContact contact[MAX_CONTACTS]; // max contacts per collision pair
2888 int b1enabled = 0, b2enabled = 0;
2889 dBodyID b1, b2;
2890 dJointID c;
2891 int i;
2892 int numcontacts;
2893 float bouncefactor1 = 0.0f;
2894 float bouncestop1 = 60.0f / 800.0f;
2895 float bouncefactor2 = 0.0f;
2896 float bouncestop2 = 60.0f / 800.0f;
2897 float erp;
2898 dVector3 grav;
2899 prvm_edict_t *ed1, *ed2;
2900
2901 if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
2902 {
2903 // colliding a space with something
2904 dSpaceCollide2(o1, o2, data, &nearCallback);
2905 // Note we do not want to test intersections within a space,
2906 // only between spaces.
2907 //if (dGeomIsSpace(o1)) dSpaceCollide(o1, data, &nearCallback);
2908 //if (dGeomIsSpace(o2)) dSpaceCollide(o2, data, &nearCallback);
2909 return;
2910 }
2911
2912 b1 = dGeomGetBody(o1);
2913 if (b1)
2914 b1enabled = dBodyIsEnabled(b1);
2915 b2 = dGeomGetBody(o2);
2916 if (b2)
2917 b2enabled = dBodyIsEnabled(b2);
2918
2919 // at least one object has to be using MOVETYPE_PHYSICS and should be enabled or we just don't care
2920 if (!b1enabled && !b2enabled)
2921 return;
2922
2923 // exit without doing anything if the two bodies are connected by a joint
2924 if (b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact))
2925 return;
2926
2927 ed1 = (prvm_edict_t *) dGeomGetData(o1);
2928 if(ed1 && ed1->free)
2929 ed1 = NULL;
2930 if(ed1)
2931 {
2932 bouncefactor1 = PRVM_gameedictfloat(ed1, bouncefactor);
2933 bouncestop1 = PRVM_gameedictfloat(ed1, bouncestop);
2934 if (!bouncestop1)
2935 bouncestop1 = 60.0f / 800.0f;
2936 }
2937
2938 ed2 = (prvm_edict_t *) dGeomGetData(o2);
2939 if(ed2 && ed2->free)
2940 ed2 = NULL;
2941 if(ed2)
2942 {
2943 bouncefactor2 = PRVM_gameedictfloat(ed2, bouncefactor);
2944 bouncestop2 = PRVM_gameedictfloat(ed2, bouncestop);
2945 if (!bouncestop2)
2946 bouncestop2 = 60.0f / 800.0f;
2947 }
2948
2949 if(prog == SVVM_prog)
2950 {
2951 if(ed1 && PRVM_serveredictfunction(ed1, touch))
2952 {
2953 SV_LinkEdict_TouchAreaGrid_Call(ed1, ed2 ? ed2 : prog->edicts);
2954 }
2955 if(ed2 && PRVM_serveredictfunction(ed2, touch))
2956 {
2957 SV_LinkEdict_TouchAreaGrid_Call(ed2, ed1 ? ed1 : prog->edicts);
2958 }
2959 }
2960
2961 // merge bounce factors and bounce stop
2962 if(bouncefactor2 > 0)
2963 {
2964 if(bouncefactor1 > 0)
2965 {
2966 // TODO possibly better logic to merge bounce factor data?
2967 if(bouncestop2 < bouncestop1)
2968 bouncestop1 = bouncestop2;
2969 if(bouncefactor2 > bouncefactor1)
2970 bouncefactor1 = bouncefactor2;
2971 }
2972 else
2973 {
2974 bouncestop1 = bouncestop2;
2975 bouncefactor1 = bouncefactor2;
2976 }
2977 }
2978 dWorldGetGravity((dWorldID)world->physics.ode_world, grav);
2979 bouncestop1 *= fabs(grav[2]);
2980
2981 // get erp
2982 // select object that moves faster ang get it's erp
2984
2985 // get max contact points for this collision
2986 numcontacts = (int)PRVM_gameedictfloat(ed1, maxcontacts);
2987 if (!numcontacts)
2988 numcontacts = physics_ode_contact_maxpoints.integer;
2990 numcontacts = max(numcontacts, (int)PRVM_gameedictfloat(ed2, maxcontacts));
2991 else
2992 numcontacts = max(numcontacts, physics_ode_contact_maxpoints.integer);
2993
2994 // generate contact points between the two non-space geoms
2995 numcontacts = dCollide(o1, o2, min(MAX_CONTACTS, numcontacts), &(contact[0].geom), sizeof(contact[0]));
2996 // add these contact points to the simulation
2997 for (i = 0;i < numcontacts;i++)
2998 {
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);
3000 contact[i].surface.mu = physics_ode_contact_mu.value * ed1->priv.server->ode_friction * ed2->priv.server->ode_friction;
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);
3007 }
3008}
3009
3010void World_Physics_Frame(world_t *world, double frametime, double gravity)
3011{
3012 prvm_prog_t *prog = world->prog;
3013 double tdelta, tdelta2, tdelta3, simulationtime, collisiontime;
3014
3015 tdelta = Sys_DirtyTime();
3016 if (world->physics.ode && physics_ode.integer)
3017 {
3018 int i;
3019 prvm_edict_t *ed;
3020
3021 if (!physics_ode_constantstep.value)
3022 {
3023 world->physics.ode_iterations = bound(1, physics_ode_iterationsperframe.integer, 1000);
3024 world->physics.ode_step = frametime / world->physics.ode_iterations;
3025 }
3026 else
3027 {
3028 world->physics.ode_time += frametime;
3029 // step size
3030 if (physics_ode_constantstep.value > 0 && physics_ode_constantstep.value < 1)
3031 world->physics.ode_step = physics_ode_constantstep.value;
3032 else
3033 world->physics.ode_step = sys_ticrate.value;
3034 if (world->physics.ode_time > 0.2f)
3035 world->physics.ode_time = world->physics.ode_step;
3036 // set number of iterations to process
3037 world->physics.ode_iterations = 0;
3038 while(world->physics.ode_time >= world->physics.ode_step)
3039 {
3040 world->physics.ode_iterations++;
3041 world->physics.ode_time -= world->physics.ode_step;
3042 }
3043 }
3044 world->physics.ode_movelimit = physics_ode_movelimit.value / world->physics.ode_step;
3045 World_Physics_UpdateODE(world);
3046
3047 // copy physics properties from entities to physics engine
3048 if (prog)
3049 {
3050 for (i = 0, ed = prog->edicts + i;i < prog->num_edicts;i++, ed++)
3051 if (!prog->edicts[i].free)
3052 World_Physics_Frame_BodyFromEntity(world, ed);
3053 // oh, and it must be called after all bodies were created
3054 for (i = 0, ed = prog->edicts + i;i < prog->num_edicts;i++, ed++)
3055 if (!prog->edicts[i].free)
3056 World_Physics_Frame_JointFromEntity(world, ed);
3057 }
3058
3059 tdelta2 = Sys_DirtyTime();
3060 collisiontime = 0;
3061 for (i = 0;i < world->physics.ode_iterations;i++)
3062 {
3063 // set the gravity
3064 dWorldSetGravity((dWorldID)world->physics.ode_world, 0, 0, -gravity * physics_ode_world_gravitymod.value);
3065 // set the tolerance for closeness of objects
3066 dWorldSetContactSurfaceLayer((dWorldID)world->physics.ode_world, max(0, physics_ode_contactsurfacelayer.value));
3067 // run collisions for the current world state, creating JointGroup
3068 tdelta3 = Sys_DirtyTime();
3069 dSpaceCollide((dSpaceID)world->physics.ode_space, (void *)world, nearCallback);
3070 collisiontime += (Sys_DirtyTime() - tdelta3)*10000;
3071 // apply forces
3072 if (prog)
3073 {
3074 int j;
3075 for (j = 0, ed = prog->edicts + j;j < prog->num_edicts;j++, ed++)
3076 if (!prog->edicts[j].free)
3077 World_Physics_Frame_ForceFromEntity(world, ed);
3078 }
3079 // run physics (move objects, calculate new velocities)
3080 // be sure not to pass 0 as step time because that causes an ODE error
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);
3084 // clear the JointGroup now that we're done with it
3085 dJointGroupEmpty((dJointGroupID)world->physics.ode_contactgroup);
3086 }
3087 simulationtime = (Sys_DirtyTime() - tdelta2)*10000;
3088
3089 // copy physics properties from physics engine to entities and do some stats
3090 if (prog)
3091 {
3092 for (i = 1, ed = prog->edicts + i;i < prog->num_edicts;i++, ed++)
3093 if (!prog->edicts[i].free)
3094 World_Physics_Frame_BodyToEntity(world, ed);
3095
3096 // print stats
3097 if (physics_ode_printstats.integer)
3098 {
3099 dBodyID body;
3100
3101 world->physics.ode_numobjects = 0;
3102 world->physics.ode_activeovjects = 0;
3103 for (i = 1, ed = prog->edicts + i;i < prog->num_edicts;i++, ed++)
3104 {
3105 if (prog->edicts[i].free)
3106 continue;
3107 body = (dBodyID)prog->edicts[i].priv.server->ode_body;
3108 if (!body)
3109 continue;
3110 world->physics.ode_numobjects++;
3111 if (dBodyIsEnabled(body))
3112 world->physics.ode_activeovjects++;
3113 }
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));
3115 }
3116 }
3117 }
3118}
3119#endif
model_t * CL_GetModelByIndex(int modelindex)
client_state_t cl
Definition cl_main.c:117
int CL_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent)
Definition clvm_cmds.c:3222
#define CF_SERVER
cvar/command that only the server can change/execute
Definition cmd.h:49
#define CF_CLIENT
cvar/command that only the client can change/execute
Definition cmd.h:48
void Collision_Init(void)
Definition collision.c:25
#define List_Entry(ptr, type, member)
Definition com_list.h:44
static void List_Add_Tail(llist_t *node, llist_t *head)
Definition com_list.h:249
static void List_Delete(llist_t *node)
Definition com_list.h:274
#define List_For_Each_Entry(pos, head, type, member)
Definition com_list.h:121
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
#define CON_WARN
Definition console.h:101
string classname
float movetype
float flags
float modelindex
vector avelocity
float frametime
vector mins
vector velocity
entity world
void() predraw
float time
vector maxs
entity enemy
vector angles
vector origin
string model
float solid
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
Definition cvar.c:599
const float GEOMTYPE_TRIMESH
const float GEOMTYPE_BOX
const float JOINTTYPE_SLIDER
const float JOINTTYPE_NONE
const float JOINTTYPE_FIXED
float scale
const float GEOMTYPE_CYLINDER_Y
const float GEOMTYPE_CAPSULE_Y
float erp
const float FORCETYPE_FORCE
const float GEOMTYPE_CYLINDER_Z
float friction
const float FORCETYPE_NONE
const float JOINTTYPE_UNIVERSAL
const float FORCETYPE_TORQUE
const float JOINTTYPE_POINT
const float GEOMTYPE_CAPSULE_X
float mass
const float GEOMTYPE_SPHERE
float forcetype
const float JOINTTYPE_HINGE
float jointtype
vector massofs
float bouncefactor
float maxcontacts
const float FORCETYPE_FORCEATPOS
const float GEOMTYPE_NONE
const float GEOMTYPE_CYLINDER_X
const float JOINTTYPE_HINGE2
float geomtype
const float GEOMTYPE_CAPSULE_Z
const float GEOMTYPE_CAPSULE
const float GEOMTYPE_CYLINDER
float bouncestop
static int(ZEXPORT *qz_inflate)(z_stream *strm
GLubyte GLubyte GLubyte z
Definition glquake.h:782
GLubyte GLubyte GLubyte GLubyte w
Definition glquake.h:782
GLenum mode
Definition glquake.h:718
GLsizei const GLfloat * value
Definition glquake.h:740
GLenum GLuint GLenum GLsizei length
Definition glquake.h:657
GLuint obj
Definition glquake.h:627
const GLdouble * v
Definition glquake.h:762
GLint GLenum GLint GLint y
Definition glquake.h:651
GLint GLenum GLsizei GLsizei GLsizei depth
Definition glquake.h:648
GLint GLenum GLint x
Definition glquake.h:651
GLsizeiptr const GLvoid * data
Definition glquake.h:639
GLuint index
Definition glquake.h:629
cvar_t developer_extra
Definition host.c:49
unsigned char * Data
Definition image_png.c:240
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.
Definition mathlib.c:650
void AngleVectorsFLU(const vec3_t angles, vec3_t forward, vec3_t left, vec3_t up)
LadyHavoc: proper matrix version of AngleVectors.
Definition mathlib.c:498
#define max(A, B)
Definition mathlib.h:38
#define VectorNegate(a, b)
Definition mathlib.h:95
#define min(A, B)
Definition mathlib.h:37
#define BoxesOverlap(a, b, c, d)
Definition mathlib.h:122
#define VectorNormalize(v)
Definition mathlib.h:104
#define DEG2RAD(a)
Definition mathlib.h:65
#define VectorClear(a)
Definition mathlib.h:97
#define bound(min, num, max)
Definition mathlib.h:34
#define RAD2DEG(a)
Definition mathlib.h:66
#define VectorLength2(a)
Definition mathlib.h:110
#define VectorSet(vec, x, y, z)
Definition mathlib.h:96
#define VectorSubtract(a, b, out)
Definition mathlib.h:99
#define VectorCompare(a, b)
Definition mathlib.h:113
#define TriangleNormal(a, b, c, n)
Definition mathlib.h:126
#define DotProduct(a, b)
Definition mathlib.h:98
#define VectorCopy(in, out)
Definition mathlib.h:101
#define VectorScale(in, scale, out)
Definition mathlib.h:111
#define VectorMAM(scale1, b1, scale2, b2, out)
Definition mathlib.h:116
void Matrix4x4_Concat(matrix4x4_t *out, const matrix4x4_t *in1, const matrix4x4_t *in2)
Definition matrixlib.c:83
void Matrix4x4_CreateTranslate(matrix4x4_t *out, double x, double y, double z)
Definition matrixlib.c:584
void Matrix4x4_CreateFromQuakeEntity(matrix4x4_t *out, double x, double y, double z, double pitch, double yaw, double roll, double scale)
Definition matrixlib.c:715
void Matrix4x4_Invert_Simple(matrix4x4_t *out, const matrix4x4_t *in1)
Definition matrixlib.c:422
void Matrix4x4_FromVectors(matrix4x4_t *out, const float vx[3], const float vy[3], const float vz[3], const float t[3])
Definition matrixlib.c:970
void Matrix4x4_ToVectors(const matrix4x4_t *in, float vx[3], float vy[3], float vz[3], float t[3])
Definition matrixlib.c:939
float sqrt(float f)
float fabs(float f)
float floor(float f)
void Mod_CreateCollisionMesh(model_t *mod)
#define ENTITYGRIDAREAS
Definition progs.h:27
entity aiment
Definition progsdefs.qc:187
vector movedir
Definition progsdefs.qc:203
#define PRVM_gameedictvector(ed, fieldname)
Definition progsvm.h:161
#define PRVM_gameedictfloat(ed, fieldname)
Definition progsvm.h:160
#define CLVM_prog
Definition progsvm.h:767
#define PRVM_gameedictedict(ed, fieldname)
Definition progsvm.h:163
#define PRVM_gameedictstring(ed, fieldname)
Definition progsvm.h:162
#define PRVM_EDICT_NUM(n)
Definition progsvm.h:867
const char * PRVM_GetString(prvm_prog_t *prog, int num)
#define PRVM_NUM_FOR_EDICT(e)
Definition progsvm.h:870
#define PRVM_serveredictfloat(ed, fieldname)
Definition progsvm.h:172
#define PRVM_serveredictfunction(ed, fieldname)
Definition progsvm.h:176
#define SVVM_prog
Definition progsvm.h:766
int i
#define NULL
Definition qtypes.h:12
float vec_t
Definition qtypes.h:68
vec_t vec3_t[3]
Definition qtypes.h:71
bool qbool
Definition qtypes.h:9
#define YAW
Definition qtypes.h:19
#define PITCH
Definition qtypes.h:16
#define ROLL
Definition qtypes.h:22
#define MOVETYPE_PHYSICS
indicates this object is physics controlled
Definition server.h:326
server_t sv
local server
Definition sv_main.c:223
#define SOLID_BBOX
touch on edge, block
Definition server.h:334
#define SOLID_SLIDEBOX
touch on edge, but not an onground
Definition server.h:335
#define SOLID_PHYSICS_BOX
physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity,...
Definition server.h:341
#define SOLID_PHYSICS_SPHERE
physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity,...
Definition server.h:342
#define SOLID_CORPSE
same as SOLID_BBOX, except it behaves as SOLID_NOT against SOLID_SLIDEBOX objects (players/monsters)
Definition server.h:338
void SV_LinkEdict_TouchAreaGrid_Call(prvm_edict_t *touch, prvm_edict_t *ent)
Definition sv_phys.c:705
model_t * SV_GetModelByIndex(int modelindex)
Definition sv_main.c:1607
#define MOVETYPE_NONE
never moves
Definition server.h:312
#define SOLID_PHYSICS_CAPSULE
physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity,...
Definition server.h:343
void SV_LinkEdict(prvm_edict_t *ent)
Definition sv_phys.c:804
cvar_t sys_ticrate
Definition sv_main.c:166
#define SOLID_NOT
no interaction with other objects
Definition server.h:332
cvar_t sv_areagrid_mingridsize
Definition sv_main.c:75
int SV_GetPitchSign(prvm_prog_t *prog, prvm_edict_t *ent)
Definition sv_phys.c:47
#define SOLID_PHYSICS_CYLINDER
physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity,...
Definition server.h:345
#define SOLID_TRIGGER
touch on edge, but not blocking
Definition server.h:333
#define SOLID_PHYSICS_TRIMESH
physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity,...
Definition server.h:344
#define SOLID_BSP
bsp clip, touch on edge, block
Definition server.h:336
void SV_LinkEdict_TouchAreaGrid(prvm_edict_t *ent)
Definition sv_phys.c:727
dp_FragColor r
dp_FragColor g
float f
dp_varying highp float Depth
vec3 normal
dp_FragColor b
vec2 px
world_t world
Definition client.h:1122
Definition cvar.h:66
float value
Definition cvar.h:74
int integer
Definition cvar.h:73
struct llist_s * prev
Definition com_list.h:32
struct llist_s * next
Definition com_list.h:33
qbool free
true if this edict is unused
Definition progsvm.h:93
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...
Definition progsvm.h:106
const char * name
name of the prog, e.g. "Server", "Client" or "Menu" (used for text output)
Definition progsvm.h:700
int num_edicts
copies of some vars that were former read from sv
Definition progsvm.h:671
prvm_edict_t * edicts
Definition progsvm.h:680
mempool_t * progs_mempool
all memory allocations related to this vm_prog (code, edicts, strings)
Definition progsvm.h:602
int max_edicts
number of edicts for which space has been (should be) allocated
Definition progsvm.h:673
world_t world
collision culling data
Definition server.h:106
static vec3_t forward
Definition sv_user.c:305
static vec3_t up
Definition sv_user.c:305
void Sys_Error(const char *error,...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN
Causes the entire program to exit ASAP.
Definition sys_shared.c:724
void * dllhandle_t
Definition sys.h:169
qbool Sys_LoadDependency(const char **dllnames, dllhandle_t *handle, const dllfunction_t *fcts)
Definition sys_shared.c:131
double Sys_DirtyTime(void)
Definition sys_shared.c:417
void Sys_FreeLibrary(dllhandle_t *handle)
Definition sys_shared.c:245
static void World_LinkEdict_AreaGrid(world_t *world, prvm_edict_t *ent)
Definition world.c:280
int World_EntitiesInBox(world_t *world, const vec3_t requestmins, const vec3_t requestmaxs, int maxlist, prvm_edict_t **list)
Definition world.c:188
void World_PrintAreaStats(world_t *world, const char *worldname)
Definition world.c:104
void World_Init(void)
Definition world.c:38
void World_InsertLinkBefore(link_t *l, link_t *before, int entitynumber)
Definition world.c:90
void World_ClearLink(link_t *l)
World_ClearLink is used for new headnodes.
Definition world.c:79
void World_SetSize(world_t *world, const char *filename, const vec3_t mins, const vec3_t maxs, prvm_prog_t *prog)
Definition world.c:118
void World_UnlinkAll(world_t *world)
unlinks all entities (used before reallocation of edicts)
Definition world.c:159
void World_UnlinkEdict(prvm_edict_t *ent)
Definition world.c:178
void World_RemoveLink(link_t *l)
Definition world.c:85
void World_LinkEdict(world_t *world, prvm_edict_t *ent, const vec3_t mins, const vec3_t maxs, qbool link_solid_not)
Definition world.c:320
void World_Start(world_t *world)
Definition world.c:59
void World_End(world_t *world)
Definition world.c:69
void World_Shutdown(void)
Definition world.c:49
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)
#define AREA_GRIDNODES
Definition world.h:35
void World_Physics_Frame(world_t *world, double frametime, double gravity)
#define AREA_GRID
Definition world.h:34
void World_Physics_RemoveFromEntity(world_t *world, struct prvm_edict_s *ed)
#define Mem_Free(mem)
Definition zone.h:96
#define Mem_Alloc(pool, size)
Definition zone.h:92