void CPlayerController::Update(const Vector &position, const Vector &velocity, float secondsToArrival, bool onground, IPhysicsObject *ground) { btVector3 bullTargetPosition, bullMaxVelocity; ConvertPosToBull(position, bullTargetPosition); ConvertPosToBull(velocity, bullMaxVelocity); // If the targets haven't changed, abort. if (bullMaxVelocity.distance2(m_maxVelocity) < FLT_EPSILON && bullTargetPosition.distance2(m_targetPosition) < FLT_EPSILON) { return; } m_targetPosition = bullTargetPosition; m_maxVelocity = bullMaxVelocity; m_enable = true; // FYI: The onground stuff includes any props we may be standing on as well as the world. // The ground is valid only if it's significantly heavier than our object ("Rideable physics" > our mass * 2) m_onground = onground; if (velocity.LengthSqr() <= 0.001f) { m_enable = false; ground = NULL; } else { MaxSpeed(velocity); } m_secondsToArrival = secondsToArrival; m_pGround = (CPhysicsObject *)ground; m_ticksSinceUpdate = 0; }
void ConvertMatrixToBull(const matrix3x4_t& hl, btTransform& transform) { Vector forward, left, up, pos; forward.x = hl[0][0]; forward.y = hl[1][0]; forward.z = hl[2][0]; left.x = hl[0][1]; left.y = hl[1][1]; left.z = hl[2][1]; up.x = hl[0][2]; up.y = hl[1][2]; up.z = hl[2][2]; pos.x = hl[0][3]; pos.y = hl[1][3]; pos.z = hl[2][3]; btVector3 bullForward, bullLeft, bullUp, origin; ConvertDirectionToBull(forward, bullForward); ConvertDirectionToBull(-left, bullLeft); ConvertDirectionToBull(up, bullUp); ConvertPosToBull(pos, origin); transform.setBasis(btMatrix3x3(bullForward.x(), bullUp.x(), bullLeft.x(), bullForward.y(), bullUp.y(), bullLeft.y(), bullForward.z(), bullUp.z(), bullLeft.z())); transform.setOrigin(origin); }
void CPhysicsEnvironment::SetGravity(const Vector &gravityVector) { btVector3 temp; ConvertPosToBull(gravityVector, temp); m_pBulletEnvironment->setGravity(temp); m_softBodyWorldInfo.m_gravity = temp; }
void CShadowController::MaxSpeed(float maxSpeed, float maxAngularSpeed) { btRigidBody* body = btRigidBody::upcast(m_pObject->GetObject()); btVector3 bullSpeed; ConvertPosToBull(maxSpeed, bullSpeed); btVector3 available = bullSpeed; m_currentSpeed = bullSpeed; float length = bullSpeed.length(); bullSpeed.normalize(); float dot = bullSpeed.dot(body->getLinearVelocity()); if (dot > 0) { bullSpeed *= dot * length; available -= bullSpeed; } m_shadow.maxSpeed = available.absolute(); btVector3 bullAngular; ConvertAngularImpulseToBull(maxAngularSpeed, bullAngular); btVector3 availableAngular; float lengthAngular = bullAngular.length(); bullAngular.normalize(); float dotAngular = bullAngular.dot(body->getAngularVelocity()); if (dotAngular > 0) { bullAngular *= dotAngular * lengthAngular; availableAngular -= bullAngular; } m_shadow.maxAngular = availableAngular.absolute(); }
CPhysicsObject* CreatePhysicsSphere(CPhysicsEnvironment *pEnvironment, float radius, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams, bool isStatic) { btSphereShape* shape = new btSphereShape(ConvertDistanceToBull(radius)); btVector3 vector; btMatrix3x3 matrix; ConvertPosToBull(position, vector); ConvertRotationToBull(angles, matrix); btTransform transform(matrix, vector); float mass = pParams->mass; if (isStatic) mass = 0; btMotionState* motionstate = new btMassCenterMotionState(transform); btRigidBody::btRigidBodyConstructionInfo info(mass,motionstate,shape); btRigidBody* body = new btRigidBody(info); if (mass > 0) pEnvironment->GetBulletEnvironment()->addRigidBody(body); else pEnvironment->GetBulletEnvironment()->addRigidBody(body, 2, ~2); float volume = pParams->volume; if (volume <= 0) { volume = 4.0f * radius * radius * radius * M_PI / 3.0f; } CPhysicsObject *pObject = new CPhysicsObject(); pObject->Init(pEnvironment, body, materialIndex, volume, 0, 0, NULL); pObject->SetGameData(pParams->pGameData); pObject->EnableCollisions(pParams->enableCollisions); return pObject; }
void CPhysicsObject::ApplyForceOffset(const Vector& forceVector, const Vector& worldPosition) { Vector local; WorldToLocal(&local, worldPosition); btVector3 force, offset; ConvertForceImpulseToBull(forceVector, force); ConvertPosToBull(local, offset); m_pObject->applyForce(force, offset); }
void CPhysicsObject::SetPosition(const Vector& worldPosition, const QAngle& angles, bool isTeleport) { btVector3 pos; btMatrix3x3 matrix; ConvertPosToBull(worldPosition, pos); ConvertRotationToBull(angles, matrix); btTransform transform(matrix, pos); ((btMassCenterMotionState*)m_pObject->getMotionState())->setGraphicTransform(transform); }
void CPlayerController::StepUp(float height) { btVector3 step; ConvertPosToBull(Vector(0, 0, height), step); btRigidBody *pObject = m_pObject->GetObject(); btTransform transform = pObject->getWorldTransform(); transform.setOrigin(transform.getOrigin() + step); pObject->getMotionState()->setWorldTransform(transform); }
void CPhysicsObject::GetVelocityAtPoint(const Vector &worldPosition, Vector *pVelocity) const { if (!pVelocity) return; Vector localPos; WorldToLocal(&localPos, worldPosition); btVector3 vec; ConvertPosToBull(localPos, vec); ConvertPosToHL(m_pObject->getVelocityInLocalPoint(vec), *pVelocity); }
void CPhysicsObject::AddVelocity(const Vector* velocity, const AngularImpulse* angularVelocity) { btVector3 btvelocity, btangular; if (velocity) { ConvertPosToBull(*velocity, btvelocity); m_pObject->setLinearVelocity(m_pObject->getLinearVelocity() + btvelocity); } if (angularVelocity) { ConvertAngularImpulseToBull(*angularVelocity, btangular); m_pObject->setAngularVelocity(m_pObject->getAngularVelocity() + btangular); } }
void CPhysicsObject::SetVelocity(const Vector* velocity, const AngularImpulse* angularVelocity) { btVector3 vel, angvel; if (velocity) { ConvertPosToBull(*velocity, vel); m_pObject->setLinearVelocity(vel); } if (angularVelocity) { ConvertAngularImpulseToBull(*angularVelocity, angvel); m_pObject->setAngularVelocity(angvel); } }
void ConvertShadowControllerToBull(const hlshadowcontrol_params_t &in, shadowcontrol_params_t &out) { ConvertPosToBull(in.targetPosition, out.targetPosition); ConvertRotationToBull(in.targetRotation, out.targetRotation); out.teleportDistance = ConvertDistanceToBull(in.teleportDistance); ConvertForceImpulseToBull(in.maxSpeed, out.maxSpeed); out.maxSpeed = out.maxSpeed.absolute(); ConvertAngularImpulseToBull(in.maxAngular, out.maxAngular); out.maxAngular = out.maxAngular.absolute(); out.dampFactor = in.dampFactor; }
void ConvertShadowControllerToBull(const hlshadowcontrol_params_t &in, shadowcontrol_params_t &out) { ConvertPosToBull(in.targetPosition, out.targetPosition); ConvertRotationToBull(in.targetRotation, out.targetRotation); out.teleportDistance = ConvertDistanceToBull(in.teleportDistance); out.maxSpeed = ConvertDistanceToBull(in.maxSpeed); out.maxDampSpeed = ConvertDistanceToBull(in.maxDampSpeed); out.maxAngular = ConvertAngleToBull(in.maxAngular); out.maxDampAngular = ConvertAngleToBull(in.maxDampAngular); out.dampFactor = in.dampFactor; }
CPhysicsObject* CreatePhysicsObject(CPhysicsEnvironment *pEnvironment, const CPhysCollide *pCollisionModel, int materialIndex, const Vector &position, const QAngle& angles, objectparams_t *pParams, bool isStatic) { btCollisionShape* shape = (btCollisionShape*)pCollisionModel; btVector3 vector; btMatrix3x3 matrix; ConvertPosToBull(position, vector); ConvertRotationToBull(angles, matrix); btTransform transform(matrix, vector); PhysicsShapeInfo *shapeInfo = (PhysicsShapeInfo*)shape->getUserPointer(); btTransform masscenter(btMatrix3x3::getIdentity()); if (shapeInfo) masscenter.setOrigin(shapeInfo->massCenter); float mass = pParams->mass; if (isStatic) mass = 0; btVector3 inertia; shape->calculateLocalInertia(mass, inertia); btMotionState* motionstate = new btMassCenterMotionState(transform, masscenter); btRigidBody::btRigidBodyConstructionInfo info(mass,motionstate,shape,inertia); info.m_linearDamping = pParams->damping; info.m_angularDamping = pParams->rotdamping; //info.m_localInertia = btVector3(pParams->inertia, pParams->inertia, pParams->inertia); btRigidBody* body = new btRigidBody(info); if (mass > 0) pEnvironment->GetBulletEnvironment()->addRigidBody(body); else pEnvironment->GetBulletEnvironment()->addRigidBody(body, 2, ~2); CPhysicsObject *pObject = new CPhysicsObject(); pObject->Init(pEnvironment, body, materialIndex, pParams->volume, pParams->dragCoefficient, pParams->dragCoefficient, pParams->massCenterOverride); pObject->SetGameData(pParams->pGameData); pObject->EnableCollisions(pParams->enableCollisions); if (!isStatic && pParams->dragCoefficient != 0.0f) pObject->EnableDrag(true); /*if (mass > 0) { btVector3 mins, maxs; shape->getAabb(btTransform::getIdentity(), mins, maxs); float maxradius = min(min(abs(maxs.getX()), abs(maxs.getY())), abs(maxs.getZ())); float minradius = min(min(abs(mins.getX()), abs(mins.getY())), abs(mins.getZ())); float radius = min(maxradius,minradius)/2.0f; body->setCcdMotionThreshold(radius*0.5f); body->setCcdSweptSphereRadius(0.2f*radius); }*/ return pObject; }
void CShadowController::Update(const Vector &position, const QAngle &angles, float timeOffset) { btVector3 targetPosition = m_shadow.targetPosition; btQuaternion targetRotation = m_shadow.targetRotation; ConvertPosToBull(position, m_shadow.targetPosition); m_secondsToArrival = timeOffset < 0 ? 0 : timeOffset; ConvertRotationToBull(angles, m_shadow.targetRotation); m_enable = true; if (IsEqual(targetPosition, m_shadow.targetPosition) && IsEqual(targetRotation, m_shadow.targetRotation)) return; m_pObject->Wake(); }
void CPhysicsObject::ApplyForceOffset(const Vector &forceVector, const Vector &worldPosition) { if (!IsMoveable() || !IsMotionEnabled()) { return; } Wake(); Vector local; WorldToLocal(&local, worldPosition); btVector3 force, offset; ConvertForceImpulseToBull(forceVector, force); ConvertPosToBull(local, offset); m_pObject->applyImpulse(force, offset); Wake(); }
void CPhysicsObject::SetPosition(const Vector &worldPosition, const QAngle &angles, bool isTeleport) { btVector3 bullPos; btMatrix3x3 bullAngles; ConvertPosToBull(worldPosition, bullPos); ConvertRotationToBull(angles, bullAngles); btTransform trans(bullAngles, bullPos); m_pObject->setWorldTransform(trans * ((btMassCenterMotionState *)m_pObject->getMotionState())->m_centerOfMassOffset); // Assumed this is the behavior of IVP. If you teleport an object, you don't want it to be stupidly frozen in the air. // Change this if behavior of IVP is different! if (isTeleport) m_pObject->activate(); }
void CPlayerController::MaxSpeed(const Vector &maxVelocity) { btVector3 bullVel; ConvertPosToBull(maxVelocity, bullVel); btVector3 available = bullVel; float length = bullVel.length(); bullVel.normalize(); float dot = bullVel.dot(m_linVelocity); if (dot > 0) { bullVel *= dot * length; available -= bullVel; } m_maxSpeed = available.absolute(); }
CPhysicsObject *CreatePhysicsObject(CPhysicsEnvironment *pEnvironment, const CPhysCollide *pCollisionModel, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams, bool isStatic) { if (!pCollisionModel) return NULL; // Some checks Assert(position.IsValid() && angles.IsValid()); btCollisionShape *pShape = (btCollisionShape *)pCollisionModel->GetCollisionShape(); btTransform massCenterTrans = btTransform::getIdentity(); massCenterTrans.setOrigin(pCollisionModel->GetMassCenter()); btMassCenterMotionState *pMotionState = new btMassCenterMotionState(massCenterTrans); btVector3 bullPos; btMatrix3x3 bullMatrix; ConvertPosToBull(position, bullPos); ConvertRotationToBull(angles, bullMatrix); btTransform initialWordTrans(bullMatrix, bullPos); pMotionState->setGraphicTransform(initialWordTrans); // Grab some parameters btScalar mass = 0.f; btVector3 inertia(0, 0, 0); btVector3 inertiaCoeff(1, 1, 1); if (pParams && !isStatic) { mass = pParams->mass; // TODO: Grab massCenterOverride and set it up correctly. // Don't allow the inertia coefficient to be less than 0! if (pParams->inertia >= 0) inertiaCoeff.setValue(pParams->inertia, pParams->inertia, pParams->inertia); pShape->calculateLocalInertia(mass, inertia); //inertia = pCollisionModel->GetRotationInertia(); //inertia *= inertiaCoeff * mass; } btRigidBody::btRigidBodyConstructionInfo info(mass, pMotionState, pShape, inertia); btRigidBody *pBody = new btRigidBody(info); CPhysicsObject *pObject = new CPhysicsObject(); pObject->Init(pEnvironment, pBody, materialIndex, pParams, isStatic); return pObject; }
void CShadowController::MaxSpeed(float maxSpeed, float maxAngularSpeed) { btRigidBody *body = m_pObject->GetObject(); //---------------- // Linear //---------------- btVector3 bullSpeed; ConvertPosToBull(Vector(maxSpeed), bullSpeed); btVector3 available = bullSpeed; // m_currentSpeed = bullSpeed; float length = bullSpeed.length(); bullSpeed.normalize(); float dot = bullSpeed.dot(body->getLinearVelocity()); if (dot > 0) { bullSpeed *= dot * length; available -= bullSpeed; } // FIXME: This is wrong. Rewrite this later. m_shadow.maxSpeed = available.length(); //---------------- // Angular //---------------- btVector3 bullAngular; ConvertAngularImpulseToBull(Vector(maxAngularSpeed), bullAngular); btVector3 availableAngular; float lengthAngular = bullAngular.length(); bullAngular.normalize(); float dotAngular = bullAngular.dot(body->getAngularVelocity()); if (dotAngular > 0) { bullAngular *= dotAngular * lengthAngular; availableAngular -= bullAngular; } // FIXME: This is wrong. Rewrite this later. m_shadow.maxAngular = availableAngular.length(); }
// Output passed to ApplyForceCenter/ApplyTorqueCenter void CPhysicsObject::CalculateForceOffset(const Vector &forceVector, const Vector &worldPosition, Vector *centerForce, AngularImpulse *centerTorque) const { if (!centerForce && !centerTorque) return; btVector3 pos, force; ConvertPosToBull(worldPosition, pos); ConvertForceImpulseToBull(forceVector, force); pos = pos - m_pObject->getWorldTransform().getOrigin(); btVector3 cross = pos.cross(force); if (centerForce) { ConvertForceImpulseToHL(force, *centerForce); } if (centerTorque) { ConvertAngularImpulseToHL(cross, *centerTorque); } }
void CPhysicsDragController::Tick(btScalar dt) { for(int i = 0; i < m_ents.Size(); i++) { CPhysicsObject * object = (CPhysicsObject *)m_ents[i]; Vector dragLinearFinal(0,0,0); AngularImpulse dragAngularFinal(0,0,0); Vector vel; AngularImpulse ang; object->GetVelocity(&vel, &ang); btVector3 bull_vel; ConvertPosToBull(vel, bull_vel); float dragForce = -0.5 * object->GetDragInDirection( &bull_vel ) * m_airDensity * dt; if ( dragForce < -1.0f ) { dragForce = -1.0f; } if ( dragForce < 0 ) { Vector dragLinearFinal = vel * dragForce; } btVector3 bull_angimpulse; ConvertAngularImpulseToBull(ang, bull_angimpulse); float angDragForce = -object->GetAngularDragInDirection(&bull_angimpulse) * m_airDensity * dt; if ( angDragForce < -1.0f ) { angDragForce = -1.0f; } if( angDragForce < 0) { dragAngularFinal = ang * angDragForce; } object->AddVelocity(&dragLinearFinal, &dragAngularFinal); } }
void CPhysicsObject::AddVelocity(const Vector *velocity, const AngularImpulse *angularVelocity) { if (!velocity && !angularVelocity) return; if (!IsMoveable() || !IsMotionEnabled()) { return; } Wake(); btVector3 bullvelocity, bullangular; if (velocity) { ConvertPosToBull(*velocity, bullvelocity); m_pObject->setLinearVelocity(m_pObject->getLinearVelocity() + bullvelocity); } // Angular velocity is supplied in local space. if (angularVelocity) { ConvertAngularImpulseToBull(*angularVelocity, bullangular); bullangular = m_pObject->getWorldTransform().getBasis() * bullangular; m_pObject->setAngularVelocity(m_pObject->getAngularVelocity() + bullangular); } }
CPhysicsObject *CreatePhysicsSphere(CPhysicsEnvironment *pEnvironment, float radius, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams, bool isStatic) { if (!pEnvironment) return NULL; // Some checks Assert(position.IsValid() && angles.IsValid()); // Conversion unnecessary as this is an exposed function. btSphereShape *shape = (btSphereShape *)g_PhysicsCollision.SphereToConvex(radius); btVector3 vector; btMatrix3x3 matrix; ConvertPosToBull(position, vector); ConvertRotationToBull(angles, matrix); btTransform transform(matrix, vector); float mass = 0; float volume = 0; if (pParams) { mass = isStatic ? 0 : pParams->mass; volume = pParams->volume; if (volume <= 0) { pParams->volume = (4 / 3) * M_PI * radius * radius * radius; } } btMassCenterMotionState *motionstate = new btMassCenterMotionState(); motionstate->setGraphicTransform(transform); btRigidBody::btRigidBodyConstructionInfo info(mass, motionstate, shape); btRigidBody *body = new btRigidBody(info); CPhysicsObject *pObject = new CPhysicsObject; pObject->Init(pEnvironment, body, materialIndex, pParams, isStatic, true); return pObject; }
// Thrusters call this and pass output to AddVelocity void CPhysicsObject::CalculateVelocityOffset(const Vector &forceVector, const Vector &worldPosition, Vector *centerVelocity, AngularImpulse *centerAngularVelocity) const { if (!centerVelocity && !centerAngularVelocity) return; btVector3 force, pos; ConvertForceImpulseToBull(forceVector, force); ConvertPosToBull(worldPosition, pos); pos = pos - m_pObject->getWorldTransform().getOrigin(); btVector3 cross = pos.cross(force); // cross.set_pairwise_mult( &cross, core->get_inv_rot_inertia()); // Linear velocity if (centerVelocity) { force *= m_pObject->getInvMass(); ConvertForceImpulseToHL(force, *centerVelocity); } if (centerAngularVelocity) { ConvertAngularImpulseToHL(cross, *centerAngularVelocity); } }
void CPhysicsObject::GetVelocityAtPoint(const Vector& worldPosition, Vector* pVelocity) const { btVector3 vec; ConvertPosToBull(worldPosition, vec); ConvertPosToHL(m_pObject->getVelocityInLocalPoint(vec), *pVelocity); }
// FIXME: The API is confusing because we need to add the BT_DISABLE_WORLD_GRAVITY flag to the object // by calling EnableGravity(false) void CPhysicsObject::SetLocalGravity(const Vector &gravityVector) { btVector3 tmp; ConvertPosToBull(gravityVector, tmp); m_pObject->setGravity(tmp); }