Try to add some ragdoll joints to the bullet plugin.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5518 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2019-08-19 16:03:23 +00:00
parent a6ec9fd9b5
commit 87fdee2282
1 changed files with 161 additions and 233 deletions

View File

@ -135,18 +135,21 @@ class QCFilterCallback : public btOverlapFilterCallback
//owners don't collide (unless one is world, obviouslyish) //owners don't collide (unless one is world, obviouslyish)
if (collides) if (collides)
{ {
btRigidBody *b1 = (btRigidBody*)proxy0->m_clientObject; auto b1 = (btRigidBody*)proxy0->m_clientObject;
btRigidBody *b2 = (btRigidBody*)proxy1->m_clientObject; auto b2 = (btRigidBody*)proxy1->m_clientObject;
//don't let two qc-controlled entities collide in Bullet, that's the job of quake. //don't let two qc-controlled entities collide in Bullet, that's the job of quake.
if (b1->isStaticOrKinematicObject() && b2->isStaticOrKinematicObject()) if (b1->isStaticOrKinematicObject() && b2->isStaticOrKinematicObject())
return false; return false;
wedict_t *e1 = (wedict_t*)b1->getUserPointer(); auto e1 = (wedict_t*)b1->getUserPointer();
wedict_t *e2 = (wedict_t*)b2->getUserPointer(); auto e2 = (wedict_t*)b2->getUserPointer();
if ((e1->v->solid == SOLID_TRIGGER && e2->v->solid != SOLID_BSP) || if (e1&&e2)
(e2->v->solid == SOLID_TRIGGER && e1->v->solid != SOLID_BSP)) {
return false; //triggers only collide with bsp objects. if ((e1->v->solid == SOLID_TRIGGER && e2->v->solid != SOLID_BSP) ||
if (e1->entnum && e2->entnum) (e2->v->solid == SOLID_TRIGGER && e1->v->solid != SOLID_BSP))
collides = e1->v->owner != e2->entnum && e2->v->owner != e1->entnum; return false; //triggers only collide with bsp objects.
if (e1->entnum && e2->entnum)
collides = e1->v->owner != e2->entnum && e2->v->owner != e1->entnum;
}
} }
return collides; return collides;
@ -155,8 +158,8 @@ class QCFilterCallback : public btOverlapFilterCallback
static void QDECL World_Bullet_End(world_t *world) static void QDECL World_Bullet_End(world_t *world)
{ {
struct bulletcontext_s *ctx = (struct bulletcontext_s*)world->rbe; auto ctx = reinterpret_cast<bulletcontext_t*>(world->rbe);
world->rbe = NULL; world->rbe = nullptr;
delete ctx->dworld; delete ctx->dworld;
delete ctx->solver; delete ctx->solver;
delete ctx->collisionconfig; delete ctx->collisionconfig;
@ -176,7 +179,7 @@ static void QDECL World_Bullet_RemoveJointFromEntity(world_t *world, wedict_t *e
static void QDECL World_Bullet_RemoveFromEntity(world_t *world, wedict_t *ed) static void QDECL World_Bullet_RemoveFromEntity(world_t *world, wedict_t *ed)
{ {
struct bulletcontext_s *ctx = (struct bulletcontext_s*)world->rbe; auto ctx = reinterpret_cast<bulletcontext_t*>(world->rbe);
btRigidBody *body; btRigidBody *body;
btCollisionShape *geom; btCollisionShape *geom;
if (!ed->rbe.physics) if (!ed->rbe.physics)
@ -202,115 +205,6 @@ static void QDECL World_Bullet_RemoveFromEntity(world_t *world, wedict_t *ed)
ed->rbe.massbuf = NULL; ed->rbe.massbuf = NULL;
} }
static void World_Bullet_Frame_BodyToEntity(world_t *world, wedict_t *ed)
{
return;
#if 0
model_t *model;
const float *avel;
const float *o;
const float *r; // for some reason dBodyGetRotation returns a [3][4] matrix
const float *vel;
btRigidBody *body = (btRigidBody*)ed->rbe.body.body;
int movetype;
float bodymatrix[16];
float entitymatrix[16];
vec3_t angles;
vec3_t avelocity;
vec3_t forward, left, up;
vec3_t origin;
vec3_t spinvelocity;
vec3_t velocity;
if (!body)
return;
movetype = (int)ed->v->movetype;
if (movetype != MOVETYPE_PHYSICS)
{
switch((int)ed->xv->jointtype)
{
// TODO feed back data from physics
case JOINTTYPE_POINT:
break;
case JOINTTYPE_HINGE:
break;
case JOINTTYPE_SLIDER:
break;
case JOINTTYPE_UNIVERSAL:
break;
case JOINTTYPE_HINGE2:
break;
case JOINTTYPE_FIXED:
break;
}
return;
}
// store the physics engine data into the entity
btTransform trans;
body->getMotionState()->getWorldTransform(trans);
// o = dBodyGetPosition(body);
// r = dBodyGetRotation(body);
// vel = dBodyGetLinearVel(body);
// avel = dBodyGetAngularVel(body);
// VectorCopy(o, origin);
// forward[0] = r[0];
// forward[1] = r[4];
// forward[2] = r[8];
// left[0] = r[1];
// left[1] = r[5];
// left[2] = r[9];
// up[0] = r[2];
// up[1] = r[6];
// up[2] = r[10];
vel = body->getLinearVelocity();
avel = body->getAngularVelocity();
VectorCopy(vel, velocity);
VectorCopy(avel, spinvelocity);
trans.getBasis().getOpenGLSubMatrix(bodymatrix);
foo Matrix4x4_RM_FromVectors(bodymatrix, forward, left, up, origin);
foo Matrix4_Multiply(ed->rbe.offsetimatrix, bodymatrix, entitymatrix);
foo Matrix3x4_RM_ToVectors(entitymatrix, forward, left, up, origin);
VectorAngles(forward, up, angles);
angles[0]*=-1;
avelocity[PITCH] = RAD2DEG(spinvelocity[PITCH]);
avelocity[YAW] = RAD2DEG(spinvelocity[ROLL]);
avelocity[ROLL] = RAD2DEG(spinvelocity[YAW]);
if (ed->v->modelindex)
{
model = world->Get_CModel(world, ed->v->modelindex);
if (!model || model->type == mod_alias)
{
angles[PITCH] *= -1;
avelocity[PITCH] *= -1;
}
}
VectorCopy(origin, ed->v->origin);
VectorCopy(velocity, ed->v->velocity);
//VectorCopy(forward, ed->xv->axis_forward);
//VectorCopy(left, ed->xv->axis_left);
//VectorCopy(up, ed->xv->axis_up);
//VectorCopy(spinvelocity, ed->xv->spinvelocity);
VectorCopy(angles, ed->v->angles);
VectorCopy(avelocity, ed->v->avelocity);
// values for BodyFromEntity to check if the qc modified anything later
VectorCopy(origin, ed->rbe.origin);
VectorCopy(velocity, ed->rbe.velocity);
VectorCopy(angles, ed->rbe.angles);
VectorCopy(avelocity, ed->rbe.avelocity);
// ed->rbe.gravity = (qboolean)dBodyGetGravityMode(body);
World_LinkEdict(world, ed, true);
#endif
}
static bool NegativeMeshPitch(world_t *world, wedict_t *ent) static bool NegativeMeshPitch(world_t *world, wedict_t *ent)
{ {
if (ent->v->modelindex) if (ent->v->modelindex)
@ -340,10 +234,10 @@ static btTransform transformFromQuake(world_t *world, wedict_t *ent)
static void World_Bullet_Frame_JointFromEntity(world_t *world, wedict_t *ed) static void World_Bullet_Frame_JointFromEntity(world_t *world, wedict_t *ed)
{ {
bulletcontext_t *rbe = (bulletcontext_t*)world->rbe; auto rbe = reinterpret_cast<bulletcontext_t*>(world->rbe);
btTypedConstraint *j = NULL; btTypedConstraint *j = nullptr;
btRigidBody *b1 = NULL; btRigidBody *b1 = nullptr;
btRigidBody *b2 = NULL; btRigidBody *b2 = nullptr;
int movetype = 0; int movetype = 0;
int jointtype = 0; int jointtype = 0;
int enemy = 0, aiment = 0; int enemy = 0, aiment = 0;
@ -352,8 +246,8 @@ static void World_Bullet_Frame_JointFromEntity(world_t *world, wedict_t *ed)
vec_t Stop; vec_t Stop;
// vec_t Vel; // vec_t Vel;
vec3_t forward; vec3_t forward;
movetype = (int)ed->v->movetype; movetype = ed->v->movetype;
jointtype = (int)ed->xv->jointtype; jointtype = ed->xv->jointtype;
enemy = ed->v->enemy; enemy = ed->v->enemy;
aiment = ed->v->aiment; aiment = ed->v->aiment;
btVector3 origin(ed->v->origin[0], ed->v->origin[1], ed->v->origin[2]); btVector3 origin(ed->v->origin[0], ed->v->origin[1], ed->v->origin[2]);
@ -407,7 +301,7 @@ static void World_Bullet_Frame_JointFromEntity(world_t *world, wedict_t *ed)
{ {
j = (btTypedConstraint*)ed->rbe.joint.joint; j = (btTypedConstraint*)ed->rbe.joint.joint;
rbe->dworld->removeConstraint(j); rbe->dworld->removeConstraint(j);
ed->rbe.joint.joint = NULL; ed->rbe.joint.joint = nullptr;
delete j; delete j;
} }
if (!jointtype) if (!jointtype)
@ -427,7 +321,7 @@ static void World_Bullet_Frame_JointFromEntity(world_t *world, wedict_t *ed)
VectorCopy(ed->v->angles, ed->rbe.joint_angles); VectorCopy(ed->v->angles, ed->rbe.joint_angles);
VectorCopy(movedir, ed->rbe.joint_movedir); VectorCopy(movedir, ed->rbe.joint_movedir);
rbefuncs->AngleVectors(ed->v->angles, forward, NULL, NULL); rbefuncs->AngleVectors(ed->v->angles, forward, nullptr, nullptr);
//Con_Printf("making new joint %i\n", (int) (ed - prog->edicts)); //Con_Printf("making new joint %i\n", (int) (ed - prog->edicts));
switch(jointtype) switch(jointtype)
@ -530,7 +424,7 @@ static void World_Bullet_Frame_JointFromEntity(world_t *world, wedict_t *ed)
break; break;
case 0: case 0:
default: default:
j = NULL; j = nullptr;
break; break;
} }
@ -546,9 +440,9 @@ static void MatToTransform(const float *mat, btTransform &tr)
{ {
tr.setBasis(btMatrix3x3( tr.setBasis(btMatrix3x3(
mat[0], mat[1], mat[2], mat[0], mat[1], mat[2],
mat[3], mat[4], mat[5], mat[4], mat[5], mat[6],
mat[6], mat[7], mat[8])); mat[8], mat[9], mat[10]));
tr.setOrigin(btVector3(mat[9], mat[10], mat[11])); tr.setOrigin(btVector3(mat[3], mat[7], mat[11]));
} }
static void MatFromTransform(float *mat, const btTransform &tr) static void MatFromTransform(float *mat, const btTransform &tr)
{ {
@ -560,31 +454,32 @@ static void MatFromTransform(float *mat, const btTransform &tr)
mat[0] = r0[0]; mat[0] = r0[0];
mat[1] = r0[1]; mat[1] = r0[1];
mat[2] = r0[2]; mat[2] = r0[2];
mat[3] = r1[0]; mat[3] =o[0];
mat[4] = r1[1]; mat[4] = r1[0];
mat[5] = r1[2]; mat[5] = r1[1];
mat[6] = r2[0]; mat[6] = r1[2];
mat[7] = r2[1]; mat[7] =o[1];
mat[8] = r2[2]; mat[8] = r2[0];
mat[9] = o[0]; mat[9] = r2[1];
mat[10] = o[1]; mat[10]= r2[2];
mat[11] = o[2]; mat[11]=o[2];
} }
static qboolean QDECL World_Bullet_RagMatrixToBody(rbebody_t *bodyptr, float *mat) static qboolean QDECL World_Bullet_RagMatrixToBody(rbebody_t *bodyptr, float *mat)
{ //mat is a 4*3 matrix { //mat is a 4*3 matrix
btTransform tr; btTransform tr;
btRigidBody *body = (btRigidBody*)bodyptr->body; auto body = reinterpret_cast<btRigidBody*>(bodyptr->body);
MatToTransform(mat, tr); MatToTransform(mat, tr);
body->setWorldTransform(tr); body->setWorldTransform(tr);
return qtrue; return qtrue;
} }
static qboolean QDECL World_Bullet_RagCreateBody(world_t *world, rbebody_t *bodyptr, rbebodyinfo_t *bodyinfo, float *mat, wedict_t *ent) static qboolean QDECL World_Bullet_RagCreateBody(world_t *world, rbebody_t *bodyptr, rbebodyinfo_t *bodyinfo, float *mat, wedict_t *ent)
{ {
btRigidBody *body = NULL; btRigidBody *body = nullptr;
btCollisionShape *geom = NULL; btCollisionShape *geom = nullptr;
float radius; float radius;
float threshold;
// float length; // float length;
bulletcontext_t *ctx = (bulletcontext_t*)world->rbe; auto ctx = reinterpret_cast<bulletcontext_t*>(world->rbe);
// int axisindex; // int axisindex;
ctx->hasextraobjs = true; ctx->hasextraobjs = true;
@ -630,10 +525,13 @@ static qboolean QDECL World_Bullet_RagCreateBody(world_t *world, rbebody_t *body
Con_DPrintf("World_Bullet_RagCreateBody: unsupported geomshape %i\n", bodyinfo->geomshape); Con_DPrintf("World_Bullet_RagCreateBody: unsupported geomshape %i\n", bodyinfo->geomshape);
case GEOMTYPE_BOX: case GEOMTYPE_BOX:
geom = new btBoxShape(btVector3(bodyinfo->dimensions[0], bodyinfo->dimensions[1], bodyinfo->dimensions[2]) * 0.5); geom = new btBoxShape(btVector3(bodyinfo->dimensions[0], bodyinfo->dimensions[1], bodyinfo->dimensions[2]) * 0.5);
radius = sqrt(DotProduct(bodyinfo->dimensions,bodyinfo->dimensions));
threshold = min(bodyinfo->dimensions[0], min(bodyinfo->dimensions[1], bodyinfo->dimensions[2]));
break; break;
case GEOMTYPE_SPHERE: case GEOMTYPE_SPHERE:
geom = new btSphereShape(bodyinfo->dimensions[0] * 0.5f); threshold = radius = bodyinfo->dimensions[0] * 0.5f;
geom = new btSphereShape(radius);
break; break;
case GEOMTYPE_CAPSULE: case GEOMTYPE_CAPSULE:
@ -642,6 +540,8 @@ static qboolean QDECL World_Bullet_RagCreateBody(world_t *world, rbebody_t *body
case GEOMTYPE_CAPSULE_Z: case GEOMTYPE_CAPSULE_Z:
radius = (bodyinfo->dimensions[0]+bodyinfo->dimensions[1]) * 0.5f; radius = (bodyinfo->dimensions[0]+bodyinfo->dimensions[1]) * 0.5f;
geom = new btCapsuleShapeZ(radius, bodyinfo->dimensions[2]); geom = new btCapsuleShapeZ(radius, bodyinfo->dimensions[2]);
threshold = min(radius, bodyinfo->dimensions[2]*0.5);
radius = max(radius, bodyinfo->dimensions[2]*0.5);
break; break;
case GEOMTYPE_CYLINDER: case GEOMTYPE_CYLINDER:
@ -650,6 +550,8 @@ static qboolean QDECL World_Bullet_RagCreateBody(world_t *world, rbebody_t *body
case GEOMTYPE_CYLINDER_Z: case GEOMTYPE_CYLINDER_Z:
radius = (bodyinfo->dimensions[0] + bodyinfo->dimensions[1]) * 0.5; radius = (bodyinfo->dimensions[0] + bodyinfo->dimensions[1]) * 0.5;
geom = new btCylinderShapeZ(btVector3(radius, radius, bodyinfo->dimensions[2])*0.5); geom = new btCylinderShapeZ(btVector3(radius, radius, bodyinfo->dimensions[2])*0.5);
threshold = min(radius, bodyinfo->dimensions[2]*0.5);
radius = max(radius, bodyinfo->dimensions[2]*0.5);
break; break;
} }
bodyptr->geom = geom; bodyptr->geom = geom;
@ -657,20 +559,21 @@ static qboolean QDECL World_Bullet_RagCreateBody(world_t *world, rbebody_t *body
//now create the body too //now create the body too
btVector3 fallInertia(0, 0, 0); btVector3 fallInertia(0, 0, 0);
((btCollisionShape*)geom)->calculateLocalInertia(bodyinfo->mass, fallInertia); geom->calculateLocalInertia(bodyinfo->mass, fallInertia);
btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(bodyinfo->mass, NULL, (btCollisionShape*)geom, fallInertia); btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(bodyinfo->mass, nullptr, geom, fallInertia);
MatToTransform(mat, fallRigidBodyCI.m_startWorldTransform); MatToTransform(mat, fallRigidBodyCI.m_startWorldTransform);
body = new btRigidBody(fallRigidBodyCI); body = new btRigidBody(fallRigidBodyCI);
body->setUserPointer(ent); body->setUserPointer(ent);
bodyptr->body = (void*)body; bodyptr->body = reinterpret_cast<void*>(body);
//motion threshhold should be speed/physicsframerate. //motion threshhold should be speed/physicsframerate.
//FIXME: recalculate... //FIXME: recalculate...
body->setCcdMotionThreshold((bodyinfo->dimensions[0]+bodyinfo->dimensions[1]+bodyinfo->dimensions[2])*(4/3)); body->setCcdMotionThreshold(threshold/64);
//radius should be the body's radius //radius should be the body's radius
body->setCcdSweptSphereRadius((bodyinfo->dimensions[0]+bodyinfo->dimensions[1]+bodyinfo->dimensions[2])*(0.5/3));
ctx->dworld->addRigidBody(body, ent->xv->dimension_solid, ent->xv->dimension_hit); body->setCcdSweptSphereRadius(radius);
ctx->dworld->addRigidBody(body, ent?ent->xv->dimension_solid:~0, ent?ent->xv->dimension_hit:~0);
return qtrue; return qtrue;
} }
@ -766,47 +669,77 @@ static void QDECL World_Bullet_RagMatrixFromJoint(rbejoint_t *joint, rbejointinf
static void QDECL World_Bullet_RagMatrixFromBody(world_t *world, rbebody_t *bodyptr, float *mat) static void QDECL World_Bullet_RagMatrixFromBody(world_t *world, rbebody_t *bodyptr, float *mat)
{ {
// bulletcontext_t *ctx = (bulletcontext_t*)world->rbe; //auto ctx = reinterpret_cast<bulletcontext_t*>(world->rbe);
btRigidBody *body = (btRigidBody*)bodyptr->body; auto body = reinterpret_cast<btRigidBody*>(bodyptr->body);
MatFromTransform(mat, body->getCenterOfMassTransform()); MatFromTransform(mat, body->getCenterOfMassTransform());
} }
static void QDECL World_Bullet_RagEnableJoint(rbejoint_t *joint, qboolean enabled) static void QDECL World_Bullet_RagEnableJoint(rbejoint_t *joint, qboolean enabled)
{ {
/* auto j = reinterpret_cast<btTypedConstraint*>(joint->joint);
if (enabled) j->setEnabled(enabled);
dJointEnable(joint->ode_joint);
else
dJointDisable(joint->ode_joint);
*/
} }
static void QDECL World_Bullet_RagCreateJoint(world_t *world, rbejoint_t *joint, rbejointinfo_t *info, rbebody_t *body1, rbebody_t *body2, vec3_t aaa2[3]) static void QDECL World_Bullet_RagCreateJoint(world_t *world, rbejoint_t *joint, rbejointinfo_t *info, rbebody_t *body1, rbebody_t *body2, vec3_t aaa2[3])
{ {
/* auto ctx = reinterpret_cast<bulletcontext_t*>(world->rbe);
btTypedConstraint *j;
btVector3 org(aaa2[0][0], aaa2[0][1], aaa2[0][2]);
btVector3 axis1(aaa2[1][0], aaa2[1][1], aaa2[1][2]);
btVector3 axis2(aaa2[2][0], aaa2[2][1], aaa2[2][2]);
auto rb1 = reinterpret_cast<btRigidBody*>(body1->body);
auto rb2 = reinterpret_cast<btRigidBody*>(body2->body);
switch(info->type) switch(info->type)
{ {
case JOINTTYPE_POINT: case JOINTTYPE_POINT:
joint->ode_joint = dJointCreateBall(world->rbe.world, 0); {
break; auto point = new btPoint2PointConstraint(*rb1, *rb2, rb1->getWorldTransform().getOrigin()-org, rb2->getWorldTransform().getOrigin()-org);
case JOINTTYPE_HINGE: // point->setParam(BT_P2P_FLAGS_ERP, info->ERP);
joint->ode_joint = dJointCreateHinge(world->rbe.world, 0); // point->setParam(BT_P2P_FLAGS_CFM, info->CFM);
break; j = point;
case JOINTTYPE_SLIDER: }
joint->ode_joint = dJointCreateSlider(world->rbe.world, 0); break;
break; case JOINTTYPE_HINGE:
case JOINTTYPE_UNIVERSAL: {
joint->ode_joint = dJointCreateUniversal(world->rbe.world, 0); auto hinge = new btHingeConstraint(*rb1, *rb2, org, org, axis1, axis2);
break; hinge->setLimit(info->LoStop, info->HiStop /*other stuff!*/);
case JOINTTYPE_HINGE2: // hinge->setParam(BT_HINGE_FLAGS_CFM_NORM, info->CFM);
joint->ode_joint = dJointCreateHinge2(world->rbe.world, 0); // hinge->setParam(BT_HINGE_FLAGS_CFM_STOP, info->CFM2);
break; // hinge->setParam(BT_HINGE_FLAGS_ERP_NORM, info->ERP);
case JOINTTYPE_FIXED: // hinge->setParam(BT_HINGE_FLAGS_ERP_STOP, info->ERP2);
joint->ode_joint = dJointCreateFixed(world->rbe.world, 0); j = hinge;
break; }
default: break;
joint->ode_joint = NULL; // case JOINTTYPE_SLIDER:
break; // j = btSliderConstraint(rb1, rb2, tr1, tr2, false);
// break;
case JOINTTYPE_UNIVERSAL:
{
auto uni = new btUniversalConstraint(*rb1, *rb2, org, axis1, axis2);
// uni->setParam(BT_6DOF_FLAGS_CFM_NORM, info->CFM);
// uni->setParam(BT_6DOF_FLAGS_CFM_STOP, info->CFM2);
// uni->setParam(BT_6DOF_FLAGS_ERP_STOP, info->ERP);
uni->setUpperLimit(info->HiStop, info->HiStop2);
uni->setLowerLimit(info->LoStop, info->LoStop2);
j = uni;
}
break;
case JOINTTYPE_HINGE2:
{
auto hinge2 = new btHinge2Constraint(*rb1, *rb2, org, axis1, axis2);
hinge2->setUpperLimit(info->HiStop);
hinge2->setLowerLimit(info->LoStop);
j = hinge2;
}
break;
// case JOINTTYPE_FIXED:
// j = btFixedConstraint(rb1, rb2, tr1, tr2);
// break;
default:
Con_Printf("Bullet: joint type %i not supported\n", info->type);
j = nullptr;
break;
} }
if (joint->ode_joint) /* if (joint->ode_joint)
{ {
//Con_Printf("made new joint %i\n", (int) (ed - prog->edicts)); //Con_Printf("made new joint %i\n", (int) (ed - prog->edicts));
// dJointSetData(joint->ode_joint, NULL); // dJointSetData(joint->ode_joint, NULL);
@ -876,16 +809,19 @@ static void QDECL World_Bullet_RagCreateJoint(world_t *world, rbejoint_t *joint,
} }
} }
*/ */
if (j)
ctx->dworld->addConstraint(j, true);
joint->joint = reinterpret_cast<void*>(j);
} }
static void QDECL World_Bullet_RagDestroyBody(world_t *world, rbebody_t *bodyptr) static void QDECL World_Bullet_RagDestroyBody(world_t *world, rbebody_t *bodyptr)
{ {
bulletcontext_t *ctx = (bulletcontext_t*)world->rbe; auto ctx = reinterpret_cast<bulletcontext_t*>(world->rbe);
btRigidBody *body = (btRigidBody*)bodyptr->body; auto body = reinterpret_cast<btRigidBody*>(bodyptr->body);
btCollisionShape *geom = (btCollisionShape*)bodyptr->geom; auto geom = reinterpret_cast<btCollisionShape*>(bodyptr->geom);
bodyptr->body = NULL; bodyptr->body = nullptr;
bodyptr->geom = NULL; bodyptr->geom = nullptr;
if (body) if (body)
{ {
@ -898,11 +834,14 @@ static void QDECL World_Bullet_RagDestroyBody(world_t *world, rbebody_t *bodyptr
static void QDECL World_Bullet_RagDestroyJoint(world_t *world, rbejoint_t *joint) static void QDECL World_Bullet_RagDestroyJoint(world_t *world, rbejoint_t *joint)
{ {
/* auto ctx = reinterpret_cast<bulletcontext_t*>(world->rbe);
if (joint->ode_joint) auto j = reinterpret_cast<btTypedConstraint*>(joint->joint);
dJointDestroy(joint->ode_joint); if (j)
joint->ode_joint = NULL; {
*/ ctx->dworld->removeConstraint(j);
delete j;
}
joint->joint = nullptr;
} }
//bullet gives us a handy way to get/set motion states. we can cheesily update entity fields this way. //bullet gives us a handy way to get/set motion states. we can cheesily update entity fields this way.
@ -980,8 +919,8 @@ public:
static void World_Bullet_Frame_BodyFromEntity(world_t *world, wedict_t *ed) static void World_Bullet_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
{ {
bulletcontext_t *ctx = (bulletcontext_t*)world->rbe; auto ctx = reinterpret_cast<bulletcontext_t*>(world->rbe);
btRigidBody *body = NULL; btRigidBody *body = nullptr;
// btScalar mass; // btScalar mass;
float test; float test;
// void *dataID; // void *dataID;
@ -1013,16 +952,16 @@ static void World_Bullet_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
// vec_t spinlimit; // vec_t spinlimit;
qboolean gravity; qboolean gravity;
geomtype = (int)ed->xv->geomtype; geomtype = ed->xv->geomtype;
solid = (int)ed->v->solid; solid = ed->v->solid;
movetype = (int)ed->v->movetype; movetype = ed->v->movetype;
scale = ed->xv->scale?ed->xv->scale:1; scale = ed->xv->scale?ed->xv->scale:1;
modelindex = 0; modelindex = 0;
model = NULL; model = nullptr;
if (!geomtype) if (!geomtype)
{ {
switch((int)ed->v->solid) switch(solid)
{ {
case SOLID_NOT: geomtype = GEOMTYPE_NONE; break; case SOLID_NOT: geomtype = GEOMTYPE_NONE; break;
case SOLID_TRIGGER: geomtype = GEOMTYPE_NONE; break; case SOLID_TRIGGER: geomtype = GEOMTYPE_NONE; break;
@ -1039,11 +978,11 @@ static void World_Bullet_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
switch(geomtype) switch(geomtype)
{ {
case GEOMTYPE_TRIMESH: case GEOMTYPE_TRIMESH:
modelindex = (int)ed->v->modelindex; modelindex = ed->v->modelindex;
model = world->Get_CModel(world, modelindex); model = world->Get_CModel(world, modelindex);
if (!model || model->loadstate != MLS_LOADED) if (!model || model->loadstate != MLS_LOADED)
{ {
model = NULL; model = nullptr;
modelindex = 0; modelindex = 0;
} }
if (model) if (model)
@ -1122,7 +1061,7 @@ static void World_Bullet_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
{ {
case GEOMTYPE_TRIMESH: case GEOMTYPE_TRIMESH:
// foo Matrix4x4_Identity(ed->rbe.offsetmatrix); // foo Matrix4x4_Identity(ed->rbe.offsetmatrix);
geom = NULL; geom = nullptr;
if (!model) if (!model)
{ {
Con_Printf("entity %i (classname %s) has no model\n", NUM_FOR_EDICT(world->progs, (edict_t*)ed), PR_GetString(world->progs, ed->v->classname)); Con_Printf("entity %i (classname %s) has no model\n", NUM_FOR_EDICT(world->progs, (edict_t*)ed), PR_GetString(world->progs, ed->v->classname));
@ -1283,7 +1222,7 @@ static void World_Bullet_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
} }
else else
{ {
if (ed->rbe.body.body == NULL) if (ed->rbe.body.body == nullptr)
{ {
btRigidBody::btRigidBodyConstructionInfo rbci(ed->rbe.mass, new QCMotionState(ed,world), (btCollisionShape*)ed->rbe.body.geom, btVector3(0, 0, 0)); btRigidBody::btRigidBodyConstructionInfo rbci(ed->rbe.mass, new QCMotionState(ed,world), (btCollisionShape*)ed->rbe.body.geom, btVector3(0, 0, 0));
body = new btRigidBody(rbci); body = new btRigidBody(rbci);
@ -1432,7 +1371,7 @@ static void World_Bullet_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
// r[1][2] = up[1]; // r[1][2] = up[1];
// r[2][2] = up[2]; // r[2][2] = up[2];
QCMotionState *ms = (QCMotionState*)body->getMotionState(); auto ms = (QCMotionState*)body->getMotionState();
ms->ReloadMotionState(); ms->ReloadMotionState();
body->setMotionState(ms); body->setMotionState(ms);
body->setLinearVelocity(btVector3(velocity[0], velocity[1], velocity[2])); body->setLinearVelocity(btVector3(velocity[0], velocity[1], velocity[2]));
@ -1616,7 +1555,7 @@ static void VARGS nearCallback (void *data, dGeomID o1, dGeomID o2)
static void QDECL World_Bullet_Frame(world_t *world, double frametime, double gravity) static void QDECL World_Bullet_Frame(world_t *world, double frametime, double gravity)
{ {
struct bulletcontext_s *ctx = (struct bulletcontext_s*)world->rbe; auto ctx = reinterpret_cast<bulletcontext_t*>(world->rbe);
if (world->rbe_hasphysicsents || ctx->hasextraobjs) if (world->rbe_hasphysicsents || ctx->hasextraobjs)
{ {
int iters; int iters;
@ -1631,23 +1570,23 @@ static void QDECL World_Bullet_Frame(world_t *world, double frametime, double gr
// copy physics properties from entities to physics engine // copy physics properties from entities to physics engine
for (i = 0;i < world->num_edicts;i++) for (i = 0;i < world->num_edicts;i++)
{ {
ed = (wedict_t*)EDICT_NUM_PB(world->progs, i); ed = WEDICT_NUM_PB(world->progs, i);
if (!ED_ISFREE(ed)) if (!ED_ISFREE(ed))
World_Bullet_Frame_BodyFromEntity(world, ed); World_Bullet_Frame_BodyFromEntity(world, ed);
} }
// oh, and it must be called after all bodies were created // oh, and it must be called after all bodies were created
for (i = 0;i < world->num_edicts;i++) for (i = 0;i < world->num_edicts;i++)
{ {
ed = (wedict_t*)EDICT_NUM_PB(world->progs, i); ed = WEDICT_NUM_PB(world->progs, i);
if (!ED_ISFREE(ed)) if (!ED_ISFREE(ed))
World_Bullet_Frame_JointFromEntity(world, ed); World_Bullet_Frame_JointFromEntity(world, ed);
} }
while(ctx->cmdqueuehead) while(ctx->cmdqueuehead)
{ {
rbecommandqueue_t *cmd = ctx->cmdqueuehead; auto cmd = ctx->cmdqueuehead;
ctx->cmdqueuehead = cmd->next; ctx->cmdqueuehead = cmd->next;
if (!cmd->next) if (!cmd->next)
ctx->cmdqueuetail = NULL; ctx->cmdqueuetail = nullptr;
World_Bullet_RunCmd(world, cmd); World_Bullet_RunCmd(world, cmd);
Z_Free(cmd); Z_Free(cmd);
} }
@ -1676,23 +1615,12 @@ static void QDECL World_Bullet_Frame(world_t *world, double frametime, double gr
// clear the JointGroup now that we're done with it // clear the JointGroup now that we're done with it
// dJointGroupEmpty(world->rbe.contactgroup); // dJointGroupEmpty(world->rbe.contactgroup);
if (world->rbe_hasphysicsents)
{
// copy physics properties from physics engine to entities
for (i = 1;i < world->num_edicts;i++)
{
ed = (wedict_t*)EDICT_NUM_PB(world->progs, i);
if (!ED_ISFREE(ed))
World_Bullet_Frame_BodyToEntity(world, ed);
}
}
} }
} }
static void World_Bullet_RunCmd(world_t *world, rbecommandqueue_t *cmd) static void World_Bullet_RunCmd(world_t *world, rbecommandqueue_t *cmd)
{ {
btRigidBody *body = (btRigidBody*)(cmd->edict->rbe.body.body); auto body = (btRigidBody*)(cmd->edict->rbe.body.body);
switch(cmd->command) switch(cmd->command)
{ {
case RBECMD_ENABLE: case RBECMD_ENABLE:
@ -1725,15 +1653,15 @@ static void World_Bullet_RunCmd(world_t *world, rbecommandqueue_t *cmd)
static void QDECL World_Bullet_PushCommand(world_t *world, rbecommandqueue_t *val) static void QDECL World_Bullet_PushCommand(world_t *world, rbecommandqueue_t *val)
{ {
struct bulletcontext_s *ctx = (struct bulletcontext_s*)world->rbe; auto ctx = reinterpret_cast<bulletcontext_t*>(world->rbe);
rbecommandqueue_t *cmd = (rbecommandqueue_t*)BZ_Malloc(sizeof(*cmd)); auto cmd = (rbecommandqueue_t*)BZ_Malloc(sizeof(rbecommandqueue_t));
world->rbe_hasphysicsents = qtrue; //just in case. world->rbe_hasphysicsents = qtrue; //just in case.
memcpy(cmd, val, sizeof(*cmd)); memcpy(cmd, val, sizeof(*cmd));
cmd->next = NULL; cmd->next = nullptr;
//add on the end of the queue, so that order is preserved. //add on the end of the queue, so that order is preserved.
if (ctx->cmdqueuehead) if (ctx->cmdqueuehead)
{ {
rbecommandqueue_t *ot = ctx->cmdqueuetail; auto ot = ctx->cmdqueuetail;
ot->next = ctx->cmdqueuetail = cmd; ot->next = ctx->cmdqueuetail = cmd;
} }
else else
@ -1742,8 +1670,8 @@ static void QDECL World_Bullet_PushCommand(world_t *world, rbecommandqueue_t *va
static void QDECL World_Bullet_TraceEntity(world_t *world, wedict_t *ed, vec3_t start, vec3_t end, trace_t *trace) static void QDECL World_Bullet_TraceEntity(world_t *world, wedict_t *ed, vec3_t start, vec3_t end, trace_t *trace)
{ {
struct bulletcontext_s *ctx = (struct bulletcontext_s*)world->rbe; auto ctx = reinterpret_cast<bulletcontext_t*>(world->rbe);
btCollisionShape *shape = (btCollisionShape*)ed->rbe.body.geom; auto shape = (btCollisionShape*)ed->rbe.body.geom;
//btCollisionAlgorithm //btCollisionAlgorithm
class myConvexResultCallback : public btCollisionWorld::ConvexResultCallback class myConvexResultCallback : public btCollisionWorld::ConvexResultCallback
@ -1764,7 +1692,7 @@ static void QDECL World_Bullet_TraceEntity(world_t *world, wedict_t *ed, vec3_t
return 0; return 0;
} }
} result; } result;
result.m_impactent = NULL; result.m_impactent = nullptr;
result.m_closestHitFraction = trace->fraction; result.m_closestHitFraction = trace->fraction;
btTransform from(btMatrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1), btVector3(start[0], start[1], start[2])); btTransform from(btMatrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1), btVector3(start[0], start[1], start[2]));
@ -1785,14 +1713,14 @@ static void QDECL World_Bullet_TraceEntity(world_t *world, wedict_t *ed, vec3_t
static void QDECL World_Bullet_Start(world_t *world) static void QDECL World_Bullet_Start(world_t *world)
{ {
struct bulletcontext_s *ctx; bulletcontext_t *ctx;
if (world->rbe) if (world->rbe)
return; //no thanks, we already have one. somehow. return; //no thanks, we already have one. somehow.
if (!physics_bullet_enable->value) if (!physics_bullet_enable->value)
return; return;
ctx = (struct bulletcontext_s*)BZ_Malloc(sizeof(*ctx)); ctx = reinterpret_cast<bulletcontext_t*>(BZ_Malloc(sizeof(*ctx)));
memset(ctx, 0, sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx));
ctx->gworld = world; ctx->gworld = world;
ctx->funcs.End = World_Bullet_End; ctx->funcs.End = World_Bullet_End;
@ -1869,7 +1797,7 @@ static bool World_Bullet_DoInit(void)
{ {
if (!rbefuncs || !rbefuncs->RegisterPhysicsEngine) if (!rbefuncs || !rbefuncs->RegisterPhysicsEngine)
{ {
rbefuncs = NULL; rbefuncs = nullptr;
Con_Printf("Bullet plugin failed: Engine doesn't support physics engine plugins.\n"); Con_Printf("Bullet plugin failed: Engine doesn't support physics engine plugins.\n");
} }
else if (!rbefuncs->RegisterPhysicsEngine("Bullet", World_Bullet_Start)) else if (!rbefuncs->RegisterPhysicsEngine("Bullet", World_Bullet_Start))