diff --git a/Unreal/CarlaUE4/Plugins/CarlaTools/Content/USDImporter/UW_USDVehicleImporterEditorWidget.uasset b/Unreal/CarlaUE4/Plugins/CarlaTools/Content/USDImporter/UW_USDVehicleImporterEditorWidget.uasset index a5e7d326d..a19930ff0 100644 Binary files a/Unreal/CarlaUE4/Plugins/CarlaTools/Content/USDImporter/UW_USDVehicleImporterEditorWidget.uasset and b/Unreal/CarlaUE4/Plugins/CarlaTools/Content/USDImporter/UW_USDVehicleImporterEditorWidget.uasset differ diff --git a/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/Private/USDImporterWidget.cpp b/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/Private/USDImporterWidget.cpp index c0b065c6f..697839a11 100644 --- a/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/Private/USDImporterWidget.cpp +++ b/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/Private/USDImporterWidget.cpp @@ -19,7 +19,17 @@ #include "EditorAssetLibrary.h" #include #include +#include "Components/LightComponent.h" #include "Components/PointLightComponent.h" +#include "Components/SpotLightComponent.h" +#include "VehicleWheel.h" +#include "IAssetTools.h" +#include "AssetToolsModule.h" +#include "AssetRegistryModule.h" +#include "Factories/BlueprintFactory.h" +#include "Kismet2/BlueprintEditorUtils.h" +#include "BlueprintEditor.h" +#include "Carla/Vehicle/CarlaWheeledVehicle.h" void UUSDImporterWidget::ImportUSDProp( @@ -36,11 +46,15 @@ void UUSDImporterWidget::ImportUSDProp( void UUSDImporterWidget::ImportUSDVehicle( const FString& USDPath, const FString& DestinationAssetPath, + FWheelTemplates BaseWheelData, TArray& LightList, + FWheelTemplates& WheelObjects, bool bAsBlueprint) { #ifdef WITH_OMNIVERSE + // Import meshes UUSDCARLAInterface::ImportUSD(USDPath, DestinationAssetPath, false, bAsBlueprint); + // Import Lights TArray USDLights = UUSDCARLAInterface::GetUSDLights(USDPath); LightList.Empty(); for (const FUSDCARLALight& USDLight : USDLights) @@ -48,6 +62,58 @@ void UUSDImporterWidget::ImportUSDVehicle( FVehicleLight Light {USDLight.Name, USDLight.Location, USDLight.Color}; LightList.Add(Light); } + // Import Wheel and suspension data + TArray WheelsData = UUSDCARLAInterface::GetUSDWheelData(USDPath); + auto CreateVehicleWheel = + [&](const FUSDCARLAWheelData& WheelData, + TSubclassOf TemplateClass, + const FString &PackagePathName) + -> TSubclassOf + { + // Get a reference to the editor subsystem + constexpr float MToCM = 0.01f; + constexpr float RadToDeg = 360.f/3.14159265359f; + FString BlueprintName = FPaths::GetBaseFilename(PackagePathName); + FString BlueprintPath = FPaths::GetPath(PackagePathName); + IAssetTools& AssetTools = FModuleManager::LoadModuleChecked("AssetTools").Get(); + // Create a new Blueprint factory + UBlueprintFactory* Factory = NewObject(); + // Set the parent class for the new Blueprint + Factory->ParentClass = TemplateClass; + // Create a new Blueprint asset with the given name + UObject* NewAsset = AssetTools.CreateAsset(BlueprintName, BlueprintPath, UBlueprint::StaticClass(), Factory); + // Cast the new asset to a UBlueprint + UBlueprint* NewBlueprint = Cast(NewAsset); + // Modify the new Blueprint + NewBlueprint->Modify(); + // Edit the default object for the new Blueprint + UVehicleWheel* Result = Cast(NewBlueprint->GeneratedClass->ClassDefaultObject); + Result->MaxBrakeTorque = MToCM*WheelData.MaxBrakeTorque; + if (WheelData.MaxHandBrakeTorque != 0) + { + Result->MaxHandBrakeTorque = MToCM*WheelData.MaxHandBrakeTorque; + } + Result->SteerAngle = RadToDeg*WheelData.MaxSteerAngle; + Result->SuspensionMaxDrop = MToCM*WheelData.MaxDroop; + Result->LatStiffValue = WheelData.LateralStiffnessY; + Result->LongStiffValue = WheelData.LongitudinalStiffness; + return Result->GetClass(); + }; + // Save wheel objects + FString AssetPath = DestinationAssetPath + FPaths::GetBaseFilename(USDPath); + FString PathWheelFL = AssetPath + "_Wheel_FLW"; + FString PathWheelFR = AssetPath + "_Wheel_FRW"; + FString PathWheelRL = AssetPath + "_Wheel_RLW"; + FString PathWheelRR = AssetPath + "_Wheel_RRW"; + WheelObjects.WheelFL = CreateVehicleWheel( + WheelsData[0], BaseWheelData.WheelFL, PathWheelFL); + WheelObjects.WheelFR = CreateVehicleWheel( + WheelsData[1], BaseWheelData.WheelFR, PathWheelFR); + WheelObjects.WheelRL = CreateVehicleWheel( + WheelsData[2], BaseWheelData.WheelRL, PathWheelRL); + WheelObjects.WheelRR = CreateVehicleWheel( + WheelsData[3], BaseWheelData.WheelRR, PathWheelRR); + #else UE_LOG(LogCarlaTools, Error, TEXT("Omniverse Plugin is not enabled")); #endif @@ -128,13 +194,16 @@ bool IsChildrenOf(USceneComponent* Component, FString StringInParent) } FVehicleMeshParts UUSDImporterWidget::SplitVehicleParts( - AActor* BlueprintActor, const TArray& LightList) + AActor* BlueprintActor, + const TArray& LightList, + UMaterialInterface* GlassMaterial) { FVehicleMeshParts Result; Result.Lights = LightList; TArray MeshComponents; BlueprintActor->GetComponents(MeshComponents, false); FVector BodyLocation = FVector(0,0,0); + TArray GlassComponents; for (UStaticMeshComponent* Component : MeshComponents) { if (!Component->GetStaticMesh()) @@ -142,22 +211,22 @@ FVehicleMeshParts UUSDImporterWidget::SplitVehicleParts( continue; } FString ComponentName = UKismetSystemLibrary::GetDisplayName(Component); - if (ComponentName.Contains("door_0")) + if (IsChildrenOf(Component, "door_0")) { Result.DoorFL.Add(Component); Result.Anchors.DoorFL = Component->GetComponentTransform().GetLocation(); } - else if (ComponentName.Contains("door_1")) + else if (IsChildrenOf(Component, "door_1")) { Result.DoorFR.Add(Component); Result.Anchors.DoorFR = Component->GetComponentTransform().GetLocation(); } - else if (ComponentName.Contains("door_2")) + else if (IsChildrenOf(Component, "door_2")) { Result.DoorRL.Add(Component); Result.Anchors.DoorRL = Component->GetComponentTransform().GetLocation(); } - else if (ComponentName.Contains("door_3")) + else if (IsChildrenOf(Component, "door_3")) { Result.DoorRR.Add(Component); Result.Anchors.DoorRR = Component->GetComponentTransform().GetLocation(); @@ -216,6 +285,12 @@ FVehicleMeshParts UUSDImporterWidget::SplitVehicleParts( BodyLocation = Component->GetComponentTransform().GetLocation(); } } + + if(ComponentName.Contains("glass") || + IsChildrenOf(Component, "glass")) + { + GlassComponents.Add(Component); + } } Result.Anchors.DoorFR -= BodyLocation; Result.Anchors.DoorFL -= BodyLocation; @@ -231,6 +306,23 @@ FVehicleMeshParts UUSDImporterWidget::SplitVehicleParts( { Light.Location -= BodyLocation; } + // fix glass materials not being transparent + for (UStaticMeshComponent* Compopnent : GlassComponents) + { + const TArray& Materials = Compopnent->GetMaterials(); + for (int32 i = 0; i < Materials.Num(); i++) + { + UMaterialInterface* Material = Materials[i]; + if (Material) + { + FString MaterialName = Material->GetName(); + if (MaterialName == "DefaultMaterial") + { + Compopnent->SetMaterial(i, GlassMaterial); + } + } + } + } return Result; } @@ -339,7 +431,8 @@ AActor* UUSDImporterWidget::GenerateNewVehicleBlueprint( UClass* BaseClass, USkeletalMesh* NewSkeletalMesh, const FString &DestPath, - const FMergedVehicleMeshParts& VehicleMeshes) + const FMergedVehicleMeshParts& VehicleMeshes, + const FWheelTemplates& WheelTemplates) { std::unordered_map> MeshMap = { {"SM_DoorFR", {VehicleMeshes.DoorFR, VehicleMeshes.Anchors.DoorFR}}, @@ -404,15 +497,75 @@ AActor* UUSDImporterWidget::GenerateNewVehicleBlueprint( UE_LOG(LogCarlaTools, Log, TEXT("Num Lights %d"), VehicleMeshes.Lights.Num()); for (const FVehicleLight& Light : VehicleMeshes.Lights) { - UPointLightComponent* PointLightComponent = NewObject(TemplateActor, FName(*GetCarlaLightName(Light.Name))); - PointLightComponent->RegisterComponent(); - PointLightComponent->AttachToComponent(TemplateActor->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform); - PointLightComponent->SetRelativeLocation(Light.Location); // Set the position of the light relative to the actor - PointLightComponent->SetIntensity(5000.f); // Set the brightness of the light - PointLightComponent->SetLightColor(Light.Color); - TemplateActor->AddInstanceComponent(PointLightComponent); + FString FixedLightName = GetCarlaLightName(Light.Name); + UClass * LightClass = UPointLightComponent::StaticClass(); + if (FixedLightName.Contains("beam")) + { + LightClass = USpotLightComponent::StaticClass(); + } + ULocalLightComponent * LightComponent = NewObject(TemplateActor, LightClass, FName(*FixedLightName)); + LightComponent->RegisterComponent(); + LightComponent->AttachToComponent( + TemplateActor->GetRootComponent(), + FAttachmentTransformRules::KeepRelativeTransform); + LightComponent->SetRelativeLocation(Light.Location); // Set the position of the light relative to the actor + LightComponent->SetIntensityUnits(ELightUnits::Lumens); + LightComponent->SetIntensity(5000.f); // Set the brightness of the light + LightComponent->SetVolumetricScatteringIntensity(0.f); + if (FixedLightName.Contains("high_beam")) + { + USpotLightComponent* SpotLight = + Cast(LightComponent); + SpotLight->SetRelativeRotation(FRotator(-1.5f, 0, 0)); + SpotLight->SetAttenuationRadius(5000.f); + SpotLight->SetInnerConeAngle(20.f); + SpotLight->SetOuterConeAngle(30.f); + LightComponent->SetIntensity(150000.f); // Set the brightness of the light + LightComponent->SetVolumetricScatteringIntensity(0.025f); + } + else if (FixedLightName.Contains("low_beam")) + { + USpotLightComponent* SpotLight = + Cast(LightComponent); + LightComponent->SetRelativeRotation(FRotator(-3.f, 0, 0)); + LightComponent->SetAttenuationRadius(3000.f); + SpotLight->SetInnerConeAngle(50.f); + SpotLight->SetOuterConeAngle(65.f); + LightComponent->SetIntensity(15000.f); // Set the brightness of the light + LightComponent->SetVolumetricScatteringIntensity(0.025f); + } + LightComponent->SetLightColor(Light.Color); + TemplateActor->AddInstanceComponent(LightComponent); UE_LOG(LogCarlaTools, Log, TEXT("Spawn Light %s, %s, %s"), *Light.Name, *Light.Location.ToString(), *Light.Color.ToString()); } + // assign generated wheel types + TArray WheelSetups; + FWheelSetup Setup; + Setup.WheelClass = WheelTemplates.WheelFL; + Setup.BoneName = "Wheel_Front_Left"; + WheelSetups.Add(Setup); + Setup.WheelClass = WheelTemplates.WheelFR; + Setup.BoneName = "Wheel_Front_Right"; + WheelSetups.Add(Setup); + Setup.WheelClass = WheelTemplates.WheelRL; + Setup.BoneName = "Wheel_Rear_Left"; + WheelSetups.Add(Setup); + Setup.WheelClass = WheelTemplates.WheelRR; + Setup.BoneName = "Wheel_Rear_Right"; + WheelSetups.Add(Setup); + ACarlaWheeledVehicle* CarlaVehicle = + Cast(TemplateActor); + if(CarlaVehicle) + { + UWheeledVehicleMovementComponent4W* MovementComponent = + Cast( + CarlaVehicle->GetVehicleMovementComponent()); + MovementComponent->WheelSetups = WheelSetups; + } + else + { + UE_LOG(LogCarlaTools, Error, TEXT("Null CarlaVehicle")); + } // Create the new blueprint vehicle FKismetEditorUtilities::FCreateBlueprintFromActorParams Params; diff --git a/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/Public/USDImporterWidget.h b/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/Public/USDImporterWidget.h index 7022d825f..0e9aab595 100644 --- a/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/Public/USDImporterWidget.h +++ b/Unreal/CarlaUE4/Plugins/CarlaTools/Source/CarlaTools/Public/USDImporterWidget.h @@ -5,9 +5,25 @@ #include "CoreMinimal.h" #include "Blueprint/UserWidget.h" #include "Animation/Skeleton.h" +#include "VehicleWheel.h" +#include "Materials/MaterialInterface.h" #include "USDImporterWidget.generated.h" +USTRUCT(BlueprintType) +struct FWheelTemplates +{ + GENERATED_BODY() + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheel") + TSubclassOf WheelFR; + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheel") + TSubclassOf WheelFL; + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheel") + TSubclassOf WheelRR; + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheel") + TSubclassOf WheelRL; +}; + USTRUCT(BlueprintType) struct FVehicleLight { @@ -127,7 +143,9 @@ public: void ImportUSDVehicle( const FString& USDPath, const FString& DestinationAssetPath, + FWheelTemplates BaseWheelData, TArray& LightList, + FWheelTemplates& WheelObjects, bool bAsBlueprint = true); UFUNCTION(BlueprintCallable, Category="USD Importer") static AActor* GetGeneratedBlueprint(UWorld* World, const FString& USDPath); @@ -137,7 +155,9 @@ public: static TArray MergeMeshComponents(TArray Components, const FString& DestMesh); UFUNCTION(BlueprintCallable, Category="USD Importer") static FVehicleMeshParts SplitVehicleParts( - AActor* BlueprintActor, const TArray& LightList); + AActor* BlueprintActor, + const TArray& LightList, + UMaterialInterface* GlassMaterial); UFUNCTION(BlueprintCallable, Category="USD Importer") static FMergedVehicleMeshParts GenerateVehicleMeshes(const FVehicleMeshParts& VehicleMeshParts, const FString& DestPath); UFUNCTION(BlueprintCallable, Category="USD Importer") @@ -146,10 +166,11 @@ public: UClass* BaseClass, USkeletalMesh* NewSkeletalMesh, const FString &DestPath, - const FMergedVehicleMeshParts& VehicleMeshes); + const FMergedVehicleMeshParts& VehicleMeshes, + const FWheelTemplates& WheelTemplates); UFUNCTION(BlueprintCallable, Category="USD Importer") static bool EditSkeletalMeshBones( - USkeletalMesh* Skeleton, + USkeletalMesh* Skeleton, const TMap &NewBoneTransforms); }; diff --git a/Util/Patches/omniverse_4.26/USDCARLAInterface.cpp b/Util/Patches/omniverse_4.26/USDCARLAInterface.cpp index 9d9a0101d..722851086 100644 --- a/Util/Patches/omniverse_4.26/USDCARLAInterface.cpp +++ b/Util/Patches/omniverse_4.26/USDCARLAInterface.cpp @@ -49,4 +49,117 @@ TArray UUSDCARLAInterface::GetUSDLights(const FString& Path) Result.Add(LightParams); } return Result; +} + +TArray UUSDCARLAInterface::GetUSDWheelData(const FString& Path) +{ + pxr::UsdStageRefPtr Stage = + FOmniverseUSDHelper::LoadUSDStageFromPath(Path); + + // Get the wheel data + const std::string UsdPhysxWheelPath = "/vehicle/_physx/_physxWheels/"; + const std::string UsdPhysxSuspensionPath = "/vehicle/_physx/_physxSuspensions/"; + auto GetFloatAttributeValue = [](pxr::UsdPrim& Prim, const std::string& AttrName) -> float + { + pxr::UsdAttribute Attribute = + Prim.GetAttribute(pxr::TfToken(AttrName)); + if(!Attribute) + { + return 0.f; + } + float Value = 0.f; + Attribute.Get(&Value); + return Value; + }; + auto GetPrimFromRelationship = [&]( + pxr::UsdRelationship& Relationship) -> pxr::UsdPrim + { + std::vector Targets; + Relationship.GetTargets(&Targets); + if (!Targets.size()) + { + return pxr::UsdPrim(); + } + return Stage->GetPrimAtPath(Targets.front()); + }; + auto ParseWheelData = [&]( + const std::string& WheelName, + FUSDCARLAWheelData& OutWheelData) -> bool + { + pxr::SdfPath WheelPath(UsdPhysxWheelPath + WheelName); + pxr::UsdPrim WheelPrim = Stage->GetPrimAtPath(WheelPath); + if(!WheelPrim) + { + UE_LOG(LogOmniverseUsd, Warning, TEXT("Wheel prim fail")); + } + pxr::UsdRelationship WheelRelationship; + pxr::UsdRelationship TireRelationship; + pxr::UsdRelationship SuspensionRelationship; + for (pxr::UsdProperty& Property : WheelPrim.GetProperties()) + { + FString Name (Property.GetBaseName().GetText()); + if(Name == "wheel") + { + WheelRelationship = Property.As(); + } + if(Name == "tire") + { + TireRelationship = Property.As(); + } + if(Name == "suspension") + { + SuspensionRelationship = + Property.As(); + } + } + if(!WheelRelationship || !TireRelationship || !SuspensionRelationship) + { + UE_LOG(LogOmniverseUsd, Warning, TEXT("Relationships fail: %d %d %d"), + bool(WheelRelationship), bool(TireRelationship), bool(SuspensionRelationship)); + return false; + } + pxr::UsdPrim PhysxWheelPrim = GetPrimFromRelationship(WheelRelationship); + pxr::UsdPrim PhysxTirePrim = GetPrimFromRelationship(TireRelationship); + pxr::UsdPrim PhysxSuspensionlPrim = GetPrimFromRelationship(SuspensionRelationship); + + if (!PhysxWheelPrim || !PhysxTirePrim || !PhysxSuspensionlPrim) + { + UE_LOG(LogOmniverseUsd, Warning, TEXT("Prims fail: %d %d %d"), + bool(PhysxWheelPrim), bool(PhysxTirePrim), bool(PhysxSuspensionlPrim)); + return false; + } + OutWheelData.MaxBrakeTorque = + GetFloatAttributeValue(PhysxWheelPrim, "physxVehicleWheel:maxBrakeTorque"); + OutWheelData.MaxHandBrakeTorque = + GetFloatAttributeValue(PhysxWheelPrim, "physxVehicleWheel:maxHandBrakeTorque"); + OutWheelData.MaxSteerAngle = + GetFloatAttributeValue(PhysxWheelPrim, "physxVehicleWheel:maxSteerAngle"); + OutWheelData.SpringStrength = + GetFloatAttributeValue(PhysxSuspensionlPrim, "physxVehicleSuspension:springStrength"); + OutWheelData.MaxCompression = + GetFloatAttributeValue(PhysxSuspensionlPrim, "physxVehicleSuspension:maxCompression"); + OutWheelData.MaxDroop = + GetFloatAttributeValue(PhysxSuspensionlPrim, "physxVehicleSuspension:maxDroop"); + OutWheelData.LateralStiffnessX = + GetFloatAttributeValue(PhysxTirePrim, "physxVehicleTire:latStiffX"); + OutWheelData.LateralStiffnessY = + GetFloatAttributeValue(PhysxTirePrim, "physxVehicleTire:latStiffY"); + OutWheelData.LongitudinalStiffness = + GetFloatAttributeValue( + PhysxTirePrim, "physxVehicleTire:longitudinalStiffnessPerUnitGravity"); + + UE_LOG(LogOmniverseUsd, Warning, TEXT("USD values: %f %f %f %f %f %f %f %f %f"), + OutWheelData.MaxBrakeTorque, OutWheelData.MaxHandBrakeTorque, OutWheelData.MaxSteerAngle, + OutWheelData.SpringStrength, OutWheelData.MaxCompression, OutWheelData.MaxDroop, + OutWheelData.LateralStiffnessX, OutWheelData.LateralStiffnessY, OutWheelData.LongitudinalStiffness); + + return true; + }; + FUSDCARLAWheelData Wheel0, Wheel1, Wheel2, Wheel3; + ParseWheelData("wheel_0", Wheel0); + ParseWheelData("wheel_1", Wheel1); + ParseWheelData("wheel_2", Wheel2); + ParseWheelData("wheel_3", Wheel3); + + return {Wheel0, Wheel1, Wheel2, Wheel3}; } \ No newline at end of file diff --git a/Util/Patches/omniverse_4.26/USDCARLAInterface.h b/Util/Patches/omniverse_4.26/USDCARLAInterface.h index 210ca7fce..39aab5929 100644 --- a/Util/Patches/omniverse_4.26/USDCARLAInterface.h +++ b/Util/Patches/omniverse_4.26/USDCARLAInterface.h @@ -5,6 +5,30 @@ #include "CoreMinimal.h" #include "USDCARLAInterface.generated.h" +USTRUCT(BlueprintType) +struct FUSDCARLAWheelData +{ + GENERATED_BODY() + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheeel Data") + float MaxBrakeTorque = 0; + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheeel Data") + float MaxHandBrakeTorque = 0; + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheeel Data") + float MaxSteerAngle = 0; + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheeel Data") + float SpringStrength = 0; + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheeel Data") + float MaxCompression = 0; + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheeel Data") + float MaxDroop = 0; + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheeel Data") + float LateralStiffnessX = 0; + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheeel Data") + float LateralStiffnessY = 0; + UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="USD Wheeel Data") + float LongitudinalStiffness = 0; +}; + USTRUCT(BlueprintType) struct FUSDCARLALight { @@ -29,4 +53,6 @@ public: bool bImportUnusedReferences, bool bImportAsBlueprint); UFUNCTION(BlueprintCallable, Category="USD Carla Interface") static TArray GetUSDLights(const FString& Path); + UFUNCTION(BlueprintCallable, Category="USD Carla Interface") + static TArray GetUSDWheelData(const FString& Path); };