#22 Add road segment class

This commit is contained in:
nsubiron 2017-04-27 19:19:41 +01:00
parent aac57cd14d
commit 4a7b934d96
4 changed files with 315 additions and 0 deletions

View File

@ -0,0 +1,53 @@
// CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
#include "Carla.h"
#include "StaticMeshCollection.h"
#include "Components/InstancedStaticMeshComponent.h"
#include "Engine/StaticMesh.h"
AStaticMeshCollection::AStaticMeshCollection(
const FObjectInitializer& ObjectInitializer) :
Super(ObjectInitializer)
{
PrimaryActorTick.bCanEverTick = false;
RootComponent =
ObjectInitializer.CreateDefaultSubobject<USceneComponent>(this, TEXT("SceneComponent"));
RootComponent->SetMobility(EComponentMobility::Static);
}
void AStaticMeshCollection::PushBackInstantiator(UStaticMesh *Mesh)
{
auto Instantiator = NewObject<UInstancedStaticMeshComponent>(this);
check(Instantiator != nullptr);
Instantiator->SetMobility(EComponentMobility::Static);
Instantiator->SetupAttachment(RootComponent);
Instantiator->SetStaticMesh(Mesh);
Instantiator->RegisterComponent();
MeshInstatiators.Add(Instantiator);
}
void AStaticMeshCollection::SetStaticMesh(uint32 i, UStaticMesh *Mesh)
{
check(GetNumberOfInstantiators() > i);
MeshInstatiators[i]->SetStaticMesh(Mesh);
}
void AStaticMeshCollection::AddInstance(uint32 i, const FTransform &Transform)
{
check(GetNumberOfInstantiators() > i);
MeshInstatiators[i]->AddInstance(Transform);
}
void AStaticMeshCollection::ClearInstances()
{
for (auto *Instantiator : MeshInstatiators) {
Instantiator->ClearInstances();
}
}
void AStaticMeshCollection::ClearInstantiators()
{
ClearInstances();
MeshInstatiators.Empty();
}

View File

@ -0,0 +1,42 @@
// CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
#pragma once
#include "GameFramework/Actor.h"
#include "StaticMeshCollection.generated.h"
class UInstancedStaticMeshComponent;
/// Holds static mesh instatiators.
UCLASS(Abstract)
class CARLA_API AStaticMeshCollection : public AActor
{
GENERATED_BODY()
public:
AStaticMeshCollection(const FObjectInitializer& ObjectInitializer);
protected:
uint32 GetNumberOfInstantiators() const
{
return MeshInstatiators.Num();
}
void PushBackInstantiator(UStaticMesh *Mesh);
void SetStaticMesh(uint32 i, UStaticMesh *Mesh);
void AddInstance(uint32 i, const FTransform &Transform);
void ClearInstances();
/// Clear the instances too.
void ClearInstantiators();
private:
UPROPERTY(Category = "Instanced Static Mesh Collection", VisibleAnywhere)
TArray<UInstancedStaticMeshComponent *> MeshInstatiators;
};

View File

@ -0,0 +1,84 @@
// CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
#include "Carla.h"
#include "RoadSegment.h"
#include "Engine/StaticMesh.h"
enum RoadSegmentItems {
ELaneLeft,
ELaneRight,
ESidewalkLeft,
ESidewalkRight,
ELaneMarkingSolid,
ELaneMarkingBroken,
NUMBER_OF_ITEMS
};
ARoadSegment::ARoadSegment(const FObjectInitializer& ObjectInitializer) :
Super(ObjectInitializer)
{
PrimaryActorTick.bCanEverTick = false;
}
void ARoadSegment::OnConstruction(const FTransform &Transform)
{
Super::OnConstruction(Transform);
UpdateMeshes();
}
#if WITH_EDITOR
void ARoadSegment::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
if (PropertyChangedEvent.Property) {
GenerateRoad();
}
}
#endif // WITH_EDITOR
void ARoadSegment::GenerateRoad()
{
UpdateMeshes();
UpdateRoad();
}
void ARoadSegment::UpdateMeshes()
{
if (GetNumberOfInstantiators() != NUMBER_OF_ITEMS) {
ClearInstantiators();
for (auto i = 0u; i < NUMBER_OF_ITEMS; ++i) {
PushBackInstantiator(nullptr);
}
}
SetStaticMesh(ELaneLeft, LaneLeft);
SetStaticMesh(ELaneRight, LaneRight);
SetStaticMesh(ESidewalkLeft, SidewalkLeft);
SetStaticMesh(ESidewalkRight, SidewalkRight);
SetStaticMesh(ELaneMarkingSolid, LaneMarkingSolid);
SetStaticMesh(ELaneMarkingBroken, LaneMarkingBroken);
}
void ARoadSegment::UpdateRoad()
{
ClearInstances();
Scale = (LaneLeft != nullptr ? LaneLeft->GetBoundingBox().GetSize().X : 1.0f);
FVector Translation(0.0f, 0.0f, 0.0f);
for (auto &Item : RoadDescription) {
FTransform Transform{Translation};
AddInstance(ELaneLeft, Transform);
AddInstance(ELaneRight, Transform);
if (Item.bHasRightSidewalk) {
AddInstance(ESidewalkRight, Transform);
}
if (Item.bHasLeftSidewalk) {
AddInstance(ESidewalkLeft, Transform);
}
if (Item.LaneMarking == ELaneMarkingType::Solid) {
AddInstance(ELaneMarkingSolid, Transform);
} else if (Item.LaneMarking == ELaneMarkingType::Broken) {
AddInstance(ELaneMarkingBroken, Transform);
}
Translation.X += Scale;
}
}

136
Source/Carla/RoadSegment.h Normal file
View File

@ -0,0 +1,136 @@
// CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
#pragma once
#include "MapGen/StaticMeshCollection.h"
#include "RoadSegment.generated.h"
UENUM(BlueprintType)
enum class ELaneMarkingType : uint8
{
None UMETA(DisplayName = "None"),
Solid UMETA(DisplayName = "Solid Lane Marking"),
Broken UMETA(DisplayName = "Broken Lane Marking")
};
/// Description of a road segment piece.
USTRUCT()
struct FRoadSegmentPiece
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool bHasLeftSidewalk = true;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool bHasRightSidewalk = true;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
ELaneMarkingType LaneMarking = ELaneMarkingType::Solid;
};
/// A straight segment of road.
///
/// Please call GenerateRoad after modifying it.
UCLASS()
class CARLA_API ARoadSegment : public AStaticMeshCollection
{
GENERATED_BODY()
public:
ARoadSegment(const FObjectInitializer& ObjectInitializer);
virtual void OnConstruction(const FTransform &Transform) override;
#if WITH_EDITOR
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif // WITH_EDITOR
UFUNCTION(BlueprintCallable, Category="Road Description")
void GenerateRoad();
UFUNCTION(BlueprintCallable, Category="Road Description")
int32 GetNumberOfPieces() const
{
return RoadDescription.Num();
}
UFUNCTION(BlueprintCallable, Category="Road Description")
void AppendPiece(const FRoadSegmentPiece &RoadSegmentPiece)
{
RoadDescription.Add(RoadSegmentPiece);
}
UFUNCTION(BlueprintCallable, Category="Road Description")
void RemoveAllPieces()
{
RoadDescription.Empty();
}
UFUNCTION(BlueprintCallable, Category="Set Static Mesh")
void SetStaticMesh_LaneLeft(UStaticMesh *StaticMesh)
{
LaneLeft = StaticMesh;
}
UFUNCTION(BlueprintCallable, Category="Set Static Mesh")
void SetStaticMesh_LaneRight(UStaticMesh *StaticMesh)
{
LaneRight = StaticMesh;
}
UFUNCTION(BlueprintCallable, Category="Set Static Mesh")
void SetStaticMesh_SidewalkLeft(UStaticMesh *StaticMesh)
{
SidewalkLeft = StaticMesh;
}
UFUNCTION(BlueprintCallable, Category="Set Static Mesh")
void SetStaticMesh_SidewalkRight(UStaticMesh *StaticMesh)
{
SidewalkRight = StaticMesh;
}
UFUNCTION(BlueprintCallable, Category="Set Static Mesh")
void SetStaticMesh_LaneMarkingSolid(UStaticMesh *StaticMesh)
{
LaneMarkingSolid = StaticMesh;
}
UFUNCTION(BlueprintCallable, Category="Set Static Mesh")
void SetStaticMesh_LaneMarkingBroken(UStaticMesh *StaticMesh)
{
LaneMarkingBroken = StaticMesh;
}
private:
void UpdateMeshes();
void UpdateRoad();
UPROPERTY(Category = "Road Description", EditAnywhere)
TArray<FRoadSegmentPiece> RoadDescription;
UPROPERTY(Category = "Road Description", AdvancedDisplay, EditAnywhere)
float Scale = 1.0f;
UPROPERTY(Category = "Meshes", EditAnywhere)
UStaticMesh *LaneLeft;
UPROPERTY(Category = "Meshes", EditAnywhere)
UStaticMesh *LaneRight;
UPROPERTY(Category = "Meshes", EditAnywhere)
UStaticMesh *SidewalkLeft;
UPROPERTY(Category = "Meshes", EditAnywhere)
UStaticMesh *SidewalkRight;
UPROPERTY(Category = "Meshes", EditAnywhere)
UStaticMesh *LaneMarkingSolid;
UPROPERTY(Category = "Meshes", EditAnywhere)
UStaticMesh *LaneMarkingBroken;
};