8#include "CoreMinimal.h"
10#include "Misc/FileHelper.h"
11#include "Async/Async.h"
12#include "HAL/PlatformFileManager.h"
21 if (points.Num() == 0)
26 if (!FullFileName.EndsWith(TEXT(
".ply")))
28 UE_LOG(LogTemp, Warning, TEXT(
"PointcloudUtilities.cpp: Invalid file format. Expecting filename to end with '.ply'!"));
32 FString Directory = FPaths::GetPath(FullFileName);
33 IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
34 if (!PlatformFile.DirectoryExists(*Directory))
36 if (!PlatformFile.CreateDirectoryTree(*Directory))
42 AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [FullFileName, points]()
45 std::string header =
"ply\nformat binary_little_endian 1.0\n"
46 "element vertex " + std::to_string(points.Num()) +
"\n"
47 "property double x\nproperty double y\nproperty double z\n"
51 size_t numPoints = points.Num();
52 size_t bufferSize = numPoints *
sizeof(FVector);
55 std::ofstream plyFile(TCHAR_TO_UTF8(*FullFileName), std::ios::out | std::ios::binary);
56 if (!plyFile.is_open())
62 plyFile.write(header.c_str(), header.size());
65 plyFile.write(
reinterpret_cast<const char*
>(points.GetData()), bufferSize);
79 if (!FullFileName.EndsWith(TEXT(
".ply")))
81 UE_LOG(LogTemp, Warning, TEXT(
"PointcloudUtilities.cpp: Invalid file format. Expecting filename to end with '.ply'!"));
85 FString Directory = FPaths::GetPath(FullFileName);
86 IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
87 if (!PlatformFile.DirectoryExists(*Directory))
89 if (!PlatformFile.CreateDirectoryTree(*Directory))
95 AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [FullFileName, points]()
98 std::string header =
"ply\nformat binary_little_endian 1.0\n"
99 "element vertex " + std::to_string(points.size()) +
"\n"
100 "property float x\nproperty float y\nproperty float z\n"
101 "property uchar red\nproperty uchar green\nproperty uchar blue\n"
105 size_t numPoints = points.size();
106 size_t bufferSize = numPoints * (
sizeof(float) * 3 +
sizeof(uint8_t) * 3);
107 std::vector<char> buffer;
108 buffer.reserve(bufferSize);
111 for (
const auto& point : points)
114 buffer.insert(buffer.end(),
reinterpret_cast<const char*
>(&point.X),
reinterpret_cast<const char*
>(&point.X) +
sizeof(float));
115 buffer.insert(buffer.end(),
reinterpret_cast<const char*
>(&point.Y),
reinterpret_cast<const char*
>(&point.Y) +
sizeof(float));
116 buffer.insert(buffer.end(),
reinterpret_cast<const char*
>(&point.Z),
reinterpret_cast<const char*
>(&point.Z) +
sizeof(float));
119 uint8_t red = (point.RGB >> 16) & 0xFF;
120 uint8_t green = (point.RGB >> 8) & 0xFF;
121 uint8_t blue = point.RGB & 0xFF;
122 buffer.insert(buffer.end(),
reinterpret_cast<const char*
>(&red),
reinterpret_cast<const char*
>(&red) +
sizeof(uint8_t));
123 buffer.insert(buffer.end(),
reinterpret_cast<const char*
>(&green),
reinterpret_cast<const char*
>(&green) +
sizeof(uint8_t));
124 buffer.insert(buffer.end(),
reinterpret_cast<const char*
>(&blue),
reinterpret_cast<const char*
>(&blue) +
sizeof(uint8_t));
128 std::ofstream plyFile(TCHAR_TO_UTF8(*FullFileName), std::ios::out | std::ios::binary);
129 if (!plyFile.is_open())
131 UE_LOG(LogTemp, Warning, TEXT(
"Failed to open file for writing: %s"), *FullFileName);
136 plyFile.write(header.c_str(), header.size());
139 plyFile.write(buffer.data(), buffer.size());
static void SaveTArrayAsPlyAsync(FString FullFileName, const TArray< FVector > points)
static void SaveVectorArrayAsPlyAsync(FString FullFileName, const std::vector< FPointData > points)