(六)flax Engine 游戏引擎——载具

2021SC@SDUSC

上次我们分析了flaxEgnine游戏引擎中WheeledVehicle.h文件。而本次我将针对flaxEngine游戏引擎中的WheeledVehicle.c文件进行源码的分析。

void FreeDrive(WheeledVehicle::DriveTypes driveType, PxVehicleWheels* drive)
    {
        switch (driveType)
        {
        case WheeledVehicle::DriveTypes::Drive4W:
            ((PxVehicleDrive4W*)drive)->free();
            break;
        case WheeledVehicle::DriveTypes::DriveNW:
            ((PxVehicleDriveNW*)drive)->free();
            break;
        case WheeledVehicle::DriveTypes::NoDrive:
            ((PxVehicleNoDrive*)drive)->free();
            break;
        }
    }

上述代码是构建一个自由交通工具的代码段,包括四轮,n轮,无论驱动的三种类型的汽车。

WheeledVehicle::WheeledVehicle(const SpawnParams& params)
    : RigidBody(params)
{
    _useCCD = 1;
}

上述代码是WheeledVehicle的构造函数,继承自刚体。

WheeledVehicle::DriveTypes WheeledVehicle::GetDriveType() const
{
    return _driveType;
}

void WheeledVehicle::SetDriveType(DriveTypes value)
{
    if (_driveType == value)
        return;
    _driveType = value;
    Setup();
}

const Array<WheeledVehicle::Wheel>& WheeledVehicle::GetWheels() const
{
    return _wheels;
}

void WheeledVehicle::SetWheels(const Array<Wheel>& value)
{
    _wheels = value;
    Setup();
}

WheeledVehicle::EngineSettings WheeledVehicle::GetEngine() const
{
    return _engine;
}

void WheeledVehicle::SetEngine(const EngineSettings& value)
{
    _engine = value;
}

WheeledVehicle::DifferentialSettings WheeledVehicle::GetDifferential() const
{
    return _differential;
}

void WheeledVehicle::SetDifferential(const DifferentialSettings& value)
{
    _differential = value;
}

WheeledVehicle::GearboxSettings WheeledVehicle::GetGearbox() const
{
    return _gearbox;
}

void WheeledVehicle::SetGearbox(const GearboxSettings& value)

上述代码是WheeledVehicle.h头文件中定义的变量的get和set方法。

包括:1:载具类型 2:车轮数量 3:汽车引擎 4:齿轮 5:不同种类

void WheeledVehicle::SetThrottle(float value)
{
    _throttle = Math::Clamp(value, -1.0f, 1.0f);
}

void WheeledVehicle::SetSteering(float value)
{
    _steering = Math::Clamp(value, -1.0f, 1.0f);
}

void WheeledVehicle::SetBrake(float value)
{
    _brake = Math::Saturate(value);
}

void WheeledVehicle::SetHandbrake(float value)
{
    _handBrake = Math::Saturate(value);
}

void WheeledVehicle::ClearInput()
{
    _throttle = 0;
    _steering = 0;
    _brake = 0;
    _handBrake = 0;
}

float WheeledVehicle::GetForwardSpeed() const
{
#if WITH_VEHICLE
    auto& drive = (const PxVehicleWheels*&)_drive;
    return drive ? drive->computeForwardSpeed() : 0.0f;
#else
    return 0.0f;
#endif
}

float WheeledVehicle::GetSidewaysSpeed() const
{
#if WITH_VEHICLE
    auto& drive = (const PxVehicleWheels*&)_drive;
    return drive ? drive->computeSidewaysSpeed() : 0.0f;
#else
    return 0.0f;
#endif
}

float WheeledVehicle::GetEngineRotationSpeed() const
{
#if WITH_VEHICLE
    auto& drive = (const PxVehicleDrive*&)_drive;
    return drive && _driveType != DriveTypes::NoDrive ? RadPerSToRpm(drive->mDriveDynData.getEngineRotationSpeed()) : 0.0f;
#else
    return 0.0f;
#endif
}

int32 WheeledVehicle::GetCurrentGear() const
{
#if WITH_VEHICLE
    auto& drive = (const PxVehicleDrive*&)_drive;
    return drive && _driveType != DriveTypes::NoDrive ? (int32)drive->mDriveDynData.getCurrentGear() - 1 : 0;
#else
    return 0;
#endif
}

void WheeledVehicle::SetCurrentGear(int32 value)
{
#if WITH_VEHICLE
    auto& drive = (PxVehicleDrive*&)_drive;
    if (drive && _driveType != DriveTypes::NoDrive)
    {
        drive->mDriveDynData.forceGearChange((PxU32)(value + 1));
    }
#endif
}

int32 WheeledVehicle::GetTargetGear() const
{
#if WITH_VEHICLE
    auto& drive = (const PxVehicleDrive*&)_drive;
    return drive && _driveType != DriveTypes::NoDrive ? (int32)drive->mDriveDynData.getTargetGear() - 1 : 0;
#else
    return 0;
#endif
}

void WheeledVehicle::SetTargetGear(int32 value)
{
#if WITH_VEHICLE
    auto& drive = (PxVehicleDrive*&)_drive;
    if (drive && _driveType != DriveTypes::NoDrive)
    {
        drive->mDriveDynData.startGearChange((PxU32)(value + 1));
    }
#endif
}

void WheeledVehicle::GetWheelState(int32 index, WheelState& result)
{
    if (index >= 0 && index < _wheels.Count())
    {
        const auto collider = _wheels[index].Collider.Get();
        for (auto& wheelData : _wheelsData)
        {
            if (wheelData.Collider == collider)
            {
                result = wheelData.State;
                return;
            }
        }
    }
}

上述代码代码还是WheeledVehicle.h头文件中定义的变量的get和set方法。

包括变量1:油门 2:刹车 3:手刹 4:前进速度 5:横向速度 6:发动机转速 7:电流齿轮 8:靶机 这8个变量的get和set方法。

下面的WheeledVehicle载具的set up设置的源代码:

if (drive)
    {
        WheelVehicles.Remove(this);
        FreeDrive(_driveTypeCurrent, drive);
        drive = nullptr;
    }

首先判断drive有没有存在的。如果有的删去,新创建一个自由汽车。

Array<Wheel*, FixedAllocation<PX_MAX_NB_WHEELS>> wheels;
    _wheelsData.Clear();
    for (auto& wheel : _wheels)
    {
        if (!wheel.Collider)
        {
            LOG(Warning, "Missing wheel collider in vehicle {0}", ToString());
            continue;
        }
        if (wheel.Collider->GetParent() != this)
        {
            LOG(Warning, "Invalid wheel collider {1} in vehicle {0} attached to {2} (wheels needs to be added as children to vehicle)", ToString(), wheel.Collider->ToString(), wheel.Collider->GetParent() ? wheel.Collider->GetParent()->ToString() : String::Empty);
            continue;
        }
        if (wheel.Collider->GetIsTrigger())
        {
            LOG(Warning, "Invalid wheel collider {1} in vehicle {0} cannot be a trigger", ToString(), wheel.Collider->ToString());
            continue;
        }
        if (wheel.Collider->IsDuringPlay())
        {
            wheels.Add(&wheel);
        }
    }
    if (wheels.IsEmpty())
    {
        // No wheel, no car
        // No woman, no cry
        return;
    }
    _wheelsData.Resize(wheels.Count());

其次是初始化车轮,添加一个自动轮胎。

1:判断是否有车轮连接装置:如果没有的话发出警告

2:判断车轮联动装置:如果没有的话发出警告

3:判断联机装置:添加车轮联动装置。

 Array<PxShape*, InlinedAllocation<8>> shapes;
    shapes.Resize(_actor->getNbShapes());
    _actor->getShapes(shapes.Get(), shapes.Count(), 0);
    const PxTransform centerOfMassOffset = _actor->getCMassLocalPose();

上述代码是获取轮子贴图的链接形状

 PxVec3 offsets[PX_MAX_NB_WHEELS];
    for (int32 i = 0; i < wheels.Count(); i++)
    {
        Wheel& wheel = *wheels[i];
        offsets[i] = C2P(wheel.Collider->GetLocalPosition());
    }
    PxF32 sprungMasses[PX_MAX_NB_WHEELS];
    const float mass = _actor->getMass();
    PxVehicleComputeSprungMasses(wheels.Count(), offsets, centerOfMassOffset.p, mass, 1, sprungMasses);
    PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(wheels.Count());

上述代码是初始化车轮模拟数据

 PxFilterData filter = wheelShape->getQueryFilterData();
            filter.word3 = _id.D + 1;
            wheelShape->setQueryFilterData(filter);
            wheelShape->setSimulationFilterData(filter);
            wheelsSimData->setSceneQueryFilterData(i, filter);

上述代码是在word3内设置车辆ID,以便悬架光线投射忽略自身。

wheelShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);

上述代码从模拟中拆下车轮(悬架力保持车辆)

 _driveTypeCurrent = _driveType;
    switch (_driveType)
    {
    case DriveTypes::Drive4W:
    {
        PxVehicleDriveSimData4W driveSimData;

        // Differential
        PxVehicleDifferential4WData diff;
        diff.mType = (PxVehicleDifferential4WData::Enum)_differential.Type;
        diff.mFrontRearSplit = _differential.FrontRearSplit;
        diff.mFrontLeftRightSplit = _differential.FrontLeftRightSplit;
        diff.mRearLeftRightSplit = _differential.RearLeftRightSplit;
        diff.mCentreBias = _differential.CentreBias;
        diff.mFrontBias = _differential.FrontBias;
        diff.mRearBias = _differential.RearBias;
        driveSimData.setDiffData(diff);

        // Engine
        PxVehicleEngineData engine;
        engine.mMOI = M2ToCm2(_engine.MOI);
        engine.mPeakTorque = M2ToCm2(_engine.MaxTorque);
        engine.mMaxOmega = RpmToRadPerS(_engine.MaxRotationSpeed);
        engine.mDampingRateFullThrottle = M2ToCm2(0.15f);
        engine.mDampingRateZeroThrottleClutchEngaged = M2ToCm2(2.0f);
        engine.mDampingRateZeroThrottleClutchDisengaged = M2ToCm2(0.35f);
        driveSimData.setEngineData(engine);

        // Gears
        PxVehicleGearsData gears;
        gears.mSwitchTime = Math::Max(_gearbox.SwitchTime, 0.0f);
        driveSimData.setGearsData(gears);

        // Auto Box
        PxVehicleAutoBoxData autoBox;
        driveSimData.setAutoBoxData(autoBox);

        // Clutch
        PxVehicleClutchData clutch;
        clutch.mStrength = M2ToCm2(_gearbox.ClutchStrength);
        driveSimData.setClutchData(clutch);

        // Ackermann steer accuracy
        PxVehicleAckermannGeometryData ackermann;
        ackermann.mAxleSeparation = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).x);
        ackermann.mFrontWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z);
        ackermann.mRearWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z);
        driveSimData.setAckermannGeometryData(ackermann);

        // Create vehicle drive
        auto drive4W = PxVehicleDrive4W::allocate(wheels.Count());
        drive4W->setup(CPhysX, _actor, *wheelsSimData, driveSimData, Math::Max(wheels.Count() - 4, 0));
        drive4W->setToRestState();
        drive4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
        drive4W->mDriveDynData.setUseAutoGears(_gearbox.AutoGear);
        drive = drive4W;
        break;
    }

上述代码是初始化载具。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值