diff --git a/Flax.flaxproj b/Flax.flaxproj index 86d7c268d..432045578 100644 --- a/Flax.flaxproj +++ b/Flax.flaxproj @@ -3,7 +3,7 @@ "Version": { "Major": 1, "Minor": 5, - "Build": 6339 + "Build": 6341 }, "Company": "Flax", "Copyright": "Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.", diff --git a/Source/Engine/Level/Prefabs/PrefabManager.cpp b/Source/Engine/Level/Prefabs/PrefabManager.cpp index 88d80a41a..a2b148f28 100644 --- a/Source/Engine/Level/Prefabs/PrefabManager.cpp +++ b/Source/Engine/Level/Prefabs/PrefabManager.cpp @@ -102,6 +102,7 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, Actor* parent, Dictionary::ScopeCache sceneObjects = ActorsCache::SceneObjectsListCache.Get(); sceneObjects->Resize(objectsCount); CollectionPoolCache::ScopeCache modifier = Cache::ISerializeModifier.Get(); + modifier->EngineBuild = prefab->DataEngineBuild; modifier->IdsMapping.EnsureCapacity(prefab->ObjectsIds.Count() * 4); for (int32 i = 0; i < prefab->ObjectsIds.Count(); i++) { diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.cpp b/Source/Engine/Physics/Actors/WheeledVehicle.cpp index cc28ef756..b491a12fd 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.cpp +++ b/Source/Engine/Physics/Actors/WheeledVehicle.cpp @@ -212,7 +212,7 @@ void WheeledVehicle::Setup() void WheeledVehicle::DrawPhysicsDebug(RenderView& view) { // Wheels shapes - for (auto& data : _wheelsData) + for (const auto& data : _wheelsData) { int32 wheelIndex = 0; for (; wheelIndex < _wheels.Count(); wheelIndex++) @@ -222,7 +222,7 @@ void WheeledVehicle::DrawPhysicsDebug(RenderView& view) } if (wheelIndex == _wheels.Count()) break; - auto& wheel = _wheels[wheelIndex]; + const auto& wheel = _wheels[wheelIndex]; if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger()) { const Vector3 currentPos = wheel.Collider->GetPosition(); @@ -242,7 +242,7 @@ void WheeledVehicle::DrawPhysicsDebug(RenderView& view) void WheeledVehicle::OnDebugDrawSelected() { // Wheels shapes - for (auto& data : _wheelsData) + for (const auto& data : _wheelsData) { int32 wheelIndex = 0; for (; wheelIndex < _wheels.Count(); wheelIndex++) @@ -252,7 +252,7 @@ void WheeledVehicle::OnDebugDrawSelected() } if (wheelIndex == _wheels.Count()) break; - auto& wheel = _wheels[wheelIndex]; + const auto& wheel = _wheels[wheelIndex]; if (wheel.Collider && wheel.Collider->GetParent() == this && !wheel.Collider->GetIsTrigger()) { const Vector3 currentPos = wheel.Collider->GetPosition(); @@ -311,6 +311,9 @@ void WheeledVehicle::Deserialize(DeserializeStream& stream, ISerializeModifier* DESERIALIZE_MEMBER(Engine, _engine); DESERIALIZE_MEMBER(Differential, _differential); DESERIALIZE_MEMBER(Gearbox, _gearbox); + + // [Deprecated on 13.06.2023, expires on 13.06.2025] + _fixInvalidForwardDir |= modifier->EngineBuild < 6341; } void WheeledVehicle::OnColliderChanged(Collider* c) @@ -331,6 +334,41 @@ void WheeledVehicle::OnPhysicsSceneChanged(PhysicsScene* previous) #endif } +void WheeledVehicle::OnTransformChanged() +{ + RigidBody::OnTransformChanged(); + + // Initially vehicles were using X axis as forward which was kind of bad idea as engine uses Z as forward + // [Deprecated on 13.06.2023, expires on 13.06.2025] + if (_fixInvalidForwardDir) + { + _fixInvalidForwardDir = false; + + // Transform all vehicle children around the vehicle origin to fix the vehicle facing direction + const Quaternion rotationDelta(0.0f, -0.7071068f, 0.0f, 0.7071068f); + const Vector3 origin = GetPosition(); + for (Actor* child : Children) + { + Transform trans = child->GetTransform();; + const Vector3 pivotOffset = trans.Translation - origin; + if (pivotOffset.IsZero()) + { + trans.Orientation *= Quaternion::Invert(trans.Orientation) * rotationDelta * trans.Orientation; + } + else + { + Matrix transWorld, deltaWorld; + Matrix::RotationQuaternion(trans.Orientation, transWorld); + Matrix::RotationQuaternion(rotationDelta, deltaWorld); + Matrix world = transWorld * Matrix::Translation(pivotOffset) * deltaWorld * Matrix::Translation(-pivotOffset); + trans.SetRotation(world); + trans.Translation += world.GetTranslation(); + } + child->SetTransform(trans); + } + } +} + void WheeledVehicle::BeginPlay(SceneBeginData* data) { RigidBody::BeginPlay(data); diff --git a/Source/Engine/Physics/Actors/WheeledVehicle.h b/Source/Engine/Physics/Actors/WheeledVehicle.h index 7e046d1a2..b478006d9 100644 --- a/Source/Engine/Physics/Actors/WheeledVehicle.h +++ b/Source/Engine/Physics/Actors/WheeledVehicle.h @@ -328,6 +328,7 @@ private: EngineSettings _engine; DifferentialSettings _differential; GearboxSettings _gearbox; + bool _fixInvalidForwardDir = false; // [Deprecated on 13.06.2023, expires on 13.06.2025] public: /// @@ -488,6 +489,7 @@ protected: void OnPhysicsSceneChanged(PhysicsScene* previous) override; // [Vehicle] + void OnTransformChanged() override; void BeginPlay(SceneBeginData* data) override; void EndPlay() override; }; diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp index 097ca4853..8f1aa6eb0 100644 --- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp +++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp @@ -477,7 +477,7 @@ void InitVehicleSDK() { VehicleSDKInitialized = true; PxInitVehicleSDK(*PhysX); - PxVehicleSetBasisVectors(PxVec3(0, 1, 0), PxVec3(1, 0, 0)); + PxVehicleSetBasisVectors(PxVec3(0, 1, 0), PxVec3(0, 0, 1)); PxVehicleSetUpdateMode(PxVehicleUpdateMode::eVELOCITY_CHANGE); } } @@ -1018,7 +1018,7 @@ void PhysicsBackend::EndSimulateScene(void* scene) 5.0f, // fall rate eANALOG_INPUT_STEER_RIGHT } }; - PxVehicleKeySmoothingData keySmoothing = + static constexpr PxVehicleKeySmoothingData keySmoothing = { { 3.0f, // rise rate eANALOG_INPUT_ACCEL @@ -1216,7 +1216,7 @@ void PhysicsBackend::EndSimulateScene(void* scene) // Update wheel collider transformation auto localPose = shape->getLocalPose(); Transform t = wheelData.Collider->GetLocalTransform(); - t.Orientation = Quaternion::Euler(0, state.SteerAngle, state.RotationAngle) * wheelData.LocalOrientation; + t.Orientation = Quaternion::Euler(-state.RotationAngle, state.SteerAngle, 0) * wheelData.LocalOrientation; t.Translation = P2C(localPose.p) / wheelVehicle->GetScale() - t.Orientation * wheelData.Collider->GetCenter(); wheelData.Collider->SetLocalTransform(t); } @@ -2592,6 +2592,7 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor) } PxF32 sprungMasses[PX_MAX_NB_WHEELS]; const float mass = actorPhysX->getMass(); + // TODO: get gravityDirection from scenePhysX->Scene->getGravity() PxVehicleComputeSprungMasses(wheels.Count(), offsets, centerOfMassOffset.p, mass, 1, sprungMasses); PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(wheels.Count()); for (int32 i = 0; i < wheels.Count(); i++) @@ -2742,9 +2743,9 @@ void* PhysicsBackend::CreateVehicle(WheeledVehicle* actor) // 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); + ackermann.mAxleSeparation = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z); + ackermann.mFrontWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x); + ackermann.mRearWidth = Math::Abs(wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).x - wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).x); driveSimData.setAckermannGeometryData(ackermann); // Create vehicle drive