From 89ba3f03973232da86f1c69e27df2c005a427894 Mon Sep 17 00:00:00 2001 From: LuisPoveda <101111439+LuisPoveda@users.noreply.github.com> Date: Wed, 28 Sep 2022 13:53:43 +0200 Subject: [PATCH] Luis/fix package (#5794) * fixed not finding skeletal blueprints in shipping builds * Physics fixed. - Removed re-aplying forces all the time. - Removed collisions with the static meshes. * Added parameter to modify torque and forces for nested bones. * Forgot to add file. * removed old unused code * fix windows compilation * collisions now are applied from the closest point. added debug bools to enable more collisions and draw collision points. * Removed old code. * Fixed bug with distance less than zero. * Try to stabilize a bit * CHanged repulsion forces so that contacts end with equilibrium * Now all foliages are spawned correctly. - SpringBasedVegetationComponent: Added the posibility to set bones as static. This static bones will use the OnCollisionEvent instead overlap events. - VegetationManager: Removed unnecessary variables. - VegetationManager: Now the FTileData supports multiple level loads for the same tile. - VegetationManager: Refactor the code. * Remove unnecessary logs * Resolve Conflict * Removed Freeing CacheData * Removing 'can rest' feature Co-authored-by: bernatx Co-authored-by: Axel --- .../Source/Carla/MapGen/LargeMapManager.h | 2 +- .../SpringBasedVegetationComponent.cpp | 326 +++++++------ .../SpringBasedVegetationComponent.h | 28 +- .../Carla/Vegetation/VegetationManager.cpp | 433 +++++++++--------- .../Carla/Vegetation/VegetationManager.h | 33 +- .../Carla/Vehicle/CarlaWheeledVehicle.cpp | 25 +- .../Carla/Vehicle/CarlaWheeledVehicle.h | 2 +- 7 files changed, 472 insertions(+), 377 deletions(-) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/LargeMapManager.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/LargeMapManager.h index a8f89fbc6..96fd9ff0d 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/LargeMapManager.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/MapGen/LargeMapManager.h @@ -184,7 +184,7 @@ public: TileID GetTileID(FDVector TileLocation) const; TileID GetTileID(FIntVector TileVectorID) const; - +public: FCarlaMapTile& GetCarlaMapTile(FVector Location); FCarlaMapTile& GetCarlaMapTile(ULevel* InLevel); diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/SpringBasedVegetationComponent.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/SpringBasedVegetationComponent.cpp index 1e653cea9..8d7b9506a 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/SpringBasedVegetationComponent.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/SpringBasedVegetationComponent.cpp @@ -9,6 +9,7 @@ #include "Math/Matrix.h" #include "Components/CapsuleComponent.h" #include "DrawDebugHelpers.h" +#include "Kismet/KismetMathLibrary.h" #include #include #include "carla/rpc/String.h" @@ -48,24 +49,6 @@ #define OTHER_LOG(...) #endif -static float ClampToPositiveDegrees(float d) -{ - if (d < 0.0f) - { - while (d < 0.0f) - { - d += 360.0f; - } - } - else - { - while (d >= 360.0f) - { - d -= 360.0f; - } - } - return d; -} template static T GetSign(T n) { @@ -208,7 +191,7 @@ void FSkeletonHierarchy::AddForce(const FString& BoneName, const FVector& Force) { if(Joint.JointName == BoneName) { - Joint.ExternalForces += Force * 0.001f; + Joint.ExternalForces += Force; } } } @@ -374,28 +357,7 @@ void USpringBasedVegetationComponent::BeginPlay() void USpringBasedVegetationComponent::ResetComponent() { Skeleton.ClearExternalForces(); - // Get resting pose for bones - auto *AnimInst = SkeletalMesh->GetAnimInstance(); - if (!AnimInst) - { - OTHER_LOG(Error, "Could not get animation instance."); - return; - } - UWalkerAnim *WalkerAnim = Cast(AnimInst); - if (!WalkerAnim) - { - OTHER_LOG(Error, "Could not get UWalkerAnim."); - return; - } - - // get current pose - FPoseSnapshot TempSnapshot; - SkeletalMesh->SnapshotPose(TempSnapshot); - - // copy pose - WalkerAnim->Snap = TempSnapshot; - - UpdateGlobalTransform(); + SkeletalMesh->ResetAllBodiesSimulatePhysics(); } void USpringBasedVegetationComponent::GenerateCollisionCapsules() @@ -415,10 +377,20 @@ void USpringBasedVegetationComponent::GenerateCollisionCapsules() Capsule->SetRelativeTransform(CapsuleTransform); Capsule->SetCapsuleHalfHeight(Bone.Length*0.5f); Capsule->SetCapsuleRadius(6); - Capsule->SetGenerateOverlapEvents(true); - Capsule->SetCollisionProfileName("OverlapAll"); - Capsule->OnComponentBeginOverlap.AddDynamic(this, &USpringBasedVegetationComponent::OnBeginOverlapEvent); - Capsule->OnComponentEndOverlap.AddDynamic(this, &USpringBasedVegetationComponent::OnEndOverlapEvent); + if (Joint.bIsStatic) + { + Capsule->SetGenerateOverlapEvents(false); + Capsule->SetCollisionProfileName("BlockAll"); + Capsule->OnComponentHit.AddDynamic(this, &USpringBasedVegetationComponent::OnCollisionEvent); + } + else + { + Capsule->SetGenerateOverlapEvents(true); + Capsule->SetCollisionProfileName("OverlapAll"); + Capsule->OnComponentBeginOverlap.AddDynamic(this, &USpringBasedVegetationComponent::OnBeginOverlapEvent); + Capsule->OnComponentEndOverlap.AddDynamic(this, &USpringBasedVegetationComponent::OnEndOverlapEvent); + } + BoneCapsules.Add(Capsule); CapsuleToJointId.Add(Capsule, Joint.JointId); } @@ -445,7 +417,6 @@ void USpringBasedVegetationComponent::ComputeSpringStrengthForBranches() OTHER_LOG(Log, "Joint: %s, location %s, Strength %f", *Joint.JointName, *JointLocation.ToString(), Joint.SpringStrength); } - } void USpringBasedVegetationComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) @@ -470,9 +441,7 @@ void USpringBasedVegetationComponent::ComputePerJointProperties( Properties.JointToGlobalMatrix = ToEigenMatrix(Joint.GlobalTransform); JointPropertiesList[Joint.JointId].JointToGlobalMatrix = Properties.JointToGlobalMatrix; if (!Joint.Bones.Num()) - { continue; - } // COM and mass for (FSkeletonBone& Bone : Joint.Bones) { @@ -491,9 +460,7 @@ void USpringBasedVegetationComponent::ComputePerJointProperties( for (FSkeletonBone& Bone : Joint.Bones) { if (Bone.Length < 1) - { continue; - } float CylinderRadius = 0.1f; float CylinderHeight = Bone.Length/100.f; Eigen::Matrix3d LocalCylinderInertia; @@ -505,9 +472,7 @@ void USpringBasedVegetationComponent::ComputePerJointProperties( Eigen::Vector3d LocalV1 = BoneVector.normalized(); Eigen::Vector3d LocalV2 = LocalV1.cross(Eigen::Vector3d(0,1,0)); if (LocalV2.norm() == 0) - { LocalV2 = LocalV1.cross(Eigen::Vector3d(0,0,1)); - } LocalV2.normalize(); Eigen::Vector3d LocalV3 = LocalV1.cross(LocalV2); Eigen::Matrix3d LocalToJointMatrix; @@ -520,6 +485,7 @@ void USpringBasedVegetationComponent::ComputePerJointProperties( ACC_LOG(Log, "Local Joint: %s \n Inertia \n %s \n Force \n %s \n Torque \n %s \n COM: \n %s \n Mass %f", *Joint.JointName, *EigenToFString(Properties.InertiaTensor), *EigenToFString(Properties.Force), *EigenToFString(Properties.Torque), *EigenToFString(Properties.CenterOfMass), Properties.Mass); } } + // Compute accumulated properties (Center of Mass, Inertia, Forces and Torque) void USpringBasedVegetationComponent::ComputeCompositeBodyContribution( std::vector& JointLocalPropertiesList, @@ -637,75 +603,115 @@ void USpringBasedVegetationComponent::ResolveContactsAndCollisions( std::vector& JointPropertiesList) { TRACE_CPUPROFILER_EVENT_SCOPE(USpringBasedVegetationComponent::ResolveContactsAndCollisions); - float MinDistance = INFINITY; - FVector ClosestSurfacePoint; for (auto& ActorCapsules : OverlappingActors) { + TRACE_CPUPROFILER_EVENT_SCOPE(ActorLoop); AActor* CollidingActor = ActorCapsules.Key; - UPrimitiveComponent* Primitive = Cast(CollidingActor->GetRootComponent()); - if (!Primitive) - { + if (!IsValid(CollidingActor)) + continue; + UPrimitiveComponent* Primitive = Cast(CollidingActor->GetRootComponent()); + if (!IsValid(Primitive)) continue; - } // force transferring momentum (for the initial collision frame) - FVector PrimitiveVelocity = Primitive->GetComponentVelocity(); - Eigen::Vector3d ColliderVelocity = ToEigenVector(PrimitiveVelocity)/100.f; - FVector Impulse = (Primitive->GetMass() * PrimitiveVelocity); - Eigen::Vector3d CollisionImpulse = ToEigenVector(Impulse)/100.f; + const FVector PrimitiveVelocity = Primitive->GetComponentVelocity(); + const Eigen::Vector3d ColliderVelocity = ToEigenVector(PrimitiveVelocity) / 100.f; + const FVector Impulse = (Primitive->GetMass() * PrimitiveVelocity); + const Eigen::Vector3d CollisionImpulse = 0*ToEigenVector(Impulse) / 100.f; TArray& CollidingCapsules = ActorCapsules.Value; for (UPrimitiveComponent* Capsule : CollidingCapsules) - { - FVector auxVector; - float distance = Primitive->GetClosestPointOnCollision(Capsule->GetComponentLocation(), auxVector); - float DistanceToRoot = 0.0f; - if (distance < MinDistance) + { + TRACE_CPUPROFILER_EVENT_SCOPE(CapsuleLoop); + if (!IsValid(Capsule)) + continue; + const FVector CapsuleLocation = Capsule->GetComponentLocation(); + const FVector PrimitiveLocation = Primitive->GetComponentLocation(); + static constexpr float MIN_DISTANCE = 1.0f; + FVector ClosestPointOnCapsule; + float DistanceOnCapsule; + FHitResult HitResult; + bool HitFound; + FVector ClosestPointOnCollider; + float DistanceToCollider; { - MinDistance = distance; - ClosestSurfacePoint = auxVector; - const FVector RootLocation = Skeleton.Joints[0].GlobalTransform.GetLocation(); - DistanceToRoot = FMath::Sqrt(std::pow(auxVector.X - RootLocation.X, 2) + std::pow(auxVector.Y - RootLocation.Y, 2) + std::pow(auxVector.Z - RootLocation.Z, 2)); + TRACE_CPUPROFILER_EVENT_SCOPE(ColliderPenetrationDistance); + DistanceOnCapsule = Capsule->GetClosestPointOnCollision(PrimitiveLocation, ClosestPointOnCapsule); + FVector LineDirection = (ClosestPointOnCapsule - PrimitiveLocation).GetSafeNormal(); + FVector LineTraceStart = ClosestPointOnCapsule + LineTraceMaxDistance*LineDirection; + FVector LineTraceEnd = ClosestPointOnCapsule; + HitFound = Primitive->LineTraceComponent(HitResult, + LineTraceStart, LineTraceEnd, FCollisionQueryParams()); + ClosestPointOnCollider = HitResult.Location; + DistanceToCollider = (ClosestPointOnCollider - ClosestPointOnCapsule).Size(); + } + if(!HitFound) + { + continue; } - - int JointId = CapsuleToJointId[Capsule]; - FSkeletonJoint& Joint = Skeleton.Joints[JointId]; - FJointProperties& JointProperties = JointLocalPropertiesList[Joint.JointId]; - Eigen::Vector3d JointGlobalPosition = ToEigenVector(Joint.GlobalTransform.GetLocation())/100.f; - Eigen::Vector3d CapsulePosition = ToEigenVector(Capsule->GetComponentLocation())/100.f; - Eigen::Vector3d ColliderPosition = ToEigenVector(Primitive->GetComponentLocation())/100.f; - Eigen::Vector3d CollisionTorque = Eigen::Vector3d::Zero(); - const float SpringStrength = Joint.SpringStrength; + if (DebugEnableVisualization) + { + TRACE_CPUPROFILER_EVENT_SCOPE(DebugEnableVisualization); + DrawDebugLine(GetWorld(), ClosestPointOnCapsule, ClosestPointOnCollider, FColor::Green, false, 0.1f, 0.0f, 1.f); + static constexpr float DEBUG_SPHERE_SIZE = 5.0f; + DrawDebugSphere(GetWorld(), ClosestPointOnCapsule, DEBUG_SPHERE_SIZE, 64, FColor(255, 0, 255, 255)); + DrawDebugSphere(GetWorld(), ClosestPointOnCollider, DEBUG_SPHERE_SIZE, 64, FColor(255, 0, 255, 255)); + DrawDebugSphere(GetWorld(), CapsuleLocation, DEBUG_SPHERE_SIZE, 64, FColor(255, 255, 255, 255)); + DrawDebugSphere(GetWorld(), PrimitiveLocation, DEBUG_SPHERE_SIZE, 64, FColor(0, 0, 0, 255)); + } + + const int JointId = CapsuleToJointId[Capsule]; + const FSkeletonJoint& Joint = Skeleton.Joints[JointId]; + FJointProperties& JointProperties = JointLocalPropertiesList[Joint.JointId]; + const Eigen::Vector3d JointGlobalPosition = ToEigenVector(Joint.GlobalTransform.GetLocation()) / 100.f; + const Eigen::Vector3d CapsulePosition = ToEigenVector(CapsuleLocation) / 100.f; + const Eigen::Vector3d PointOnCapsulePosition = ToEigenVector(ClosestPointOnCapsule) / 100.f; + const Eigen::Vector3d ColliderPosition = ToEigenVector(ClosestPointOnCollider) / 100.f; + Eigen::Vector3d CollisionTorque = Eigen::Vector3d::Zero(); // Contact forces due to spring strength - FRotator CurrRotator = Joint.Transform.Rotator(); - FRotator RestRotator = Joint.RestingAngles; - FRotator DeltaRotator ( + const FRotator CurrRotator = Joint.Transform.Rotator(); + const FRotator RestRotator = Joint.RestingAngles; + const FRotator DeltaRotator ( CurrRotator.Pitch - RestRotator.Pitch, CurrRotator.Yaw - RestRotator.Yaw, CurrRotator.Roll - RestRotator.Roll); - const Eigen::Vector3d SpringTorque = SpringStrength*RotatorToEigenVector(DeltaRotator); + const Eigen::Vector3d SpringTorque = Joint.SpringStrength * RotatorToEigenVector(DeltaRotator); const Eigen::Vector3d JointCapsuleVector = JointGlobalPosition - CapsulePosition; - const Eigen::Vector3d SpringForce = SpringTorque.cross(JointCapsuleVector)*JointCapsuleVector.squaredNorm(); - const Eigen::Vector3d RepulsionForce = SpringForce; - - Primitive->AddForceAtLocation(-ToUnrealVector(RepulsionForce)*100.f, Capsule->GetComponentLocation()); - + const Eigen::Vector3d RepulsionForce = SpringTorque.cross(JointCapsuleVector) * JointCapsuleVector.squaredNorm(); + + FVector RepulsionForceUE = -ToUnrealVector(RepulsionForce) * 100.f; + Primitive->AddForceAtLocation(RepulsionForceUE, CapsuleLocation); + // force to repel geometry overlapping - Eigen::Vector3d OverlappingForces = (CapsulePosition - ColliderPosition).normalized()*CollisionForceParameter; - Primitive->AddForceAtLocation(-ToUnrealVector(OverlappingForces)*100.f, Capsule->GetComponentLocation()); - CollisionTorque += (JointProperties.CenterOfMass - JointGlobalPosition).cross(RepulsionForce + CollisionImpulse + OverlappingForces); + float ForceFactor = 1.f; + // from eq f = 1 - a*d^p, f: ForceFactor, a: ProportionalConstant, p: ForceDistanceFalloffExponent, d: DistanceOnCapsule + // float ProportionalConstant = 1.f/(FMath::Pow(ForceMaxDistance, ForceDistanceFalloffExponent)); + // ForceFactor = 1.f - ProportionalConstant * FMath::Pow(DistanceOnCapsule, ForceDistanceFalloffExponent); + // from eq f = a*d^p, f: ForceFactor, a: ProportionalConstant, p: ForceDistanceFalloffExponent, d: DistanceToCollider + float ProportionalConstant = 1.f/(FMath::Pow(ForceMaxDistance, ForceDistanceFalloffExponent)); + ForceFactor = ProportionalConstant * FMath::Pow(DistanceToCollider, ForceDistanceFalloffExponent); + ForceFactor = FMath::Clamp(ForceFactor, MinForceFactor, 1.f); + // const Eigen::Vector3d OverlappingForces = (ColliderPosition - CapsulePosition).normalized() * CollisionForceParameter * ForceFactor; + const Eigen::Vector3d OverlappingForces = (ColliderPosition - PointOnCapsulePosition).normalized() * CollisionForceParameter * ForceFactor; + Primitive->AddForceAtLocation(-ToUnrealVector(OverlappingForces) * 100.f, ClosestPointOnCollider); + CollisionTorque += (JointProperties.CenterOfMass - JointGlobalPosition).cross(CollisionImpulse + OverlappingForces); JointProperties.Torque += CollisionTorque; // COLLISION_LOG(Log, "Joint: %s \n ProjectedSpeed %f, ProportionalFactor %f \n RepulsionForce %s \n", *Joint.JointName,ProjectedSpeed,ProportionalFactor,*EigenToFString(RepulsionForce),*EigenToFString(CollisionTorque)); + UE_LOG(LogCarla, Display, TEXT("DistanceToCollider: %f, ForceFactor: %f"), DistanceToCollider, ForceFactor); + + if (DebugEnableVisualization) + { + // drawing + const FVector Start = Capsule->GetComponentLocation(); + const FVector End = Primitive->GetComponentLocation(); + const FColor LineColor(FColor::Green); + DrawDebugLine(GetWorld(), Start, End, LineColor, false, 0.1f, 0.0f, 1.f); + DrawDebugLine(GetWorld(), CapsuleLocation, CapsuleLocation+RepulsionForceUE.GetSafeNormal()*5.f, FColor::Red, false, 0.1f, 0.0f, 1.f); + } } } - if (MinDistance != INFINITY) - { - - //DrawDebugPoint(GetWorld(), ClosestSurfacePoint, 5, FColor(255,0,0), false, 100.f); - } } - void USpringBasedVegetationComponent::SolveEquationOfMotion( std::vector& JointPropertiesList, float DeltaTime) @@ -719,6 +725,16 @@ void USpringBasedVegetationComponent::SolveEquationOfMotion( continue; } FJointProperties& JointProperties = JointPropertiesList[Joint.JointId]; + + // drawing + if (Joint.ParentId != -1 && DebugEnableVisualization) + { + const FVector Start = Joint.GlobalTransform.GetLocation(); + const FVector End = Skeleton.Joints[Joint.ParentId].GlobalTransform.GetLocation(); + const FColor LineColor(FColor::Blue); + DrawDebugLine(GetWorld(), Start, End, LineColor, false, 0.1f, 0.0f, 1.f); + } + float Mass = JointProperties.Mass; Eigen::Vector3d CenterToJoint = JointProperties.CenterOfMass - ToEigenVector(Joint.GlobalTransform.GetLocation())/100.f; Eigen::Matrix3d GlobalToJointMatrix = JointProperties.JointToGlobalMatrix.transpose(); @@ -729,6 +745,7 @@ void USpringBasedVegetationComponent::SolveEquationOfMotion( Eigen::Matrix3d I = JointSpaceIntertiaTensor; float SpringStrength = Joint.SpringStrength; float beta = Beta; + float alpha = Alpha; Eigen::Matrix3d K; K << SpringStrength,0.f,0.f, 0.f,SpringStrength,0.f, @@ -743,7 +760,7 @@ void USpringBasedVegetationComponent::SolveEquationOfMotion( Eigen::Matrix3d U = Linv.transpose()*X; // Eigen::Matrix3d Uinv = U.inverse(); Eigen::Matrix3d Uinv = X.transpose()*L.transpose(); - Eigen::Vector3d Coeffsb = beta*Lambda*Eigen::Vector3d(1,1,1); + Eigen::Vector3d Coeffsb = Eigen::Vector3d(alpha,alpha,alpha) + beta*Lambda*Eigen::Vector3d(1,1,1); Eigen::Vector3d Coeffsk = Lambda*Eigen::Vector3d(1,1,1); Eigen::Vector3d Coeffsf = U.transpose()*Torque; FString StringI = EigenToFString(I); @@ -846,30 +863,6 @@ void USpringBasedVegetationComponent::SolveEquationOfMotion( FRotator NewAngularVelocity = EigenVectorToRotator(FinalNewThetaVelocity); FRotator NewAngularAccel = EigenVectorToRotator(FinalNewThetaAccel); - const float ClampedNewPitch = ClampToPositiveDegrees(NewPitch); - const float ClampedNewYaw = ClampToPositiveDegrees(MaxYaw); - const float ClampedNewRoll = ClampToPositiveDegrees(MaxRoll); - - if (ClampedNewPitch > MaxPitch){ - NewPitch = ClampedNewPitch; - - NewAngularVelocity.Pitch = 0.0f; - NewAngularAccel.Pitch = 0.0f; - } - - if (ClampedNewYaw > MaxYaw){ - NewYaw = ClampedNewYaw; - - NewAngularVelocity.Yaw = 0.0f; - NewAngularAccel.Yaw = 0.0f; - } - - if (ClampedNewRoll > MaxRoll){ - NewRoll = ClampedNewRoll; - NewAngularVelocity.Roll = 0.0f; - NewAngularAccel.Roll = 0.0f; - } - FRotator NewAngle( RestRotator.Pitch + NewPitch, RestRotator.Yaw - NewYaw, @@ -894,9 +887,8 @@ void USpringBasedVegetationComponent::TickComponent( float DeltaTimeFinal = DeltaTime; if (DeltaTimeOverride > 0) - { DeltaTimeFinal = DeltaTimeOverride; - } + std::vector JointPropertiesList; JointPropertiesList.resize(Skeleton.Joints.Num()); std::vector JointLocalPropertiesList; @@ -924,7 +916,25 @@ void USpringBasedVegetationComponent::OnCollisionEvent( FVector NormalImpulse, const FHitResult& Hit) { - UE_LOG(LogCarla, Log, TEXT("Collision with bone %s, with impulse %s"), *Hit.MyBoneName.ToString(), *NormalImpulse.ToString()); + // prevent self collision + if (OtherActor == GetOwner()) + return; + // prevent collision with other tree actors + if(OtherActor->GetComponentByClass(USpringBasedVegetationComponent::StaticClass()) != nullptr) + return; + ACarlaWheeledVehicle* Vehicle = nullptr; + if (DebugEnableAllCollisions) + { + if (!IsValid(OtherActor)) + return; + } + else + { + Vehicle = Cast(OtherActor); + if (!IsValid(Vehicle)) + return; + } + COLLISION_LOG(LogCarla, Log, TEXT("Collision with bone %s, with impulse %s"), *Hit.MyBoneName.ToString(), *NormalImpulse.ToString()); Skeleton.AddForce(Hit.MyBoneName.ToString(), NormalImpulse); } @@ -937,18 +947,33 @@ void USpringBasedVegetationComponent::OnBeginOverlapEvent( const FHitResult& SweepResult) { // prevent self collision - if(OtherActor == GetOwner()) - { + if (OtherActor == GetOwner()) return; - } // prevent collision with other tree actors if(OtherActor->GetComponentByClass(USpringBasedVegetationComponent::StaticClass()) != nullptr) - { return; + ACarlaWheeledVehicle* Vehicle = nullptr; + if (DebugEnableAllCollisions) + { + if (!IsValid(OtherActor)) + return; + } + else + { + Vehicle = Cast(OtherActor); + if (!IsValid(Vehicle)) + return; + } + + if (!OverlappingActors.Contains(OtherActor)) + { + OverlappingActors.Add(OtherActor); } - // OverlappingActors.Add(OtherActor); TArray& OverlappingCapsules = OverlappingActors.FindOrAdd(OtherActor); - OverlappingCapsules.Add(OverlapComponent); + if (!OverlappingCapsules.Contains(OverlapComponent)) + { + OverlappingCapsules.Add(OverlapComponent); + } } void USpringBasedVegetationComponent::OnEndOverlapEvent( @@ -957,19 +982,35 @@ void USpringBasedVegetationComponent::OnEndOverlapEvent( UPrimitiveComponent* OtherComponent, int32 OtherBodyIndex) { - if(OtherActor == GetOwner()) - { + // prevent self collision + if (OtherActor == GetOwner()) return; - } + // prevent collision with other tree actors if(OtherActor->GetComponentByClass(USpringBasedVegetationComponent::StaticClass()) != nullptr) - { return; - } - TArray& OverlappingCapsules = OverlappingActors.FindOrAdd(OtherActor); - OverlappingCapsules.RemoveSingle(OverlapComponent); - if (OverlappingCapsules.Num() == 0) + ACarlaWheeledVehicle* Vehicle = nullptr; + if (DebugEnableAllCollisions) { - OverlappingActors.Remove(OtherActor); + if (!IsValid(OtherActor)) + return; + } + else + { + Vehicle = Cast(OtherActor); + if (!IsValid(Vehicle)) + return; + } + + if (!OverlappingActors.Contains(OtherActor)) + return; + TArray& OverlappingCapsules = OverlappingActors.FindOrAdd(OtherActor); + if (OverlappingCapsules.Contains(OverlapComponent)) + { + OverlappingCapsules.RemoveSingle(OverlapComponent); + if (OverlappingCapsules.Num() == 0) + { + OverlappingActors.Remove(OtherActor); + } } } @@ -1023,8 +1064,5 @@ void USpringBasedVegetationComponent::UpdateGlobalTransform() FTransform Transform = Joint.Transform * ParentJoint.GlobalTransform; Joint.GlobalTransform = Transform; Joint.GolbalInverseTransform = Transform.Inverse(); - - } - } diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/SpringBasedVegetationComponent.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/SpringBasedVegetationComponent.h index ce6f73c6b..a2c06a116 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/SpringBasedVegetationComponent.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/SpringBasedVegetationComponent.h @@ -214,6 +214,9 @@ private: UPROPERTY(EditAnywhere, Category = "Spring Based Vegetation Component") float Beta = 0.5f; + UPROPERTY(EditAnywhere, Category = "Spring Based Vegetation Component") + float Alpha = 0.f; + UPROPERTY(EditAnywhere, Category = "Spring Based Vegetation Component") FVector Gravity = FVector(0,0,-1); @@ -239,18 +242,23 @@ private: float CollisionForceMinVel = 1.f; UPROPERTY(EditAnywhere, Category = "Spring Based Vegetation Component") + float ForceDistanceFalloffExponent = 1.f; + UPROPERTY(EditAnywhere, Category = "Spring Based Vegetation Component") + float ForceMaxDistance = 180.f; + UPROPERTY(EditAnywhere, Category = "Spring Based Vegetation Component") + float MinForceFactor = 0.01; + UPROPERTY(EditAnywhere, Category = "Spring Based Vegetation Component") + float LineTraceMaxDistance = 180.f; +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spring Based Vegetation Component") FSkeletonHierarchy Skeleton; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spring Based Vegetation Component") + bool DebugEnableVisualization { false }; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spring Based Vegetation Component") + bool DebugEnableAllCollisions { false }; +private: UPROPERTY(EditAnywhere, Category = "Spring Based Vegetation Component") bool bAutoComputeStrength = true; - - UPROPERTY(EditAnywhere, Category = "Spring Based Vegetation Component") - float MaxYaw = 0.0f; - - UPROPERTY(EditAnywhere, Category = "Spring Based Vegetation Component") - float MaxPitch = 180.0f; - - UPROPERTY(EditAnywhere, Category = "Spring Based Vegetation Component") - float MaxRoll = 180.0f; }; - diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/VegetationManager.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/VegetationManager.cpp index 9a756c135..05bb20303 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/VegetationManager.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/VegetationManager.cpp @@ -81,7 +81,9 @@ void FPooledActor::DisableActor() /********************************************************************************/ bool FFoliageBlueprint::IsValid() const { - return !BPFullClassName.IsEmpty() && SpawnedClass; + if (BPFullClassName.IsEmpty() || !BPFullClassName.Contains("_C")) + return false; + return SpawnedClass != nullptr; } bool FFoliageBlueprint::SetBPClassName(const FString& Path) @@ -94,7 +96,7 @@ bool FFoliageBlueprint::SetBPClassName(const FString& Path) int Position = ParsedString.Num() - 1; const FString FullVersion = GetVersionFromFString(ParsedString[Position]); const FString Folder = ParsedString[--Position]; - BPClassName = "BP_" + Folder + FullVersion; + const FString BPClassName = "BP_" + Folder + FullVersion; BPFullClassName = "Blueprint'"; for (int i = 0; i <= Position; ++i) { @@ -104,18 +106,17 @@ bool FFoliageBlueprint::SetBPClassName(const FString& Path) BPFullClassName += BPClassName; BPFullClassName += "."; BPFullClassName += BPClassName; - BPFullClassName += "'"; + BPFullClassName += "_C'"; return true; } bool FFoliageBlueprint::SetSpawnedClass() { TRACE_CPUPROFILER_EVENT_SCOPE(FoliageBlueprintCache::SetSpawnedClass); - UObject* LoadedObject = StaticLoadObject(UObject::StaticClass(), nullptr, *BPFullClassName); - UBlueprint* CastedBlueprint = Cast(LoadedObject); - if (CastedBlueprint && CastedBlueprint->GeneratedClass->IsChildOf(AActor::StaticClass())) + UClass* CastedBlueprint = LoadObject< UClass >(nullptr, *BPFullClassName); + if (CastedBlueprint) { - SpawnedClass = *CastedBlueprint->GeneratedClass; + SpawnedClass = CastedBlueprint; return true; } SpawnedClass = nullptr; @@ -125,12 +126,43 @@ bool FFoliageBlueprint::SetSpawnedClass() /********************************************************************************/ /********** TILE DATA STRUCT ****************************************************/ /********************************************************************************/ -void FTileData::UpdateMaterialCache(const FLinearColor& Value) +void FTileData::UpdateTileMeshComponent(UInstancedStaticMeshComponent* NewInstancedStaticMeshComponent) +{ + UInstancedStaticMeshComponent* Aux { nullptr }; + for (FTileMeshComponent& Element : TileMeshesCache) + { + if (Element.InstancedStaticMeshComponent == NewInstancedStaticMeshComponent) + { + int32 CurrentCount = Element.InstancedStaticMeshComponent->GetInstanceCount(); + int32 NewCount = NewInstancedStaticMeshComponent->GetInstanceCount(); + if (NewCount > CurrentCount) + { + Element.InstancedStaticMeshComponent = NewInstancedStaticMeshComponent; + Element.IndicesInUse.Empty(); + } + } + } +} + +bool FTileData::ContainsMesh(const UInstancedStaticMeshComponent* Mesh) const +{ + for (const FTileMeshComponent& Element : TileMeshesCache) + { + if (Element.InstancedStaticMeshComponent == Mesh) + return true; + } + return false; +} + +void FTileData::UpdateMaterialCache(const FLinearColor& Value, bool DebugMaterials) { TRACE_CPUPROFILER_EVENT_SCOPE(FTileData::UpdateMaterialCache); for (UMaterialInstanceDynamic* Material : MaterialInstanceDynamicCache) { - Material->SetScalarParameterValue("ActivateDebug", 0); + if (DebugMaterials) + Material->SetScalarParameterValue("ActivateDebug", 1); + else + Material->SetScalarParameterValue("ActivateDebug", 0); Material->SetScalarParameterValue("ActivateOpacity", 1); Material->SetVectorParameterValue("VehiclePosition", Value); } @@ -143,6 +175,9 @@ void AVegetationManager::BeginPlay() { TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::BeginPlay); Super::BeginPlay(); + LargeMap = UCarlaStatics::GetLargeMapManager(GetWorld()); + FWorldDelegates::LevelAddedToWorld.AddUObject(this, &AVegetationManager::OnLevelAddedToWorld); + FWorldDelegates::LevelRemovedFromWorld.AddUObject(this, &AVegetationManager::OnLevelRemovedFromWorld); } void AVegetationManager::Tick(float DeltaTime) @@ -151,21 +186,19 @@ void AVegetationManager::Tick(float DeltaTime) { TRACE_CPUPROFILER_EVENT_SCOPE(Parent Tick); Super::Tick(DeltaTime); - } + } + if (!LargeMap) + return; bool FoundVehicles = CheckIfAnyVehicleInLevel(); if (!FoundVehicles) return; + UpdateVehiclesDetectionBoxes(); - bool NewTilesFound = CheckForNewTiles(); - if (NewTilesFound) - { - UpdateFoliageBlueprintCache(); - UpdateTileDataCache(); - GenerateTileDataInternals(); - } + TArray TilesInUse = GetTilesInUse(); if (TilesInUse.Num() == 0) return; + UpdateMaterials(TilesInUse); TArray>> ElementsToSpawn = GetElementsToSpawn(TilesInUse); SpawnSkeletalFoliages(ElementsToSpawn); @@ -200,61 +233,116 @@ void AVegetationManager::RemoveVehicle(ACarlaWheeledVehicle* Vehicle) /********************************************************************************/ /********** CACHES **************************************************************/ /********************************************************************************/ -void AVegetationManager::UpdateTileDataCache() +void AVegetationManager::CreateOrUpdateTileCache(ULevel* InLevel) { - TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::UpdateTileDataCache); - const UObject* World = GetWorld(); - TArray NewKeys; - TArray ActorsInLevel; - UGameplayStatics::GetAllActorsOfClass(World, AInstancedFoliageActor::StaticClass(), ActorsInLevel); - for (AActor* Actor : ActorsInLevel) + TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::CreateOrUpdateTileCache); + FTileData TileData {}; + for (AActor* Actor : InLevel->Actors) + { + AInstancedFoliageActor* InstancedFoliageActor = Cast(Actor); + if (!IsValid(InstancedFoliageActor)) + continue; + TileData.InstancedFoliageActor = InstancedFoliageActor; + break; + } + + for (AActor* Actor : InLevel->Actors) + { + AProceduralFoliageVolume* ProceduralFoliageVolume = Cast(Actor); + if (!IsValid(ProceduralFoliageVolume)) + continue; + TileData.ProceduralFoliageVolume = ProceduralFoliageVolume; + break; + } + const FString TileName = TileData.InstancedFoliageActor->GetLevel()->GetOuter()->GetName(); + FTileData* ExistingTileData = TileCache.Find(TileName); + if (ExistingTileData) + { + ExistingTileData->InstancedFoliageActor = TileData.InstancedFoliageActor; + ExistingTileData->ProceduralFoliageVolume = TileData.ProceduralFoliageVolume; + SetTileDataInternals(*ExistingTileData); + } + else + { + SetTileDataInternals(TileData); + TileCache.Emplace(TileName, TileData); + } + +} + +void AVegetationManager::SetTileDataInternals(FTileData& TileData) +{ + TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::SetTileDataInternals); + SetInstancedStaticMeshComponentCache(TileData); + SetMaterialCache(TileData); +} + +void AVegetationManager::SetInstancedStaticMeshComponentCache(FTileData& TileData) +{ + TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::SetInstancedStaticMeshComponentCache); + const TSet& ActorComponents = TileData.InstancedFoliageActor->GetComponents(); + for (UActorComponent* Component : ActorComponents) + { + UInstancedStaticMeshComponent* Mesh = Cast(Component); + if (!IsValid(Mesh)) + continue; + const FString Path = Mesh->GetStaticMesh()->GetPathName(); + const FFoliageBlueprint* BPCache = FoliageBlueprintCache.Find(Path); + if (!BPCache) + continue; + + if (TileData.ContainsMesh(Mesh)) + { + TileData.UpdateTileMeshComponent(Mesh); + } + else + { + FTileMeshComponent Aux; + Aux.InstancedStaticMeshComponent = Mesh; + TileData.TileMeshesCache.Emplace(Aux); + } + } +} + +void AVegetationManager::SetMaterialCache(FTileData& TileData) +{ + TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::SetMaterialCache); + if (TileData.MaterialInstanceDynamicCache.Num() > 0) + TileData.MaterialInstanceDynamicCache.Empty(); + + const float Distance = VehiclesInLevel.Last()->DetectionSize * 2.0f; + for (FTileMeshComponent& Element : TileData.TileMeshesCache) + { + UInstancedStaticMeshComponent* Mesh = Element.InstancedStaticMeshComponent; + int32 Index = -1; + for (UMaterialInterface* Material : Mesh->GetMaterials()) + { + ++Index; + if (!IsValid(Material)) + continue; + UMaterialInstanceDynamic* MaterialInstanceDynamic = UMaterialInstanceDynamic::Create(Material, this); + if (!MaterialInstanceDynamic) + continue; + if (TileData.MaterialInstanceDynamicCache.Contains(MaterialInstanceDynamic)) + continue; + MaterialInstanceDynamic->SetScalarParameterValue("ActivateOpacity", 0); + MaterialInstanceDynamic->SetScalarParameterValue("ActivateDebug", 0); + MaterialInstanceDynamic->SetScalarParameterValue("Distance", Distance); + Mesh->SetMaterial(Index, MaterialInstanceDynamic); + TileData.MaterialInstanceDynamicCache.Emplace(MaterialInstanceDynamic); + } + } +} + +void AVegetationManager::UpdateFoliageBlueprintCache(ULevel* InLevel) +{ + TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::UpdateFoliageBlueprintCache); + for (AActor* Actor : InLevel->Actors) { AInstancedFoliageActor* InstancedFoliageActor = Cast(Actor); if (!IsValid(InstancedFoliageActor)) continue; const FString TileName = InstancedFoliageActor->GetLevel()->GetOuter()->GetName(); - if (TileDataCache.Contains(TileName)) - { - UE_LOG(LogCarla, Warning, TEXT("Tile: %s is already in the cache."), *TileName); - continue; - } - FTileData TileData {}; - TileData.InstancedFoliageActor = InstancedFoliageActor; - TileDataCache.Emplace(TileName, TileData); - NewKeys.Emplace(TileName); - } - - ActorsInLevel.Reset(); - UGameplayStatics::GetAllActorsOfClass(World, AProceduralFoliageVolume::StaticClass(), ActorsInLevel); - for (AActor* Actor : ActorsInLevel) - { - AProceduralFoliageVolume* Procedural = Cast(Actor); - if (!IsValid(Procedural)) - continue; - const FString TileName = Procedural->GetLevel()->GetOuter()->GetName(); - if (NewKeys.Contains(TileName)) - { - FTileData* TileData = TileDataCache.Find(TileName); - if (TileData) - { - TileData->ProceduralFoliageVolume = Procedural; - UE_LOG(LogCarla, Display, TEXT("Tile: %s added to the cache."), *TileName); - } - } - } -} - -void AVegetationManager::UpdateFoliageBlueprintCache() -{ - TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::UpdateFoliageBlueprintCache); - const UObject* World = GetWorld(); - TArray ActorsInLevel; - UGameplayStatics::GetAllActorsOfClass(World, AInstancedFoliageActor::StaticClass(), ActorsInLevel); - for (AActor* Actor : ActorsInLevel) - { - AInstancedFoliageActor* InstancedFoliageActor = Cast(Actor); - if (!IsValid(InstancedFoliageActor)) - continue; const TSet& ActorComponents = InstancedFoliageActor->GetComponents(); for (UActorComponent* Component : ActorComponents) { @@ -269,95 +357,48 @@ void AVegetationManager::UpdateFoliageBlueprintCache() FFoliageBlueprint NewFoliageBlueprint; NewFoliageBlueprint.SetBPClassName(Path); NewFoliageBlueprint.SetSpawnedClass(); - FoliageBlueprintCache.Emplace(Path, NewFoliageBlueprint); if (!NewFoliageBlueprint.IsValid()) - { - UE_LOG(LogCarla, Warning, TEXT("Blueprint %s was invalid."), *NewFoliageBlueprint.BPClassName); + { + UE_LOG(LogCarla, Error, TEXT("Blueprint %s was invalid."), *NewFoliageBlueprint.BPFullClassName); } else { - UE_LOG(LogCarla, Display, TEXT("Blueprint %s created."), *NewFoliageBlueprint.BPClassName); + UE_LOG(LogCarla, Display, TEXT("Blueprint %s created."), *NewFoliageBlueprint.BPFullClassName); + FoliageBlueprintCache.Emplace(Path, NewFoliageBlueprint); CreatePoolForBPClass(NewFoliageBlueprint); } } } } -void AVegetationManager::GenerateTileDataInternals() +void AVegetationManager::FreeTileCache(ULevel* InLevel) { - TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::GenerateTileDataInternals); - for (TPair& Element : TileDataCache) + FTileData TileData {}; + for (AActor* Actor : InLevel->Actors) { - if (Element.Value.TileMeshesCache.Num() > 0) + AInstancedFoliageActor* InstancedFoliageActor = Cast(Actor); + if (!IsValid(InstancedFoliageActor)) continue; - InitializeInstancedStaticMeshComponentCache(Element.Value); - InitializeMaterialCache(Element.Value); + TileData.InstancedFoliageActor = InstancedFoliageActor; + break; } -} - -void AVegetationManager::InitializeInstancedStaticMeshComponentCache(FTileData& TileData) -{ - TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::InitializeInstancedStaticMeshComponentCache); - const TSet& ActorComponents = TileData.InstancedFoliageActor->GetComponents(); - for (UActorComponent* Component : ActorComponents) + if (TileData.InstancedFoliageActor == nullptr) + return; + const FString TileName = TileData.InstancedFoliageActor->GetLevel()->GetOuter()->GetName(); + FTileData* ExistingTileData = TileCache.Find(TileName); + if (ExistingTileData) { - UInstancedStaticMeshComponent* Mesh = Cast(Component); - if (!IsValid(Mesh)) - continue; - const FString Path = Mesh->GetStaticMesh()->GetPathName(); - const FFoliageBlueprint* BPCache = FoliageBlueprintCache.Find(Path); - if (!BPCache) - continue; - if (!BPCache->IsValid()) - continue; - bool Found = false; - for (auto& Element : TileData.TileMeshesCache) + ExistingTileData->MaterialInstanceDynamicCache.Empty(); + for (FTileMeshComponent& Element : ExistingTileData->TileMeshesCache) { - if (Element.InstancedStaticMeshComponent == Mesh) - { - Found = true; - break; - } + Element.IndicesInUse.Empty(); } - if (Found) - continue; - FTileMeshComponent Aux; - Aux.InstancedStaticMeshComponent = Mesh; - TileData.TileMeshesCache.Emplace(Aux); + ExistingTileData->TileMeshesCache.Empty(); + TileCache.Remove(TileName); } } -void AVegetationManager::InitializeMaterialCache(FTileData& TileData) -{ - TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::InitializeMaterialCache); - const float Distance = VehiclesInLevel[0]->DetectionSize * 2.0f; - for (FTileMeshComponent& Element : TileData.TileMeshesCache) - { - UInstancedStaticMeshComponent* Mesh = Element.InstancedStaticMeshComponent; - UMaterialInterface* Material {nullptr}; - int32 Index {0}; - do - { - Material = Mesh->GetMaterial(Index); - if (!Material) - continue; - UMaterialInstanceDynamic* MaterialInstanceDynamic = UMaterialInstanceDynamic::Create(Material, this); - if (!MaterialInstanceDynamic) - continue; - if (TileData.MaterialInstanceDynamicCache.Contains(MaterialInstanceDynamic)) - continue; - MaterialInstanceDynamic->SetScalarParameterValue("ActivateOpacity", 0); - MaterialInstanceDynamic->SetScalarParameterValue("ActivateDebug", 0); - MaterialInstanceDynamic->SetScalarParameterValue("Distance", Distance); - Mesh->SetMaterial(Index, MaterialInstanceDynamic); - TileData.MaterialInstanceDynamicCache.Emplace(MaterialInstanceDynamic); - ++Index; - } while (Material); - } -} - - /********************************************************************************/ /********** TICK ****************************************************************/ /********************************************************************************/ @@ -371,13 +412,13 @@ void AVegetationManager::UpdateVehiclesDetectionBoxes() void AVegetationManager::UpdateMaterials(TArray& Tiles) { TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::UpdateMaterials); - FLinearColor Position = FLinearColor(VehiclesInLevel[0]->GetActorLocation()); + const FLinearColor Position = VehiclesInLevel.Last()->GetActorLocation(); for (const FString& TileName : Tiles) { - FTileData* TileData = TileDataCache.Find(TileName); + FTileData* TileData = TileCache.Find(TileName); if (!TileData) continue; - TileData->UpdateMaterialCache(Position); + TileData->UpdateMaterialCache(Position, DebugMaterials); } } @@ -385,60 +426,40 @@ TArray>> AVegetationManager::GetElem { TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::GetElementsToSpawn); TArray>> Results; - ALargeMapManager* LargeMap = - UCarlaStatics::GetLargeMapManager(GetWorld()); - check(LargeMap); for (const FString& TileKey : Tiles) { - FTileData* Tile = TileDataCache.Find(TileKey); + FTileData* Tile = TileCache.Find(TileKey); if (!Tile) continue; for (FTileMeshComponent& Element : Tile->TileMeshesCache) { TRACE_CPUPROFILER_EVENT_SCOPE(Update Foliage Usage); UInstancedStaticMeshComponent* InstancedStaticMeshComponent = Element.InstancedStaticMeshComponent; - FString Path = InstancedStaticMeshComponent->GetStaticMesh()->GetPathName(); + const FString Path = InstancedStaticMeshComponent->GetStaticMesh()->GetPathName(); FFoliageBlueprint* BP = FoliageBlueprintCache.Find(Path); if (!BP) continue; - if (!BP->IsValid()) - continue; - TArray Indices = VehiclesInLevel[0]->GetFoliageInstancesCloseToVehicle(InstancedStaticMeshComponent); + TArray Indices = VehiclesInLevel.Last()->GetFoliageInstancesCloseToVehicle(InstancedStaticMeshComponent); if (Indices.Num() == 0) continue; - for (int32 i = 0; i < Element.IndicesInUse.Num(); ++i) - { - if (Element.IndicesInUse[i] == -1) - continue; - if (Indices.Contains(Element.IndicesInUse[i])) - continue; - Element.IndicesInUse[i] = -1; - } - TPair> NewElement {}; - NewElement.Key = *BP; - TArray Transforms; + + TArray NewIndices; for (int32 Index : Indices) { if (Element.IndicesInUse.Contains(Index)) continue; + NewIndices.Emplace(Index); + } + Element.IndicesInUse = Indices; + TPair> NewElement {}; + NewElement.Key = *BP; + TArray Transforms; + for (int32 Index : NewIndices) + { FTransform Transform; InstancedStaticMeshComponent->GetInstanceTransform(Index, Transform, true); FTransform GlobalTransform = LargeMap->LocalToGlobalTransform(Transform); Transforms.Emplace(GlobalTransform); - bool Found = false; - //Add Index to Array - for (int32 i = 0; i < Element.IndicesInUse.Num(); ++i) - { - if (Element.IndicesInUse[i] == -1) - { - Element.IndicesInUse[i] = Index; - Found = true; - break; - } - } - if (!Found) - Element.IndicesInUse.Emplace(Index); - //---------------------------------------------------- } if (Transforms.Num() > 0) { @@ -453,23 +474,16 @@ TArray>> AVegetationManager::GetElem void AVegetationManager::SpawnSkeletalFoliages(TArray>>& ElementsToSpawn) { TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::SpawnSkeletalFoliages); - ALargeMapManager* LargeMap = - UCarlaStatics::GetLargeMapManager(GetWorld()); - check(LargeMap); for (TPair>& Element : ElementsToSpawn) { FFoliageBlueprint BP = Element.Key; - if (!BP.IsValid()) - continue; - TArray* Pool = ActorPool.Find(BP.BPClassName); - if (!Pool) - continue; + TArray* Pool = ActorPool.Find(BP.BPFullClassName); for (const FTransform& Transform : Element.Value) { bool Ok = EnableActorFromPool(Transform, *Pool); if (Ok) { - UE_LOG(LogCarla, Display, TEXT("Pooled actor from pool: %s"), *BP.BPClassName); + UE_LOG(LogCarla, Display, TEXT("Pooled actor: %s"), *BP.BPFullClassName); } else { @@ -481,7 +495,7 @@ void AVegetationManager::SpawnSkeletalFoliages(TArrayEmplace(NewElement); - UE_LOG(LogCarla, Display, TEXT("Created actor for pool: %s"), *BP.BPClassName); + UE_LOG(LogCarla, Display, TEXT("Created actor: %s"), *BP.BPFullClassName); } } } @@ -491,9 +505,6 @@ void AVegetationManager::SpawnSkeletalFoliages(TArray>& Element : ActorPool) { TArray& Pool = Element.Value; @@ -502,10 +513,10 @@ void AVegetationManager::DestroySkeletalFoliages() if (!Actor.InUse) continue; const FVector Location = Actor.GlobalTransform.GetLocation(); - if (!VehiclesInLevel[0]->IsInVehicleRange(Location)) + if (!VehiclesInLevel.Last()->IsInVehicleRange(Location)) { Actor.DisableActor(); - UE_LOG(LogCarla, Display, TEXT("Disabled Actor from pool")); + UE_LOG(LogCarla, Display, TEXT("Disabled Actor")); } } } @@ -513,15 +524,14 @@ void AVegetationManager::DestroySkeletalFoliages() bool AVegetationManager::EnableActorFromPool(const FTransform& Transform, TArray& Pool) { - ALargeMapManager* LargeMap = - UCarlaStatics::GetLargeMapManager(GetWorld()); - check(LargeMap); + TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::EnableActorFromPool); for (FPooledActor& PooledActor : Pool) { if (PooledActor.InUse) continue; PooledActor.GlobalTransform = Transform; - FTransform LocalTransform = LargeMap->GlobalToLocalTransform(Transform); + FTransform LocalTransform = Transform; + LocalTransform = LargeMap->GlobalToLocalTransform(Transform); PooledActor.EnableActor(); PooledActor.Actor->SetActorLocationAndRotation(LocalTransform.GetLocation(), LocalTransform.Rotator(), true, nullptr, ETeleportType::ResetPhysics); if (SpawnScale <= 1.01f && SpawnScale >= 0.99f) @@ -547,34 +557,48 @@ void AVegetationManager::CreatePoolForBPClass(const FFoliageBlueprint& BP) NewElement.Actor = CreateFoliage(BP, Transform); if (IsValid(NewElement.Actor)) { - UE_LOG(LogCarla, Display, TEXT("Created actor for pool: %s"), *BP.BPClassName); + UE_LOG(LogCarla, Display, TEXT("Created actor for pool")); NewElement.DisableActor(); AuxPool.Emplace(NewElement); } else { - UE_LOG(LogCarla, Error, TEXT("Failed to create actor for pool: %s"), *BP.BPClassName); + UE_LOG(LogCarla, Error, TEXT("Failed to create actor for pool")); } } - ActorPool.Emplace(BP.BPClassName, AuxPool); + ActorPool.Emplace(BP.BPFullClassName, AuxPool); + UE_LOG(LogCarla, Display, TEXT("CreatePoolForBPClass: %s"), *BP.BPFullClassName); } AActor* AVegetationManager::CreateFoliage(const FFoliageBlueprint& BP, const FTransform& Transform) const { TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::CreateFoliage); + AActor* Actor = GetWorld()->SpawnActor(BP.SpawnedClass, Transform.GetLocation(), Transform.Rotator()); if (SpawnScale <= 1.01f && SpawnScale >= 0.99f) Actor->SetActorScale3D(Transform.GetScale3D()); else Actor->SetActorScale3D({SpawnScale, SpawnScale, SpawnScale}); - Actor->SetTickableWhenPaused(false); return Actor; } /********************************************************************************/ -/********** OTHER ***************************************************************/ +/********** TILES ***************************************************************/ /********************************************************************************/ +void AVegetationManager::OnLevelAddedToWorld(ULevel* InLevel, UWorld* InWorld) +{ + TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::OnLevelAddedToWorld); + UpdateFoliageBlueprintCache(InLevel); + CreateOrUpdateTileCache(InLevel); +} + +void AVegetationManager::OnLevelRemovedFromWorld(ULevel* InLevel, UWorld* InWorld) +{ + TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::OnLevelRemovedFromWorld); + +} + bool AVegetationManager::CheckIfAnyVehicleInLevel() const { TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::CheckIfAnyVehicleInLevel); @@ -585,16 +609,16 @@ bool AVegetationManager::IsFoliageTypeEnabled(const FString& Path) const { TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::IsFoliageTypeEnabled); if (!SpawnRocks) - if (Path.Contains("Rock")) + if (Path.Contains("/Rock/")) return false; if (!SpawnTrees) - if (Path.Contains("Tree")) + if (Path.Contains("/Tree/")) return false; if (!SpawnBushes) - if (Path.Contains("Bush")) + if (Path.Contains("/Bush/")) return false; if (!SpawnPlants) - if (Path.Contains("Plant")) + if (Path.Contains("/Plant/")) return false; return true; } @@ -611,7 +635,7 @@ bool AVegetationManager::CheckForNewTiles() const if (!IsValid(InstancedFoliageActor)) continue; const FString TileName = InstancedFoliageActor->GetLevel()->GetOuter()->GetName(); - if (!TileDataCache.Contains(TileName)) + if (!TileCache.Contains(TileName)) return true; } return false; @@ -622,26 +646,25 @@ TArray AVegetationManager::GetTilesInUse() TRACE_CPUPROFILER_EVENT_SCOPE(AVegetationManager::GetTilesInUse); TArray Results; - for (const TPair& Element : TileDataCache) + for (const TPair& Element : TileCache) { const FTileData& TileData = Element.Value; if (!IsValid(TileData.InstancedFoliageActor) || !IsValid(TileData.ProceduralFoliageVolume)) { - TileDataCache.Remove(Element.Key); + TileCache.Remove(Element.Key); return Results; } if (Results.Contains(Element.Key)) continue; const AProceduralFoliageVolume* Procedural = TileData.ProceduralFoliageVolume; if (!IsValid(Procedural)) - continue; - if (!IsValid(Procedural->ProceduralComponent)) continue; - if (Element.Key.IsEmpty()) + if (!IsValid(Procedural->ProceduralComponent)) continue; const FBox Box = Procedural->ProceduralComponent->GetBounds(); if (!Box.IsValid) - continue; + continue; + for (ACarlaWheeledVehicle* Vehicle : VehiclesInLevel) { if (!IsValid(Vehicle)) diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/VegetationManager.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/VegetationManager.h index 84855f519..d08d37c44 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/VegetationManager.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vegetation/VegetationManager.h @@ -14,6 +14,7 @@ #include "Containers/Array.h" #include "Containers/Map.h" +#include "Carla/MapGen/LargeMapManager.h" #include "Carla/Vehicle/CarlaWheeledVehicle.h" #include "VegetationManager.generated.h" @@ -35,14 +36,15 @@ struct FTileData TArray TileMeshesCache {}; TArray MaterialInstanceDynamicCache {}; - void UpdateMaterialCache(const FLinearColor& Value); + bool ContainsMesh(const UInstancedStaticMeshComponent*) const; + void UpdateTileMeshComponent(UInstancedStaticMeshComponent* NewInstancedStaticMeshComponent); + void UpdateMaterialCache(const FLinearColor& Value, bool DebugMaterials); }; USTRUCT() struct FFoliageBlueprint { GENERATED_BODY() - FString BPClassName {}; FString BPFullClassName {}; TSubclassOf SpawnedClass { nullptr }; @@ -73,7 +75,8 @@ public: void RemoveVehicle(ACarlaWheeledVehicle* Vehicle); public: -//Cuando se carge un level engancharme al broadcast del delate del collision + UPROPERTY(Category = "CARLA Vegetation Spwaner", EditDefaultsOnly) + bool DebugMaterials {false}; //Filters for debug UPROPERTY(Category = "CARLA Vegetation Spwaner", EditDefaultsOnly) bool SpawnBushes {true}; @@ -106,6 +109,7 @@ private: bool IsFoliageTypeEnabled(const FString& Path) const; bool CheckIfAnyVehicleInLevel() const; bool CheckForNewTiles() const; + TArray GetTilesInUse(); void UpdateVehiclesDetectionBoxes(); @@ -115,18 +119,29 @@ private: void DestroySkeletalFoliages(); bool EnableActorFromPool(const FTransform& Transform, TArray& Pool); - void UpdateTileDataCache(); - void UpdateFoliageBlueprintCache(); - void GenerateTileDataInternals(); - void InitializeInstancedStaticMeshComponentCache(FTileData& TileData); - void InitializeMaterialCache(FTileData& TileData); + void CreateOrUpdateTileCache(ULevel* InLevel); + void UpdateFoliageBlueprintCache(ULevel* InLevel); + void SetTileDataInternals(FTileData& TileData); + void SetInstancedStaticMeshComponentCache(FTileData& TileData); + void SetMaterialCache(FTileData& TileData); + + void FreeTileCache(ULevel* InLevel); + + void OnLevelAddedToWorld(ULevel* InLevel, UWorld* InWorld); + void OnLevelRemovedFromWorld(ULevel* InLevel, UWorld* InWorld); void CreatePoolForBPClass(const FFoliageBlueprint& BP); AActor* CreateFoliage(const FFoliageBlueprint& BP, const FTransform& Transform) const; + void GetSketalTemplates(); + private: + //Actors + ALargeMapManager* LargeMap {nullptr}; TArray VehiclesInLevel {}; + //Caches TMap FoliageBlueprintCache {}; + TMap TileCache {}; + //Pools TMap> ActorPool {}; - TMap TileDataCache {}; }; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp index fa5b9b16c..a7bab3368 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.cpp @@ -205,11 +205,18 @@ void ACarlaWheeledVehicle::BeginPlay() bool ACarlaWheeledVehicle::IsInVehicleRange(const FVector& Location) const { TRACE_CPUPROFILER_EVENT_SCOPE(ACarlaWheeledVehicle::IsInVehicleRange); - ALargeMapManager* LargeMap = - UCarlaStatics::GetLargeMapManager(GetWorld()); - check(LargeMap); - FTransform GlobalTransform = LargeMap->LocalToGlobalTransform(GetActorTransform()); - float Distance = Distance = FVector::Distance(Location, GlobalTransform.GetLocation()); + + float Distance = 0.0f; + ALargeMapManager* LargeMap = UCarlaStatics::GetLargeMapManager(GetWorld()); + if (LargeMap) + { + FTransform GlobalTransform = LargeMap->LocalToGlobalTransform(GetActorTransform()); + Distance = FVector::Distance(Location, GlobalTransform.GetLocation()); + } + else + { + Distance = FVector::Distance(Location, GetActorTransform().GetLocation()); + } return Distance < DetectionSize * 10.0f; } @@ -236,6 +243,12 @@ void ACarlaWheeledVehicle::DrawFoliageBoundingBox() const FBoxSphereBounds ACarlaWheeledVehicle::GetBoxSphereBounds() const { + ALargeMapManager* LargeMap = UCarlaStatics::GetLargeMapManager(GetWorld()); + if (LargeMap) + { + FTransform GlobalTransform = LargeMap->LocalToGlobalTransform(GetActorTransform()); + return VehicleBounds->CalcBounds(GlobalTransform); + } return VehicleBounds->CalcBounds(GetActorTransform()); } @@ -383,8 +396,6 @@ void ACarlaWheeledVehicle::SetWheelsFrictionScale(TArray &WheelsFrictionS } } - - FVehiclePhysicsControl ACarlaWheeledVehicle::GetVehiclePhysicsControl() const { FVehiclePhysicsControl PhysicsControl; diff --git a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h index 77eeaacec..7cd7d0a6c 100644 --- a/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h +++ b/Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Vehicle/CarlaWheeledVehicle.h @@ -354,7 +354,7 @@ private: public: UPROPERTY(Category = "CARLA Wheeled Vehicle", EditDefaultsOnly) - float DetectionSize {200.0f}; + float DetectionSize { 200.0f }; UPROPERTY(Category = "CARLA Wheeled Vehicle", VisibleAnywhere, BlueprintReadOnly) FBox FoliageBoundingBox;