PxVehicleDriveSimData4W Vehicle::initDriveSimData(PxVehicleWheelsSimData* wheelsSimData) { PxVehicleDriveSimData4W driveSimData; //Diff PxVehicleDifferential4WData diff; diff.mType = PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD; driveSimData.setDiffData(diff); //Engine PxVehicleEngineData engine; engine.mPeakTorque = 500.0f; engine.mMaxOmega = 300.0f;//approx 6000 rpm driveSimData.setEngineData(engine); // TODO: Don't want gears. Will // Changing switch time to 0 be good enough for that? //Gears PxVehicleGearsData gears; gears.mSwitchTime = 0.0f; driveSimData.setGearsData(gears); //Clutch PxVehicleClutchData clutch; clutch.mStrength = 10.0f; driveSimData.setClutchData(clutch); //Ackermann steer accuracy PxVehicleAckermannGeometryData ackermann; ackermann.mAccuracy = 1.0f; ackermann.mAxleSeparation = wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z; ackermann.mFrontWidth = wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x; ackermann.mRearWidth = wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).x; driveSimData.setAckermannGeometryData(ackermann); return driveSimData; }
void SetupDriveHelper(const UWheeledVehicleMovementComponent4W* VehicleData, const PxVehicleWheelsSimData* PWheelsSimData, PxVehicleDriveSimData4W& DriveData) { PxVehicleDifferential4WData DifferentialSetup; GetVehicleDifferential4WSetup(VehicleData->DifferentialSetup, DifferentialSetup); DriveData.setDiffData(DifferentialSetup); PxVehicleEngineData EngineSetup; GetVehicleEngineSetup(VehicleData->EngineSetup, EngineSetup); DriveData.setEngineData(EngineSetup); PxVehicleClutchData ClutchSetup; ClutchSetup.mStrength = VehicleData->ClutchStrength; DriveData.setClutchData(ClutchSetup); FVector WheelCentreOffsets[4]; WheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_LEFT] = P2UVector(PWheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT)); WheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT] = P2UVector(PWheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT)); WheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_LEFT] = P2UVector(PWheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT)); WheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_RIGHT] = P2UVector(PWheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT)); PxVehicleAckermannGeometryData AckermannSetup; AckermannSetup.mAccuracy = VehicleData->AckermannAccuracy; AckermannSetup.mAxleSeparation = FMath::Abs(WheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].X - WheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_LEFT].X); AckermannSetup.mFrontWidth = FMath::Abs(WheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].Y - WheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].Y); AckermannSetup.mRearWidth = FMath::Abs(WheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].Y - WheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_LEFT].Y); DriveData.setAckermannGeometryData(AckermannSetup); PxVehicleGearsData GearSetup; GetVehicleGearSetup(VehicleData->GearSetup, GearSetup); DriveData.setGearsData(GearSetup); PxVehicleAutoBoxData AutoBoxSetup; GetVehicleAutoBoxSetup(VehicleData->AutoBoxSetup, AutoBoxSetup); DriveData.setAutoBoxData(AutoBoxSetup); }
bool CTank::CreateTankActor( CPhysX * pPhysX ) { if( !LoadData( "InitShader.lua" ) ) return false; // CParamTank* pParamTank = new CParamTank; // // if( !CLua::LoadParamTank( "", &pParamTank ) ) // { // // } if( GameObject * pBody = GetDetail( BODY ) ) { if ( pBody->CreateTriangleMesh( pPhysX ) ) { pBody->Update( 0.f ); PxTriangleMesh* triangleMesh = pBody->GetTriangleMesh(); D3DXVECTOR3 Position = pBody->GetPosition(); //D3DXComputeBoundingBox(Vertices, g_pMesh->GetNumVertices(), FVFVertexSize, &pMin, &pMax); //PxRigidDynamic* pRigDynAct = pPhysX->GetPhysics()->createRigidDynamic( PxTransform( physx::PxVec3( Position.x, Position.y, Position.z ) ) ); // PxRigidDynamic* pRigDynAct = PxCreateDynamic( *pPhysX->GetPhysics(), PxTransform( physx::PxVec3( Position.x, Position.y, Position.z ) ), PxBoxGeometry( 14.f, 4.6f, 6.f ), *pMaterial, 1.f ); // // if( pRigDynAct && pMaterial && triangleMesh ) // { // //pRigDynAct->createShape( PxTriangleMeshGeometry( triangleMesh ), *pMaterial ); // // pRigDynAct->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, false); // pRigDynAct->setActorFlag( PxActorFlag::eVISUALIZATION, true ); // pRigDynAct->setAngularDamping( 0.5f ); // //pRigDynAct->setMass( 10000.f ); // PxRigidBodyExt::updateMassAndInertia( *pRigDynAct, 10.f ); // // if( pMaterial ) // pPhysX->PushMaterial( pMaterial ); // // pPhysX->AddActorScene( pRigDynAct ); // m_pActor = pRigDynAct; // // return true; // } const int nWheels = 12; PxF32 chassisMass = 1500.f; const PxF32 wheelMass = 50.f; PxF32 fShift = -0.85f; PxVec3 wheelCentreOffsets[ nWheels ]; for( int i = 0; i < nWheels/2; ++i ) { wheelCentreOffsets[ i*2 ] = PxVec3( -1.2f, -0.5f, 2.1f + i * fShift ); wheelCentreOffsets[ i*2+1 ] = PxVec3( 1.2f, -0.5f, 2.1f + i * fShift ); } // размеры корпуса const PxVec3 chassisDims( 2.4f, 1.f, 6.f );// = computeChassisAABBDimensions(chassisConvexMesh); // Начало координат находится в центре шасси сетки // Установить центр масс будет ниже этой точки const PxVec3 chassisCMOffset = PxVec3( 0.f, -chassisDims.y * 0.5f - 0.65f, 0.f ); PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate( nWheels ); PxVehicleWheelsSimData& wheelsData = *wheelsSimData; PxVehicleDriveSimData4W driveData; PxVec3 chassisMOI( (chassisDims.y*chassisDims.y + chassisDims.z * chassisDims.z) * chassisMass / 12.f, (chassisDims.x*chassisDims.x + chassisDims.z * chassisDims.z) * chassisMass / 12.f, (chassisDims.x*chassisDims.x + chassisDims.y * chassisDims.y) * chassisMass / 12.f); // структура шасси PxVehicleChassisData chassisData; chassisData.mMass = chassisMass; // Масса транспортного средства жесткой актер тела chassisData.mMOI = chassisMOI; // Момент инерции автомобиля жесткая актер тела. chassisData.mCMOffset = chassisCMOffset; // Центр масс смещение автомобиля жесткая актер тела. // Немного настройки здесь.Автомобиль будет иметь более отзывчивым поворот, если мы сведем // у-компоненты шасси момента инерции. chassisMOI.y *= 0.8f; const PxF32 massRear = 0.5f * chassisMass * ( chassisDims.z - 3 * chassisCMOffset.z ) / chassisDims.z; const PxF32 massFront = massRear; //Extract the wheel radius and width from the wheel convex meshes PxF32 wheelWidths[ nWheels ] = {0.f}; PxF32 wheelRadii[ nWheels ] = {0.f}; for( PxU32 i = 0; i < nWheels; ++i ) { wheelWidths[ i ] = 0.5f; wheelRadii [ i ] = 0.32f; } // Теперь вычислим колеса массы и инерции компонентов вокруг оси оси PxF32 wheelMOIs[ nWheels ]; for( PxU32 i = 0; i < nWheels; ++i ) { wheelMOIs[ i ] = 0.5f * wheelMass * wheelRadii[ i ] * wheelRadii[ i ]; } // Давайте создадим структуру данных колеса теперь с радиусом, массы и МВД PxVehicleWheelData wheels[ nWheels ]; for(PxU32 i = 0; i < nWheels; ++i ) { wheels[ i ].mRadius = wheelRadii[ i ]; // Радиус блок, который включает в себя колеса металл плюс резиновые шины wheels[ i ].mMass = wheelMass; // Масса колеса плюс шины wheels[ i ].mMOI = wheelMOIs[ i ]; // Момент инерции колеса wheels[ i ].mWidth = wheelWidths[ i ]; // Максимальная ширина блок, который включает в себя колеса плюс шин //wheels[ i ].mMaxHandBrakeTorque = 0.f; // Отключение стояночного тормоза от передних колес и позволяют для задних колес //wheels[ i ].mMaxSteer = 0.f; // Включить рулевого управления для передних колес и отключить для передних колес //wheels[ i ].mDampingRate = 1.f; // Скорость затухания описывает скорость, с которой свободно вращающееся колесо теряет скорость вращения } //Let's set up the tire data structures now. //Put slicks on the front tires and wets on the rear tires. PxVehicleTireData tires[ nWheels ]; for(PxU32 i = 0; i < nWheels; ++i ) { tires[ i ].mType = 1; // тип сцепления шин с поверхностью } // Структура данных подвески PxVehicleSuspensionData susps[ nWheels ]; for( PxU32 i = 0; i < nWheels; i++ ) { susps[ i ].mMaxCompression = 0.03f; // Максимальное сжатие пружинной подвески susps[ i ].mMaxDroop = 0.03f; // Максимальное удлинение пружинной подвески susps[ i ].mSpringStrength = 20000.f; // пружинная сила подвески блока susps[ i ].mSpringDamperRate = 500.f; susps[ i ].mSprungMass = chassisMass / nWheels; // Масса транспортного средства, которая поддерживается пружинная подвеска, указанных в кг. } PxVec3 suspTravelDirections[ nWheels ]; PxVec3 wheelCentreCMOffsets[ nWheels ]; PxVec3 suspForceAppCMOffsets[ nWheels ]; PxVec3 tireForceAppCMOffsets[ nWheels ]; for( PxU32 i = 0 ; i < nWheels; ++i ) { wheelCentreCMOffsets [ i ] = wheelCentreOffsets[ i ] - chassisCMOffset; suspForceAppCMOffsets[ i ] = PxVec3( wheelCentreCMOffsets[ i ].x, -0.3f, wheelCentreCMOffsets[ i ].z ); tireForceAppCMOffsets[ i ] = PxVec3( wheelCentreCMOffsets[ i ].x, -0.3f, wheelCentreCMOffsets[ i ].z ); suspTravelDirections [ i ] = PxVec3( 0, -1, 0 ); // направление подвески } // Теперь добавьте колеса, шины и подвеска данных for( PxU32 i = 0; i < nWheels; ++i ) { wheelsData.setWheelData( i, wheels[ i ] ); // установить данные колеса wheelsData.setTireData( i, tires[ i ] ); // Установите шину данных колеса wheelsData.setSuspensionData( i, susps[ i ] ); // Установите подвеску данные колеса wheelsData.setSuspTravelDirection( i, suspTravelDirections[ i ] ); // Установить направление движения подвески колес wheelsData.setWheelCentreOffset( i, wheelCentreCMOffsets[ i ] ); // Установить смещение от центра жесткой тело массой в центре колеса wheelsData.setSuspForceAppPointOffset( i, suspForceAppCMOffsets[ i ] ); // Установить приложение точкой подвески силу подвески колес wheelsData.setTireForceAppPointOffset( i, tireForceAppCMOffsets[ i ] ); // Установить приложение точку шин силу шинах колес } //Diff PxVehicleDifferential4WData diff; diff.mType = PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD; driveData.setDiffData( diff ); //Engine PxVehicleEngineData engine; engine.mPeakTorque = 300.f; // максимальная скорость вращения двигателя engine.mMaxOmega = 400.f; // Максимальный крутящий момент доступен обратиться к двигателю engine.mDampingRateFullThrottle = 0.15f; // скорость затухания двигатель при полностью открытой дроссельной заслонке engine.mDampingRateZeroThrottleClutchEngaged = 8.f; // скорость затухания двигатель при нулевой газ при включении сцепления engine.mDampingRateZeroThrottleClutchDisengaged = 0.35f; // Краткие скорость затухания двигатель при нулевой газ при выключенном сцеплении (на нейтральной передаче) driveData.setEngineData( engine ); //Gears PxVehicleGearsData gears; gears.mSwitchTime = 0.5f; driveData.setGearsData( gears ); // Прочность сцепления PxVehicleClutchData clutch; clutch.mStrength = PxVehicleGearsData::eMAX_NUM_GEAR_RATIOS; driveData.setClutchData( clutch ); //Ackermann steer accuracy PxVehicleAckermannGeometryData ackermann; ackermann.mAccuracy = 0.1f; ackermann.mAxleSeparation = wheelCentreOffsets[ 0 ].z - wheelCentreOffsets[ nWheels - 1 ].z; // Расстояние между центром передней оси и центром задней оси ackermann.mFrontWidth = wheelCentreOffsets[ 0 ].x - wheelCentreOffsets[ 1 ].x; // Расстояние между центральной точке два передних колеса ackermann.mRearWidth = wheelCentreOffsets[ nWheels - 2 ].x - wheelCentreOffsets[ nWheels - 1 ].x; // Расстояние между центральной точке два задних колеса driveData.setAckermannGeometryData(ackermann); PxTriangleMesh * pTriangleMesh = 0; D3DXVECTOR3 vPosition; if( GameObject * pRoller = GetDetail( WHEEL_LEFT_1ST ) ) { if( pRoller->CreateTriangleMesh( pPhysX ) ) { pRoller->Update( 0.f ); pTriangleMesh = pRoller->GetTriangleMesh(); Position = pRoller->GetPosition(); } } // Нам нужно добавить колеса столкновения форм, их местный позы, материал для колес, и моделирование фильтра для колес PxTriangleMeshGeometry WheelGeom( pTriangleMesh ); PxGeometry* wheelGeometries[ nWheels ] = {0}; PxTransform wheelLocalPoses[ nWheels ]; for( PxU32 i = 0; i < nWheels; ++i ) { wheelGeometries[ i ] = &WheelGeom; wheelLocalPoses[ i ] = PxTransform::createIdentity(); } PxMaterial* pMaterial = pPhysX->GetPhysics()->createMaterial( 0.5f, 0.5f, 0.1f ); //коэффициенты трения скольжения и покоя(Dynamic friction,Static friction), коэффициент упругости const PxMaterial& wheelMaterial = *pMaterial; PxFilterData wheelCollFilterData; wheelCollFilterData.word0 = COLLISION_FLAG_WHEEL; wheelCollFilterData.word1 = COLLISION_FLAG_WHEEL_AGAINST; // Нам нужно добавить шасси столкновения форм, их местный позы, материала для шасси и моделирования фильтр для шасси. //PxBoxGeometry chassisConvexGeom( 1.5f, 0.3f, 4.f ); PxBoxGeometry chassisConvexGeom( chassisDims.x/2, chassisDims.y/2, chassisDims.z/2 ); const PxGeometry* chassisGeoms = &chassisConvexGeom; const PxTransform chassisLocalPoses = PxTransform::createIdentity(); const PxMaterial& chassisMaterial = *pMaterial; PxFilterData chassisCollFilterData; chassisCollFilterData.word0 = COLLISION_FLAG_CHASSIS; chassisCollFilterData.word1 = COLLISION_FLAG_CHASSIS_AGAINST; // Создание фильтра запроса данных для автомобилей, чтобы машины не пытайтесь ездить на себя. PxFilterData vehQryFilterData; SampleVehicleSetupVehicleShapeQueryFilterData( &vehQryFilterData ); PxRigidDynamic* vehActor = pPhysX->GetPhysics()->createRigidDynamic( PxTransform::createIdentity() ); //Add all the wheel shapes to the actor. for( PxU32 i = 0; i < nWheels; ++i ) { PxShape* wheelShape=vehActor->createShape( *wheelGeometries[ i ], wheelMaterial ); wheelShape->setQueryFilterData( vehQryFilterData ); wheelShape->setSimulationFilterData( wheelCollFilterData ); wheelShape->setLocalPose( wheelLocalPoses[ i ] ); wheelShape->setFlag( PxShapeFlag::eSIMULATION_SHAPE, true ); } //Add the chassis shapes to the actor PxShape* chassisShape = vehActor->createShape( *chassisGeoms, chassisMaterial ); chassisShape->setQueryFilterData( vehQryFilterData ); chassisShape->setSimulationFilterData( chassisCollFilterData ); chassisShape->setLocalPose( PxTransform( physx::PxVec3( 0, 0, 0 ) ) ); vehActor->setMass( chassisData.mMass ); vehActor->setMassSpaceInertiaTensor( chassisData.mMOI ); vehActor->setCMassLocalPose( PxTransform( chassisData.mCMOffset, PxQuat::createIdentity() ) ); vehActor->setGlobalPose( PxTransform( physx::PxVec3( 0, 8, 0 ), PxQuat::createIdentity() ) ); PxVehicleDriveTank* pTank = PxVehicleDriveTank::allocate( nWheels ); pTank->setup( pPhysX->GetPhysics(), vehActor, *wheelsSimData, driveData, nWheels ); pPhysX->AddActorScene( vehActor ); m_pActor = vehActor; pPhysX->AddTank( pTank ); //Free the sim data because we don't need that any more. wheelsSimData->free(); //pTank->setDriveModel( PxVehicleDriveTank::eDRIVE_MODEL_SPECIAL ); pTank->setToRestState(); pTank->mDriveDynData.setUseAutoGears( true ); return true; } } return false; }
void CreateVehicle4WSimulationData( PxConvexMesh* chassisConvexMesh, PxConvexMesh** wheelConvexMeshes, const PxVec3* wheelCenterOffsets, PxVehicleWheelsSimData& wheelsData, PxVehicleDriveSimData4W& driveData, PhysXVehicleInitData* generalData, PhysXVehicleInitData** wheelDatas ) { float chassisMass = generalData->GetFloatParameter( "massChassis" ); PxF32 wheelWidths[ 4 ]; PxF32 wheelRadii[ 4 ]; ComputeWheelWidthsAndRadii( wheelConvexMeshes, wheelWidths, wheelRadii ); //Wheels for( int n = 0; n < 4; n++ ) { PhysXVehicleInitData* wheelInitData = wheelDatas[ n ]; PxVehicleWheelData wheelData; wheelData.mRadius = wheelRadii[ n ]; wheelData.mMass = wheelInitData->GetFloatParameter( "mass" ); wheelData.mMOI = 0.5f * wheelData.mMass * wheelRadii[ n ] * wheelRadii[ n ]; wheelData.mWidth = wheelWidths[ n ]; wheelData.mDampingRate = wheelInitData->GetFloatParameter( "wheelDampingRate" ); wheelData.mMaxBrakeTorque = wheelInitData->GetFloatParameter( "wheelMaxBrakeTorque" ); wheelData.mMaxHandBrakeTorque = wheelInitData->GetFloatParameter( "wheelMaxHandBrakeTorque" ); wheelData.mMaxSteer = DegToRad( wheelInitData->GetFloatParameter("wheelMaxSteer") ); wheelData.mToeAngle = DegToRad( wheelInitData->GetFloatParameter("wheelToeAngle") ); wheelsData.setWheelData( n, wheelData ); PxVehicleTireData tireData; tireData.mLatStiffX = wheelInitData->GetFloatParameter( "tireLatStiffX" ); tireData.mLatStiffY = wheelInitData->GetFloatParameter( "tireLatStiffY" ); tireData.mLongitudinalStiffnessPerUnitGravity = wheelInitData->GetFloatParameter( "tireLongitudinalStiffnessPerUnitGravity" ); tireData.mCamberStiffness = wheelInitData->GetFloatParameter( "tireCamberStiffness" ); tireData.mFrictionVsSlipGraph[ 0 ][ 1 ] = wheelInitData->GetFloatParameter( "frictionVsSlipGraphZeroLongitudinalSlip" ); tireData.mFrictionVsSlipGraph[ 1 ][ 0 ] = wheelInitData->GetFloatParameter( "frictionVsSlipGraphLongitudinalSlipWithMaximumFriction" ); tireData.mFrictionVsSlipGraph[ 1 ][ 1 ] = wheelInitData->GetFloatParameter( "frictionVsSlipGraphMaximumFriction" ); tireData.mFrictionVsSlipGraph[ 2 ][ 0 ] = wheelInitData->GetFloatParameter( "frictionVsSlipGraphEndPointOfGraph" ); tireData.mFrictionVsSlipGraph[ 2 ][ 1 ] = wheelInitData->GetFloatParameter( "frictionVsSlipGraphValueOfFrictionForSlipsGreaterThanEndPointOfGraph" ); wheelsData.setTireData( n, tireData ); PxVehicleSuspensionData suspensionData; suspensionData.mMaxCompression = wheelInitData->GetFloatParameter( "suspensionMaxCompression" ); suspensionData.mMaxDroop = wheelInitData->GetFloatParameter( "suspensionMaxDroop" ); suspensionData.mSpringStrength = wheelInitData->GetFloatParameter( "suspensionSpringStrength" ); suspensionData.mSpringDamperRate = wheelInitData->GetFloatParameter( "suspensionSpringDamperRate" ); suspensionData.mSprungMass = chassisMass * wheelInitData->GetFloatParameter( "suspensionSprungMassCoefficient" ); wheelsData.setSuspensionData( n, suspensionData ); PxVec3 suspensionForceApplicationPointOffset = PxVec3( wheelInitData->GetFloatParameter( "suspensionForceApplicationPointOffset.X" ), wheelInitData->GetFloatParameter( "suspensionForceApplicationPointOffset.Y" ), wheelInitData->GetFloatParameter( "suspensionForceApplicationPointOffset.Z" ) ); PxVec3 tireForceApplicationPointOffset = PxVec3( wheelInitData->GetFloatParameter( "tireForceApplicationPointOffset.X" ), wheelInitData->GetFloatParameter( "tireForceApplicationPointOffset.Y" ), wheelInitData->GetFloatParameter( "tireForceApplicationPointOffset.Z" ) ); wheelsData.setSuspTravelDirection( n, PxVec3( 0, 0, -1 ) ); wheelsData.setWheelCentreOffset( n, wheelCenterOffsets[ n ] ); wheelsData.setSuspForceAppPointOffset( n, wheelCenterOffsets[ n ] + suspensionForceApplicationPointOffset ); wheelsData.setTireForceAppPointOffset( n, wheelCenterOffsets[ n ] + tireForceApplicationPointOffset ); } //Differential { PxVehicleDifferential4WData differential; differential.mType = (int)( generalData->GetFloatParameter( "differentialType" ) + .0001f ); differential.mFrontRearSplit = generalData->GetFloatParameter( "differentialFrontRearSplit" ); differential.mFrontLeftRightSplit = generalData->GetFloatParameter( "differentialFrontLeftRightSplit" ); differential.mRearLeftRightSplit = generalData->GetFloatParameter( "differentialRearLeftRightSplit" ); differential.mCentreBias = generalData->GetFloatParameter( "differentialCenterBias" ); differential.mFrontBias = generalData->GetFloatParameter( "differentialFrontBias" ); differential.mRearBias = generalData->GetFloatParameter( "differentialRearBias" ); driveData.setDiffData( differential ); } //Engine { PxVehicleEngineData engine; engine.mPeakTorque = generalData->GetFloatParameter("enginePeakTorque");// 500.0f; engine.mMaxOmega = generalData->GetFloatParameter("engineMaxRPM") * PI * 2.0f / 60.0f;//600.0f;//approx 6000 rpm engine.mDampingRateFullThrottle = generalData->GetFloatParameter("engineDampingRateFullThrottle"); engine.mDampingRateZeroThrottleClutchEngaged = generalData->GetFloatParameter("engineDampingRateZeroThrottleClutchEngaged"); engine.mDampingRateZeroThrottleClutchDisengaged = generalData->GetFloatParameter("engineDampingRateZeroThrottleClutchDisengaged"); PxFixedSizeLookupTable<PxVehicleEngineData::eMAX_NUM_ENGINE_TORQUE_CURVE_ENTRIES> torqueCurve; for( int n = 0; n < PxVehicleEngineData::eMAX_NUM_ENGINE_TORQUE_CURVE_ENTRIES; n++ ) { char s[50]; sprintf(s, "engineTorqueCurveTorque%d", n); if(!generalData->IsFloatParameterExist(s)) break; float torque = generalData->GetFloatParameter(s); sprintf(s, "engineTorqueCurveRev%d", n); float rev = generalData->GetFloatParameter(s); torqueCurve.addPair(torque, rev); } engine.mTorqueCurve = torqueCurve; driveData.setEngineData( engine ); } //Gears { PxVehicleGearsData gears; for( int n = 0; n < PxVehicleGearsData::eMAX_NUM_GEAR_RATIOS; n++) gears.mRatios[ n ] = 0; int minNumber = 100000; int maxNumber = -100000; for( int number = -1; number <= 30; number++ ) { char s[25]; sprintf(s, "gear%d", number); if(generalData->IsFloatParameterExist(s)) { float ratio = generalData->GetFloatParameter(s); gears.mRatios[ number + 1 ] = ratio; if(number < minNumber) minNumber = number; if(number > maxNumber) maxNumber = number; } } gears.mFinalRatio = 1; gears.mNumRatios = maxNumber - minNumber + 1; gears.mSwitchTime = generalData->GetFloatParameter(L"gearsSwitchTime");//0.5f; driveData.setGearsData(gears); } //Clutch PxVehicleClutchData clutch; clutch.mStrength = generalData->GetFloatParameter(L"clutchStrength"); driveData.setClutchData(clutch); //Ackermann steer accuracy PxVehicleAckermannGeometryData ackermann; ackermann.mAccuracy = generalData->GetFloatParameter(L"ackermannSteerAccuracy"); ackermann.mAxleSeparation = fabs( wheelCenterOffsets[PxVehicleDrive4W::eFRONT_LEFT_WHEEL].x - wheelCenterOffsets[PxVehicleDrive4W::eREAR_LEFT_WHEEL].x); ackermann.mFrontWidth = fabs( wheelCenterOffsets[PxVehicleDrive4W::eFRONT_RIGHT_WHEEL].y - wheelCenterOffsets[PxVehicleDrive4W::eFRONT_LEFT_WHEEL].y); ackermann.mRearWidth = fabs( wheelCenterOffsets[PxVehicleDrive4W::eREAR_LEFT_WHEEL].y - wheelCenterOffsets[PxVehicleDrive4W::eREAR_RIGHT_WHEEL].y); driveData.setAckermannGeometryData(ackermann); }
void PxVehicle4WEnable3WMode(const bool removeFrontWheel, PxVehicleWheelsSimData& wheelsSimData, PxVehicleDriveSimData4W& driveSimData) { const PxU32 wheelToRemove = removeFrontWheel ? PxVehicleDrive4W::eFRONT_LEFT_WHEEL : PxVehicleDrive4W::eREAR_LEFT_WHEEL; const PxU32 wheelToModify = removeFrontWheel ? PxVehicleDrive4W::eFRONT_RIGHT_WHEEL : PxVehicleDrive4W::eREAR_RIGHT_WHEEL; //Disable the front left wheel. wheelsSimData.disableWheel(wheelToRemove); //Now reposition the front-right wheel so that it lies at the centre of the front axle. { PxVec3 offsets[4]={ wheelsSimData.getWheelCentreOffset(PxVehicleDrive4W::eFRONT_LEFT_WHEEL), wheelsSimData.getWheelCentreOffset(PxVehicleDrive4W::eFRONT_RIGHT_WHEEL), wheelsSimData.getWheelCentreOffset(PxVehicleDrive4W::eREAR_LEFT_WHEEL), wheelsSimData.getWheelCentreOffset(PxVehicleDrive4W::eREAR_RIGHT_WHEEL)}; offsets[wheelToModify].x=0; wheelsSimData.setWheelCentreOffset(PxVehicleDrive4W::eFRONT_LEFT_WHEEL,offsets[PxVehicleDrive4W::eFRONT_LEFT_WHEEL]); wheelsSimData.setWheelCentreOffset(PxVehicleDrive4W::eFRONT_RIGHT_WHEEL,offsets[PxVehicleDrive4W::eFRONT_RIGHT_WHEEL]); wheelsSimData.setWheelCentreOffset(PxVehicleDrive4W::eREAR_LEFT_WHEEL,offsets[PxVehicleDrive4W::eREAR_LEFT_WHEEL]); wheelsSimData.setWheelCentreOffset(PxVehicleDrive4W::eREAR_RIGHT_WHEEL,offsets[PxVehicleDrive4W::eREAR_RIGHT_WHEEL]); } { PxVec3 suspOffset=wheelsSimData.getSuspForceAppPointOffset(wheelToModify); suspOffset.x=0; wheelsSimData.setSuspForceAppPointOffset(wheelToModify,suspOffset); } { PxVec3 tireOffset=wheelsSimData.getTireForceAppPointOffset(wheelToModify); tireOffset.x=0; wheelsSimData.setTireForceAppPointOffset(wheelToModify,tireOffset); } if(PxVehicleDrive4W::eFRONT_RIGHT_WHEEL==wheelToModify) { //Disable the ackermann steer correction because we only have a single steer wheel now. PxVehicleAckermannGeometryData ackermannData=driveSimData.getAckermannGeometryData(); ackermannData.mAccuracy=0.0f; driveSimData.setAckermannGeometryData(ackermannData); } //We need to set up the differential to make sure that the missing wheel is ignored. PxVehicleDifferential4WData diffData =driveSimData.getDiffData(); if(PxVehicleDrive4W::eFRONT_RIGHT_WHEEL==wheelToModify) { diffData.mFrontBias=PX_MAX_F32; diffData.mFrontLeftRightSplit=0.0f; } else { diffData.mRearBias=PX_MAX_F32; diffData.mRearLeftRightSplit=0.0f; } driveSimData.setDiffData(diffData); //The front-right wheel needs to support the mass that was supported by the disabled front-left wheel. //Update the suspension data to preserve both the natural frequency and damping ratio. PxVehicleSuspensionData suspData=wheelsSimData.getSuspensionData(wheelToModify); suspData.mSprungMass*=2.0f; suspData.mSpringStrength*=2.0f; suspData.mSpringDamperRate*=2.0f; wheelsSimData.setSuspensionData(wheelToModify,suspData); }
void createVehicle4WSimulationData (const PxF32 chassisMass, PxConvexMesh* chassisConvexMesh, const PxF32 wheelMass, PxConvexMesh** wheelConvexMeshes, const PxVec3* wheelCentreOffsets, PxVehicleWheelsSimData& wheelsData, PxVehicleDriveSimData4W& driveData, PxVehicleChassisData& chassisData) { //Extract the chassis AABB dimensions from the chassis convex mesh. const PxVec3 chassisDims=computeChassisAABBDimensions(chassisConvexMesh); //The origin is at the center of the chassis mesh. //Set the center of mass to be below this point and a little towards the front. const PxVec3 chassisCMOffset=PxVec3(0.0f,-chassisDims.y*0.5f+0.65f,0.25f); //Now compute the chassis mass and moment of inertia. //Use the moment of inertia of a cuboid as an approximate value for the chassis moi. PxVec3 chassisMOI ((chassisDims.y*chassisDims.y + chassisDims.z*chassisDims.z)*chassisMass/12.0f, (chassisDims.x*chassisDims.x + chassisDims.z*chassisDims.z)*chassisMass/12.0f, (chassisDims.x*chassisDims.x + chassisDims.y*chassisDims.y)*chassisMass/12.0f); //A bit of tweaking here. The car will have more responsive turning if we reduce the //y-component of the chassis moment of inertia. chassisMOI.y*=0.8f; //Let's set up the chassis data structure now. chassisData.mMass=chassisMass; chassisData.mMOI=chassisMOI; chassisData.mCMOffset=chassisCMOffset; //Work out the front/rear mass split from the cm offset. //This is a very approximate calculation with lots of assumptions. //massRear*zRear + massFront*zFront = mass*cm (1) //massRear + massFront = mass (2) //Rearrange (2) //massFront = mass - massRear (3) //Substitute (3) into (1) //massRear(zRear - zFront) + mass*zFront = mass*cm (4) //Solve (4) for massRear //massRear = mass(cm - zFront)/(zRear-zFront) (5) //Now we also have //zFront = (z-cm)/2 (6a) //zRear = (-z-cm)/2 (6b) //Substituting (6a-b) into (5) gives //massRear = 0.5*mass*(z-3cm)/z (7) const PxF32 massRear=0.5f*chassisMass*(chassisDims.z-3*chassisCMOffset.z)/chassisDims.z; const PxF32 massFront=chassisMass-massRear; //Extract the wheel radius and width from the wheel convex meshes. PxF32 wheelWidths[4]; PxF32 wheelRadii[4]; computeWheelWidthsAndRadii(wheelConvexMeshes,wheelWidths,wheelRadii); //Now compute the wheel masses and inertias components around the axle's axis. //http://en.wikipedia.org/wiki/List_of_moments_of_inertia PxF32 wheelMOIs[4]; for(PxU32 i=0;i<4;i++) { wheelMOIs[i]=0.5f*wheelMass*wheelRadii[i]*wheelRadii[i]; } //Let's set up the wheel data structures now with radius, mass, and moi. PxVehicleWheelData wheels[4]; for(PxU32 i=0;i<4;i++) { wheels[i].mRadius=wheelRadii[i]; wheels[i].mMass=wheelMass; wheels[i].mMOI=wheelMOIs[i]; wheels[i].mWidth=wheelWidths[i]; } //Disable the handbrake from the front wheels and enable for the rear wheels wheels[PxVehicleDrive4W::eFRONT_LEFT_WHEEL].mMaxHandBrakeTorque=0.0f; wheels[PxVehicleDrive4W::eFRONT_RIGHT_WHEEL].mMaxHandBrakeTorque=0.0f; wheels[PxVehicleDrive4W::eREAR_LEFT_WHEEL].mMaxHandBrakeTorque=4000.0f; wheels[PxVehicleDrive4W::eREAR_RIGHT_WHEEL].mMaxHandBrakeTorque=4000.0f; //Enable steering for the front wheels and disable for the front wheels. wheels[PxVehicleDrive4W::eFRONT_LEFT_WHEEL].mMaxSteer=PxPi*0.3333f; wheels[PxVehicleDrive4W::eFRONT_RIGHT_WHEEL].mMaxSteer=PxPi*0.3333f; wheels[PxVehicleDrive4W::eREAR_LEFT_WHEEL].mMaxSteer=0.0f; wheels[PxVehicleDrive4W::eREAR_RIGHT_WHEEL].mMaxSteer=0.0f; //Let's set up the tire data structures now. //Put slicks on the front tires and wets on the rear tires. PxVehicleTireData tires[4]; tires[PxVehicleDrive4W::eFRONT_LEFT_WHEEL].mType=TIRE_TYPE_SLICKS; tires[PxVehicleDrive4W::eFRONT_RIGHT_WHEEL].mType=TIRE_TYPE_SLICKS; tires[PxVehicleDrive4W::eREAR_LEFT_WHEEL].mType=TIRE_TYPE_WETS; tires[PxVehicleDrive4W::eREAR_RIGHT_WHEEL].mType=TIRE_TYPE_WETS; //Let's set up the suspension data structures now. PxVehicleSuspensionData susps[4]; for(PxU32 i=0;i<4;i++) { susps[i].mMaxCompression=0.3f; susps[i].mMaxDroop=0.1f; susps[i].mSpringStrength=35000.0f; susps[i].mSpringDamperRate=4500.0f; } susps[PxVehicleDrive4W::eFRONT_LEFT_WHEEL].mSprungMass=massFront*0.5f; susps[PxVehicleDrive4W::eFRONT_RIGHT_WHEEL].mSprungMass=massFront*0.5f; susps[PxVehicleDrive4W::eREAR_LEFT_WHEEL].mSprungMass=massRear*0.5f; susps[PxVehicleDrive4W::eREAR_RIGHT_WHEEL].mSprungMass=massRear*0.5f; //We need to set up geometry data for the suspension, wheels, and tires. //We already know the wheel centers described as offsets from the rigid body centre of mass. //From here we can approximate application points for the tire and suspension forces. //Lets assume that the suspension travel directions are absolutely vertical. //Also assume that we apply the tire and suspension forces 30cm below the centre of mass. PxVec3 suspTravelDirections[4]={PxVec3(0,-1,0),PxVec3(0,-1,0),PxVec3(0,-1,0),PxVec3(0,-1,0)}; PxVec3 wheelCentreCMOffsets[4]; PxVec3 suspForceAppCMOffsets[4]; PxVec3 tireForceAppCMOffsets[4]; for(PxU32 i=0;i<4;i++) { wheelCentreCMOffsets[i]=wheelCentreOffsets[i]-chassisCMOffset; suspForceAppCMOffsets[i]=PxVec3(wheelCentreCMOffsets[i].x,-0.3f,wheelCentreCMOffsets[i].z); tireForceAppCMOffsets[i]=PxVec3(wheelCentreCMOffsets[i].x,-0.3f,wheelCentreCMOffsets[i].z); } //Now add the wheel, tire and suspension data. for(PxU32 i=0;i<4;i++) { wheelsData.setWheelData(i,wheels[i]); wheelsData.setTireData(i,tires[i]); wheelsData.setSuspensionData(i,susps[i]); wheelsData.setSuspTravelDirection(i,suspTravelDirections[i]); wheelsData.setWheelCentreOffset(i,wheelCentreCMOffsets[i]); wheelsData.setSuspForceAppPointOffset(i,suspForceAppCMOffsets[i]); wheelsData.setTireForceAppPointOffset(i,tireForceAppCMOffsets[i]); } //Now set up the differential, engine, gears, clutch, and ackermann steering. //Diff PxVehicleDifferential4WData diff; diff.mType=PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD; driveData.setDiffData(diff); //Engine PxVehicleEngineData engine; engine.mPeakTorque=500.0f; engine.mMaxOmega=600.0f;//approx 6000 rpm driveData.setEngineData(engine); //Gears PxVehicleGearsData gears; gears.mSwitchTime=0.5f; driveData.setGearsData(gears); //Clutch PxVehicleClutchData clutch; clutch.mStrength=10.0f; driveData.setClutchData(clutch); //Ackermann steer accuracy PxVehicleAckermannGeometryData ackermann; ackermann.mAccuracy=1.0f; ackermann.mAxleSeparation=wheelCentreOffsets[PxVehicleDrive4W::eFRONT_LEFT_WHEEL].z-wheelCentreOffsets[PxVehicleDrive4W::eREAR_LEFT_WHEEL].z; ackermann.mFrontWidth=wheelCentreOffsets[PxVehicleDrive4W::eFRONT_RIGHT_WHEEL].x-wheelCentreOffsets[PxVehicleDrive4W::eFRONT_LEFT_WHEEL].x; ackermann.mRearWidth=wheelCentreOffsets[PxVehicleDrive4W::eREAR_RIGHT_WHEEL].x-wheelCentreOffsets[PxVehicleDrive4W::eREAR_LEFT_WHEEL].x; driveData.setAckermannGeometryData(ackermann); }