diff --git a/Plugins/BrickGrid/Source/BrickGrid/Classes/BrickGridComponent.h b/Plugins/BrickGrid/Source/BrickGrid/Classes/BrickGridComponent.h index 4e276e0..e3f29de 100644 --- a/Plugins/BrickGrid/Source/BrickGrid/Classes/BrickGridComponent.h +++ b/Plugins/BrickGrid/Source/BrickGrid/Classes/BrickGridComponent.h @@ -6,7 +6,7 @@ namespace BrickGridConstants { enum { MaxBricksPerRegionAxisLog2 = 7 }; - enum { MaxBricksPerRegionAxis = 1 << MaxBricksPerRegionAxisLog2 }; + enum { MaxBricksPerRegionAxis = 1 << MaxBricksPerRegionAxisLog2 }; }; /** Shifts a number right with sign extension. */ @@ -26,19 +26,27 @@ inline int32 SignedShiftRight(int32 A,int32 B) #endif } +UENUM(BlueprintType) +enum class EBrickFace : uint8 +{ + BF_PlusZ UMETA(DisplayName = "PlusZ"), + BF_MinusZ UMETA(DisplayName = "MinusZ"), + BF_PlusX UMETA(DisplayName = "PlusX"), + BF_MinusX UMETA(DisplayName = "MinusX"), + BF_PlusY UMETA(DisplayName = "PlusY"), + BF_MinusY UMETA(DisplayName = "MinusY") +}; + /** Information about a brick material. */ USTRUCT(BlueprintType) struct FBrickMaterial { - GENERATED_USTRUCT_BODY() + GENERATED_USTRUCT_BODY() - UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = Bricks) - class UMaterialInterface* SurfaceMaterial; - - UPROPERTY(EditAnywhere,BlueprintReadWrite,Category = Bricks) - class UMaterialInterface* OverrideTopSurfaceMaterial; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Bricks) + TArray FaceMaterials; - FBrickMaterial() : SurfaceMaterial(NULL), OverrideTopSurfaceMaterial(NULL) {} + FBrickMaterial() {} }; /** Information about a brick. */ @@ -157,7 +165,7 @@ struct FBrickRegion // Contains the material index for each brick, stored in an 8-bit integer. UPROPERTY() - TArray BrickContents; + TArray BrickContents; // Contains the occupied brick with highest Z in this region for each XY coordinate in the region. -1 means no non-empty bricks in this region at that XY. TArray MaxNonEmptyBrickRegionZs; @@ -170,11 +178,11 @@ struct FBrickGridParameters GENERATED_USTRUCT_BODY() // The materials to render for each brick material. - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Materials) + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = Materials) TArray Materials; // The material index that means "empty". - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = Materials) + UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = Materials) int32 EmptyMaterialIndex; // The number of bricks along each axis of a region is 2^BricksPerChunkLog2 @@ -242,8 +250,8 @@ class UBrickGridComponent : public USceneComponent UFUNCTION(BlueprintCallable,Category = "Brick Grid") BRICKGRID_API FBrick GetBrick(const FInt3& BrickCoordinates) const; - BRICKGRID_API void GetBrickMaterialArray(const FInt3& MinBrickCoordinates,const FInt3& MaxBrickCoordinates,TArray& OutBrickMaterials) const; - BRICKGRID_API void SetBrickMaterialArray(const FInt3& MinBrickCoordinates,const FInt3& MaxBrickCoordinates,const TArray& BrickMaterials); + BRICKGRID_API void GetBrickMaterialArray(const FInt3& MinBrickCoordinates,const FInt3& MaxBrickCoordinates,TArray& OutBrickMaterials) const; + BRICKGRID_API void SetBrickMaterialArray(const FInt3& MinBrickCoordinates,const FInt3& MaxBrickCoordinates,const TArray& BrickMaterials); // Returns a height-map containing the non-empty brick with greatest Z for each XY in the rectangle bounded by MinBrickCoordinates.XY-MaxBrickCoordinates.XY. // The returned heights are relative to MinBrickCoordinates.Z, but MaxBrickCoordinates.Z is ignored. diff --git a/Plugins/BrickGrid/Source/BrickGrid/Private/BrickAmbientOcclusion.inl b/Plugins/BrickGrid/Source/BrickGrid/Private/BrickAmbientOcclusion.inl index c5562ec..569b67b 100644 --- a/Plugins/BrickGrid/Source/BrickGrid/Private/BrickAmbientOcclusion.inl +++ b/Plugins/BrickGrid/Source/BrickGrid/Private/BrickAmbientOcclusion.inl @@ -6,7 +6,7 @@ static void ComputeChunkAO( const FInt3 LocalBrickExpansion, const FInt3 LocalBricksDim, const FInt3 LocalVertexDim, - const TArray& LocalBrickMaterials, + const TArray& LocalBrickMaterials, TArray& OutLocalVertexAmbientFactors ) { diff --git a/Plugins/BrickGrid/Source/BrickGrid/Private/BrickCollisionComponent.cpp b/Plugins/BrickGrid/Source/BrickGrid/Private/BrickCollisionComponent.cpp index 03f0d9a..aee9d07 100644 --- a/Plugins/BrickGrid/Source/BrickGrid/Private/BrickCollisionComponent.cpp +++ b/Plugins/BrickGrid/Source/BrickGrid/Private/BrickCollisionComponent.cpp @@ -15,7 +15,7 @@ static const FInt3 FaceNormals[6] = FInt3(0, 0, +1) }; -UBrickCollisionComponent::UBrickCollisionComponent( const FPostConstructInitializeProperties& PCIP ) +UBrickCollisionComponent::UBrickCollisionComponent(const FObjectInitializer& PCIP) : Super( PCIP ) { PrimaryComponentTick.bCanEverTick = false; @@ -65,7 +65,7 @@ void UBrickCollisionComponent::UpdateCollisionBody() // Read the brick materials for all the bricks that affect this chunk. const FInt3 LocalBricksDim = Grid->BricksPerCollisionChunk + LocalBrickExpansion * FInt3::Scalar(2); - TArray LocalBrickMaterials; + TArray LocalBrickMaterials; LocalBrickMaterials.Init(LocalBricksDim.X * LocalBricksDim.Y * LocalBricksDim.Z); Grid->GetBrickMaterialArray(MinLocalBrickCoordinates,MinLocalBrickCoordinates + LocalBricksDim - FInt3::Scalar(1),LocalBrickMaterials); diff --git a/Plugins/BrickGrid/Source/BrickGrid/Private/BrickGridComponent.cpp b/Plugins/BrickGrid/Source/BrickGrid/Private/BrickGridComponent.cpp index ab73f53..2855c95 100644 --- a/Plugins/BrickGrid/Source/BrickGrid/Private/BrickGridComponent.cpp +++ b/Plugins/BrickGrid/Source/BrickGrid/Private/BrickGridComponent.cpp @@ -95,7 +95,7 @@ FBrick UBrickGridComponent::GetBrick(const FInt3& BrickCoordinates) const return FBrick(Parameters.EmptyMaterialIndex); } -void UBrickGridComponent::GetBrickMaterialArray(const FInt3& MinBrickCoordinates,const FInt3& MaxBrickCoordinates,TArray& OutBrickMaterials) const +void UBrickGridComponent::GetBrickMaterialArray(const FInt3& MinBrickCoordinates,const FInt3& MaxBrickCoordinates,TArray& OutBrickMaterials) const { const FInt3 OutputSize = MaxBrickCoordinates - MinBrickCoordinates + FInt3::Scalar(1); const FInt3 MinRegionCoordinates = BrickToRegionCoordinates(MinBrickCoordinates); @@ -123,11 +123,11 @@ void UBrickGridComponent::GetBrickMaterialArray(const FInt3& MinBrickCoordinates const uint32 RegionBaseBrickIndex = (((RegionBrickY << Parameters.BricksPerRegionLog2.X) + RegionBrickX) << Parameters.BricksPerRegionLog2.Z) + MinOutputRegionBrickCoordinates.Z; if(RegionIndex) { - FMemory::Memcpy(&OutBrickMaterials[OutputBaseBrickIndex],&Regions[*RegionIndex].BrickContents[RegionBaseBrickIndex],OutputSizeZ * sizeof(uint8)); + FMemory::Memcpy(&OutBrickMaterials[OutputBaseBrickIndex], &Regions[*RegionIndex].BrickContents[RegionBaseBrickIndex], OutputSizeZ * sizeof(OutBrickMaterials[0])); } else { - FMemory::Memset(&OutBrickMaterials[OutputBaseBrickIndex],Parameters.EmptyMaterialIndex,OutputSizeZ * sizeof(uint8)); + FMemory::Memset(&OutBrickMaterials[OutputBaseBrickIndex], Parameters.EmptyMaterialIndex, OutputSizeZ * sizeof(OutBrickMaterials[0])); } } } @@ -136,7 +136,7 @@ void UBrickGridComponent::GetBrickMaterialArray(const FInt3& MinBrickCoordinates } } -void UBrickGridComponent::SetBrickMaterialArray(const FInt3& MinBrickCoordinates,const FInt3& MaxBrickCoordinates,const TArray& BrickMaterials) +void UBrickGridComponent::SetBrickMaterialArray(const FInt3& MinBrickCoordinates, const FInt3& MaxBrickCoordinates, const TArray& BrickMaterials) { const FInt3 InputSize = MaxBrickCoordinates - MinBrickCoordinates + FInt3::Scalar(1); const FInt3 MinRegionCoordinates = BrickToRegionCoordinates(MinBrickCoordinates); @@ -164,7 +164,7 @@ void UBrickGridComponent::SetBrickMaterialArray(const FInt3& MinBrickCoordinates const uint32 RegionBaseBrickIndex = (((RegionBrickY << Parameters.BricksPerRegionLog2.X) + RegionBrickX) << Parameters.BricksPerRegionLog2.Z) + MinInputRegionBrickCoordinates.Z; if(RegionIndex) { - FMemory::Memcpy(&Regions[*RegionIndex].BrickContents[RegionBaseBrickIndex],&BrickMaterials[InputBaseBrickIndex],InputSizeZ * sizeof(uint8)); + FMemory::Memcpy(&Regions[*RegionIndex].BrickContents[RegionBaseBrickIndex], &BrickMaterials[InputBaseBrickIndex], InputSizeZ * sizeof(BrickMaterials[0])); } } } @@ -519,7 +519,7 @@ FBrickGridParameters::FBrickGridParameters() Materials.Add(FBrickMaterial()); } -UBrickGridComponent::UBrickGridComponent(const FPostConstructInitializeProperties& PCIP) +UBrickGridComponent::UBrickGridComponent(const FObjectInitializer& PCIP) : Super( PCIP ) { PrimaryComponentTick.bStartWithTickEnabled =true; diff --git a/Plugins/BrickGrid/Source/BrickGrid/Private/BrickRenderComponent.cpp b/Plugins/BrickGrid/Source/BrickGrid/Private/BrickRenderComponent.cpp index 3905fed..3e66d00 100644 --- a/Plugins/BrickGrid/Source/BrickGrid/Private/BrickRenderComponent.cpp +++ b/Plugins/BrickGrid/Source/BrickGrid/Private/BrickRenderComponent.cpp @@ -59,7 +59,7 @@ class FBrickChunkVertexBuffer : public FVertexBuffer VertexBufferRHI = RHICreateVertexBuffer(Vertices.Num() * sizeof(FBrickVertex), BUF_Dynamic, CreateInfo); // Copy the vertex data into the vertex buffer. void* VertexBufferData = RHILockVertexBuffer(VertexBufferRHI, 0, Vertices.Num() * sizeof(FBrickVertex), RLM_WriteOnly); - FMemory::Memcpy(VertexBufferData, Vertices.GetTypedData(), Vertices.Num() * sizeof(FBrickVertex)); + FMemory::Memcpy(VertexBufferData, Vertices.GetData(), Vertices.Num() * sizeof(FBrickVertex)); RHIUnlockVertexBuffer(VertexBufferRHI); } } @@ -78,7 +78,7 @@ class FBrickChunkIndexBuffer : public FIndexBuffer IndexBufferRHI = RHICreateIndexBuffer(sizeof(uint16), Indices.Num() * sizeof(uint16), BUF_Static, CreateInfo); // Write the indices to the index buffer. void* Buffer = RHILockIndexBuffer(IndexBufferRHI, 0, Indices.Num() * sizeof(uint16), RLM_WriteOnly); - FMemory::Memcpy(Buffer, Indices.GetTypedData(), Indices.Num() * sizeof(uint16)); + FMemory::Memcpy(Buffer, Indices.GetData(), Indices.Num() * sizeof(uint16)); RHIUnlockIndexBuffer(IndexBufferRHI); } } @@ -190,7 +190,7 @@ class FBrickChunkSceneProxy : public FPrimitiveSceneProxy PrimitiveUniformBuffer = CreatePrimitiveUniformBufferImmediate(FScaleMatrix(FVector(255, 255, 255)) * GetLocalToWorld(), GetBounds(), GetLocalBounds(), true, UseEditorDepthTest()); } - virtual void DrawDynamicElements(FPrimitiveDrawInterface* PDI,const FSceneView* View) override + virtual void DrawDynamicElements(FPrimitiveDrawInterface* PDI,const FSceneView* View) { // Set up the wireframe material Face. FColoredMaterialRenderProxy WireframeMaterialFace( @@ -318,7 +318,7 @@ class FBrickChunkSceneProxy : public FPrimitiveSceneProxy } }; -UBrickRenderComponent::UBrickRenderComponent( const FPostConstructInitializeProperties& PCIP ) +UBrickRenderComponent::UBrickRenderComponent(const FObjectInitializer& PCIP) : Super( PCIP ) { PrimaryComponentTick.bCanEverTick = false; @@ -354,7 +354,7 @@ FPrimitiveSceneProxy* UBrickRenderComponent::CreateSceneProxy() // Read the brick materials for all the bricks that affect this chunk. const FInt3 LocalBricksDim = Grid->BricksPerRenderChunk + LocalBrickExpansion * FInt3::Scalar(2); - TArray LocalBrickMaterials; + TArray LocalBrickMaterials; LocalBrickMaterials.Init(LocalBricksDim.X * LocalBricksDim.Y * LocalBricksDim.Z); Grid->GetBrickMaterialArray(MinLocalBrickCoordinates,MinLocalBrickCoordinates + LocalBricksDim - FInt3::Scalar(1),LocalBrickMaterials); @@ -440,7 +440,7 @@ FPrimitiveSceneProxy* UBrickRenderComponent::CreateSceneProxy() { // Only draw faces of bricks that aren't empty. const uint32 LocalBrickIndex = (LocalBrickY * LocalBricksDim.X + LocalBrickX) * LocalBricksDim.Z + LocalBrickZ; - const uint8 BrickMaterial = LocalBrickMaterials[LocalBrickIndex]; + const uint16 BrickMaterial = LocalBrickMaterials[LocalBrickIndex]; if (BrickMaterial != EmptyMaterialIndex) { const FInt3 RelativeBrickCoordinates = FInt3(LocalBrickX,LocalBrickY,LocalBrickZ) - LocalBrickExpansion; @@ -488,32 +488,31 @@ FPrimitiveSceneProxy* UBrickRenderComponent::CreateSceneProxy() } } SceneProxy->IndexBuffer.Indices.Empty(NumIndices); - for(int32 BrickMaterialIndex = 0; BrickMaterialIndex < MaterialBatches.Num(); ++BrickMaterialIndex) - { - UMaterialInterface* SurfaceMaterial = Grid->Parameters.Materials[BrickMaterialIndex].SurfaceMaterial; - if(SurfaceMaterial == NULL) - { - SurfaceMaterial = UMaterial::GetDefaultMaterial(MD_Surface); - } - SceneProxy->MaterialRelevance |= SurfaceMaterial->GetRelevance_Concurrent(GetScene()->GetFeatureLevel()); - const int32 ProxyMaterialIndex = SceneProxy->Materials.AddUnique(SurfaceMaterial); - UMaterialInterface* OverrideTopSurfaceMaterial = Grid->Parameters.Materials[BrickMaterialIndex].OverrideTopSurfaceMaterial; - if(OverrideTopSurfaceMaterial) - { - SceneProxy->MaterialRelevance |= OverrideTopSurfaceMaterial->GetRelevance_Concurrent(GetScene()->GetFeatureLevel()); - } - const int32 TopProxyMaterialIndex = OverrideTopSurfaceMaterial ? SceneProxy->Materials.AddUnique(OverrideTopSurfaceMaterial) : ProxyMaterialIndex; + UMaterialInterface* defaultMaterial = UMaterial::GetDefaultMaterial(MD_Surface); + // Setup materials for the faces + for(int32 BrickMaterialIndex = 0; BrickMaterialIndex < MaterialBatches.Num(); ++BrickMaterialIndex) + { + TArray& faceMaterials = Grid->Parameters.Materials[BrickMaterialIndex].FaceMaterials; for(uint32 FaceIndex = 0;FaceIndex < 6;++FaceIndex) - { + { + UMaterialInterface* faceMaterial = (faceMaterials.Num() > 0) ? faceMaterials[0] : defaultMaterial; + if (faceMaterials.Num() > 0 && FaceIndex < (uint32)(faceMaterials.Num())) + { + faceMaterial = faceMaterials[FaceIndex]; + } + auto relevance = faceMaterial->GetRelevance(GetScene()->GetFeatureLevel()); + SceneProxy->MaterialRelevance |= relevance; + + const int32 ProxyMaterialIndex = SceneProxy->Materials.AddUnique(faceMaterial); const FFaceBatch& FaceBatch = MaterialBatches[BrickMaterialIndex].FaceBatches[FaceIndex]; if (FaceBatch.Indices.Num() > 0) { FBrickChunkSceneProxy::FElement& Element = *new(SceneProxy->Elements)FBrickChunkSceneProxy::FElement; Element.FirstIndex = SceneProxy->IndexBuffer.Indices.Num(); Element.NumPrimitives = FaceBatch.Indices.Num() / 3; - Element.MaterialIndex = FaceIndex == 5 ? TopProxyMaterialIndex : ProxyMaterialIndex; + Element.MaterialIndex = ProxyMaterialIndex; Element.FaceIndex = FaceIndex; // Append the batch's indices to the index buffer.