void SubmitConstraints(dFloat timestep, int threadIndex) { CustomBallAndSocket::SubmitConstraints(timestep, threadIndex); float invTimestep = 1.0f / timestep; dMatrix matrix0; dMatrix matrix1; CalculateGlobalMatrix(matrix0, matrix1); if (m_anim_speed != 0.0f) // some animation to illustrate purpose { m_anim_time += timestep * m_anim_speed; float a0 = sin(m_anim_time); float a1 = m_anim_offset * 3.14f; dVector axis(sin(a1), 0.0f, cos(a1)); //dVector axis (1,0,0); m_target = dQuaternion(axis, a0 * 0.5f); } // measure error dQuaternion q0(matrix0); dQuaternion q1(matrix1); dQuaternion qt0 = m_target * q1; dQuaternion qErr = ((q0.DotProduct(qt0) < 0.0f) ? dQuaternion(-q0.m_q0, q0.m_q1, q0.m_q2, q0.m_q3) : dQuaternion(q0.m_q0, -q0.m_q1, -q0.m_q2, -q0.m_q3)) * qt0; float errorAngle = 2.0f * acos(dMax(-1.0f, dMin(1.0f, qErr.m_q0))); dVector errorAngVel(0, 0, 0); dMatrix basis; if (errorAngle > 1.0e-10f) { dVector errorAxis(qErr.m_q1, qErr.m_q2, qErr.m_q3, 0.0f); errorAxis = errorAxis.Scale(1.0f / dSqrt(errorAxis % errorAxis)); errorAngVel = errorAxis.Scale(errorAngle * invTimestep); basis = dGrammSchmidt(errorAxis); } else { basis = dMatrix(qt0, dVector(0.0f, 0.0f, 0.0f, 1.0f)); } dVector angVel0, angVel1; NewtonBodyGetOmega(m_body0, (float*)&angVel0); NewtonBodyGetOmega(m_body1, (float*)&angVel1); dVector angAcc = (errorAngVel.Scale(m_reduceError) - (angVel0 - angVel1)).Scale(invTimestep); // motor for (int n = 0; n < 3; n++) { // calculate the desired acceleration dVector &axis = basis[n]; float relAccel = angAcc % axis; NewtonUserJointAddAngularRow(m_joint, 0.0f, &axis[0]); NewtonUserJointSetRowAcceleration(m_joint, relAccel); NewtonUserJointSetRowMinimumFriction(m_joint, -m_angularFriction); NewtonUserJointSetRowMaximumFriction(m_joint, m_angularFriction); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); } }
//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~ const Math::Vector3 PhysicsActor::getAngularVelocity() const { Math::Vector3 omega; NewtonBodyGetOmega(m_pActor, omega.m_array); return omega; }
void RigidBodyData::Save(ISave* const isave) { ULONG nwrit; int revision = D_FILE_REVISION; dVector mass; dVector com; dVector veloc; dVector omega; dMatrix matrix; RigidBodyWorldDesc& me = *(RigidBodyWorldDesc*) RigidBodyWorldDesc::GetDescriptor(); NewtonBodyGetMatrix(m_body, &matrix[0][0]); NewtonBodyGetVelocity(m_body, &veloc[0]); NewtonBodyGetOmega(m_body, &omega[0]); NewtonCollision* const collision = NewtonBodyGetCollision(m_body); isave->Write((const char*)&revision, sizeof (revision), &nwrit); isave->Write((const char*)&m_oldControlerID, sizeof (m_oldControlerID), &nwrit); isave->Write((const char*)&m_collisionShape, sizeof (m_collisionShape), &nwrit); isave->Write((const char*)&m_hideGizmos, sizeof (m_hideGizmos), &nwrit); isave->Write((const char*)&m_mass, sizeof (m_mass), &nwrit); isave->Write((const char*)&m_inertia, sizeof (m_inertia), &nwrit); isave->Write((const char*)&m_origin, sizeof (m_origin), &nwrit); isave->Write((const char*)&matrix, sizeof (matrix), &nwrit); isave->Write((const char*)&veloc, sizeof (veloc), &nwrit); isave->Write((const char*)&omega, sizeof (omega), &nwrit); NewtonCollisionSerialize (me.m_newton, collision, SaveCollision, isave); }
NzVector3f NzPhysObject::GetAngularVelocity() const { NzVector3f angularVelocity; NewtonBodyGetOmega(m_body, angularVelocity); return angularVelocity; }
void CalculatePickForceAndTorque (const NewtonBody* const body, const dVector& pointOnBodyInGlobalSpace, const dVector& targetPositionInGlobalSpace, dFloat timestep) { dFloat mass; dFloat Ixx; dFloat Iyy; dFloat Izz; const dFloat stiffness = 0.33f; const dFloat damping = -0.05f; NewtonBodyGetMass(body, &mass, &Ixx, &Iyy, &Izz); // calculate the desired impulse dVector posit(targetPositionInGlobalSpace - pointOnBodyInGlobalSpace); dVector impulse(posit.Scale(stiffness * mass)); // apply linear impulse NewtonBodyApplyImpulseArray(body, 1, sizeof (dVector), &impulse[0], &pointOnBodyInGlobalSpace[0], timestep); // apply linear and angular damping dMatrix inertia; dVector linearMomentum(0.0f); dVector angularMomentum(0.0f); NewtonBodyGetOmega(body, &angularMomentum[0]); NewtonBodyGetVelocity(body, &linearMomentum[0]); NewtonBodyGetInertiaMatrix(body, &inertia[0][0]); angularMomentum = inertia.RotateVector(angularMomentum); angularMomentum = angularMomentum.Scale(damping); linearMomentum = linearMomentum.Scale(mass * damping); NewtonBodyApplyImpulsePair(body, &linearMomentum[0], &angularMomentum[0], timestep); }
// rolling friction works as follow: the idealization of the contact of a spherical object // with a another surface is a point that pass by the center of the sphere. // in most cases this is enough to model the collision but in insufficient for modeling // the rolling friction. In reality contact with the sphere with the other surface is not // a point but a contact patch. A contact patch has the property the it generates a fix // constant rolling torque that opposes the movement of the sphere. // we can model this torque by adding a clamped torque aligned to the instantaneously axis // of rotation of the ball. and with a magnitude of the stopping angular acceleration. void CustomDryRollingFriction::SubmitConstrainst (dFloat timestep, int threadIndex) { dVector omega; dFloat omegaMag; dFloat torqueFriction; // get the omega vector NewtonBodyGetOmega(m_body0, &omega[0]); omegaMag = dSqrt (omega % omega); if (omegaMag > 0.1f) { // tell newton to used this the friction of the omega vector to apply the rolling friction dVector pin (omega.Scale (1.0f / omegaMag)); NewtonUserJointAddAngularRow (m_joint, 0.0f, &pin[0]); // calculate the acceleration to stop the ball in one time step NewtonUserJointSetRowAcceleration (m_joint, -omegaMag / timestep); // set the friction limit proportional the sphere Inertia torqueFriction = m_frictionTorque * m_frictionCoef; NewtonUserJointSetRowMinimumFriction (m_joint, -torqueFriction); NewtonUserJointSetRowMaximumFriction (m_joint, torqueFriction); } else { // when omega is too low sheath a little bit and damp the omega directly omega = omega.Scale (0.2f); NewtonBodySetOmega(m_body0, &omega[0]); } }
void dCustomTireSpringDG::SubmitConstraints(dFloat timestep, int threadIndex) { NewtonBody* BodyAttach; //NewtonBody* BodyFrame; // dVector tireOmega = dVector(0.0f, 0.0f, 0.0f); //BodyFrame = GetBody0(); BodyAttach = GetBody1(); // SteeringController(timestep); // // calculate the position of the pivot point and the Jacobian direction vectors, in global space. CalculateGlobalMatrix(mChassisPivotMatrix, mTirePivotMatrix); // NewtonBodyGetOmega(BodyAttach, &tireOmega[0]); // mRealOmega = dAbs(tireOmega.DotProduct3(mChassisPivotMatrix.m_front)); // TireCenterPin(timestep); // TireCenterBolt(timestep); // SuspenssionSpringLimits(timestep); // TireBreakAction(BodyAttach, timestep); }
void dCustomCorkScrew::SubmitAngularRow(const dMatrix& matrix0, const dMatrix& matrix1, dFloat timestep) { const dFloat angleError = GetMaxAngleError(); dFloat angle0 = CalculateAngle(matrix0.m_front, matrix1.m_front, matrix1.m_up); NewtonUserJointAddAngularRow(m_joint, angle0, &matrix1.m_up[0]); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); if (dAbs(angle0) > angleError) { const dFloat alpha = NewtonUserJointCalculateRowZeroAcceleration(m_joint) + dFloat(0.25f) * angle0 / (timestep * timestep); NewtonUserJointSetRowAcceleration(m_joint, alpha); } dFloat angle1 = CalculateAngle(matrix0.m_front, matrix1.m_front, matrix1.m_right); NewtonUserJointAddAngularRow(m_joint, angle1, &matrix1.m_right[0]); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); if (dAbs(angle1) > angleError) { const dFloat alpha = NewtonUserJointCalculateRowZeroAcceleration(m_joint) + dFloat(0.25f) * angle1 / (timestep * timestep); NewtonUserJointSetRowAcceleration(m_joint, alpha); } // the joint angle can be determined by getting the angle between any two non parallel vectors m_curJointAngle.Update(-CalculateAngle(matrix0.m_up, matrix1.m_up, matrix1.m_front)); // save the current joint Omega dVector omega0(0.0f); dVector omega1(0.0f); NewtonBodyGetOmega(m_body0, &omega0[0]); if (m_body1) { NewtonBodyGetOmega(m_body1, &omega1[0]); } m_angularOmega = (omega0 - omega1).DotProduct3(matrix1.m_front); if (m_options.m_option2) { if (m_options.m_option3) { dCustomCorkScrew::SubmitConstraintLimitSpringDamper(matrix0, matrix1, timestep); } else { dCustomCorkScrew::SubmitConstraintLimits(matrix0, matrix1, timestep); } } else if (m_options.m_option3) { dCustomCorkScrew::SubmitConstraintSpringDamper(matrix0, matrix1, timestep); } else if (m_angularFriction != 0.0f) { NewtonUserJointAddAngularRow(m_joint, 0, &matrix1.m_front[0]); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); NewtonUserJointSetRowAcceleration(m_joint, -m_angularOmega / timestep); NewtonUserJointSetRowMinimumFriction(m_joint, -m_angularFriction); NewtonUserJointSetRowMaximumFriction(m_joint, m_angularFriction); } }
void dCustomHinge::SubmitConstraints(dFloat timestep, int threadIndex) { dMatrix matrix0; dMatrix matrix1; dFloat sinAngle; dFloat cosAngle; // calculate the position of the pivot point and the Jacobian direction vectors, in global space. CalculateGlobalMatrix(matrix0, matrix1); // Restrict the movement on the pivot point along all tree orthonormal direction NewtonUserJointAddLinearRow(m_joint, &matrix0.m_posit[0], &matrix1.m_posit[0], &matrix1.m_front[0]); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); NewtonUserJointAddLinearRow(m_joint, &matrix0.m_posit[0], &matrix1.m_posit[0], &matrix1.m_up[0]); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); NewtonUserJointAddLinearRow(m_joint, &matrix0.m_posit[0], &matrix1.m_posit[0], &matrix1.m_right[0]); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); // two rows to restrict rotation around around the parent coordinate system NewtonUserJointAddAngularRow(m_joint, CalculateAngle(matrix0.m_front, matrix1.m_front, matrix1.m_up), &matrix1.m_up[0]); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); NewtonUserJointAddAngularRow(m_joint, CalculateAngle(matrix0.m_front, matrix1.m_front, matrix1.m_right), &matrix1.m_right[0]); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); // the joint angle can be determined by getting the angle between any two non parallel vectors CalculateAngle (matrix1.m_up, matrix0.m_up, matrix1.m_front, sinAngle, cosAngle); m_curJointAngle.Update(cosAngle, sinAngle); // save the current joint Omega dVector omega0(0.0f); dVector omega1(0.0f); NewtonBodyGetOmega(m_body0, &omega0[0]); if (m_body1) { NewtonBodyGetOmega(m_body1, &omega1[0]); } m_jointOmega = (omega0 - omega1).DotProduct3(matrix1.m_front); m_lastRowWasUsed = false; if (m_setAsSpringDamper) { ApplySpringDamper (timestep, matrix0, matrix1); } else { SubmitConstraintsFreeDof (timestep, matrix0, matrix1); } }
void dCustomCorkScrew::SubmitAngularRow(const dMatrix& matrix0, const dMatrix& matrix1, dFloat timestep) { dMatrix localMatrix(matrix0 * matrix1.Inverse()); dVector euler0; dVector euler1; localMatrix.GetEulerAngles(euler0, euler1, m_pitchRollYaw); dVector rollPin(dSin(euler0[1]), dFloat(0.0f), dCos(euler0[1]), dFloat(0.0f)); rollPin = matrix1.RotateVector(rollPin); NewtonUserJointAddAngularRow(m_joint, -euler0[1], &matrix1[1][0]); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); NewtonUserJointAddAngularRow(m_joint, -euler0[2], &rollPin[0]); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); // the joint angle can be determined by getting the angle between any two non parallel vectors m_curJointAngle.Update(euler0.m_x); // save the current joint Omega dVector omega0(0.0f); dVector omega1(0.0f); NewtonBodyGetOmega(m_body0, &omega0[0]); if (m_body1) { NewtonBodyGetOmega(m_body1, &omega1[0]); } m_angularOmega = (omega0 - omega1).DotProduct3(matrix1.m_front); if (m_options.m_option2) { if (m_options.m_option3) { dCustomCorkScrew::SubmitConstraintLimitSpringDamper(matrix0, matrix1, timestep); } else { dCustomCorkScrew::SubmitConstraintLimits(matrix0, matrix1, timestep); } } else if (m_options.m_option3) { dCustomCorkScrew::SubmitConstraintSpringDamper(matrix0, matrix1, timestep); } else if (m_angularFriction != 0.0f) { NewtonUserJointAddAngularRow(m_joint, 0, &matrix1.m_front[0]); NewtonUserJointSetRowStiffness(m_joint, m_stiffness); NewtonUserJointSetRowAcceleration(m_joint, -m_angularOmega / timestep); NewtonUserJointSetRowMinimumFriction(m_joint, -m_angularFriction); NewtonUserJointSetRowMaximumFriction(m_joint, m_angularFriction); } }
dVector BodyGetPointVelocity(const NewtonBody* const body, const dVector &point) { dVector v, w, c; NewtonBodyGetVelocity(body, &v[0]); NewtonBodyGetOmega(body, &w[0]); dMatrix matrix; NewtonBodyGetMatrix(body, &matrix[0][0]); c = matrix.m_posit; // TODO: Does not handle COM offset !!! return v + w * (point - c); }
void CustomBallAndSocketWithFriction::SubmitConstraints(dFloat timestep, int threadIndex) { CustomBallAndSocket::SubmitConstraints(timestep, threadIndex); dVector omega0(0.0f, 0.0f, 0.0f, 0.0f); dVector omega1(0.0f, 0.0f, 0.0f, 0.0f); // get the omega vector NewtonBodyGetOmega(m_body0, &omega0[0]); if (m_body1) { NewtonBodyGetOmega(m_body1, &omega1[0]); } dVector relOmega(omega0 - omega1); dFloat omegaMag = dSqrt(relOmega % relOmega); if (omegaMag > 0.1f) { // tell newton to used this the friction of the omega vector to apply the rolling friction dMatrix basis(dGrammSchmidt(relOmega)); NewtonUserJointAddAngularRow(m_joint, 0.0f, &basis[2][0]); NewtonUserJointSetRowMinimumFriction(m_joint, -m_dryFriction); NewtonUserJointSetRowMaximumFriction(m_joint, m_dryFriction); NewtonUserJointAddAngularRow(m_joint, 0.0f, &basis[1][0]); NewtonUserJointSetRowMinimumFriction(m_joint, -m_dryFriction); NewtonUserJointSetRowMaximumFriction(m_joint, m_dryFriction); // calculate the acceleration to stop the ball in one time step dFloat invTimestep = (timestep > 0.0f) ? 1.0f / timestep : 1.0f; NewtonUserJointAddAngularRow(m_joint, 0.0f, &basis[0][0]); NewtonUserJointSetRowAcceleration(m_joint, -omegaMag * invTimestep); NewtonUserJointSetRowMinimumFriction(m_joint, -m_dryFriction); NewtonUserJointSetRowMaximumFriction(m_joint, m_dryFriction); } else { // when omega is too low this is correct but the small angle approximation theorem. dMatrix basis(dGetIdentityMatrix()); for (int i = 0; i < 3; i++) { NewtonUserJointAddAngularRow(m_joint, 0.0f, &basis[i][0]); NewtonUserJointSetRowMinimumFriction(m_joint, -m_dryFriction); NewtonUserJointSetRowMaximumFriction(m_joint, m_dryFriction); } } }
void SubmitConstraints (dFloat timestep, int threadIndex) { // calculate suspension bumpers and forces dMatrix threadMatrix; dMatrix parentMatrix; dVector threadCOM; dVector parentCOM; dVector threadVeloc; dVector parentVeloc; dVector threadOmega; dVector parentOmega; // get the physics body state; NewtonBodyGetOmega(m_body0, &threadOmega[0]); NewtonBodyGetOmega(m_body1, &parentOmega[0]); NewtonBodyGetVelocity(m_body0, &threadVeloc[0]); NewtonBodyGetVelocity(m_body1, &parentVeloc[0]); NewtonBodyGetCentreOfMass(m_body0, &threadCOM[0]); NewtonBodyGetCentreOfMass(m_body1, &parentCOM[0]); NewtonBodyGetMatrix(m_body0, &threadMatrix[0][0]); NewtonBodyGetMatrix(m_body1, &parentMatrix[0][0]); threadCOM = threadMatrix.TransformVector(threadCOM); parentCOM = parentMatrix.TransformVector(parentCOM); ApplySuspesionForce (timestep, m_body0, m_rearHarpointOnThread, threadMatrix, threadCOM, threadVeloc, threadOmega, m_body1, m_rearHarpointOnParent, parentMatrix, parentCOM, parentVeloc, parentOmega); ApplySuspesionForce (timestep, m_body0, m_frontHarpointOnThread, threadMatrix, threadCOM, threadVeloc, threadOmega, m_body1, m_frontHarpointOnParent, parentMatrix, parentCOM, parentVeloc, parentOmega); CustomSlidingContact::SubmitConstraints (timestep, threadIndex); }
void dCustomHinge::SubmitConstraintsFreeDof(int freeDof, const dMatrix& matrix0, const dMatrix& matrix1, dFloat timestep, int threadIndex) { dAssert (freeDof == 1); dVector omega0(0.0f); dVector omega1(0.0f); NewtonBodyGetOmega(m_body0, &omega0[0]); if (m_body1) { NewtonBodyGetOmega(m_body1, &omega1[0]); } m_jointOmega = (omega0 - omega1).DotProduct3(matrix1.m_front); //m_friction = 0; //m_limitsOn = false; //m_setAsSpringDamper = 1; //m_spring = 1000; //m_damper = 10.0f; //m_springDamperRelaxation = 0.97f; if (m_setAsSpringDamper) { //m_lastRowWasUsed = true; NewtonUserJointAddAngularRow(m_joint, -GetPitch(), &matrix0.m_front[0]); NewtonUserJointSetRowSpringDamperAcceleration(m_joint, m_springDamperRelaxation, m_spring, m_damper); } else { if (m_limitsOn) { if (m_friction != 0.0f) { SubmitConstraintsFrictionAndLimit(matrix0, matrix1, timestep); } else { SubmitConstraintsLimitsOnly(matrix0, matrix1, timestep); } } else { if (m_friction != 0.0f) { SubmitConstraintsFrictionOnly(matrix0, matrix1, timestep); } } } }
void dNewtonBody::CalculateBuoyancyForces(const void* plane, void* force, void* torque, float bodyDensity) { dFloat Ixx; dFloat Iyy; dFloat Izz; dFloat mass; NewtonBodyGetMass(m_body, &mass, &Ixx, &Iyy, &Izz); if (mass > 0.0f) { dMatrix matrix; dVector cog(0.0f); dVector accelPerUnitMass(0.0f); dVector torquePerUnitMass(0.0f); const dVector gravity(0.0f, -9.8f, 0.0f, 0.0f); NewtonBodyGetMatrix(m_body, &matrix[0][0]); NewtonBodyGetCentreOfMass(m_body, &cog[0]); cog = matrix.TransformVector(cog); NewtonCollision* const collision = NewtonBodyGetCollision(m_body); dFloat shapeVolume = NewtonConvexCollisionCalculateVolume(collision); dFloat fluidDensity = 1.0f / (bodyDensity * shapeVolume); dFloat viscosity = 0.995f; NewtonConvexCollisionCalculateBuoyancyAcceleration(collision, &matrix[0][0], &cog[0], &gravity[0], (float*)plane, fluidDensity, viscosity, &accelPerUnitMass[0], &torquePerUnitMass[0]); dVector finalForce(accelPerUnitMass.Scale(mass)); dVector finalTorque(torquePerUnitMass.Scale(mass)); dVector omega(0.0f); NewtonBodyGetOmega(m_body, &omega[0]); omega = omega.Scale(viscosity); NewtonBodySetOmega(m_body, &omega[0]); ((float*)force)[0] = finalForce.m_x ; ((float*)force)[1] = finalForce.m_y ; ((float*)force)[2] = finalForce.m_z ; ((float*)torque)[0] = finalTorque.m_x; ((float*)torque)[1] = finalTorque.m_y; ((float*)torque)[2] = finalTorque.m_z; } }
static void PhysicsApplyPickForce (const NewtonBody* body, dFloat timestep, int threadIndex) { dFloat mass; dFloat Ixx; dFloat Iyy; dFloat Izz; dVector com; dVector veloc; dVector omega; dMatrix matrix; // apply the thew body forces if (chainForceCallback) { chainForceCallback (body, timestep, threadIndex); } // add the mouse pick penalty force and torque NewtonBodyGetVelocity(body, &veloc[0]); NewtonBodyGetOmega(body, &omega[0]); NewtonBodyGetVelocity(body, &veloc[0]); NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz); dVector force (pickedForce.Scale (mass * MOUSE_PICK_STIFFNESS)); dVector dampForce (veloc.Scale (MOUSE_PICK_DAMP * mass)); force -= dampForce; NewtonBodyGetMatrix(body, &matrix[0][0]); NewtonBodyGetCentreOfMass (body, &com[0]); // calculate local point relative to center of mass dVector point (matrix.RotateVector (attachmentPoint - com)); dVector torque (point * force); dVector torqueDamp (omega.Scale (mass * 0.1f)); NewtonBodyAddForce (body, &force.m_x); NewtonBodyAddTorque (body, &torque.m_x); // make sure the body is unfrozen, if it is picked NewtonBodySetFreezeState (body, 0); }
void dCustomRackAndPinion::SubmitConstraints (dFloat timestep, int threadIndex) { dMatrix matrix0; dMatrix matrix1; dVector omega0(0.0f); dVector veloc1(0.0f); dFloat jacobian0[6]; dFloat jacobian1[6]; // calculate the position of the pivot point and the Jacobian direction vectors, in global space. CalculateGlobalMatrix (matrix0, matrix1); // calculate the angular velocity for both bodies NewtonBodyGetOmega(m_body0, &omega0[0]); NewtonBodyGetVelocity(m_body1, &veloc1[0]); dVector dir0 (matrix0.m_front.Scale (m_gearRatio)); const dVector& dir1 = matrix1.m_front; jacobian0[0] = dFloat(0.0f); jacobian0[1] = dFloat(0.0f); jacobian0[2] = dFloat(0.0f); jacobian0[3] = dir0.m_x; jacobian0[4] = dir0.m_y; jacobian0[5] = dir0.m_z; jacobian1[0] = dir1.m_x; jacobian1[1] = dir1.m_y; jacobian1[2] = dir1.m_z; jacobian1[3] = dFloat(0.0f); jacobian1[4] = dFloat(0.0f); jacobian1[5] = dFloat(0.0f); dFloat w0 = omega0.DotProduct3(dir0); dFloat w1 = veloc1.DotProduct3(dir1); dFloat relOmega = w0 + w1; dFloat invTimestep = (timestep > 0.0f) ? 1.0f / timestep : 1.0f; dFloat relAccel = -0.5f * relOmega * invTimestep; NewtonUserJointAddGeneralRow (m_joint, jacobian0, jacobian1); NewtonUserJointSetRowAcceleration (m_joint, relAccel); }
void OnInside(NewtonBody* const visitor) { dFloat Ixx; dFloat Iyy; dFloat Izz; dFloat mass; NewtonBodyGetMass(visitor, &mass, &Ixx, &Iyy, &Izz); if (mass > 0.0f) { dMatrix matrix; dVector cog(0.0f); dVector accelPerUnitMass(0.0f); dVector torquePerUnitMass(0.0f); const dVector gravity (0.0f, DEMO_GRAVITY, 0.0f, 0.0f); NewtonBodyGetMatrix (visitor, &matrix[0][0]); NewtonBodyGetCentreOfMass(visitor, &cog[0]); cog = matrix.TransformVector (cog); NewtonCollision* const collision = NewtonBodyGetCollision(visitor); dFloat shapeVolume = NewtonConvexCollisionCalculateVolume (collision); dFloat fluidDentity = 1.0f / (m_waterToSolidVolumeRatio * shapeVolume); dFloat viscosity = 0.995f; NewtonConvexCollisionCalculateBuoyancyAcceleration (collision, &matrix[0][0], &cog[0], &gravity[0], &m_plane[0], fluidDentity, viscosity, &accelPerUnitMass[0], &torquePerUnitMass[0]); dVector force (accelPerUnitMass.Scale (mass)); dVector torque (torquePerUnitMass.Scale (mass)); dVector omega(0.0f); NewtonBodyGetOmega(visitor, &omega[0]); omega = omega.Scale (viscosity); NewtonBodySetOmega(visitor, &omega[0]); NewtonBodyAddForce (visitor, &force[0]); NewtonBodyAddTorque (visitor, &torque[0]); } }
static void ClampAngularVelocity(const NewtonBody* body, dFloat timestep, int threadIndex) { dVector omega; NewtonBodyGetOmega(body, &omega[0]); omega.m_w = 0.0f; dFloat mag2 = omega.DotProduct3(omega); if (mag2 > (100.0f * 100.0f)) { omega = omega.Normalize().Scale(100.0f); NewtonBodySetOmega(body, &omega[0]); } //PhysicsApplyGravityForce(body, timestep, threadIndex); dFloat Ixx; dFloat Iyy; dFloat Izz; dFloat mass; dFloat gravity = -0.0f; NewtonBodyGetMass(body, &mass, &Ixx, &Iyy, &Izz); dVector dir(0.0f, gravity, 0.0f); dVector force(dir.Scale(mass)); NewtonBodySetForce(body, &force.m_x); }
void dVehicleSingleBody::RigidBodyToStates() { dVector vector; dMatrix matrix; dComplementaritySolver::dBodyState* const chassisBody = GetBody(); // get data from engine rigid body and copied to the vehicle chassis body NewtonBodyGetMatrix(m_newtonBody, &matrix[0][0]); chassisBody->SetMatrix(matrix); static int xxx; xxx++; if (xxx == 1500) { // NewtonBodyGetVelocity(m_newtonBody, &vector[0]); // vector.m_x += 2.0f; // NewtonBodySetVelocity(m_newtonBody, &vector[0]); } NewtonBodyGetVelocity(m_newtonBody, &vector[0]); chassisBody->SetVeloc(vector); NewtonBodyGetOmega(m_newtonBody, &vector[0]); chassisBody->SetOmega(vector); NewtonBodyGetForce(m_newtonBody, &vector[0]); chassisBody->SetForce(vector); NewtonBodyGetTorque(m_newtonBody, &vector[0]); chassisBody->SetTorque(vector); chassisBody->UpdateInertia(); dVehicleInterface::RigidBodyToStates(); }
cVector3f cPhysicsBodyNewton::GetAngularVelocity() const { cVector3f vVel; NewtonBodyGetOmega(m_pNewtonBody, vVel.v); return vVel; }
void CustomDGRayCastCar::IntegrateTires (dFloat timestep, int threadIndex) { dMatrix bodyMatrix; // get the vehicle global matrix, and use it in several calculations NewtonBodyGetMatrix (m_body0, &bodyMatrix[0][0]); dMatrix chassisMatrix (m_localFrame * bodyMatrix); // get the chassis instantaneous linear and angular velocity in the local space of the chassis dVector bodyOmega; dVector bodyVelocity; NewtonBodyGetVelocity (m_body0, &bodyVelocity[0]); NewtonBodyGetOmega (m_body0, &bodyOmega[0]); // set the current vehicle speed m_curSpeed = bodyMatrix.m_front % bodyVelocity; for (int i = 0; i < m_tiresCount; i ++ ) { Tire& tire = m_tires[i]; /* if (tire.m_tireIsConstrained) { // the torqued generate by the tire can no be larger than the external torque on the tire // when this happens ther tire is spinning unde contrained rotation // V % dir + W * R % dir = 0 // where V is the tire Axel velocity // W is the tire local angular velocity // R is the tire radius // dir is the longitudinal direction of of the tire. dFloat contactRadius; dFloat axelLinealSpeed; dVector tireAxelPosit (chassisMatrix.TransformVector (tire.m_harpoint - m_localFrame.m_up.Scale (tire.m_posit))); dVector tireAxelVeloc = bodyVelocity + bodyOmega * (tireAxelPosit - chassisMatrix.m_posit) - tire.m_hitBodyPointVelocity; axelLinealSpeed = tireAxelVeloc % chassisMatrix.m_front; dVector tireRadius (tire.m_contactPoint - tire.m_tireAxelPosit); contactRadius = (tire.m_lateralPin * tireRadius) % tire.m_longitudinalPin; tire.m_angularVelocity = - axelLinealSpeed / contactRadius ; } else if (tire.m_tireIsOnAir) { if (tire.m_breakForce > 1.0e-3f) { tire.m_angularVelocity = 0.0f; } else { //the tire is on air, need to be integrate net toque and apply a drag coneficenct // dFloat nettorque = tire.m_angularVelocity; // // this checkup is suposed to fix a infinit division by zero... // if ( dAbs(tireContactSpeed) > 1.0e-3) { // nettorque = - (tireLinearSpeed) / (tireContactSpeed); // } //tire.m_angularVelocity = - tireLinearSpeed / tireContactSpeed; dFloat torque; torque = tire.m_torque - tire.m_angularVelocity * tire.m_Ixx * TIRE_VISCUOS_DAMP; tire.m_angularVelocity += torque * tire.m_IxxInv * timestep; } } else { // there is a next torque on the tire dFloat torque; torque = tire.m_torque - tire.m_angularVelocity * tire.m_Ixx * TIRE_VISCUOS_DAMP; tire.m_angularVelocity += torque * tire.m_IxxInv * timestep; } */ if (tire.m_tireIsOnAir) { if (tire.m_breakForce > 1.0e-3f) { tire.m_angularVelocity = 0.0f; } else { //the tire is on air, need to be integrate net toque and apply a drag coeficient dFloat torque; torque = tire.m_torque - tire.m_angularVelocity * tire.m_Ixx * TIRE_VISCUOS_DAMP; tire.m_angularVelocity += torque * tire.m_IxxInv * timestep; } } else if (tire.m_tireIsConstrained) { // the torqued generate by the tire can no be larger than the external torque on the tire // when this happens there tire is spinning under constrained rotation // V % dir + W * R % dir = 0 // where V is the tire Axel velocity // W is the tire local angular velocity // R is the tire radius // dir is the longitudinal direction of of the tire. dFloat contactRadius; dFloat axelLinealSpeed; dVector tireAxelPosit (chassisMatrix.TransformVector (tire.m_harpoint - m_localFrame.m_up.Scale (tire.m_posit))); dVector tireAxelVeloc = bodyVelocity + bodyOmega * (tireAxelPosit - chassisMatrix.m_posit) - tire.m_hitBodyPointVelocity; axelLinealSpeed = tireAxelVeloc % chassisMatrix.m_front; dVector tireRadius (tire.m_contactPoint - tire.m_tireAxelPosit); contactRadius = (tire.m_lateralPin * tireRadius) % tire.m_longitudinalPin; tire.m_angularVelocity = - axelLinealSpeed / contactRadius ; } else { // there is a next torque on the tire dFloat torque; torque = tire.m_torque - tire.m_angularVelocity * tire.m_Ixx * TIRE_VISCUOS_DAMP; tire.m_angularVelocity += torque * tire.m_IxxInv * timestep; } // spin the tire by the angular velocity tire.m_spinAngle = dMod (tire.m_spinAngle + tire.m_angularVelocity * timestep, 3.14159265f * 2.0f); // reset the tire torque tire.m_torque = 0.0f; tire.m_breakForce = 0.0f; } }
void CustomPlayerController::PostUpdate(dFloat timestep, int threadIndex) { dMatrix matrix; dQuaternion bodyRotation; dVector veloc(0.0f, 0.0f, 0.0f, 0.0f); dVector omega(0.0f, 0.0f, 0.0f, 0.0f); CustomPlayerControllerManager* const manager = (CustomPlayerControllerManager*) GetManager(); NewtonWorld* const world = manager->GetWorld(); // apply the player motion, by calculation the desired plane linear and angular velocity manager->ApplyPlayerMove (this, timestep); // get the body motion state NewtonBodyGetMatrix(m_body, &matrix[0][0]); NewtonBodyGetVelocity(m_body, &veloc[0]); NewtonBodyGetOmega(m_body, &omega[0]); // integrate body angular velocity NewtonBodyGetRotation (m_body, &bodyRotation.m_q0); bodyRotation = bodyRotation.IntegrateOmega(omega, timestep); matrix = dMatrix (bodyRotation, matrix.m_posit); // integrate linear velocity dFloat normalizedTimeLeft = 1.0f; dFloat step = timestep * dSqrt (veloc % veloc) ; dFloat descreteTimeStep = timestep * (1.0f / D_DESCRETE_MOTION_STEPS); int prevContactCount = 0; CustomControllerConvexCastPreFilter castFilterData (m_body); NewtonWorldConvexCastReturnInfo prevInfo[PLAYER_CONTROLLER_MAX_CONTACTS]; dVector updir (matrix.RotateVector(m_upVector)); dVector scale; NewtonCollisionGetScale (m_upperBodyShape, &scale.m_x, &scale.m_y, &scale.m_z); //const dFloat radio = m_outerRadio * 4.0f; const dFloat radio = (m_outerRadio + m_restrainingDistance) * 4.0f; NewtonCollisionSetScale (m_upperBodyShape, m_height - m_stairStep, radio, radio); NewtonWorldConvexCastReturnInfo upConstratint; memset (&upConstratint, 0, sizeof (upConstratint)); upConstratint.m_normal[0] = m_upVector.m_x; upConstratint.m_normal[1] = m_upVector.m_y; upConstratint.m_normal[2] = m_upVector.m_z; upConstratint.m_normal[3] = m_upVector.m_w; for (int j = 0; (j < D_PLAYER_MAX_INTERGRATION_STEPS) && (normalizedTimeLeft > 1.0e-5f); j ++ ) { if ((veloc % veloc) < 1.0e-6f) { break; } dFloat timetoImpact; NewtonWorldConvexCastReturnInfo info[PLAYER_CONTROLLER_MAX_CONTACTS]; dVector destPosit (matrix.m_posit + veloc.Scale (timestep)); int contactCount = NewtonWorldConvexCast (world, &matrix[0][0], &destPosit[0], m_upperBodyShape, &timetoImpact, &castFilterData, CustomControllerConvexCastPreFilter::Prefilter, info, sizeof (info) / sizeof (info[0]), threadIndex); if (contactCount) { contactCount = manager->ProcessContacts (this, info, contactCount); } if (contactCount) { matrix.m_posit += veloc.Scale (timetoImpact * timestep); if (timetoImpact > 0.0f) { matrix.m_posit -= veloc.Scale (D_PLAYER_CONTACT_SKIN_THICKNESS / dSqrt (veloc % veloc)) ; } normalizedTimeLeft -= timetoImpact; dFloat speed[PLAYER_CONTROLLER_MAX_CONTACTS * 2]; dFloat bounceSpeed[PLAYER_CONTROLLER_MAX_CONTACTS * 2]; dVector bounceNormal[PLAYER_CONTROLLER_MAX_CONTACTS * 2]; for (int i = 1; i < contactCount; i ++) { dVector n0 (info[i-1].m_normal); for (int j = 0; j < i; j ++) { dVector n1 (info[j].m_normal); if ((n0 % n1) > 0.9999f) { info[i] = info[contactCount - 1]; i --; contactCount --; break; } } } int count = 0; if (!m_isJumping) { upConstratint.m_point[0] = matrix.m_posit.m_x; upConstratint.m_point[1] = matrix.m_posit.m_y; upConstratint.m_point[2] = matrix.m_posit.m_z; upConstratint.m_point[3] = matrix.m_posit.m_w; speed[count] = 0.0f; bounceNormal[count] = dVector (upConstratint.m_normal); bounceSpeed[count] = CalculateContactKinematics(veloc, &upConstratint); count ++; } for (int i = 0; i < contactCount; i ++) { speed[count] = 0.0f; bounceNormal[count] = dVector (info[i].m_normal); bounceSpeed[count] = CalculateContactKinematics(veloc, &info[i]); count ++; } for (int i = 0; i < prevContactCount; i ++) { speed[count] = 0.0f; bounceNormal[count] = dVector (prevInfo[i].m_normal); bounceSpeed[count] = CalculateContactKinematics(veloc, &prevInfo[i]); count ++; } dFloat residual = 10.0f; dVector auxBounceVeloc (0.0f, 0.0f, 0.0f, 0.0f); for (int i = 0; (i < D_PLAYER_MAX_SOLVER_ITERATIONS) && (residual > 1.0e-3f); i ++) { residual = 0.0f; for (int k = 0; k < count; k ++) { dVector normal (bounceNormal[k]); dFloat v = bounceSpeed[k] - normal % auxBounceVeloc; dFloat x = speed[k] + v; if (x < 0.0f) { v = 0.0f; x = 0.0f; } if (dAbs (v) > residual) { residual = dAbs (v); } auxBounceVeloc += normal.Scale (x - speed[k]); speed[k] = x; } } dVector velocStep (0.0f, 0.0f, 0.0f, 0.0f); for (int i = 0; i < count; i ++) { dVector normal (bounceNormal[i]); velocStep += normal.Scale (speed[i]); } veloc += velocStep; dFloat velocMag2 = velocStep % velocStep; if (velocMag2 < 1.0e-6f) { dFloat advanceTime = dMin (descreteTimeStep, normalizedTimeLeft * timestep); matrix.m_posit += veloc.Scale (advanceTime); normalizedTimeLeft -= advanceTime / timestep; } prevContactCount = contactCount; memcpy (prevInfo, info, prevContactCount * sizeof (NewtonWorldConvexCastReturnInfo)); } else { matrix.m_posit = destPosit; matrix.m_posit.m_w = 1.0f; break; } } NewtonCollisionSetScale (m_upperBodyShape, scale.m_x, scale.m_y, scale.m_z); // determine if player is standing on some plane dMatrix supportMatrix (matrix); supportMatrix.m_posit += updir.Scale (m_sphereCastOrigin); if (m_isJumping) { dVector dst (matrix.m_posit); UpdateGroundPlane (matrix, supportMatrix, dst, threadIndex); } else { step = dAbs (updir % veloc.Scale (timestep)); dFloat castDist = ((m_groundPlane % m_groundPlane) > 0.0f) ? m_stairStep : step; dVector dst (matrix.m_posit - updir.Scale (castDist * 2.0f)); UpdateGroundPlane (matrix, supportMatrix, dst, threadIndex); } // set player velocity, position and orientation NewtonBodySetVelocity(m_body, &veloc[0]); NewtonBodySetMatrix (m_body, &matrix[0][0]); }
void CustomCorkScrew::SubmitConstraints (dFloat timestep, int threadIndex) { dMatrix matrix0; dMatrix matrix1; // calculate the position of the pivot point and the Jacobian direction vectors, in global space. CalculateGlobalMatrix (matrix0, matrix1); // Restrict the movement on the pivot point along all two orthonormal axis direction perpendicular to the motion NewtonUserJointAddLinearRow (m_joint, &matrix0.m_posit[0], &matrix1.m_posit[0], &matrix0.m_up[0]); NewtonUserJointAddLinearRow (m_joint, &matrix0.m_posit[0], &matrix1.m_posit[0], &matrix0.m_right[0]); // two rows to restrict rotation around around the parent coordinate system dFloat sinAngle; dFloat cosAngle; CalculateYawAngle(matrix0, matrix1, sinAngle, cosAngle); NewtonUserJointAddAngularRow(m_joint, -dAtan2(sinAngle, cosAngle), &matrix1.m_up[0]); CalculateRollAngle(matrix0, matrix1, sinAngle, cosAngle); NewtonUserJointAddAngularRow(m_joint, -dAtan2(sinAngle, cosAngle), &matrix1.m_right[0]); // if limit are enable ... if (m_limitsLinearOn) { dFloat dist = (matrix0.m_posit - matrix1.m_posit) % matrix0.m_front; if (dist < m_minLinearDist) { // get a point along the up vector and set a constraint NewtonUserJointAddLinearRow (m_joint, &matrix0.m_posit[0], &matrix0.m_posit[0], &matrix0.m_front[0]); // allow the object to return but not to kick going forward NewtonUserJointSetRowMinimumFriction (m_joint, 0.0f); } else if (dist > m_maxLinearDist) { // get a point along the up vector and set a constraint NewtonUserJointAddLinearRow (m_joint, &matrix0.m_posit[0], &matrix0.m_posit[0], &matrix0.m_front[0]); // allow the object to return but not to kick going forward NewtonUserJointSetRowMaximumFriction (m_joint, 0.0f); } } CalculatePitchAngle (matrix0, matrix1, sinAngle, cosAngle); dFloat angle = -m_curJointAngle.Update (cosAngle, sinAngle); if (m_limitsAngularOn) { // the joint angle can be determine by getting the angle between any two non parallel vectors if (angle < m_minAngularDist) { dFloat relAngle = angle - m_minAngularDist; // the angle was clipped save the new clip limit //m_curJointAngle.m_angle = m_minAngularDist; // tell joint error will minimize the exceeded angle error NewtonUserJointAddAngularRow (m_joint, relAngle, &matrix0.m_front[0]); // need high stiffness here NewtonUserJointSetRowStiffness (m_joint, 1.0f); // allow the joint to move back freely NewtonUserJointSetRowMaximumFriction (m_joint, 0.0f); } else if (angle > m_maxAngularDist) { dFloat relAngle = angle - m_maxAngularDist; // the angle was clipped save the new clip limit //m_curJointAngle.m_angle = m_maxAngularDist; // tell joint error will minimize the exceeded angle error NewtonUserJointAddAngularRow (m_joint, relAngle, &matrix0.m_front[0]); // need high stiffness here NewtonUserJointSetRowStiffness (m_joint, 1.0f); // allow the joint to move back freely NewtonUserJointSetRowMinimumFriction (m_joint, 0.0f); } } if (m_angularmotorOn) { dVector omega0 (0.0f, 0.0f, 0.0f); dVector omega1 (0.0f, 0.0f, 0.0f); // get relative angular velocity NewtonBodyGetOmega(m_body0, &omega0[0]); if (m_body1) { NewtonBodyGetOmega(m_body1, &omega1[0]); } // calculate the desired acceleration dFloat relOmega = (omega0 - omega1) % matrix0.m_front; dFloat relAccel = m_angularAccel - m_angularDamp * relOmega; // if the motor capability is on, then set angular acceleration with zero angular correction NewtonUserJointAddAngularRow (m_joint, 0.0f, &matrix0.m_front[0]); // override the angular acceleration for this Jacobian to the desired acceleration NewtonUserJointSetRowAcceleration (m_joint, relAccel); } }
void CustomKinematicController::SubmitConstraints (dFloat timestep, int threadIndex) { // check if this is an impulsive time step if (timestep > 0.0f) { dMatrix matrix0; dVector v(0.0f); dVector w(0.0f); dVector cg(0.0f); dFloat invTimestep = 1.0f / timestep; // calculate the position of the pivot point and the Jacobian direction vectors, in global space. NewtonBodyGetOmega (m_body0, &w[0]); NewtonBodyGetVelocity (m_body0, &v[0]); NewtonBodyGetCentreOfMass (m_body0, &cg[0]); NewtonBodyGetMatrix (m_body0, &matrix0[0][0]); dVector p0 (matrix0.TransformVector (m_localHandle)); dVector pointVeloc (v + w * matrix0.RotateVector (m_localHandle - cg)); dVector relPosit (m_targetPosit - p0); dVector relVeloc (relPosit.Scale (invTimestep) - pointVeloc); dVector relAccel (relVeloc.Scale (invTimestep * 0.3f)); // Restrict the movement on the pivot point along all tree orthonormal direction NewtonUserJointAddLinearRow (m_joint, &p0[0], &m_targetPosit[0], &matrix0.m_front[0]); NewtonUserJointSetRowAcceleration (m_joint, relAccel % matrix0.m_front); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxLinearFriction); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxLinearFriction); NewtonUserJointAddLinearRow (m_joint, &p0[0], &m_targetPosit[0], &matrix0.m_up[0]); NewtonUserJointSetRowAcceleration (m_joint, relAccel % matrix0.m_up); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxLinearFriction); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxLinearFriction); NewtonUserJointAddLinearRow (m_joint, &p0[0], &m_targetPosit[0], &matrix0.m_right[0]); NewtonUserJointSetRowAcceleration (m_joint, relAccel % matrix0.m_right); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxLinearFriction); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxLinearFriction); if (m_pickMode) { dQuaternion rotation; NewtonBodyGetRotation (m_body0, &rotation.m_q0); if (m_targetRot.DotProduct (rotation) < 0.0f) { rotation.m_q0 *= -1.0f; rotation.m_q1 *= -1.0f; rotation.m_q2 *= -1.0f; rotation.m_q3 *= -1.0f; } dVector relOmega (rotation.CalcAverageOmega (m_targetRot, invTimestep) - w); dFloat mag = relOmega % relOmega; if (mag > 1.0e-6f) { dVector pin (relOmega.Scale (1.0f / mag)); dMatrix basis (dGrammSchmidt (pin)); dFloat relSpeed = dSqrt (relOmega % relOmega); dFloat relAlpha = relSpeed * invTimestep; NewtonUserJointAddAngularRow (m_joint, 0.0f, &basis.m_front[0]); NewtonUserJointSetRowAcceleration (m_joint, relAlpha); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxAngularFriction); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxAngularFriction); NewtonUserJointAddAngularRow (m_joint, 0.0f, &basis.m_up[0]); NewtonUserJointSetRowAcceleration (m_joint, 0.0f); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxAngularFriction); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxAngularFriction); NewtonUserJointAddAngularRow (m_joint, 0.0f, &basis.m_right[0]); NewtonUserJointSetRowAcceleration (m_joint, 0.0f); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxAngularFriction); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxAngularFriction); } else { dVector relAlpha (w.Scale (-invTimestep)); NewtonUserJointAddAngularRow (m_joint, 0.0f, &matrix0.m_front[0]); NewtonUserJointSetRowAcceleration (m_joint, relAlpha % matrix0.m_front); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxAngularFriction); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxAngularFriction); NewtonUserJointAddAngularRow (m_joint, 0.0f, &matrix0.m_up[0]); NewtonUserJointSetRowAcceleration (m_joint, relAlpha % matrix0.m_up); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxAngularFriction); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxAngularFriction); NewtonUserJointAddAngularRow (m_joint, 0.0f, &matrix0.m_right[0]); NewtonUserJointSetRowAcceleration (m_joint, relAlpha % matrix0.m_right); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxAngularFriction); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxAngularFriction); } } else { // this is the single handle pick mode, add some angular friction dVector relAlpha = w.Scale (-invTimestep); NewtonUserJointAddAngularRow (m_joint, 0.0f, &matrix0.m_front[0]); NewtonUserJointSetRowAcceleration (m_joint, relAlpha % matrix0.m_front); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxAngularFriction * 0.025f); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxAngularFriction * 0.025f); NewtonUserJointAddAngularRow (m_joint, 0.0f, &matrix0.m_up[0]); NewtonUserJointSetRowAcceleration (m_joint, relAlpha % matrix0.m_up); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxAngularFriction * 0.025f); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxAngularFriction * 0.025f); NewtonUserJointAddAngularRow (m_joint, 0.0f, &matrix0.m_right[0]); NewtonUserJointSetRowAcceleration (m_joint, relAlpha % matrix0.m_right); NewtonUserJointSetRowMinimumFriction (m_joint, -m_maxAngularFriction * 0.025f); NewtonUserJointSetRowMaximumFriction (m_joint, m_maxAngularFriction * 0.025f); } } }
void CustomDGRayCastCar::SubmitConstraints (dFloat timestep, int threadIndex) { // get the simulation time // dFloat invTimestep = 1.0f / timestep ; // get the vehicle global matrix, and use it in several calculations dMatrix bodyMatrix; NewtonBodyGetMatrix (m_body0, &bodyMatrix[0][0]); dMatrix chassisMatrix (m_localFrame * bodyMatrix); // get the chassis instantaneous linear and angular velocity in the local space of the chassis dVector bodyForce; dVector bodyOmega; dVector bodyVelocity; NewtonBodyGetVelocity (m_body0, &bodyVelocity[0]); NewtonBodyGetOmega (m_body0, &bodyOmega[0]); //static int xxx; //dTrace (("frame %d veloc(%f %f %f)\n", xxx, bodyVelocity[0], bodyVelocity[1], bodyVelocity[2])); //xxx ++; //if (xxx >= 210) { //xxx *=1; //bodyVelocity.m_x = 0; //bodyVelocity.m_z = 10; //NewtonBodySetVelocity (m_body0, &bodyVelocity[0]); //} // dVector normalForces (0.0f, 0.0f, 0.0f, 0.0f); // all tire is on air check m_vehicleOnAir = 0; // int constraintIndex = 0; for (int i = 0; i < m_tiresCount; i ++) { // dTrace (("tire: %d ", i)); Tire& tire = m_tires[i]; tire.m_tireIsOnAir = 1; // tire.m_tireIsConstrained = 0; tire.m_tireForceAcc = dVector(0.0f, 0.0f, 0.0f, 0.0f); // calculate all suspension matrices in global space and tire collision dMatrix suspensionMatrix (CalculateSuspensionMatrix (i, 0.0f) * chassisMatrix); // calculate the tire collision CalculateTireCollision (tire, suspensionMatrix, threadIndex); // calculate the linear velocity of the tire at the ground contact tire.m_tireAxelPositGlobal = chassisMatrix.TransformVector (tire.m_harpointInJointSpace - m_localFrame.m_up.Scale (tire.m_posit)); tire.m_tireAxelVelocGlobal = bodyVelocity + bodyOmega * (tire.m_tireAxelPositGlobal - chassisMatrix.m_posit); tire.m_lateralPinGlobal = chassisMatrix.RotateVector (tire.m_localAxisInJointSpace); tire.m_longitudinalPinGlobal = chassisMatrix.m_up * tire.m_lateralPinGlobal; if (tire.m_posit < tire.m_suspensionLenght ) { tire.m_tireIsOnAir = 0; tire.m_hitBodyPointVelocity = dVector (0.0f, 0.0f, 0.0f, 1.0f); if (tire.m_HitBody){ dMatrix matrix; dVector com; dVector omega; NewtonBodyGetOmega (tire.m_HitBody, &omega[0]); NewtonBodyGetMatrix (tire.m_HitBody, &matrix[0][0]); NewtonBodyGetCentreOfMass (tire.m_HitBody, &com[0]); NewtonBodyGetVelocity (tire.m_HitBody, &tire.m_hitBodyPointVelocity[0]); tire.m_hitBodyPointVelocity += (tire.m_contactPoint - matrix.TransformVector (com)) * omega; } // calculate the relative velocity dVector tireHubVeloc (tire.m_tireAxelVelocGlobal - tire.m_hitBodyPointVelocity); dFloat suspensionSpeed = - (tireHubVeloc % chassisMatrix.m_up); // now calculate the tire load at the contact point // Tire suspension distance and hard limit. dFloat distance = tire.m_suspensionLenght - tire.m_posit; _ASSERTE (distance <= tire.m_suspensionLenght); tire.m_tireLoad = - NewtonCalculateSpringDamperAcceleration (timestep, tire.m_springConst, distance, tire.m_springDamper, suspensionSpeed ); if ( tire.m_tireLoad < 0.0f ) { // since the tire is not a body with real mass it can only push the chassis. tire.m_tireLoad = 0.0f; } //this suspension is applying a normalize force to the car chassis, need to scales by the mass of the car tire.m_tireLoad *= (m_mass * 0.5f); // dTrace (("(load = %f) ", tire.m_tireLoad)); //tire.m_tireIsConstrained = (dAbs (tire.m_torque) < 0.3f); // convert the tire load force magnitude to a torque and force. // accumulate the force doe to the suspension spring and damper tire.m_tireForceAcc += chassisMatrix.m_up.Scale (tire.m_tireLoad); // calculate relative velocity at the tire center //dVector tireAxelRelativeVelocity (tire.m_tireAxelVeloc - tire.m_hitBodyPointVelocity); // axle linear speed //axelLinealSpeed = tireAxelRelativeVelocity % chassisMatrix.m_front; dFloat axelLinearSpeed = tireHubVeloc % chassisMatrix.m_front; // calculate tire rotation velocity at the tire radio //dVector tireAngularVelocity (tire.m_lateralPinGlobal.Scale (tire.m_angularVelocity)); //dVector tireRadius (tire.m_contactPoint - tire.m_tireAxelPositGlobal); //dVector tireRotationalVelocityAtContact (tireAngularVelocity * tireRadius); // calculate slip ratio and max longitudinal force //dFloat tireRotationSpeed = -(tireRotationalVelocityAtContact % tire.m_longitudinalPinGlobal); //dFloat slipRatioCoef = (dAbs (axelLinearSpeed) > 1.e-3f) ? ((tireRotationSpeed - axelLinearSpeed) / dAbs (axelLinearSpeed)) : 0.0f; //dTrace (("(slipRatio = %f) ", slipRatioCoef)); // calculate the formal longitudinal force the tire apply to the chassis //dFloat longitudinalForceMag = m_normalizedLongitudinalForce.GetValue (slipRatioCoef) * tire.m_tireLoad * tire.m_groundFriction; dFloat longitudinalForceMag = CalculateLongitudinalForce (i, axelLinearSpeed, tire.m_tireLoad * tire.m_groundFriction); // dTrace (("(longForce = %f) ", longitudinalForceMag)); #if 0 // now calculate relative velocity a velocity at contact point //dVector tireContactRelativeVelocity (tireAxelRelativeVelocity + tireRotationalVelocityAtContact); //dVector tireContactAbsoluteVelocity (tireHubVeloc + tireRotationalVelocityAtContact); // calculate the side slip as the angle between the tire lateral speed and longitudinal speed //dFloat lateralSpeed = tireContactRelativeVelocity % tire.m_lateralPin; dFloat lateralSpeed = tireHubVeloc % tire.m_lateralPinGlobal; dFloat sideSlipCoef = dAtan2 (dAbs (lateralSpeed), dAbs (axelLinearSpeed)); dFloat lateralFrictionForceMag = m_normalizedLateralForce.GetValue (sideSlipCoef) * tire.m_tireLoad * tire.m_groundFriction; // Apply brake, need some little fix here. // The fix is need to generate axial force when the brake is apply when the vehicle turn from the steer or on sliding. if ( tire.m_breakForce > 1.0e-3f ) { _ASSERTE (0); /* // row constrained force is save for later determine the dynamic state of this tire tire.m_isBrakingForceIndex = constraintIndex; constraintIndex ++; frictionCircleMag = tire.m_tireLoad * tire.m_groundFriction; if (tire.m_breakForce > frictionCircleMag) { tire.m_breakForce = frictionCircleMag; } //NewtonUserJointAddLinearRow ( m_joint, &tire.m_tireAxelPosit[0], &tire.m_tireAxelPosit[0], &chassisMatrix.m_front.m_x ); NewtonUserJointAddLinearRow (m_joint, &tire.m_tireAxelPosit[0], &tire.m_tireAxelPosit[0], &tire.m_longitudinalPin.m_x); NewtonUserJointSetRowMaximumFriction( m_joint, tire.m_breakForce); NewtonUserJointSetRowMinimumFriction( m_joint, -tire.m_breakForce); // there is a longitudinal force that will reduce the lateral force, we need to recalculate the lateral force tireForceMag = lateralFrictionForceMag * lateralFrictionForceMag + tire.m_breakForce * tire.m_breakForce; if (tireForceMag > (frictionCircleMag * frictionCircleMag)) { lateralFrictionForceMag *= 0.25f * frictionCircleMag / dSqrt (tireForceMag); } */ } //project the longitudinal and lateral forces over the circle of friction for this tire; dFloat frictionCircleMag = tire.m_tireLoad * tire.m_groundFriction; dFloat tireForceMag = lateralFrictionForceMag * lateralFrictionForceMag + longitudinalForceMag * longitudinalForceMag; if (tireForceMag > (frictionCircleMag * frictionCircleMag)) { dFloat invMag2; invMag2 = frictionCircleMag / dSqrt (tireForceMag); longitudinalForceMag *= invMag2; lateralFrictionForceMag *= invMag2; } // submit this constraint for calculation of side slip forces lateralFrictionForceMag = dAbs (lateralFrictionForceMag); tire.m_lateralForceIndex = constraintIndex; constraintIndex ++; NewtonUserJointAddLinearRow (m_joint, &tire.m_tireAxelPositGlobal[0], &tire.m_tireAxelPositGlobal[0], &tire.m_lateralPinGlobal[0]); NewtonUserJointSetRowMaximumFriction (m_joint, lateralFrictionForceMag); NewtonUserJointSetRowMinimumFriction (m_joint, -lateralFrictionForceMag); #endif // accumulate the longitudinal force dVector tireForce (tire.m_longitudinalPinGlobal.Scale (longitudinalForceMag)); tire.m_tireForceAcc += tireForce; // now we apply the combined tire force generated by this tire, to the car chassis dVector r (tire.m_tireAxelPositGlobal - chassisMatrix.m_posit); // add the toque the tire asserts on the car body (principle of action reaction) dVector torque (r * tire.m_tireForceAcc - tire.m_lateralPinGlobal.Scale (tire.m_torque)); NewtonBodyAddForce (m_body0, &tire.m_tireForceAcc[0]); NewtonBodyAddTorque( m_body0, &torque[0] ); /* // calculate the net torque on the tire dFloat tireTorqueMag = -((tireRadius * tireForce) % tire.m_lateralPinGlobal); if (dAbs (tireTorqueMag) > dAbs (tire.m_torque)) { // the tire reaction force cannot be larger than the applied engine torque // when this happens the net torque is zero and the tire is constrained to the vehicle linear motion tire.m_tireIsConstrained = 1; tireTorqueMag = tire.m_torque; } tire.m_torque -= tireTorqueMag; */ // normalForces += tire.m_tireForceAcc; } else { // there is a next torque on the tire tire.m_torque -= tire.m_angularVelocity * tire.m_Ixx * DG_TIRE_VISCUOS_DAMP; tire.m_angularVelocity += tire.m_torque * tire.m_IxxInv * timestep; if (m_tires[i].m_breakForce > dFloat (0.1f)) { tire.m_angularVelocity = 0.0f; } } // dTrace (("(tireTorque = %f) ", tire.m_torque)); // spin the tire by the angular velocity tire.m_spinAngle = dMod (tire.m_spinAngle + tire.m_angularVelocity * timestep, 3.14159265f * 2.0f); // reset the tire torque tire.m_torque = 0.0f; tire.m_breakForce = 0.0f; // dTrace (("\n")); } // add a row to simulate the engine rolling resistance // float bodyWeight = dAbs (normalForces % chassisMatrix.m_up) * m_rollingResistance; // if (bodyWeight > (1.0e-3f) * m_mass) { // NewtonUserJointAddLinearRow (m_joint, &chassisMatrix.m_posit[0], &chassisMatrix.m_posit[0], &chassisMatrix.m_front[0]); // NewtonUserJointSetRowMaximumFriction( m_joint, bodyWeight); // NewtonUserJointSetRowMinimumFriction( m_joint, -bodyWeight); // } }
Ogre::Vector3 Body::getOmega() { Ogre::Vector3 ret; NewtonBodyGetOmega( m_body, &ret.x ); return ret; }
void CalculatePickForceAndTorque (const NewtonBody* const body, const dVector& pointOnBodyInGlobalSpace, const dVector& targetPositionInGlobalSpace, dFloat timestep) { dVector com; dMatrix matrix; dVector omega0; dVector veloc0; dVector omega1; dVector veloc1; dVector pointVeloc; const dFloat stiffness = 0.3f; const dFloat angularDamp = 0.95f; dFloat invTimeStep = 1.0f / timestep; NewtonWorld* const world = NewtonBodyGetWorld (body); NewtonWorldCriticalSectionLock (world, 0); // calculate the desired impulse NewtonBodyGetMatrix(body, &matrix[0][0]); NewtonBodyGetOmega (body, &omega0[0]); NewtonBodyGetVelocity (body, &veloc0[0]); NewtonBodyGetPointVelocity (body, &pointOnBodyInGlobalSpace[0], &pointVeloc[0]); dVector deltaVeloc (targetPositionInGlobalSpace - pointOnBodyInGlobalSpace); deltaVeloc = deltaVeloc.Scale (stiffness * invTimeStep) - pointVeloc; for (int i = 0; i < 3; i ++) { dVector veloc (0.0f, 0.0f, 0.0f, 0.0f); veloc[i] = deltaVeloc[i]; NewtonBodyAddImpulse (body, &veloc[0], &pointOnBodyInGlobalSpace[0]); } // damp angular velocity NewtonBodyGetOmega (body, &omega1[0]); NewtonBodyGetVelocity (body, &veloc1[0]); omega1 = omega1.Scale (angularDamp); // restore body velocity and angular velocity NewtonBodySetOmega (body, &omega0[0]); NewtonBodySetVelocity(body, &veloc0[0]); // convert the delta velocity change to a external force and torque dFloat Ixx; dFloat Iyy; dFloat Izz; dFloat mass; NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz); dVector angularMomentum (Ixx, Iyy, Izz); angularMomentum = matrix.RotateVector (angularMomentum.CompProduct(matrix.UnrotateVector(omega1 - omega0))); dVector force ((veloc1 - veloc0).Scale (mass * invTimeStep)); dVector torque (angularMomentum.Scale(invTimeStep)); NewtonBodyAddForce(body, &force[0]); NewtonBodyAddTorque(body, &torque[0]); // make sure the body is unfrozen, if it is picked NewtonBodySetSleepState (body, 0); NewtonWorldCriticalSectionUnlock (world); }
void CustomDGRayCastCar::SubmitConstraints (dFloat timestep, int threadIndex) { int constraintIndex; dFloat invTimestep; dMatrix bodyMatrix; // get the simulation time invTimestep = 1.0f / timestep ; // get the vehicle global matrix, and use it in several calculations NewtonBodyGetMatrix (m_body0, &bodyMatrix[0][0]); dMatrix chassisMatrix (m_localFrame * bodyMatrix); // get the chassis instantaneous linear and angular velocity in the local space of the chassis dVector bodyOmega; dVector bodyVelocity; NewtonBodyGetVelocity (m_body0, &bodyVelocity[0]); NewtonBodyGetOmega (m_body0, &bodyOmega[0]); // all tire is on air check m_vehicleOnAir = 0; constraintIndex = 0; for ( int i = 0; i < m_tiresCount; i ++ ) { Tire& tire = m_tires[i]; tire.m_tireIsOnAir = 1; tire.m_tireIsConstrained = 0; tire.m_tireForceAcc = dVector(0.0f, 0.0f, 0.0f, 0.0f); // calculate all suspension matrices in global space and tire collision dMatrix suspensionMatrix (CalculateSuspensionMatrix (i, 0.0f) * chassisMatrix); // calculate the tire collision CalculateTireCollision (tire, suspensionMatrix, threadIndex); // calculate the linear velocity of the tire at the ground contact tire.m_tireAxelPosit = chassisMatrix.TransformVector( tire.m_harpoint - m_localFrame.m_up.Scale (tire.m_posit)); tire.m_tireAxelVeloc = bodyVelocity + bodyOmega * (tire.m_tireAxelPosit - chassisMatrix.m_posit); tire.m_lateralPin = ( chassisMatrix.RotateVector ( tire.m_localAxis ) ); tire.m_longitudinalPin = ( chassisMatrix.m_up * tire.m_lateralPin ); if (tire.m_posit < tire.m_suspensionLenght ) { dFloat distance; dFloat sideSlipCoef; dFloat slipRatioCoef; dFloat tireForceMag; dFloat tireTorqueMag; dFloat suspensionSpeed; dFloat axelLinealSpeed; dFloat tireRotationSpeed; dFloat frictionCircleMag; dFloat longitudinalForceMag; dFloat lateralFrictionForceMag; tire.m_tireIsOnAir = 0; tire.m_hitBodyPointVelocity = dVector (0.0f, 0.0f, 0.0f, 1.0f); if (tire.m_HitBody){ dMatrix matrix; dVector com; dVector omega; NewtonBodyGetOmega (tire.m_HitBody, &omega[0]); NewtonBodyGetMatrix (tire.m_HitBody, &matrix[0][0]); NewtonBodyGetCentreOfMass (tire.m_HitBody, &com[0]); NewtonBodyGetVelocity (tire.m_HitBody, &tire.m_hitBodyPointVelocity[0]); tire.m_hitBodyPointVelocity += (tire.m_contactPoint - matrix.TransformVector (com)) * omega; } // calculate the relative velocity dVector relVeloc (tire.m_tireAxelVeloc - tire.m_hitBodyPointVelocity); suspensionSpeed = - (relVeloc % chassisMatrix.m_up); // now calculate the tire load at the contact point // Tire suspension distance and hard limit. distance = tire.m_suspensionLenght - tire.m_posit; _ASSERTE (distance <= tire.m_suspensionLenght); tire.m_tireLoad = - NewtonCalculateSpringDamperAcceleration (timestep, tire.m_springConst, distance, tire.m_springDamper, suspensionSpeed ); if ( tire.m_tireLoad < 0.0f ) { // since the tire is not a body with real mass it can only push the chassis. tire.m_tireLoad = 0.0f; } //this suspension is applying a normalize force to the car chassis, need to scales by the mass of the car tire.m_tireLoad *= (m_mass * 0.5f); tire.m_tireIsConstrained = (dAbs (tire.m_torque) < 0.3f); // convert the tire load force magnitude to a torque and force. // accumulate the force doe to the suspension spring and damper tire.m_tireForceAcc += chassisMatrix.m_up.Scale (tire.m_tireLoad); // calculate relative velocity at the tire center dVector tireAxelRelativeVelocity (tire.m_tireAxelVeloc - tire.m_hitBodyPointVelocity); // axle linear speed axelLinealSpeed = tireAxelRelativeVelocity % chassisMatrix.m_front; // calculate tire rotation velocity at the tire radio dVector tireAngularVelocity (tire.m_lateralPin.Scale (tire.m_angularVelocity)); dVector tireRadius (tire.m_contactPoint - tire.m_tireAxelPosit); dVector tireRotationalVelocityAtContact (tireAngularVelocity * tireRadius); longitudinalForceMag = 0.0f; // if (!tire.m_tireIsConstrained) { // calculate slip ratio and max longitudinal force tireRotationSpeed = tireRotationalVelocityAtContact % tire.m_longitudinalPin; slipRatioCoef = (dAbs (axelLinealSpeed) > 1.e-3f) ? ((-tireRotationSpeed - axelLinealSpeed) / dAbs (axelLinealSpeed)) : 0.0f; // calculate the formal longitudinal force the tire apply to the chassis longitudinalForceMag = m_normalizedLongitudinalForce.GetValue (slipRatioCoef) * tire.m_tireLoad * tire.m_groundFriction; // } // now calculate relative velocity a velocity at contact point dVector tireContactRelativeVelocity (tireAxelRelativeVelocity + tireRotationalVelocityAtContact); // calculate the sideslip as the angle between the tire lateral speed and longitudila speed sideSlipCoef = dAtan2 (dAbs (tireContactRelativeVelocity % tire.m_lateralPin), dAbs (axelLinealSpeed)); lateralFrictionForceMag = m_normalizedLateralForce.GetValue (sideSlipCoef) * tire.m_tireLoad * tire.m_groundFriction; // Apply brake, need some little fix here. // The fix is need to generate axial force when the brake is apply when the vehicle turn from the steer or on sliding. if ( tire.m_breakForce > 1.0e-3f ) { // row constrained force is save for later determine the dynamic state of this tire tire.m_isBrakingForceIndex = constraintIndex; constraintIndex ++; frictionCircleMag = tire.m_tireLoad * tire.m_groundFriction; if (tire.m_breakForce > frictionCircleMag) { tire.m_breakForce = frictionCircleMag; } //NewtonUserJointAddLinearRow ( m_joint, &tire.m_tireAxelPosit[0], &tire.m_tireAxelPosit[0], &chassisMatrix.m_front.m_x ); NewtonUserJointAddLinearRow (m_joint, &tire.m_tireAxelPosit[0], &tire.m_tireAxelPosit[0], &tire.m_longitudinalPin.m_x); NewtonUserJointSetRowMaximumFriction( m_joint, tire.m_breakForce); NewtonUserJointSetRowMinimumFriction( m_joint, -tire.m_breakForce); // there is a longitudinal force that will reduce the lateral force, we need to recalculate the lateral force tireForceMag = lateralFrictionForceMag * lateralFrictionForceMag + tire.m_breakForce * tire.m_breakForce; if (tireForceMag > (frictionCircleMag * frictionCircleMag)) { lateralFrictionForceMag *= 0.25f * frictionCircleMag / dSqrt (tireForceMag); } } //project the longitudinal and lateral forces over the circle of friction for this tire; frictionCircleMag = tire.m_tireLoad * tire.m_groundFriction; tireForceMag = lateralFrictionForceMag * lateralFrictionForceMag + longitudinalForceMag * longitudinalForceMag; if (tireForceMag > (frictionCircleMag * frictionCircleMag)) { dFloat invMag2; invMag2 = frictionCircleMag / dSqrt (tireForceMag); longitudinalForceMag *= invMag2; lateralFrictionForceMag *= invMag2; } // submit this constraint for calculation of side slip forces lateralFrictionForceMag = dAbs (lateralFrictionForceMag); tire.m_lateralForceIndex = constraintIndex; constraintIndex ++; NewtonUserJointAddLinearRow (m_joint, &tire.m_tireAxelPosit[0], &tire.m_tireAxelPosit[0], &tire.m_lateralPin[0]); NewtonUserJointSetRowMaximumFriction (m_joint, lateralFrictionForceMag); NewtonUserJointSetRowMinimumFriction (m_joint, -lateralFrictionForceMag); // accumulate the longitudinal force dVector tireForce (tire.m_longitudinalPin.Scale (longitudinalForceMag)); tire.m_tireForceAcc += tireForce; // now we apply the combined tire force generated by this tire, to the car chassis dVector torque ((tire.m_tireAxelPosit - chassisMatrix.m_posit) * tire.m_tireForceAcc); NewtonBodyAddForce (m_body0, &tire.m_tireForceAcc[0]); NewtonBodyAddTorque( m_body0, &torque[0] ); // calculate the net torque on the tire tireTorqueMag = -((tireRadius * tireForce) % tire.m_lateralPin); if (dAbs (tireTorqueMag) > dAbs (tire.m_torque)) { // the tire reaction force can no be larger than the applied engine torque // when this happens the net torque is zero and the tire is constrained to the vehicle linear motion tire.m_tireIsConstrained = 1; tireTorqueMag = tire.m_torque; } tire.m_torque -= tireTorqueMag; } } }
void* dNewtonBody::GetOmega() { NewtonBodyGetOmega(m_body, &m_omega.m_x); return &m_omega; }