
Here's my map loading code (sorry if it's a bit long

- Code: Select all
static qboolean LoadSurfaces ( byte* base, lump_t* surfaces, lump_t* vertices, lump_t* bmodels )
{
dsurface_t* surf = (dsurface_t*)(base + surfaces->fileofs);
drawVert_t* vert = (drawVert_t*)(base + vertices->fileofs);
dmodel_t* model = (dmodel_t*)(base + bmodels->fileofs);
NewtonCollision* collision = NULL;
int numSurfaces, numModels;
int surfaceCount = 0, vertexCount = 0;
int i, j;
int stride;
int limit;
numSurfaces = surfaces->filelen / sizeof (*surf);
numModels = bmodels->filelen / sizeof (*model);
--numModels;
if ( numModels > 0 )
{
++model;
}
world = NewtonCreate (NULL, NULL);
collision = NewtonCreateTreeCollision (world);
NewtonTreeCollisionBeginBuild (collision);
stride = sizeof (drawVert_t);
for ( i = 0; i < numSurfaces; ++i, ++surf )
{
// IsModelSurface checks if the surface belongs to a map model.
// I don't want these to be added to the collision tree.
if ( IsModelSurface (model, numModels, i) )
{
continue;
}
qboolean flip = qfalse;
switch ( surf->surfaceType )
{
case MST_TRIANGLE_SOUP:
case MST_PLANAR:
vec3_t v[3];
limit = surf->numVerts - 2;
for ( j = limit - 1; j >= 0; --j )
//for ( j = 0; j < limit; ++j )
{
if ( flip )
{
VectorCopy (vert[surf->firstVert + j + 2].xyz, v[0]);
VectorCopy (vert[surf->firstVert + j + 1].xyz, v[1]);
VectorCopy (vert[surf->firstVert + j + 0].xyz, v[2]);
}
else
{
VectorCopy (vert[surf->firstVert + j + 0].xyz, v[0]);
VectorCopy (vert[surf->firstVert + j + 1].xyz, v[1]);
VectorCopy (vert[surf->firstVert + j + 2].xyz, v[2]);
}
NewtonTreeCollisionAddFace (collision, 3, &v[0][0], sizeof (vec3_t), 1);
flip = (qboolean)!flip;
}
vertexCount += surf->numVerts;
++surfaceCount;
break;
case MST_PATCH:
// Haven't done this bit yet.
break;
case MST_FLARE:
// This is a billboard. Don't need to worry about collisions with these.
break;
default:
break;
}
}
NewtonTreeCollisionEndBuild (collision, 1);
G_Printf ("...%d surfaces loaded, %d vertices total\n", surfaceCount, vertexCount);
worldBody = NewtonCreateBody (world, collision);
NewtonReleaseCollision (world, collision);
worldMatrix = GetIdentityMatrix();
NewtonBodySetMatrix (worldBody, &worldMatrix[0][0]);
vec3_t max;
vec3_t min;
NewtonCollisionCalculateAABB (collision, &worldMatrix[0][0], &min[0], &max[0]);
NewtonSetWorldSize (world, &min[0], &max[0]);
return qtrue;
}
I then add the rigid bodies like so:
- Code: Select all
static void PhysicsEntityAdd ( gentity_t* ent )
{
NewtonBody* body = NULL;
NewtonCollision* collision = NULL;
vec3_t size;
VectorSubtract (ent->r.maxs, ent->r.mins, size);
collision = NewtonCreateBox (world, size[0], size[1], size[2], NULL);
body = NewtonCreateBody (world, collision);
NewtonReleaseCollision (world, collision);
NewtonBodySetUserData (body, (void*)ent);
NewtonBodySetDestructorCallback (body, PhysicsEntityDie);
NewtonBodySetContinuousCollisionMode (body, 1);
NewtonBodySetCentreOfMass (body, &ent->s.origin[0]);
NewtonBodySetForceAndTorqueCallback (body, PhysicsEntityThink);
NewtonBodySetTransformCallback (body, PhysicsEntitySetTransform);
vec3_t inertia;
inertia[0] = (ent->mass / 12.0f) * (size[1] * size[1] + size[2] * size[2]);
inertia[1] = (ent->mass / 12.0f) * (size[0] * size[0] + size[2] * size[2]);
inertia[2] = (ent->mass / 12.0f) * (size[1] * size[1] + size[0] * size[0]);
NewtonBodySetMassMatrix (body, ent->mass, inertia[0], inertia[1], inertia[2]);
dMatrix matrix;
matrix.m_posit.m_x = ent->s.origin[0];
matrix.m_posit.m_y = ent->s.origin[1];
matrix.m_posit.m_z = ent->s.origin[2];
NewtonBodySetMatrix (body, &matrix[0][0]);
}
PhysicsEntityThink is defined as:
- Code: Select all
static void PhysicsEntityThink ( const NewtonBody* body, dFloat timestep, int threadIndex)
{
vec3_t force, inertia;
float mass;
NewtonBodyGetMassMatrix (body, &mass, &inertia[0], &inertia[1], &inertia[2]);
force[0] = 0.0f;
force[1] = 0.0f;
force[2] = mass * -100.0f;
NewtonBodyAddForce (body, &force[0]);
}
And PhysicsEntitySetTransform as defined as:
- Code: Select all
static void PhysicsEntitySetTransform ( const NewtonBody* body, const dFloat* matrix, int threadIndex )
{
gentity_t *ent = NULL;
vec3_t newPosition;
vec3_t angles;
ent = (gentity_t*)NewtonBodyGetUserData (body);
VectorCopy (ent->r.currentOrigin, oldPosition);
newPosition[0] = matrix[12];
newPosition[1] = matrix[13];
newPosition[2] = matrix[14];
NewtonGetEulerAngle (&matrix[0], &angles[0]);
trap_UnlinkEntity (ent);
G_SetOrigin (ent, newPosition);
G_SetAngles (ent, angles);
trap_LinkEntity (ent);
}
Just to clear any confusion, Quake3 has the Y and Z axes swapped (Y is forward, Z is up). The problem is the rigid bodies don't behave as I would expect them to. In the simplest case, I have a box resting on the ground, but it slides around sideways. I'm thinking the problem is caused by the swapped Y and Z coordinates in Q3. I read in this topic that I need to set the initial matrices of something to fit Newton's coordinate system:
Paril wrote:Maybe the problem is the orientation when the object is create, it can look good but maybe the initial rotation is not the same in all side.
I talk about the direction and up and right, when you create the visual object you really need to have the same dir,up,right that newton using.
Do you have try to play with the offset matrix when you create your newton object ? maybe it can fix your problem.
But do I set the matrix of the collision or the rigid body or both? And my matrix maths isn't particular good, so could someone please tell me what is the initial matrix I need to use?
Thanks!