commit
96e9af4438
@ -0,0 +1,15 @@
|
||||
Binaries
|
||||
DerivedDataCache
|
||||
Intermediate
|
||||
Saved
|
||||
Build
|
||||
.vscode
|
||||
.vs
|
||||
*.VC.db
|
||||
*.opensdf
|
||||
*.opendb
|
||||
*.sdf
|
||||
*.sln
|
||||
*.suo
|
||||
*.xcodeproj
|
||||
*.xcworkspace
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 zhaizhenbo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,11 @@
|
||||
#include "Blueprint/VoxelBlueprintLibrary.h"
|
||||
|
||||
#include "VoxelSubsystem.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
void UVoxelBlueprintLibrary::AddBlockType(const UObject* WorldContextObject, const FName& Name, const FVoxelBlockType& BlockType)
|
||||
{
|
||||
UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(WorldContextObject);
|
||||
UVoxelSubsystem* LockstepSubsystem = GameInstance->GetSubsystem<UVoxelSubsystem>();
|
||||
LockstepSubsystem->BlockTypes.Add(Name, BlockType);
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "Voxel.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FVoxelModule"
|
||||
|
||||
void FVoxelModule::StartupModule()
|
||||
{
|
||||
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
|
||||
}
|
||||
|
||||
void FVoxelModule::ShutdownModule()
|
||||
{
|
||||
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
|
||||
// we call this function before unloading the module.
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FVoxelModule, Voxel)
|
@ -0,0 +1,11 @@
|
||||
#include "VoxelAgentInterface.h"
|
||||
|
||||
FIntVector IVoxelAgentInterface::GetAgentLocation_Implementation() const
|
||||
{
|
||||
return FIntVector(0);
|
||||
}
|
||||
|
||||
FVector IVoxelAgentInterface::GetAgentPartialLocation_Implementation() const
|
||||
{
|
||||
return FVector(0.0f);
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
#include "VoxelBlock.h"
|
||||
|
||||
#include "VoxelWorld.h"
|
||||
|
||||
const FVoxelBlock FVoxelBlock::InvalidBlock = FVoxelBlock(NAME_None);
|
||||
|
||||
const FVoxelBlockType FVoxelBlockType::InvalidBlockType = FVoxelBlockType(EVoxelBlockShape::Invalid);
|
@ -0,0 +1,323 @@
|
||||
#include "VoxelChunk.h"
|
||||
|
||||
#include "VoxelLog.h"
|
||||
#include "VoxelWorld.h"
|
||||
#include "VoxelSubsystem.h"
|
||||
#include "ProceduralMeshComponent.h"
|
||||
#include "KismetProceduralMeshLibrary.h"
|
||||
|
||||
AVoxelChunk::AVoxelChunk(const class FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
|
||||
|
||||
MeshComponents.SetNum(16);
|
||||
for (int32 i = 0; i < 16; ++i)
|
||||
{
|
||||
FString ComponentName = FString::Printf(TEXT("MeshComponent_%d"), i);
|
||||
MeshComponents[i] = CreateDefaultSubobject<UProceduralMeshComponent>(FName(ComponentName));
|
||||
MeshComponents[i]->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
|
||||
}
|
||||
|
||||
FlushMeshFlags = -1;
|
||||
}
|
||||
|
||||
void AVoxelChunk::BeginPlay()
|
||||
{
|
||||
UGameInstance* GameInstance = GetGameInstance();
|
||||
VoxelSubsystem = GameInstance->GetSubsystem<UVoxelSubsystem>();
|
||||
}
|
||||
|
||||
const FVoxelBlock & AVoxelChunk::GetBlockByRelativeLocation(const FIntVector & Location) const
|
||||
{
|
||||
checkCode(
|
||||
if (!FMath::IsWithin(Location.X, 0, 16)
|
||||
|| !FMath::IsWithin(Location.Y, 0, 16)
|
||||
|| !FMath::IsWithin(Location.Z, 0, 256))
|
||||
{
|
||||
UE_LOG(LogVoxel, Warning, TEXT("The Block %d, %d, %d Is Invalid In Chunk %d, %d"), Location.X, Location.Y, Location.Z, ChunkLocation.X, ChunkLocation.Y);
|
||||
return FVoxelBlock::InvalidBlock;
|
||||
}
|
||||
);
|
||||
|
||||
return Blocks[Location.X][Location.Y][Location.Z];
|
||||
}
|
||||
|
||||
void AVoxelChunk::SetBlockByRelativeLocation(const FIntVector& Location, const FVoxelBlock& NewBlock)
|
||||
{
|
||||
checkCode(
|
||||
if (!FMath::IsWithin(Location.X, 0, 16)
|
||||
|| !FMath::IsWithin(Location.Y, 0, 16)
|
||||
|| !FMath::IsWithin(Location.Z, 0, 256))
|
||||
{
|
||||
UE_LOG(LogVoxel, Warning, TEXT("The Block %d, %d, %d Is Invalid In Chunk %d, %d"), Location.X, Location.Y, Location.Z, ChunkLocation.X, ChunkLocation.Y);
|
||||
return;
|
||||
}
|
||||
);
|
||||
|
||||
Blocks[Location.X][Location.Y][Location.Z] = NewBlock;
|
||||
|
||||
FlushMeshFlags |= 1 << (Location.Z / 16);
|
||||
|
||||
if (Location.Z % 16 == 0 && Location.Z / 16 != 0)
|
||||
FlushMeshFlags |= 1 << (Location.Z / 16 - 1);
|
||||
|
||||
if (Location.Z % 16 == 15 && Location.Z / 16 != 15)
|
||||
FlushMeshFlags |= 1 << (Location.Z / 16 + 1);
|
||||
|
||||
const TMap<FIntPoint, AVoxelChunk*>& Chunks = VoxelWorld->GetChunks();
|
||||
|
||||
if (Location.X == 15)
|
||||
{
|
||||
FIntPoint NeighborLocation = FIntPoint(ChunkLocation.X + 1, ChunkLocation.Y);
|
||||
|
||||
if (Chunks.Contains(NeighborLocation))
|
||||
{
|
||||
AVoxelChunk* Neighbor = Chunks[NeighborLocation];
|
||||
Neighbor->FlushMeshFlags |= 1 << (Location.Z / 16);
|
||||
VoxelWorld->AddChunkToMeshFlushBuffer(NeighborLocation);
|
||||
}
|
||||
}
|
||||
|
||||
if (Location.X == 0)
|
||||
{
|
||||
FIntPoint NeighborLocation = FIntPoint(ChunkLocation.X - 1, ChunkLocation.Y);
|
||||
|
||||
if (Chunks.Contains(NeighborLocation))
|
||||
{
|
||||
AVoxelChunk* Neighbor = Chunks[NeighborLocation];
|
||||
Neighbor->FlushMeshFlags |= 1 << (Location.Z / 16);
|
||||
VoxelWorld->AddChunkToMeshFlushBuffer(NeighborLocation);
|
||||
}
|
||||
}
|
||||
|
||||
if (Location.Y == 15)
|
||||
{
|
||||
FIntPoint NeighborLocation = FIntPoint(ChunkLocation.X, ChunkLocation.Y + 1);
|
||||
|
||||
if (Chunks.Contains(NeighborLocation))
|
||||
{
|
||||
AVoxelChunk* Neighbor = Chunks[NeighborLocation];
|
||||
Neighbor->FlushMeshFlags |= 1 << (Location.Z / 16);
|
||||
VoxelWorld->AddChunkToMeshFlushBuffer(NeighborLocation);
|
||||
}
|
||||
}
|
||||
|
||||
if (Location.Y == 0)
|
||||
{
|
||||
FIntPoint NeighborLocation = FIntPoint(ChunkLocation.X, ChunkLocation.Y - 1);
|
||||
|
||||
if (Chunks.Contains(NeighborLocation))
|
||||
{
|
||||
AVoxelChunk* Neighbor = Chunks[NeighborLocation];
|
||||
Neighbor->FlushMeshFlags |= 1 << (Location.Z / 16);
|
||||
VoxelWorld->AddChunkToMeshFlushBuffer(NeighborLocation);
|
||||
}
|
||||
}
|
||||
|
||||
VoxelWorld->AddChunkToMeshFlushBuffer(ChunkLocation);
|
||||
}
|
||||
|
||||
void AVoxelChunk::FlushMeshs()
|
||||
{
|
||||
if (!FlushMeshFlags) return;
|
||||
|
||||
for (int32 i = 0; i < 16; ++i)
|
||||
{
|
||||
int32 FlushMeshFlag = 1 << i;
|
||||
|
||||
if (!(FlushMeshFlags & FlushMeshFlag))
|
||||
continue;
|
||||
|
||||
FlushMeshSection(i);
|
||||
}
|
||||
|
||||
FlushMeshFlags = 0;
|
||||
}
|
||||
|
||||
void AVoxelChunk::FlushMaterials()
|
||||
{
|
||||
for (int32 i = 0; i < 16; ++i)
|
||||
{
|
||||
for (int32 j = 0; j < VoxelSubsystem->Materials.Num(); ++j)
|
||||
{
|
||||
MeshComponents[i]->SetMaterial(j, VoxelSubsystem->Materials[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AVoxelChunk::Load()
|
||||
{
|
||||
QUICK_SCOPE_CYCLE_COUNTER(STAT_VoxelChunk_Load);
|
||||
|
||||
if (VoxelWorld->GetWorldSetting().ArchiveFolder.IsEmpty())
|
||||
{
|
||||
ArchiveFile.Empty();
|
||||
return;
|
||||
}
|
||||
|
||||
ArchiveFile = VoxelWorld->GetWorldSetting().ArchiveFolder / FString::Printf(TEXT("%08X%08X"), ChunkLocation.X, ChunkLocation.Y) + ChunkFileExtension;
|
||||
|
||||
if (FPaths::FileExists(ArchiveFile))
|
||||
{
|
||||
TArray<uint8> ChunkDataBuffer;
|
||||
if (FFileHelper::LoadFileToArray(ChunkDataBuffer, *ArchiveFile))
|
||||
{
|
||||
FMemoryReader MemoryReader(ChunkDataBuffer);
|
||||
|
||||
UScriptStruct* VoxelBlockStruct = FVoxelBlock::StaticStruct();
|
||||
|
||||
for (int32 X = 0; X < 16; ++X)
|
||||
{
|
||||
for (int32 Y = 0; Y < 16; ++Y)
|
||||
{
|
||||
for (int32 Z = 0; Z < 256; ++Z)
|
||||
{
|
||||
VoxelBlockStruct->SerializeItem(MemoryReader, &Blocks[X][Y][Z], nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UE_LOG(LogVoxel, Log, TEXT("Load Chunk %d, %d From File '%s'"), ChunkLocation.X, ChunkLocation.Y, *ArchiveFile);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AVoxelChunk::Unload()
|
||||
{
|
||||
QUICK_SCOPE_CYCLE_COUNTER(STAT_VoxelChunk_Unload);
|
||||
|
||||
if (ArchiveFile.IsEmpty()) return;
|
||||
|
||||
TArray<uint8> ChunkDataBuffer;
|
||||
FMemoryWriter MemoryWriter(ChunkDataBuffer);
|
||||
|
||||
UScriptStruct* VoxelBlockStruct = FVoxelBlock::StaticStruct();
|
||||
|
||||
for (int32 X = 0; X < 16; ++X)
|
||||
{
|
||||
for (int32 Y = 0; Y < 16; ++Y)
|
||||
{
|
||||
for (int32 Z = 0; Z < 256; ++Z)
|
||||
{
|
||||
VoxelBlockStruct->SerializeItem(MemoryWriter, &Blocks[X][Y][Z], nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FFileHelper::SaveArrayToFile(ChunkDataBuffer, *ArchiveFile))
|
||||
{
|
||||
UE_LOG(LogVoxel, Log, TEXT("Save Chunk %d, %d To File '%s'"), ChunkLocation.X, ChunkLocation.Y, *ArchiveFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogVoxel, Error, TEXT("Failed To Save Chunk %d, %d To File '%s'"), ChunkLocation.X, ChunkLocation.Y, *ArchiveFile);
|
||||
}
|
||||
}
|
||||
|
||||
void AVoxelChunk::FlushMeshSection(int32 SectionIndex)
|
||||
{
|
||||
static FVoxelMeshData CubeTopFaceBuffer = FVoxelMeshData::CubeTopFace;
|
||||
static FVoxelMeshData CubeBottomFaceBuffer = FVoxelMeshData::CubeBottomFace;
|
||||
static FVoxelMeshData CubeFrontFaceBuffer = FVoxelMeshData::CubeFrontFace;
|
||||
static FVoxelMeshData CubeBackFaceBuffer = FVoxelMeshData::CubeBackFace;
|
||||
static FVoxelMeshData CubeLeftFaceBuffer = FVoxelMeshData::CubeLeftFace;
|
||||
static FVoxelMeshData CubeRightFaceBuffer = FVoxelMeshData::CubeRightFace;
|
||||
|
||||
MeshSectionBuffer.Reset();
|
||||
|
||||
FIntPoint FrontChunkLocation = FIntPoint(ChunkLocation.X + 1, ChunkLocation.Y);
|
||||
FIntPoint BackChunkLocation = FIntPoint(ChunkLocation.X - 1, ChunkLocation.Y);
|
||||
FIntPoint RightChunkLocation = FIntPoint(ChunkLocation.X, ChunkLocation.Y + 1);
|
||||
FIntPoint LeftChunkLocation = FIntPoint(ChunkLocation.X, ChunkLocation.Y - 1);
|
||||
|
||||
const TMap<FIntPoint, AVoxelChunk*>& Chunks = VoxelWorld->GetChunks();
|
||||
AVoxelChunk* FrontChunk = Chunks.Contains(FrontChunkLocation) ? Chunks[FrontChunkLocation] : nullptr;
|
||||
AVoxelChunk* BackChunk = Chunks.Contains(BackChunkLocation) ? Chunks[BackChunkLocation] : nullptr;
|
||||
AVoxelChunk* RightChunk = Chunks.Contains(RightChunkLocation) ? Chunks[RightChunkLocation] : nullptr;
|
||||
AVoxelChunk* LeftChunk = Chunks.Contains(LeftChunkLocation) ? Chunks[LeftChunkLocation] : nullptr;
|
||||
|
||||
for (int32 X = 0; X < 16; ++X)
|
||||
{
|
||||
for (int32 Y = 0; Y < 16; ++Y)
|
||||
{
|
||||
for (int32 Z = 0 + SectionIndex * 16; Z < 16 + SectionIndex * 16; ++Z)
|
||||
{
|
||||
const FVoxelBlockType& CurrentVoxelBlock = VoxelSubsystem->GetBlockType(Blocks[X][Y][Z].Type);
|
||||
|
||||
if (CurrentVoxelBlock.Shape != EVoxelBlockShape::Cube) continue;
|
||||
|
||||
const FVoxelBlockType& TopVoxelBlock = VoxelSubsystem->GetBlockType(Z + 1 < 256 ? Blocks[X][Y][Z + 1].Type : TEXT("Air"));
|
||||
const FVoxelBlockType& BottomVoxelBlock = VoxelSubsystem->GetBlockType(Z - 1 >= 0 ? Blocks[X][Y][Z - 1].Type : TEXT("Air"));
|
||||
const FVoxelBlockType& FrontVoxelBlock = VoxelSubsystem->GetBlockType(X + 1 < 16 ? Blocks[X + 1][Y][Z].Type : (FrontChunk ? FrontChunk->GetBlockByRelativeLocation(FIntVector(0, Y, Z)).Type : TEXT("Air")));
|
||||
const FVoxelBlockType& BackVoxelBlock = VoxelSubsystem->GetBlockType(X - 1 >= 0 ? Blocks[X - 1][Y][Z].Type : (BackChunk ? BackChunk->GetBlockByRelativeLocation(FIntVector(15, Y, Z)).Type : TEXT("Air")));
|
||||
const FVoxelBlockType& LeftVoxelBlock = VoxelSubsystem->GetBlockType(Y - 1 >= 0 ? Blocks[X][Y - 1][Z].Type : (LeftChunk ? LeftChunk->GetBlockByRelativeLocation(FIntVector(X, 15, Z)).Type : TEXT("Air")));
|
||||
const FVoxelBlockType& RightVoxelBlock = VoxelSubsystem->GetBlockType(Y + 1 < 16 ? Blocks[X][Y + 1][Z].Type : (RightChunk ? RightChunk->GetBlockByRelativeLocation(FIntVector(X, 0, Z)).Type : TEXT("Air")));
|
||||
|
||||
if (TopVoxelBlock.Shape != EVoxelBlockShape::Cube)
|
||||
{
|
||||
for (FVector2D& UV3 : CubeTopFaceBuffer.UV3)
|
||||
UV3 = CurrentVoxelBlock.CustomTopFaceUV;
|
||||
|
||||
MeshSectionBuffer.Append(CubeTopFaceBuffer, FVector(X, Y, Z) * 100.0f);
|
||||
}
|
||||
|
||||
if (BottomVoxelBlock.Shape != EVoxelBlockShape::Cube)
|
||||
{
|
||||
for (FVector2D& UV3 : CubeBottomFaceBuffer.UV3)
|
||||
UV3 = CurrentVoxelBlock.CustomBottomFaceUV;
|
||||
|
||||
MeshSectionBuffer.Append(CubeBottomFaceBuffer, FVector(X, Y, Z) * 100.0f);
|
||||
}
|
||||
|
||||
if (FrontVoxelBlock.Shape != EVoxelBlockShape::Cube)
|
||||
{
|
||||
for (FVector2D& UV3 : CubeFrontFaceBuffer.UV3)
|
||||
UV3 = CurrentVoxelBlock.CustomFrontFaceUV;
|
||||
|
||||
MeshSectionBuffer.Append(CubeFrontFaceBuffer, FVector(X, Y, Z) * 100.0f);
|
||||
}
|
||||
|
||||
if (BackVoxelBlock.Shape != EVoxelBlockShape::Cube)
|
||||
{
|
||||
for (FVector2D& UV3 : CubeBackFaceBuffer.UV3)
|
||||
UV3 = CurrentVoxelBlock.CustomBackFaceUV;
|
||||
|
||||
MeshSectionBuffer.Append(CubeBackFaceBuffer, FVector(X, Y, Z) * 100.0f);
|
||||
}
|
||||
|
||||
if (LeftVoxelBlock.Shape != EVoxelBlockShape::Cube)
|
||||
{
|
||||
for (FVector2D& UV3 : CubeLeftFaceBuffer.UV3)
|
||||
UV3 = CurrentVoxelBlock.CustomLeftFaceUV;
|
||||
|
||||
MeshSectionBuffer.Append(CubeLeftFaceBuffer, FVector(X, Y, Z) * 100.0f);
|
||||
}
|
||||
|
||||
if (RightVoxelBlock.Shape != EVoxelBlockShape::Cube)
|
||||
{
|
||||
for (FVector2D& UV3 : CubeRightFaceBuffer.UV3)
|
||||
UV3 = CurrentVoxelBlock.CustomRightFaceUV;
|
||||
|
||||
MeshSectionBuffer.Append(CubeRightFaceBuffer, FVector(X, Y, Z) * 100.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MeshComponents[SectionIndex]->CreateMeshSection_LinearColor
|
||||
(
|
||||
0,
|
||||
MeshSectionBuffer.Vertices,
|
||||
MeshSectionBuffer.Triangles,
|
||||
MeshSectionBuffer.Normals,
|
||||
MeshSectionBuffer.UV0,
|
||||
MeshSectionBuffer.UV1,
|
||||
MeshSectionBuffer.UV2,
|
||||
MeshSectionBuffer.UV3,
|
||||
MeshSectionBuffer.VertexColors,
|
||||
TArray<FProcMeshTangent>(),
|
||||
true
|
||||
);
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
#include "VoxelHelper.h"
|
||||
|
||||
#include "VoxelWorld.h"
|
||||
|
||||
AVoxelWorld * UVoxelHelper::CreateVoxelWorld(UObject* WorldContextObject, const FVoxelWorldSetting& WorldSetting)
|
||||
{
|
||||
UWorld* World = WorldContextObject->GetWorld();
|
||||
|
||||
if (!World) return nullptr;
|
||||
|
||||
AVoxelWorld* VoxelWorld = World->SpawnActor<AVoxelWorld>();
|
||||
|
||||
VoxelWorld->WorldSetting = WorldSetting;
|
||||
|
||||
return VoxelWorld;
|
||||
}
|
||||
|
||||
void UVoxelHelper::WorldToRelativeLocation(const FIntVector & InWorldLocation, FIntPoint & OutChunkLocation, FIntVector & OutRelativeLocation)
|
||||
{
|
||||
OutChunkLocation.X = InWorldLocation.X / 16;
|
||||
OutChunkLocation.Y = InWorldLocation.Y / 16;
|
||||
|
||||
OutRelativeLocation.X = InWorldLocation.X % 16;
|
||||
OutRelativeLocation.Y = InWorldLocation.Y % 16;
|
||||
OutRelativeLocation.Z = InWorldLocation.Z;
|
||||
|
||||
if (OutRelativeLocation.X < 0)
|
||||
{
|
||||
OutRelativeLocation.X += 16;
|
||||
OutChunkLocation.X -= 1;
|
||||
}
|
||||
|
||||
if (OutRelativeLocation.Y < 0)
|
||||
{
|
||||
OutRelativeLocation.Y += 16;
|
||||
OutChunkLocation.Y -= 1;
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
#include "VoxelLog.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogVoxel);
|
@ -0,0 +1,426 @@
|
||||
#include "VoxelMesh.h"
|
||||
|
||||
const FVoxelMeshData FVoxelMeshData::CubeTopFace =
|
||||
{
|
||||
// Vertices
|
||||
{
|
||||
{ 0.0f, 0.0f, 100.0f },
|
||||
{ 100.0f, 0.0f, 100.0f },
|
||||
{ 0.0f, 100.0f, 100.0f },
|
||||
{ 100.0f, 100.0f, 100.0f },
|
||||
},
|
||||
|
||||
// Triangles
|
||||
{
|
||||
2, 1, 0,
|
||||
2, 3, 1,
|
||||
},
|
||||
|
||||
// Normals
|
||||
{
|
||||
{ 0.0f, 0.0f, 1.0f },
|
||||
{ 0.0f, 0.0f, 1.0f },
|
||||
{ 0.0f, 0.0f, 1.0f },
|
||||
{ 0.0f, 0.0f, 1.0f },
|
||||
},
|
||||
|
||||
// UV0
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 1.0f, 0.0f },
|
||||
{ 0.0f, 1.0f },
|
||||
{ 1.0f, 1.0f },
|
||||
},
|
||||
|
||||
// UV1
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV2
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV3
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// VertexColors
|
||||
{
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
},
|
||||
};
|
||||
|
||||
const FVoxelMeshData FVoxelMeshData::CubeBottomFace =
|
||||
{
|
||||
// Vertices
|
||||
{
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 100.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 100.0f, 0.0f },
|
||||
{ 100.0f, 100.0f, 0.0f },
|
||||
},
|
||||
|
||||
// Triangles
|
||||
{
|
||||
0, 1, 2,
|
||||
1, 3, 2,
|
||||
},
|
||||
|
||||
// Normals
|
||||
{
|
||||
{ 0.0f, 0.0f, -1.0f },
|
||||
{ 0.0f, 0.0f, -1.0f },
|
||||
{ 0.0f, 0.0f, -1.0f },
|
||||
{ 0.0f, 0.0f, -1.0f },
|
||||
},
|
||||
|
||||
// UV0
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 1.0f, 0.0f },
|
||||
{ 0.0f, 1.0f },
|
||||
{ 1.0f, 1.0f },
|
||||
},
|
||||
|
||||
// UV1
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV2
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV3
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// VertexColors
|
||||
{
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
},
|
||||
};
|
||||
|
||||
const FVoxelMeshData FVoxelMeshData::CubeFrontFace =
|
||||
{
|
||||
// Vertices
|
||||
{
|
||||
{ 100.0f, 0.0f, 0.0f },
|
||||
{ 100.0f, 0.0f, 100.0f },
|
||||
{ 100.0f, 100.0f, 0.0f },
|
||||
{ 100.0f, 100.0f, 100.0f },
|
||||
},
|
||||
|
||||
// Triangles
|
||||
{
|
||||
0, 1, 2,
|
||||
1, 3, 2,
|
||||
},
|
||||
|
||||
// Normals
|
||||
{
|
||||
{ 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV0
|
||||
{
|
||||
{ 0.0f, 1.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 1.0f, 1.0f },
|
||||
{ 1.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV1
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV2
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV3
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// VertexColors
|
||||
{
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
},
|
||||
};
|
||||
|
||||
const FVoxelMeshData FVoxelMeshData::CubeBackFace =
|
||||
{
|
||||
// Vertices
|
||||
{
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 100.0f },
|
||||
{ 0.0f, 100.0f, 0.0f },
|
||||
{ 0.0f, 100.0f, 100.0f },
|
||||
},
|
||||
|
||||
// Triangles
|
||||
{
|
||||
2, 1, 0,
|
||||
2, 3, 1,
|
||||
},
|
||||
|
||||
// Normals
|
||||
{
|
||||
{ -1.0f, 0.0f, 0.0f },
|
||||
{ -1.0f, 0.0f, 0.0f },
|
||||
{ -1.0f, 0.0f, 0.0f },
|
||||
{ -1.0f, 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV0
|
||||
{
|
||||
{ 1.0f, 1.0f },
|
||||
{ 1.0f, 0.0f },
|
||||
{ 0.0f, 1.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV1
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV2
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV3
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// VertexColors
|
||||
{
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
},
|
||||
};
|
||||
|
||||
const FVoxelMeshData FVoxelMeshData::CubeLeftFace =
|
||||
{
|
||||
// Vertices
|
||||
{
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 100.0f },
|
||||
{ 100.0f, 0.0f, 0.0f },
|
||||
{ 100.0f, 0.0f, 100.0f },
|
||||
},
|
||||
|
||||
// Triangles
|
||||
{
|
||||
0, 1, 2,
|
||||
1, 3, 2,
|
||||
},
|
||||
|
||||
// Normals
|
||||
{
|
||||
{ 0.0f, -1.0f, 0.0f },
|
||||
{ 0.0f, -1.0f, 0.0f },
|
||||
{ 0.0f, -1.0f, 0.0f },
|
||||
{ 0.0f, -1.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV0
|
||||
{
|
||||
{ 0.0f, 1.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 1.0f, 1.0f },
|
||||
{ 1.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV1
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV2
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV3
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// VertexColors
|
||||
{
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
},
|
||||
};
|
||||
|
||||
const FVoxelMeshData FVoxelMeshData::CubeRightFace =
|
||||
{
|
||||
// Vertices
|
||||
{
|
||||
{ 0.0f, 100.0f, 0.0f },
|
||||
{ 0.0f, 100.0f, 100.0f },
|
||||
{ 100.0f, 100.0f, 0.0f },
|
||||
{ 100.0f, 100.0f, 100.0f },
|
||||
},
|
||||
|
||||
// Triangles
|
||||
{
|
||||
2, 1, 0,
|
||||
2, 3, 1,
|
||||
},
|
||||
|
||||
// Normals
|
||||
{
|
||||
{ 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV0
|
||||
{
|
||||
{ 1.0f, 1.0f },
|
||||
{ 1.0f, 0.0f },
|
||||
{ 0.0f, 1.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV1
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV2
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// UV3
|
||||
{
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f },
|
||||
},
|
||||
|
||||
// VertexColors
|
||||
{
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f },
|
||||
},
|
||||
};
|
||||
|
||||
void FVoxelMeshData::Reset()
|
||||
{
|
||||
Vertices.Reset();
|
||||
Triangles.Reset();
|
||||
Normals.Reset();
|
||||
UV0.Reset();
|
||||
UV1.Reset();
|
||||
UV2.Reset();
|
||||
UV3.Reset();
|
||||
VertexColors.Reset();
|
||||
}
|
||||
|
||||
void FVoxelMeshData::Append(const FVoxelMeshData & Source)
|
||||
{
|
||||
Vertices.Append(Source.Vertices);
|
||||
Triangles.Append(Source.Triangles);
|
||||
Normals.Append(Source.Normals);
|
||||
UV0.Append(Source.UV0);
|
||||
UV1.Append(Source.UV1);
|
||||
UV2.Append(Source.UV2);
|
||||
UV3.Append(Source.UV3);
|
||||
VertexColors.Append(Source.VertexColors);
|
||||
|
||||
for (int32 i = -Source.Triangles.Num(); i < 0; ++i)
|
||||
Triangles[Triangles.Num() + i] += Vertices.Num() - Source.Vertices.Num();
|
||||
}
|
||||
|
||||
void FVoxelMeshData::Append(const FVoxelMeshData & Source, const FVector & LocationOffset)
|
||||
{
|
||||
Append(Source);
|
||||
|
||||
for (int32 i = -Source.Vertices.Num(); i < 0; ++i)
|
||||
Vertices[Vertices.Num() + i] += LocationOffset;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
#include "VoxelSubsystem.h"
|
||||
|
||||
#include "VoxelBlock.h"
|
||||
|
||||
UVoxelSubsystem::UVoxelSubsystem(const class FObjectInitializer& ObjectInitializer)
|
||||
{
|
||||
BlockTypes.Add(TEXT("Air"), FVoxelBlockType());
|
||||
}
|
||||
|
||||
const FVoxelBlockType & UVoxelSubsystem::GetBlockType(const FName & Name) const
|
||||
{
|
||||
if (BlockTypes.Contains(Name))
|
||||
return BlockTypes[Name];
|
||||
|
||||
return FVoxelBlockType::InvalidBlockType;
|
||||
}
|
@ -0,0 +1,317 @@
|
||||
#include "VoxelWorld.h"
|
||||
|
||||
#include "VoxelLog.h"
|
||||
#include "VoxelBlock.h"
|
||||
#include "VoxelChunk.h"
|
||||
#include "VoxelHelper.h"
|
||||
#include "VoxelSubsystem.h"
|
||||
#include "VoxelAgentInterface.h"
|
||||
|
||||
const TArray<FIntPoint> ChunkLoadOrder =
|
||||
{
|
||||
{ 0, 0 },
|
||||
{ 0, -1 }, { -1, 0 }, { 0, 1 }, { 1, 0 }, { -1, -1 }, { 1, -1 }, { -1, 1 }, { 1, 1 },
|
||||
{ 2, 0 }, { -2, 0 }, { 0, -2 }, { 0, 2 }, { -2, 1 }, { 1, 2 }, { 1, -2 }, { -1, -2 },
|
||||
{ 2, 1 }, { 2, -1 }, { -1, 2 }, { -2, -1 }, { -2, -2 }, { 2, 2 }, { 2, -2 }, { -2, 2 },
|
||||
{ 0, -3 }, { 3, 0 }, { -3, 0 }, { 0, 3 }, { 3, -1 }, { -3, 1 }, { 1, -3 }, { -1, -3 },
|
||||
{ -1, 3 }, { 1, 3 }, { 3, 1 }, { -3, -1 }, { 3, -2 }, { 2, -3 }, { -3, 2 }, { -3, -2 },
|
||||
{ 3, 2 }, { -2, -3 }, { -2, 3 }, { 2, 3 }, { 4, 0 }, { 0, 4 }, { -4, 0 }, { 0, -4 },
|
||||
{ 4, 1 }, { -1, 4 }, { -4, 1 }, { 4, -1 }, { 1, -4 }, { 1, 4 }, { -4, -1 }, { -1, -4 },
|
||||
{ 3, -3 }, { -3, 3 }, { -3, -3 }, { 3, 3 }, { 4, -2 }, { -2, 4 }, { -2, -4 }, { -4, -2 },
|
||||
{ -4, 2 }, { 2, 4 }, { 2, -4 }, { 4, 2 }, { 3, -4 }, { -5, 0 }, { 0, 5 }, { -3, 4 },
|
||||
{ 4, -3 }, { -4, 3 }, { 5, 0 }, { 4, 3 }, { -4, -3 }, { 0, -5 }, { 3, 4 }, { -3, -4 },
|
||||
{ -5, -1 }, { -5, 1 }, { 5, -1 }, { 5, 1 }, { -1, 5 }, { -1, -5 }, { 1, -5 }, { 1, 5 },
|
||||
{ 5, -2 }, { 5, 2 }, { 2, -5 }, { -2, -5 }, { -5, 2 }, { -5, -2 }, { 2, 5 }, { -2, 5 },
|
||||
{ -4, 4 }, { 4, 4 }, { -4, -4 }, { 4, -4 }, { -5, -3 }, { -3, 5 }, { 5, 3 }, { 3, 5 },
|
||||
{ -5, 3 }, { 3, -5 }, { 5, -3 }, { -3, -5 }, { -6, 0 }, { 0, 6 }, { 6, 0 }, { 0, -6 },
|
||||
{ 6, -1 }, { -6, -1 }, { -6, 1 }, { -1, 6 }, { -1, -6 }, { 1, -6 }, { 1, 6 }, { 6, 1 },
|
||||
{ 2, -6 }, { -6, -2 }, { 6, 2 }, { 2, 6 }, { -6, 2 }, { -2, 6 }, { -2, -6 }, { 6, -2 },
|
||||
{ 4, -5 }, { 5, -4 }, { -5, 4 }, { 5, 4 }, { -5, -4 }, { -4, -5 }, { 4, 5 }, { -4, 5 },
|
||||
{ -6, -3 }, { 3, -6 }, { -3, -6 }, { -6, 3 }, { 6, 3 }, { 3, 6 }, { 6, -3 }, { -3, 6 },
|
||||
{ 0, 7 }, { 0, -7 }, { 7, 0 }, { -7, 0 }, { 5, -5 }, { 1, 7 }, { -7, -1 }, { -7, 1 },
|
||||
{ 1, -7 }, { -1, -7 }, { -5, -5 }, { 7, 1 }, { 5, 5 }, { -1, 7 }, { 7, -1 }, { -5, 5 },
|
||||
{ 6, -4 }, { -4, -6 }, { -6, 4 }, { -6, -4 }, { 6, 4 }, { 4, 6 }, { 4, -6 }, { -4, 6 },
|
||||
{ -2, 7 }, { 7, 2 }, { -2, -7 }, { -7, -2 }, { 2, -7 }, { 2, 7 }, { 7, -2 }, { -7, 2 },
|
||||
{ -7, 3 }, { 7, 3 }, { -7, -3 }, { -3, -7 }, { -3, 7 }, { 7, -3 }, { 3, 7 }, { 3, -7 },
|
||||
{ 6, -5 }, { -5, 6 }, { 6, 5 }, { -6, -5 }, { -5, -6 }, { 5, -6 }, { 5, 6 }, { -6, 5 },
|
||||
{ 0, -8 }, { 0, 8 }, { -8, 0 }, { 8, 0 }, { 7, 4 }, { -4, -7 }, { 7, -4 }, { 1, 8 },
|
||||
{ -1, -8 }, { 1, -8 }, { 4, -7 }, { 4, 7 }, { -7, -4 }, { -7, 4 }, { -8, 1 }, { -8, -1 },
|
||||
{ -1, 8 }, { 8, 1 }, { 8, -1 }, { -4, 7 }, { 2, -8 }, { -2, 8 }, { -2, -8 }, { -8, -2 },
|
||||
{ 8, 2 }, { 2, 8 }, { -8, 2 }, { 8, -2 }, { -6, 6 }, { -6, -6 }, { 6, 6 }, { 6, -6 },
|
||||
{ 8, -3 }, { 3, 8 }, { -3, 8 }, { 8, 3 }, { 3, -8 }, { -8, -3 }, { -8, 3 }, { -3, -8 },
|
||||
{ -5, -7 }, { 5, 7 }, { 7, -5 }, { -7, -5 }, { 7, 5 }, { -7, 5 }, { -5, 7 }, { 5, -7 },
|
||||
{ 4, 8 }, { -4, 8 }, { -8, 4 }, { -8, -4 }, { 4, -8 }, { 8, -4 }, { 8, 4 }, { -4, -8 },
|
||||
{ 0, -9 }, { 0, 9 }, { -9, 0 }, { 9, 0 }, { -1, -9 }, { 1, 9 }, { 9, -1 }, { -1, 9 },
|
||||
{ 1, -9 }, { -9, 1 }, { -9, -1 }, { 9, 1 }, { 6, 7 }, { -7, 6 }, { -9, -2 }, { 2, 9 },
|
||||
{ -2, -9 }, { -2, 9 }, { 9, 2 }, { -6, -7 }, { 7, -6 }, { -6, 7 }, { 7, 6 }, { 6, -7 },
|
||||
{ 2, -9 }, { 9, -2 }, { -9, 2 }, { -7, -6 }, { 8, -5 }, { -5, 8 }, { -8, -5 }, { 5, 8 },
|
||||
{ -5, -8 }, { 8, 5 }, { 5, -8 }, { -8, 5 }, { -3, 9 }, { -9, 3 }, { -9, -3 }, { 9, -3 },
|
||||
{ 3, 9 }, { -3, -9 }, { 3, -9 }, { 9, 3 }, { -4, 9 }, { -9, -4 }, { -4, -9 }, { 4, 9 },
|
||||
{ 9, 4 }, { 4, -9 }, { -9, 4 }, { 9, -4 }, { 7, 7 }, { -7, 7 }, { -7, -7 }, { 7, -7 },
|
||||
{ -6, -8 }, { 10, 0 }, { 8, -6 }, { -8, -6 }, { 8, 6 }, { 6, -8 }, { -6, 8 }, { 0, -10 },
|
||||
{ 0, 10 }, { -8, 6 }, { 6, 8 }, { -10, 0 }, { 10, -1 }, { -10, -1 }, { -1, -10 }, { -10, 1 },
|
||||
{ -1, 10 }, { 10, 1 }, { 1, 10 }, { 1, -10 }, { 2, 10 }, { -10, 2 }, { -10, -2 }, { -2, 10 },
|
||||
{ 2, -10 }, { 10, -2 }, { -2, -10 }, { 10, 2 }, { -9, -5 }, { -9, 5 }, { -5, -9 }, { 9, -5 },
|
||||
{ 9, 5 }, { 5, 9 }, { 5, -9 }, { -5, 9 }, { 3, 10 }, { -10, 3 }, { 3, -10 }, { -3, 10 },
|
||||
{ 10, -3 }, { -10, -3 }, { 10, 3 }, { -3, -10 }, { 8, -7 }, { 8, 7 }, { 7, 8 }, { -7, 8 },
|
||||
{ -7, -8 }, { 7, -8 }, { -8, 7 }, { -8, -7 }, { 4, -10 }, { 10, 4 }, { -4, -10 }, { -10, -4 },
|
||||
{ 10, -4 }, { -4, 10 }, { 4, 10 }, { -10, 4 }, { -6, -9 }, { 6, -9 }, { 6, 9 }, { -9, -6 },
|
||||
{ -9, 6 }, { 9, -6 }, { 9, 6 }, { -6, 9 }, { 0, 11 }, { 11, 0 }, { 0, -11 }, { -11, 0 },
|
||||
{ 1, 11 }, { -1, -11 }, { -1, 11 }, { -11, -1 }, { 11, 1 }, { 11, -1 }, { 1, -11 }, { -11, 1 },
|
||||
{ -5, -10 }, { -2, -11 }, { 11, 2 }, { -10, -5 }, { 2, 11 }, { 10, -5 }, { 5, -10 }, { 11, -2 },
|
||||
{ -5, 10 }, { -11, 2 }, { 10, 5 }, { 5, 10 }, { 2, -11 }, { -11, -2 }, { -10, 5 }, { -2, 11 },
|
||||
{ -8, -8 }, { -8, 8 }, { 8, 8 }, { 8, -8 }, { 7, 9 }, { -11, 3 }, { -11, -3 }, { 11, -3 },
|
||||
{ 9, 7 }, { -3, -11 }, { 3, -11 }, { 7, -9 }, { -9, 7 }, { -7, -9 }, { -9, -7 }, { 11, 3 },
|
||||
{ 9, -7 }, { -7, 9 }, { -3, 11 }, { 3, 11 }, { 10, -6 }, { 10, 6 }, { -10, -6 }, { -6, -10 },
|
||||
{ -6, 10 }, { -10, 6 }, { 6, -10 }, { 6, 10 }, { -4, 11 }, { -11, 4 }, { -4, -11 }, { -11, -4 },
|
||||
{ 11, -4 }, { 11, 4 }, { 4, -11 }, { 4, 11 }, { 12, 0 }, { 0, 12 }, { 0, -12 }, { -12, 0 },
|
||||
{ 12, -1 }, { 8, -9 }, { -12, -1 }, { 1, 12 }, { -1, -12 }, { -12, 1 }, { 12, 1 }, { 9, -8 },
|
||||
{ -1, 12 }, { 1, -12 }, { -9, 8 }, { -8, -9 }, { -9, -8 }, { -8, 9 }, { 9, 8 }, { 8, 9 },
|
||||
{ -11, -5 }, { 5, -11 }, { 11, 5 }, { -5, 11 }, { -5, -11 }, { 5, 11 }, { -11, 5 }, { 11, -5 },
|
||||
{ 12, -2 }, { 12, 2 }, { -2, 12 }, { -12, -2 }, { -12, 2 }, { -2, -12 }, { 2, -12 }, { 2, 12 },
|
||||
{ 7, 10 }, { 7, -10 }, { -10, 7 }, { 10, -7 }, { -7, -10 }, { 10, 7 }, { -7, 10 }, { -10, -7 },
|
||||
{ 12, -3 }, { 12, 3 }, { -3, 12 }, { 3, -12 }, { -12, 3 }, { -12, -3 }, { -3, -12 }, { 3, 12 },
|
||||
{ -6, 11 }, { -11, -6 }, { -11, 6 }, { 6, 11 }, { 11, 6 }, { -6, -11 }, { 6, -11 }, { 11, -6 },
|
||||
{ 12, -4 }, { 12, 4 }, { -12, 4 }, { 4, -12 }, { -4, -12 }, { -12, -4 }, { -4, 12 }, { 4, 12 },
|
||||
{ 9, -9 }, { -9, -9 }, { 9, 9 }, { -9, 9 }, { -10, -8 }, { 8, -10 }, { -10, 8 }, { 10, -8 },
|
||||
{ -8, 10 }, { 10, 8 }, { -8, -10 }, { 8, 10 }, { 12, -5 }, { 5, -12 }, { 0, -13 }, { 13, 0 },
|
||||
{ -5, 12 }, { 5, 12 }, { -12, 5 }, { 0, 13 }, { -5, -12 }, { 12, 5 }, { -12, -5 }, { -13, 0 },
|
||||
{ -11, -7 }, { 7, -11 }, { 11, -7 }, { -13, -1 }, { -13, 1 }, { 13, -1 }, { 13, 1 }, { 11, 7 },
|
||||
{ -1, -13 }, { -7, 11 }, { -7, -11 }, { -1, 13 }, { 1, 13 }, { 1, -13 }, { 7, 11 }, { -11, 7 },
|
||||
{ -2, 13 }, { 2, 13 }, { -13, 2 }, { 2, -13 }, { -2, -13 }, { 13, -2 }, { -13, -2 }, { 13, 2 },
|
||||
{ -13, 3 }, { 3, 13 }, { 3, -13 }, { -13, -3 }, { -3, 13 }, { -3, -13 }, { 13, -3 }, { 13, 3 },
|
||||
{ 6, -12 }, { -12, 6 }, { 12, -6 }, { -6, -12 }, { -12, -6 }, { -6, 12 }, { 6, 12 }, { 12, 6 },
|
||||
{ 10, -9 }, { -10, 9 }, { -9, -10 }, { 9, -10 }, { 9, 10 }, { -9, 10 }, { -10, -9 }, { 10, 9 },
|
||||
{ 8, 11 }, { 8, -11 }, { 11, -8 }, { 13, 4 }, { -8, 11 }, { -8, -11 }, { 4, 13 }, { -4, -13 },
|
||||
{ -4, 13 }, { 11, 8 }, { 13, -4 }, { -11, -8 }, { -13, 4 }, { -11, 8 }, { 4, -13 }, { -13, -4 },
|
||||
{ 12, -7 }, { 12, 7 }, { -12, -7 }, { 7, -12 }, { 7, 12 }, { -12, 7 }, { -7, 12 }, { -7, -12 },
|
||||
{ 13, 5 }, { -5, 13 }, { -13, -5 }, { 5, -13 }, { -13, 5 }, { 5, 13 }, { 13, -5 }, { -5, -13 },
|
||||
{ -14, 0 }, { 0, 14 }, { 0, -14 }, { 14, 0 }, { -14, 1 }, { 1, -14 }, { -14, -1 }, { -1, 14 },
|
||||
{ -1, -14 }, { 1, 14 }, { 14, -1 }, { 14, 1 }, { -2, -14 }, { 2, -14 }, { 2, 14 }, { -10, -10 },
|
||||
{ -14, 2 }, { 10, 10 }, { -14, -2 }, { 10, -10 }, { -2, 14 }, { -10, 10 }, { 14, -2 }, { 14, 2 },
|
||||
{ 11, 9 }, { 11, -9 }, { -11, -9 }, { -11, 9 }, { 9, 11 }, { -9, 11 }, { -9, -11 }, { 9, -11 },
|
||||
{ 6, -13 }, { -13, -6 }, { -14, 3 }, { -6, 13 }, { 6, 13 }, { 3, -14 }, { -3, 14 }, { -14, -3 },
|
||||
{ 13, 6 }, { 14, -3 }, { 13, -6 }, { 3, 14 }, { -6, -13 }, { -13, 6 }, { -3, -14 }, { 14, 3 },
|
||||
{ -8, -12 }, { 8, 12 }, { -8, 12 }, { -12, 8 }, { 12, -8 }, { -12, -8 }, { 8, -12 }, { 12, 8 },
|
||||
{ 4, 14 }, { -14, 4 }, { 14, 4 }, { 14, -4 }, { -4, -14 }, { 4, -14 }, { -4, 14 }, { -14, -4 },
|
||||
{ 7, 13 }, { -7, -13 }, { -13, 7 }, { -13, -7 }, { 13, -7 }, { -7, 13 }, { 7, -13 }, { 13, 7 },
|
||||
{ -10, -11 }, { 5, -14 }, { -11, -10 }, { 5, 14 }, { -11, 10 }, { 14, -5 }, { -14, 5 }, { -14, -5 },
|
||||
{ 10, -11 }, { 10, 11 }, { 11, -10 }, { 11, 10 }, { -5, 14 }, { -5, -14 }, { -10, 11 }, { 14, 5 },
|
||||
{ 0, 15 }, { 9, 12 }, { -12, 9 }, { -9, 12 }, { 15, 0 }, { 12, -9 }, { 12, 9 }, { 0, -15 },
|
||||
{ -15, 0 }, { -12, -9 }, { 9, -12 }, { -9, -12 }, { 1, 15 }, { 15, 1 }, { -15, -1 }, { -1, 15 },
|
||||
{ -1, -15 }, { 15, -1 }, { -15, 1 }, { 1, -15 }, { -15, -2 }, { 2, -15 }, { 15, 2 }, { -2, -15 },
|
||||
{ 2, 15 }, { 15, -2 }, { -2, 15 }, { -15, 2 }, { -6, 14 }, { 14, -6 }, { -14, 6 }, { -6, -14 },
|
||||
{ 6, 14 }, { -14, -6 }, { 6, -14 }, { 14, 6 }, { 8, 13 }, { 13, 8 }, { -8, -13 }, { 13, -8 },
|
||||
{ -13, -8 }, { -8, 13 }, { -13, 8 }, { 8, -13 }, { 3, 15 }, { 15, 3 }, { -3, -15 }, { -15, -3 },
|
||||
{ -3, 15 }, { -15, 3 }, { 3, -15 }, { 15, -3 }, { 15, 4 }, { 4, -15 }, { -4, -15 }, { 4, 15 },
|
||||
{ -4, 15 }, { 15, -4 }, { -15, 4 }, { -15, -4 }, { -11, -11 }, { 11, -11 }, { -11, 11 }, { 11, 11 },
|
||||
{ 12, 10 }, { -12, 10 }, { -10, -12 }, { -10, 12 }, { 10, -12 }, { 10, 12 }, { -12, -10 }, { 12, -10 },
|
||||
{ 7, -14 }, { 14, 7 }, { -14, 7 }, { 14, -7 }, { 7, 14 }, { -14, -7 }, { -7, -14 }, { -7, 14 },
|
||||
{ -15, 5 }, { -13, -9 }, { -5, -15 }, { 13, -9 }, { -9, -13 }, { 9, -13 }, { 5, 15 }, { -9, 13 },
|
||||
{ 9, 13 }, { 13, 9 }, { -5, 15 }, { -13, 9 }, { 5, -15 }, { 15, 5 }, { -15, -5 }, { 15, -5 },
|
||||
{ 0, 16 }, { -16, 0 }, { 0, -16 }, { 16, 0 }, { -16, 1 }, { -16, -1 }, { 1, 16 }, { -1, 16 },
|
||||
{ 1, -16 }, { -1, -16 }, { 16, -1 }, { 16, 1 }, { 2, -16 }, { -14, 8 }, { -2, 16 }, { 8, 14 },
|
||||
{ 14, 8 }, { -2, -16 }, { -8, -14 }, { -8, 14 }, { -14, -8 }, { 16, 2 }, { 16, -2 }, { 2, 16 },
|
||||
{ 14, -8 }, { -16, 2 }, { -16, -2 }, { 8, -14 }, { 6, 15 }, { 6, -15 }, { -6, -15 }, { 15, -6 },
|
||||
{ -15, 6 }, { 15, 6 }, { -15, -6 }, { -6, 15 }, { -3, 16 }, { 3, 16 }, { 11, 12 }, { 12, -11 },
|
||||
{ 12, 11 }, { -11, 12 }, { 16, -3 }, { 16, 3 }, { -16, 3 }, { -16, -3 }, { -3, -16 }, { -12, -11 },
|
||||
{ 11, -12 }, { -11, -12 }, { -12, 11 }, { 3, -16 }, { -10, -13 }, { -10, 13 }, { -13, 10 }, { 13, -10 },
|
||||
{ 10, -13 }, { 10, 13 }, { 13, 10 }, { -13, -10 }, { 16, -4 }, { -4, -16 }, { 16, 4 }, { 4, 16 },
|
||||
{ 4, -16 }, { -4, 16 }, { -16, -4 }, { -16, 4 }, { 7, -15 }, { 15, -7 }, { -7, 15 }, { 15, 7 },
|
||||
{ 7, 15 }, { -7, -15 }, { -15, 7 }, { -15, -7 }, { -14, 9 }, { -9, -14 }, { 9, -14 }, { -9, 14 },
|
||||
{ 14, 9 }, { 14, -9 }, { 9, 14 }, { -14, -9 }, { -16, -5 }, { -5, -16 }, { 5, 16 }, { 16, -5 },
|
||||
{ 5, -16 }, { -5, 16 }, { -16, 5 }, { 16, 5 }, { -12, 12 }, { 12, 12 }, { 12, -12 }, { -12, -12 },
|
||||
{ -15, -8 }, { 8, 15 }, { 8, -15 }, { -8, 15 }, { -8, -15 }, { 15, -8 }, { 15, 8 }, { -15, 8 },
|
||||
{ 13, -11 }, { 11, -13 }, { -11, 13 }, { -11, -13 }, { 11, 13 }, { 13, 11 }, { -13, 11 }, { -13, -11 },
|
||||
{ 16, -6 }, { -6, 16 }, { 6, -16 }, { -16, 6 }, { 16, 6 }, { -16, -6 }, { 6, 16 }, { -6, -16 },
|
||||
{ 14, 10 }, { -10, 14 }, { 14, -10 }, { -10, -14 }, { 10, -14 }, { -14, 10 }, { -14, -10 }, { 10, 14 },
|
||||
{ -16, -7 }, { 16, -7 }, { -7, -16 }, { -7, 16 }, { 16, 7 }, { 7, 16 }, { -16, 7 }, { 7, -16 },
|
||||
{ 9, -15 }, { 15, -9 }, { 9, 15 }, { 15, 9 }, { -15, 9 }, { -15, -9 }, { -9, -15 }, { -9, 15 },
|
||||
{ 13, -12 }, { -12, 13 }, { -12, -13 }, { 13, 12 }, { 12, -13 }, { -13, -12 }, { 12, 13 }, { -13, 12 },
|
||||
{ -14, 11 }, { 14, -11 }, { -14, -11 }, { -11, -14 }, { -11, 14 }, { 11, -14 }, { 14, 11 }, { 11, 14 },
|
||||
{ -16, -8 }, { -16, 8 }, { -8, 16 }, { 8, -16 }, { 16, -8 }, { 8, 16 }, { -8, -16 }, { 16, 8 },
|
||||
{ 15, 10 }, { -10, -15 }, { -15, 10 }, { -15, -10 }, { 10, 15 }, { 10, -15 }, { 15, -10 }, { -10, 15 },
|
||||
{ 9, 16 }, { -9, -16 }, { 16, -9 }, { -16, -9 }, { -9, 16 }, { 9, -16 }, { -16, 9 }, { 16, 9 },
|
||||
{ -13, -13 }, { -13, 13 }, { 13, 13 }, { 13, -13 }, { 12, 14 }, { -12, 14 }, { -12, -14 }, { 14, 12 },
|
||||
{ 12, -14 }, { 14, -12 }, { -14, -12 }, { -14, 12 }, { 11, -15 }, { -11, -15 }, { -15, -11 }, { -11, 15 },
|
||||
{ 15, 11 }, { 15, -11 }, { -15, 11 }, { 11, 15 }, { -10, 16 }, { -16, -10 }, { -10, -16 }, { 16, -10 },
|
||||
{ 10, -16 }, { 10, 16 }, { 16, 10 }, { -16, 10 }, { 14, -13 }, { 13, 14 }, { 14, 13 }, { 13, -14 },
|
||||
{ -13, -14 }, { -14, -13 }, { -13, 14 }, { -14, 13 }, { -15, -12 }, { 15, -12 }, { -12, -15 }, { -15, 12 },
|
||||
{ -12, 15 }, { 12, -15 }, { 12, 15 }, { 15, 12 }, { -11, 16 }, { 16, -11 }, { 11, -16 }, { -11, -16 },
|
||||
{ -16, 11 }, { -16, -11 }, { 11, 16 }, { 16, 11 }, { 14, 14 }, { -14, -14 }, { 14, -14 }, { -14, 14 },
|
||||
{ 15, -13 }, { -13, -15 }, { -15, 13 }, { -13, 15 }, { 15, 13 }, { -15, -13 }, { 13, -15 }, { 13, 15 },
|
||||
{ 16, -12 }, { 12, -16 }, { -12, -16 }, { 12, 16 }, { -12, 16 }, { -16, -12 }, { -16, 12 }, { 16, 12 },
|
||||
{ -15, 14 }, { 14, -15 }, { -15, -14 }, { -14, 15 }, { 14, 15 }, { -14, -15 }, { 15, -14 }, { 15, 14 },
|
||||
{ 16, -13 }, { 13, -16 }, { -16, 13 }, { 13, 16 }, { -16, -13 }, { -13, -16 }, { -13, 16 }, { 16, 13 },
|
||||
{ -15, 15 }, { -15, -15 }, { 15, -15 }, { 15, 15 }, { 16, -14 }, { -16, 14 }, { 14, -16 }, { -16, -14 },
|
||||
{ -14, -16 }, { -14, 16 }, { 14, 16 }, { 16, 14 }, { 16, -15 }, { -15, -16 }, { -16, 15 }, { -15, 16 },
|
||||
{ -16, -15 }, { 15, -16 }, { 15, 16 }, { 16, 15 }, { -16, -16 }, { -16, 16 }, { 16, -16 }, { 16, 16 },
|
||||
};
|
||||
|
||||
AVoxelWorld::AVoxelWorld(const class FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
}
|
||||
|
||||
void AVoxelWorld::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
UGameInstance* GameInstance = GetGameInstance();
|
||||
VoxelSubsystem = GameInstance->GetSubsystem<UVoxelSubsystem>();
|
||||
}
|
||||
|
||||
void AVoxelWorld::Tick(float DeltaSeconds)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
|
||||
ManageChunk();
|
||||
|
||||
FlushMeshs();
|
||||
|
||||
}
|
||||
|
||||
void AVoxelWorld::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
TArray<FIntPoint> ChunksToUnload;
|
||||
Chunks.GetKeys(ChunksToUnload);
|
||||
|
||||
for (const FIntPoint& Chunk : ChunksToUnload)
|
||||
UnloadChunk(Chunk);
|
||||
|
||||
Super::EndPlay(EndPlayReason);
|
||||
}
|
||||
|
||||
const FVoxelBlock & AVoxelWorld::GetBlockByWorldLocation(const FIntVector & Location) const
|
||||
{
|
||||
FIntPoint ChunkLocation;
|
||||
FIntVector RelativeLocation;
|
||||
|
||||
UVoxelHelper::WorldToRelativeLocation(Location, ChunkLocation, RelativeLocation);
|
||||
|
||||
if (!Chunks.Contains(ChunkLocation))
|
||||
{
|
||||
UE_LOG(LogVoxel, Warning, TEXT("The Chunk %d, %d Is Not Loaded, Block %d, %d, %d Is Invalid"), ChunkLocation.X, ChunkLocation.Y, Location.X, Location.Y, Location.Z);
|
||||
return FVoxelBlock::InvalidBlock;
|
||||
}
|
||||
|
||||
return Chunks[ChunkLocation]->GetBlockByRelativeLocation(RelativeLocation);
|
||||
}
|
||||
|
||||
void AVoxelWorld::SetBlockByWorldLocation(const FIntVector& Location, const FVoxelBlock& NewBlock)
|
||||
{
|
||||
FIntPoint ChunkLocation;
|
||||
FIntVector RelativeLocation;
|
||||
|
||||
UVoxelHelper::WorldToRelativeLocation(Location, ChunkLocation, RelativeLocation);
|
||||
|
||||
if (!Chunks.Contains(ChunkLocation))
|
||||
{
|
||||
UE_LOG(LogVoxel, Warning, TEXT("The Chunk %d, %d Is Not Loaded, Block %d, %d, %d Is Invalid"), ChunkLocation.X, ChunkLocation.Y, Location.X, Location.Y, Location.Z);
|
||||
return;
|
||||
}
|
||||
|
||||
Chunks[ChunkLocation]->SetBlockByRelativeLocation(RelativeLocation, NewBlock);
|
||||
}
|
||||
|
||||
void AVoxelWorld::LoadChunk(const FIntPoint & ChunkLocation)
|
||||
{
|
||||
if (Chunks.Contains(ChunkLocation)) return;
|
||||
|
||||
UWorld* World = GetWorld();
|
||||
|
||||
check(World);
|
||||
|
||||
AVoxelChunk* NewVoxelChunk = World->SpawnActor<AVoxelChunk>();
|
||||
NewVoxelChunk->VoxelWorld = this;
|
||||
NewVoxelChunk->ChunkLocation = ChunkLocation;
|
||||
NewVoxelChunk->SetActorLocation(FVector(ChunkLocation.X * 1600.0f, ChunkLocation.Y * 1600.0f, 0.0f));
|
||||
NewVoxelChunk->AttachToActor(this, FAttachmentTransformRules::KeepRelativeTransform);
|
||||
NewVoxelChunk->FlushMaterials();
|
||||
NewVoxelChunk->Load();
|
||||
AddChunkToMeshFlushBuffer(ChunkLocation);
|
||||
|
||||
Chunks.Add(ChunkLocation, NewVoxelChunk);
|
||||
|
||||
UE_LOG(LogVoxel, Log, TEXT("The Chunk %d, %d Is Loaded"), ChunkLocation.X, ChunkLocation.Y);
|
||||
}
|
||||
|
||||
void AVoxelWorld::UnloadChunk(const FIntPoint & ChunkLocation)
|
||||
{
|
||||
if (!Chunks.Contains(ChunkLocation)) return;
|
||||
|
||||
Chunks[ChunkLocation]->Unload();
|
||||
Chunks[ChunkLocation]->Destroy();
|
||||
|
||||
Chunks.Remove(ChunkLocation);
|
||||
|
||||
UE_LOG(LogVoxel, Log, TEXT("The Chunk %d, %d Is Unload"), ChunkLocation.X, ChunkLocation.Y);
|
||||
}
|
||||
|
||||
void AVoxelWorld::FlushMaterials()
|
||||
{
|
||||
for (const TPair<FIntPoint, AVoxelChunk*>& Chunk : Chunks)
|
||||
{
|
||||
Chunk.Value->FlushMaterials();
|
||||
}
|
||||
}
|
||||
|
||||
void AVoxelWorld::ManageChunk()
|
||||
{
|
||||
FIntPoint RootChunk;
|
||||
FIntVector RLocation;
|
||||
UVoxelHelper::WorldToRelativeLocation(IVoxelAgentInterface::Execute_GetAgentLocation(CenterAgent.GetObject()), RootChunk, RLocation);
|
||||
|
||||
// Load
|
||||
for (const FIntPoint& Chunk : ChunkLoadOrder)
|
||||
{
|
||||
const FIntPoint WorldLocation = Chunk + RootChunk;
|
||||
const FIntPoint RelativeLocation = Chunk;
|
||||
|
||||
const bool bChunkLoaded = Chunks.Contains(WorldLocation);
|
||||
const bool bInLoadDistance = FMath::Abs(RelativeLocation.X) < VoxelSubsystem->ChunkLoadDistance && FMath::Abs(RelativeLocation.Y) < VoxelSubsystem->ChunkLoadDistance;
|
||||
|
||||
if (!bChunkLoaded && bInLoadDistance)
|
||||
{
|
||||
LoadChunk(WorldLocation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Unload
|
||||
int32 ChunkUnloadDistance = VoxelSubsystem->ChunkLoadDistance + VoxelSubsystem->ChunkUnloadBuffer;
|
||||
for (const TPair<FIntPoint, AVoxelChunk*>& Chunk : Chunks)
|
||||
{
|
||||
const FIntPoint WorldLocation = Chunk.Key;
|
||||
const FIntPoint RelativeLocation = WorldLocation - RootChunk;
|
||||
|
||||
const bool bInUnloadDistance = FMath::Abs(RelativeLocation.X) > ChunkUnloadDistance && FMath::Abs(RelativeLocation.Y) > ChunkUnloadDistance;
|
||||
|
||||
if (bInUnloadDistance)
|
||||
{
|
||||
UnloadChunk(WorldLocation);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AVoxelWorld::FlushMeshs()
|
||||
{
|
||||
QUICK_SCOPE_CYCLE_COUNTER(STAT_VoxelWorld_FlushMeshs);
|
||||
|
||||
for (const FIntPoint& ChunkLocation : MeshFlushBuffer)
|
||||
{
|
||||
if (!Chunks.Contains(ChunkLocation))
|
||||
continue;
|
||||
|
||||
AVoxelChunk* ChunkActor = Chunks[ChunkLocation];
|
||||
|
||||
if (!IsValid(ChunkActor))
|
||||
continue;
|
||||
|
||||
ChunkActor->FlushMeshs();
|
||||
}
|
||||
|
||||
MeshFlushBuffer.Reset();
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "VoxelBlock.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "VoxelBlueprintLibrary.generated.h"
|
||||
|
||||
struct FVoxelBlockType;
|
||||
|
||||
UCLASS()
|
||||
class UVoxelBlueprintLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
|