Commit 3b471513 by Kai Westerkamp

start point clouds

parent 24f6dcc3
// Fill out your copyright notice in the Description page of Project Settings.
#include "MasterTestProject.h"
#include "DynamicTextureUtilities.h"
// NOTE hard-coded to 64 * 64 texture sizes! I just copied this from some of my own code and modified it for you a little. You'll want to change a bunch of stuff in here for your own purposes.
void UDynamicTextureUtilities::UpdateTextureRegion(UTexture2D* Texture, int32 MipIndex, FUpdateTextureRegion2D Region, uint32 SrcPitch, uint32 SrcBpp, uint8* SrcData, bool bFreeData)
{
if (Texture->Resource)
{
struct FUpdateTextureRegionsData
{
FTexture2DResource* Texture2DResource;
int32 MipIndex;
FUpdateTextureRegion2D Region;
uint32 SrcPitch;
uint32 SrcBpp;
uint8* SrcData;
};
FUpdateTextureRegionsData* RegionData = new FUpdateTextureRegionsData;
RegionData->Texture2DResource = (FTexture2DResource*)Texture->Resource;
RegionData->MipIndex = MipIndex;
RegionData->Region = Region;
RegionData->SrcPitch = SrcPitch;
RegionData->SrcBpp = SrcBpp;
RegionData->SrcData = SrcData;
{
ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
UpdateTextureRegionsData,
FUpdateTextureRegionsData*, RegionData, RegionData,
bool, bFreeData, bFreeData,
{
int32 CurrentFirstMip = RegionData->Texture2DResource->GetCurrentFirstMip();
if (RegionData->MipIndex >= CurrentFirstMip)
{
RHIUpdateTexture2D(
RegionData->Texture2DResource->GetTexture2DRHI(),
RegionData->MipIndex - CurrentFirstMip,
RegionData->Region,
RegionData->SrcPitch,
RegionData->SrcData
+ RegionData->Region.SrcY * RegionData->SrcPitch
+ RegionData->Region.SrcX * RegionData->SrcBpp
);
}
// TODO is this leaking if we never set this to true??
if (bFreeData)
{
FMemory::Free(RegionData->SrcData);
}
delete RegionData;
});
}
}
}
void UDynamicTextureUtilities::UpdateDynamicVectorTexture(const TArray<FLinearColor>& Source, UTexture2D* Texture)
{
// Only handles 32-bit float textures
if (!Texture || Texture->GetPixelFormat() != PF_A32B32G32R32F) return;
// Shouldn't do anything if there's no data
if (Source.Num() < 1) return;
UpdateTextureRegion(Texture, 0, FUpdateTextureRegion2D(0, 0, 0, 0, Texture->GetSizeX(), Texture->GetSizeY()), Texture->GetSizeX() * sizeof(FLinearColor), sizeof(FLinearColor), (uint8*)Source.GetData(), false);
}
UTexture2D* UDynamicTextureUtilities::CreateTransientDynamicTexture(int32 Width, int32 Height, EPixelFormat PixelFormat /*= PF_A32B32G32R32F*/)
{
auto* Texture = UTexture2D::CreateTransient(Width, Height, PixelFormat);
if (Texture)
{
Texture->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
Texture->SRGB = 0;
Texture->UpdateResource();
}
return Texture;
}
/*
void UDynamicTextureUtilities::SetDynamicTextureAndIndex(class UStaticMeshComponent* Component, class UTexture2D* Texture, int32 Index, FName IndexParameterName, FName TextureParameterName)
{
if (!Component || !Texture) return;
for (int32 i = 0; i < Component->GetNumMaterials(); i++)
{
auto* DynamicMaterial = FMyProjInstanceProcedures::TryGetDynamicMaterial(Component, i);
if (!DynamicMaterial) continue;
FLinearColor CalculatedIndex(FMath::Fmod((float)Index, 64.0f) + 0.5f, FMath::FloorToFloat((float)Index / 64.0f) + 0.5f, 0.0f, 0.0f);
CalculatedIndex /= 64.0f;
DynamicMaterial->SetVectorParameterValue(IndexParameterName, CalculatedIndex);
DynamicMaterial->SetTextureParameterValue(TextureParameterName, Texture);
}
}
*/
\ No newline at end of file
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "UObject/NoExportTypes.h"
#include "DynamicTextureUtilities.generated.h"
/**
*
*/
UCLASS()
class MASTERTESTPROJECT_API UDynamicTextureUtilities : public UObject
{
GENERATED_BODY()
//https://answers.unrealengine.com/questions/288012/is-it-possible-to-create-textures-dynamically.html
public:
// Create a dynamic texture intended to be used for passing non-texture data
// into materials. Defaults to 32-bit RGBA. The texture is not added to the
// root set, so something else will need to hold a reference to it.
static UTexture2D* CreateTransientDynamicTexture(int32 Width, int32 Height, EPixelFormat PixelFormat = PF_A32B32G32R32F);
// Updates a region of a texture with the supplied input data. Does nothing
// if the pixel formats do not match.
static void UpdateTextureRegion(UTexture2D* Texture, int32 MipIndex, FUpdateTextureRegion2D Region, uint32 SrcPitch, uint32 SrcBpp, uint8* SrcData, bool bFreeData);
// Convenience wrapper for updating a dynamic texture with an array of
// FLinearColors.
static void UpdateDynamicVectorTexture(const TArray<FLinearColor>& Source, UTexture2D* Texture);
// Sets up a component's material instance parameters (on all materials) for
// use with the supplied UTexture. The proper parameters (specified by
// IndexParameterName and TextureParameterName) should exist on the
// material, otherwise this will not have the proper effect.
//static void SetDynamicTextureAndIndex(class UStaticMeshComponent* Component, class UTexture2D* Texture, int32 Index, FName IndexParameterName, FName TextureParameterName);
};
...@@ -28,8 +28,6 @@ namespace tinygltf ...@@ -28,8 +28,6 @@ namespace tinygltf
typedef struct MATERIAL Material; typedef struct MATERIAL Material;
} }
struct FRawMesh;
/** /**
* *
*/ */
...@@ -57,55 +55,6 @@ private: ...@@ -57,55 +55,6 @@ private:
bool tinygltfLoadSuccess; bool tinygltfLoadSuccess;
FString tinygltfError; FString tinygltfError;
void ImportNodes(std::vector<std::string> nodes, FRawMesh& RawMesh, FMatrix ModelTransform);
/// Returns the transform of a node relative to its parent.
FMatrix GetNodeTransform(tinygltf::Node* Node);
//Copy methods
/// @name Level 3: GetBufferData
///@{
/// Fills a TArray with typed data; works at the glTF Accessor level and figures out which arguments to send to <B>BufferCopy()</B>.
/// @param OutArray The array to fill with data from the imported file.
/// @param Accessor A pointer to a glTF Accessor containing the type data for the geometry attribute.
/// @param Append Whether to add to the array or overwrite the elements currently in it.
//template <typename T> bool GetBufferData (TArray<T> &OutArray, tinygltf::Accessor* Accessor, bool Append = true);
///@}
/// @name Level 1: BufferValue
///@{
/// Obtains a single value from the geometry data buffer, accounting for endianness.
/// Adapted from http://stackoverflow.com/questions/13001183/how-to-read-little-endian-integers-from-file-in-c
/// @param Data A pointer to the raw data to cast to the desired type.
/// @return The typed data value.
template <typename T> T BufferValue(void* Data);
///@}
/// @name Level 2: BufferCopy
///@{
/// Handles filling the TArray at the data type level.
/// @param OutArray The array to fill with data from the imported file.
/// @param Data A pointer to the raw data to use as the argument to <B>BufferValue()</B>.
/// @param Count The number of elements to add to the array i.e. the number of calls to <B>BufferValue()</B>.
/// @param Stride The number of bytes between the first byte of each element - usually the size of one element.
template <typename SrcType, typename DstType> void BufferCopy(TArray<DstType> &OutArray, unsigned char* Data, int32 Count, size_t Stride);
template <typename SrcType> void BufferCopy(TArray<FVector2D> &OutArray, unsigned char* Data, int32 Count, size_t Stride);
template <typename SrcType> void BufferCopy(TArray<FVector> &OutArray, unsigned char* Data, int32 Count, size_t Stride);
template <typename SrcType> void BufferCopy(TArray<FVector4> &OutArray, unsigned char* Data, int32 Count, size_t Stride);
///@}
/// @name Level 3: GetBufferData
///@{
/// Fills a TArray with typed data; works at the glTF Accessor level and figures out which arguments to send to <B>BufferCopy()</B>.
/// @param OutArray The array to fill with data from the imported file.
/// @param Accessor A pointer to a glTF Accessor containing the type data for the geometry attribute.
/// @param Append Whether to add to the array or overwrite the elements currently in it.
template <typename DstType> bool GetBufferData(TArray<DstType> &OutArray, tinygltf::Accessor* Accessor, bool Append = true);
///@}
void ImportNodes(std::vector<std::string> nodes, FRawMesh& RawMesh, FMatrix ModelTransform); void ImportNodes(std::vector<std::string> nodes, FRawMesh& RawMesh, FMatrix ModelTransform);
......
...@@ -20,7 +20,7 @@ public class MasterTestProject : ModuleRules ...@@ -20,7 +20,7 @@ public class MasterTestProject : ModuleRules
public MasterTestProject(TargetInfo Target) public MasterTestProject(TargetInfo Target)
{ {
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "ImageWrapper", "RawMesh", "HTTP", "Json", "JsonUtilities", "ProceduralMeshComponent" }); PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "ImageWrapper", "RawMesh", "HTTP", "Json", "JsonUtilities", "ProceduralMeshComponent", "RHI", "RenderCore" });
PrivateDependencyModuleNames.AddRange(new string[] { }); PrivateDependencyModuleNames.AddRange(new string[] { });
......
...@@ -140,14 +140,14 @@ void ATilesetActor::updateScreenSpaceError(FTile* current, double currentSSE, do ...@@ -140,14 +140,14 @@ void ATilesetActor::updateScreenSpaceError(FTile* current, double currentSSE, do
{ {
updateScreenSpaceError(child, 0, constant, CamLocation); updateScreenSpaceError(child, 0, constant, CamLocation);
} }
current->setVisible(false); current->setVisible(true);//FIXME
} }
else { else {
current->setVisible(true); current->setVisible(true);
for (FTile* child : current->children) for (FTile* child : current->children)
{ {
child->setVisible(false); child->setVisible(true);//FIXME
} }
//UE_LOG(TILES, Error, TEXT("Set Visible %s SSError= %f"), *current->content.url, ScreenSpaceError1); //UE_LOG(TILES, Error, TEXT("Set Visible %s SSError= %f"), *current->content.url, ScreenSpaceError1);
...@@ -331,12 +331,52 @@ void ATilesetActor::parseInstanced3DTile(const TArray<uint8> data, FTile * tile) ...@@ -331,12 +331,52 @@ void ATilesetActor::parseInstanced3DTile(const TArray<uint8> data, FTile * tile)
tile->setVisible(false); tile->setVisible(false);
} }
void ATilesetActor::parsePointCloudTile(const TArray<uint8> data, FTile * tile)
{
PointCloudHeader *pntheader = (PointCloudHeader*)data.GetData();
FString featureJSONString = pntheader->getpartAsString(pntheader->getFeatureStart(), pntheader->featureTable.featureTableJSONByteLength);
UE_LOG(TILES, Warning, TEXT("PointCloudHeader: FeatureTable JSON: %s"), *featureJSONString);
TSharedPtr<FJsonObject> FeatureTableJSON;
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(featureJSONString);
if (FJsonSerializer::Deserialize(JsonReader, FeatureTableJSON))
{
int32 instances_length = FeatureTableJSON->GetIntegerField("POINTS_LENGTH");
UWorld* const World = GetWorld();
if (World)
{
if (FeatureTableJSON->HasField("POSITION")) {
uint32 featureTableBinaryOffset = pntheader->getFeatureStart() + pntheader->featureTable.featureTableJSONByteLength;
TSharedPtr<FJsonObject> binaryBodyReference = FeatureTableJSON->GetObjectField("POSITION");
int32 byteOffset = binaryBodyReference->GetIntegerField("byteOffset");
/*
TArray<FVector> positons = getAsArray<FVector>(data.GetData(), (int32)(featureTableBinaryOffset + byteOffset), instances_length);
FString outputString = "[";
for (FVector pos : positons)
{
outputString += "[" + pos.ToString() + "] ";
}
outputString += "]";
UE_LOG(TILES, Warning, TEXT("PointCloudHeader 3D Model Positions %s"), *outputString);*/
}
else {
UE_LOG(TILES, Error, TEXT("Pointcloud Quantized not supported"));
}
}
}
UE_LOG(TILES, Log, TEXT("PointCloudHeader: End"));
}
void ATilesetActor::parse3DTile(const TArray<uint8> data, FTile *tile) void ATilesetActor::parse3DTile(const TArray<uint8> data, FTile *tile)
{ {
TileHeader *header = (TileHeader*) data.GetData(); TileHeader *header = (TileHeader*) data.GetData();
tile->content.content = data; tile->content.content = data;
UE_LOG(TILES, Warning, TEXT("Shared Tile Header: Magic: %s Version %d lenght %d, array lenght %d "), *header->getMagicAsFString(), header->version, header->byteLength, data.Num()); UE_LOG(TILES, Log, TEXT("Shared Tile Header: Magic: %s Version %d lenght %d, array lenght %d "), *header->getMagicAsFString(), header->version, header->byteLength, data.Num());
if (header->isB3DM()) { if (header->isB3DM()) {
parseBatched3DTile(data, tile); parseBatched3DTile(data, tile);
...@@ -344,6 +384,9 @@ void ATilesetActor::parse3DTile(const TArray<uint8> data, FTile *tile) ...@@ -344,6 +384,9 @@ void ATilesetActor::parse3DTile(const TArray<uint8> data, FTile *tile)
else if (header->isI3DM()) { else if (header->isI3DM()) {
parseInstanced3DTile(data, tile); parseInstanced3DTile(data, tile);
} }
else if (header->isPNTS()) {
parsePointCloudTile(data, tile);
}
} }
...@@ -405,7 +448,7 @@ float FBoundingVolume::getDistanceTo(FVector Position, FMatrix bouindingTransfor ...@@ -405,7 +448,7 @@ float FBoundingVolume::getDistanceTo(FVector Position, FMatrix bouindingTransfor
FVector ZAxis = FVector(box[9], box[10], box[11]); FVector ZAxis = FVector(box[9], box[10], box[11]);
//TODO FIXME is currently spher distance //TODO FIXME is currently spher distance
UE_LOG(TILES, Error, TEXT("Box distance is not implemented")); //UE_LOG(TILES, Error, TEXT("Box distance is not implemented"));
double dist = (localPos - Center).Size(); double dist = (localPos - Center).Size();
distance = dist - FMath::Max3(XAxis.Size(), YAxis.Size(), ZAxis.Size()); distance = dist - FMath::Max3(XAxis.Size(), YAxis.Size(), ZAxis.Size());
...@@ -413,7 +456,7 @@ float FBoundingVolume::getDistanceTo(FVector Position, FMatrix bouindingTransfor ...@@ -413,7 +456,7 @@ float FBoundingVolume::getDistanceTo(FVector Position, FMatrix bouindingTransfor
else if (region.Num() == 6) { else if (region.Num() == 6) {
// WGS84 // WGS84
//TODO FIXME is currently spher distance //TODO FIXME is currently spher distance
UE_LOG(TILES, Error, TEXT("Region distance is not implemented")); //UE_LOG(TILES, Error, TEXT("Region distance is not implemented"));
FVector Center = FVector(0, 0, 6378137); FVector Center = FVector(0, 0, 6378137);
double dist = (Position - Center).Size(); double dist = (Position - Center).Size();
distance = dist; distance = dist;
......
...@@ -276,18 +276,43 @@ struct Instanced3DModelHeader { ...@@ -276,18 +276,43 @@ struct Instanced3DModelHeader {
} }
FString getpartAsString(int start, int lenght) { FString getpartAsString(int start, int lenght) {
if (lenght > 2048) { lenght = 2048; } char *ansiiData = new char[lenght + 1];
char ansiiData[2048 + 1]; //A temp buffer for the data
memcpy(ansiiData, (void*)(((uint8*)this)+start), lenght); //Assumes bytesRead is always smaller than 1024 bytes memcpy(ansiiData, (void*)(((uint8*)this)+start), lenght); //Assumes bytesRead is always smaller than 1024 bytes
ansiiData[lenght] = 0; //Add null terminator ansiiData[lenght] = 0; //Add null terminator
return ANSI_TO_TCHAR(ansiiData); //Convert to FString FString temp = ANSI_TO_TCHAR(ansiiData); //Convert to FString
delete ansiiData;
return temp;
}
};
struct PointCloudHeader {
TileHeader general;
FeatureTableHeader featureTable;
BatchTableHeader batchTable;
uint32 getFeatureStart() {
return 28 /*headersize*/;
}
uint32 getBatchStart() {
return getFeatureStart() + featureTable.length();
}
FString getpartAsString(int start, int lenght) {
char *ansiiData = new char[lenght + 1];
memcpy(ansiiData, (void*)(((uint8*)this) + start), lenght); //Assumes bytesRead is always smaller than 1024 bytes
ansiiData[lenght] = 0; //Add null terminator
FString temp = ANSI_TO_TCHAR(ansiiData); //Convert to FString
delete ansiiData;
return temp;
} }
}; };
/** /**
* *
*/ */
...@@ -329,6 +354,7 @@ private: ...@@ -329,6 +354,7 @@ private:
void parseBatched3DTile(const TArray<uint8> data, FTile *tile); void parseBatched3DTile(const TArray<uint8> data, FTile *tile);
void parseInstanced3DTile(const TArray<uint8> data, FTile *tile); void parseInstanced3DTile(const TArray<uint8> data, FTile *tile);
void parsePointCloudTile(const TArray<uint8> data, FTile *tile);
template <typename T> TArray<T> getAsArray(const uint8* data, int32 offset, int32 numberOfElements); template <typename T> TArray<T> getAsArray(const uint8* data, int32 offset, int32 numberOfElements);
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment