Compare commits
3 Commits
box
...
development
| Author | SHA1 | Date | |
|---|---|---|---|
| 48178976ff | |||
| 8621559176 | |||
| 20f4c23a6e |
Binary file not shown.
Binary file not shown.
+6
-3
@@ -3,13 +3,16 @@
|
||||
|
||||
#include "SpeckleUnrealLayer.h"
|
||||
|
||||
USpeckleUnrealLayer::USpeckleUnrealLayer()
|
||||
ASpeckleUnrealLayer::ASpeckleUnrealLayer()
|
||||
{
|
||||
|
||||
Scene = CreateDefaultSubobject<USceneComponent>("Root");
|
||||
RootComponent = Scene;
|
||||
}
|
||||
|
||||
void USpeckleUnrealLayer::Init(FString NewLayerName, int32 NewStartIndex, int32 NewObjectCount)
|
||||
void ASpeckleUnrealLayer::Init(FString NewLayerName, int32 NewStartIndex, int32 NewObjectCount)
|
||||
{
|
||||
SetActorLabel(NewLayerName);
|
||||
|
||||
LayerName = NewLayerName;
|
||||
LayerColor = FLinearColor(FMath::FRandRange(0, 1), FMath::FRandRange(0, 1), FMath::FRandRange(0, 1), 1);
|
||||
StartIndex = NewStartIndex;
|
||||
|
||||
+2
-2
@@ -89,7 +89,7 @@ void ASpeckleUnrealManager::OnStreamResponseReceived(FHttpRequestPtr Request, FH
|
||||
ScaleFactor = 2.5399986;
|
||||
|
||||
TArray<TSharedPtr<FJsonValue>> LayersInStream = Stream->GetArrayField("layers");
|
||||
SpeckleUnrealLayers = TArray<USpeckleUnrealLayer*>();
|
||||
SpeckleUnrealLayers = TArray<ASpeckleUnrealLayer*>();
|
||||
|
||||
for (size_t i = 0; i < LayersInStream.Num(); i++)
|
||||
{
|
||||
@@ -100,7 +100,7 @@ void ASpeckleUnrealManager::OnStreamResponseReceived(FHttpRequestPtr Request, FH
|
||||
int32 ObjectCount = LayerObject->GetIntegerField("objectCount");
|
||||
|
||||
//USpeckleUnrealLayer NewLayer = USpeckleUnrealLayer(LayerName, StartIndex, ObjectCount);
|
||||
USpeckleUnrealLayer* NewLayer = NewObject<USpeckleUnrealLayer> (this);
|
||||
ASpeckleUnrealLayer* NewLayer = (ASpeckleUnrealLayer*)World->SpawnActor(ASpeckleUnrealLayer::StaticClass());
|
||||
NewLayer->Init(LayerName, StartIndex, ObjectCount);
|
||||
SpeckleUnrealLayers.Add(NewLayer);
|
||||
}
|
||||
|
||||
+304
@@ -0,0 +1,304 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "SpeckleUnrealReceiver.h"
|
||||
|
||||
|
||||
// Sets default values
|
||||
USpeckleUnrealReceiver::USpeckleUnrealReceiver()
|
||||
{
|
||||
//When the object is constructed, Get the HTTP module
|
||||
Http = &FHttpModule::Get();
|
||||
// default conversion is millimeters to centimeters because streams tend to be in ml and unreal is in cm by defaults
|
||||
ScaleFactor = 0.1;
|
||||
}
|
||||
|
||||
void USpeckleUnrealReceiver::SetUpGetRequest(TSharedRef<IHttpRequest> Request)
|
||||
{
|
||||
Request->SetVerb("GET");
|
||||
Request->SetHeader("Content-Type", TEXT("application/json"));
|
||||
Request->SetHeader("Authorization", AuthToken);
|
||||
}
|
||||
|
||||
/*Http call*/
|
||||
void USpeckleUnrealReceiver::ReceiveStream()
|
||||
{
|
||||
World = GetWorld();
|
||||
|
||||
GEngine->AddOnScreenDebugMessage(0, 5.0f, FColor::Green, "Downloading: " + StreamID);
|
||||
|
||||
TSharedRef<IHttpRequest> Request = Http->CreateRequest();
|
||||
|
||||
SetUpGetRequest(Request);
|
||||
|
||||
Request->OnProcessRequestComplete().BindUObject(this, &USpeckleUnrealReceiver::OnStreamResponseReceived);
|
||||
|
||||
//This is the url on which to process the request
|
||||
Request->SetURL(ServerUrl + "streams/" + StreamID);
|
||||
|
||||
Request->ProcessRequest();
|
||||
}
|
||||
|
||||
/*Assigned function on successfull http call*/
|
||||
void USpeckleUnrealReceiver::OnStreamResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
|
||||
{
|
||||
if (!bWasSuccessful)
|
||||
{
|
||||
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red, "Stream Request failed");
|
||||
return;
|
||||
}
|
||||
|
||||
//Create a pointer to hold the json serialized data
|
||||
TSharedPtr<FJsonObject> ResponseJsonObject;
|
||||
|
||||
//Create a reader pointer to read the json data
|
||||
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Response->GetContentAsString());
|
||||
|
||||
//Deserialize the json data given Reader and the actual object to deserialize
|
||||
if (FJsonSerializer::Deserialize(Reader, ResponseJsonObject))
|
||||
{
|
||||
//Get the value of the json object by field name
|
||||
FString ResponseMessage = ResponseJsonObject->GetStringField("message");
|
||||
TSharedPtr<FJsonObject> Stream = ResponseJsonObject->GetObjectField("resource");
|
||||
FString StreamName = Stream->GetStringField("name");
|
||||
FString StreamDescription = Stream->GetStringField("description");
|
||||
|
||||
FString Units = ResponseJsonObject->GetObjectField("baseProperties")->GetStringField("units").ToLower();
|
||||
|
||||
// unreal engine units are in cm by default but the conversion is editable by users so
|
||||
// this needs to be accounted for later.
|
||||
if (Units == "meters" || Units == "metres")
|
||||
ScaleFactor = 100;
|
||||
|
||||
if (Units == "centimeters" || Units == "centimetres")
|
||||
ScaleFactor = 1;
|
||||
|
||||
if (Units == "millimeters" || Units == "millimetres")
|
||||
ScaleFactor = 0.1;
|
||||
|
||||
if (Units == "yards")
|
||||
ScaleFactor = 91.4402757;
|
||||
|
||||
if (Units == "feet")
|
||||
ScaleFactor = 30.4799990;
|
||||
|
||||
if (Units == "inches")
|
||||
ScaleFactor = 2.5399986;
|
||||
|
||||
TArray<TSharedPtr<FJsonValue>> LayersInStream = Stream->GetArrayField("layers");
|
||||
SpeckleUnrealLayers = TArray<ASpeckleUnrealLayer*>();
|
||||
|
||||
for (size_t i = 0; i < LayersInStream.Num(); i++)
|
||||
{
|
||||
TSharedPtr<FJsonObject> LayerObject = LayersInStream[i]->AsObject();
|
||||
|
||||
ASpeckleUnrealLayer* NewLayer = (ASpeckleUnrealLayer*)World->SpawnActor(ASpeckleUnrealLayer::StaticClass());
|
||||
|
||||
FString LayerName = LayerObject->GetStringField("name");
|
||||
|
||||
if (LayerName.Contains("::"))
|
||||
{
|
||||
TArray<FString> Parsed = TArray<FString> ();
|
||||
int32 heirarchySize = LayerName.ParseIntoArray(Parsed, TEXT("::"), true);
|
||||
|
||||
LayerName = Parsed[heirarchySize - 1];
|
||||
FString ParentLayerName = Parsed[heirarchySize - 2];
|
||||
|
||||
for (size_t j = 0; j < SpeckleUnrealLayers.Num(); j++)
|
||||
{
|
||||
if (SpeckleUnrealLayers[j]->LayerName == ParentLayerName)
|
||||
{
|
||||
EAttachmentRule rule = EAttachmentRule();
|
||||
FAttachmentTransformRules rules = FAttachmentTransformRules(rule, false);
|
||||
NewLayer->AttachToActor(SpeckleUnrealLayers[j], rules);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32 StartIndex = LayerObject->GetIntegerField("startIndex");
|
||||
int32 ObjectCount = LayerObject->GetIntegerField("objectCount");
|
||||
|
||||
NewLayer->Init(LayerName, StartIndex, ObjectCount);
|
||||
SpeckleUnrealLayers.Add(NewLayer);
|
||||
}
|
||||
|
||||
//Output it to the engine
|
||||
GEngine->AddOnScreenDebugMessage(0, 5.0f, FColor::Green, "Units: " + FString::SanitizeFloat(ScaleFactor));
|
||||
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Green, "Status: " + ResponseMessage);
|
||||
GEngine->AddOnScreenDebugMessage(2, 5.0f, FColor::Green, "Name: " + StreamName);
|
||||
GEngine->AddOnScreenDebugMessage(3, 5.0f, FColor::Green, "Description: " + StreamDescription);
|
||||
|
||||
TArray<TSharedPtr<FJsonValue>> ObjectPlaceholderArray = Stream->GetArrayField("objects");
|
||||
|
||||
GetStreamObjects(ObjectPlaceholderArray.Num());
|
||||
}
|
||||
else
|
||||
{
|
||||
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red, "Couldn't deserialize Json from stream response");
|
||||
GEngine->AddOnScreenDebugMessage(2, 10.0f, FColor::Red, Response->GetContentAsString());
|
||||
}
|
||||
}
|
||||
|
||||
void USpeckleUnrealReceiver::GetStreamObjects(int32 objectCount)
|
||||
{
|
||||
ObjectsReceived = TArray<bool>();
|
||||
|
||||
int32 RequestLimit = 1;
|
||||
CurrentObjectIndex = 0;
|
||||
LayerIndex = 0;
|
||||
|
||||
for (size_t i = 0; i < objectCount; i += RequestLimit)
|
||||
{
|
||||
TSharedRef<IHttpRequest> Request = Http->CreateRequest();
|
||||
|
||||
SetUpGetRequest(Request);
|
||||
|
||||
Request->OnProcessRequestComplete().BindUObject(this, &USpeckleUnrealReceiver::OnStreamObjectResponseReceived);
|
||||
|
||||
//This is the url on which to process the request
|
||||
Request->SetURL(ServerUrl + "streams/" + StreamID + "/objects?limit=" + FString::FromInt(RequestLimit) + "&offset=" + FString::FromInt(i));
|
||||
|
||||
ObjectsReceived.Add(false);
|
||||
|
||||
Request->ProcessRequest();
|
||||
}
|
||||
}
|
||||
|
||||
void USpeckleUnrealReceiver::OnStreamObjectResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
|
||||
{
|
||||
int32 Offset = FCString::Atoi(*Request->GetURLParameter("offset"));
|
||||
|
||||
if (!bWasSuccessful)
|
||||
{
|
||||
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red, "Object Request failed");
|
||||
return;
|
||||
}
|
||||
|
||||
//Create a pointer to hold the json serialized data
|
||||
TSharedPtr<FJsonObject> ResponseJsonObject;
|
||||
|
||||
//Create a reader pointer to read the json data
|
||||
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(Response->GetContentAsString());
|
||||
|
||||
//Deserialize the json data given Reader and the actual object to deserialize
|
||||
if (FJsonSerializer::Deserialize(Reader, ResponseJsonObject))
|
||||
{
|
||||
//Get the value of the json object by field name
|
||||
TArray<TSharedPtr<FJsonValue>> StreamObjects = ResponseJsonObject->GetArrayField("resources");
|
||||
|
||||
for (size_t i = 0; i < SpeckleUnrealLayers.Num(); i++)
|
||||
{
|
||||
if (Offset >= SpeckleUnrealLayers[i]->StartIndex)
|
||||
{
|
||||
if (Offset < (SpeckleUnrealLayers[i]->StartIndex + SpeckleUnrealLayers[i]->ObjectCount))
|
||||
LayerIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < StreamObjects.Num(); i++)
|
||||
{
|
||||
TSharedPtr<FJsonObject> StreamObject = StreamObjects[i].Get()->AsObject();
|
||||
|
||||
TSharedPtr<FJsonObject> ObjectToConvert = StreamObject;
|
||||
|
||||
FString objectType = ObjectToConvert->GetStringField("type");
|
||||
|
||||
if (objectType.ToLower().Contains("brep"))
|
||||
{
|
||||
ObjectToConvert = StreamObject->GetObjectField("displayValue");
|
||||
|
||||
objectType = ObjectToConvert->GetStringField("type");
|
||||
}
|
||||
|
||||
if (objectType.ToLower().Contains("mesh"))
|
||||
{
|
||||
EAttachmentRule rule = EAttachmentRule();
|
||||
FAttachmentTransformRules rules = FAttachmentTransformRules(rule, false);
|
||||
|
||||
ASpeckleUnrealMesh* MeshInstance = World->SpawnActor<ASpeckleUnrealMesh>(ASpeckleUnrealMesh::StaticClass());
|
||||
|
||||
TArray<TSharedPtr<FJsonValue>> ObjectVertices = ObjectToConvert->GetArrayField("vertices");
|
||||
TArray<TSharedPtr<FJsonValue>> ObjectFaces = ObjectToConvert->GetArrayField("faces");
|
||||
|
||||
TArray<FVector> ParsedVerticies;
|
||||
|
||||
for (size_t j = 0; j < ObjectVertices.Num(); j += 3)
|
||||
{
|
||||
ParsedVerticies.Add(FVector
|
||||
(
|
||||
(float)(ObjectVertices[j].Get()->AsNumber()) * -1,
|
||||
(float)(ObjectVertices[j + 1].Get()->AsNumber()),
|
||||
(float)(ObjectVertices[j + 2].Get()->AsNumber())
|
||||
) * ScaleFactor);
|
||||
}
|
||||
|
||||
//convert mesh faces into triangle array regardless of whether or not they are quads
|
||||
TArray<int32> ParsedTriangles;
|
||||
int32 j = 0;
|
||||
while (j < ObjectFaces.Num())
|
||||
{
|
||||
if (ObjectFaces[j].Get()->AsNumber() == 0)
|
||||
{
|
||||
//Triangles
|
||||
ParsedTriangles.Add(ObjectFaces[j + 1].Get()->AsNumber());
|
||||
ParsedTriangles.Add(ObjectFaces[j + 3].Get()->AsNumber());
|
||||
ParsedTriangles.Add(ObjectFaces[j + 2].Get()->AsNumber());
|
||||
j += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Quads to triangles
|
||||
ParsedTriangles.Add(ObjectFaces[j + 1].Get()->AsNumber());
|
||||
ParsedTriangles.Add(ObjectFaces[j + 3].Get()->AsNumber());
|
||||
ParsedTriangles.Add(ObjectFaces[j + 2].Get()->AsNumber());
|
||||
|
||||
ParsedTriangles.Add(ObjectFaces[j + 3].Get()->AsNumber());
|
||||
ParsedTriangles.Add(ObjectFaces[j + 1].Get()->AsNumber());
|
||||
ParsedTriangles.Add(ObjectFaces[j + 4].Get()->AsNumber());
|
||||
|
||||
j += 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (RandomColorsPerLayer)
|
||||
MeshInstance->SetMesh(ParsedVerticies, ParsedTriangles, DefaultMeshMaterial, SpeckleUnrealLayers[LayerIndex]->LayerColor);
|
||||
else
|
||||
MeshInstance->SetMesh(ParsedVerticies, ParsedTriangles, DefaultMeshMaterial, FLinearColor::White);
|
||||
|
||||
MeshInstance->AttachToActor(SpeckleUnrealLayers[LayerIndex], rules);
|
||||
|
||||
UE_LOG(LogTemp, Warning, TEXT("%d"), Offset);
|
||||
UE_LOG(LogTemp, Warning, TEXT("%s"), *SpeckleUnrealLayers[LayerIndex]->LayerName);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red, "Couldn't deserialize Json from object response");
|
||||
GEngine->AddOnScreenDebugMessage(2, 10.0f, FColor::Red, Response->GetContentAsString());
|
||||
}
|
||||
|
||||
|
||||
ObjectsReceived[Offset] = true;
|
||||
}
|
||||
|
||||
float USpeckleUnrealReceiver::GetStreamProgress()
|
||||
{
|
||||
if (ObjectsReceived.Num() == 0)
|
||||
return 0;
|
||||
|
||||
float ProgressMade = 0;
|
||||
|
||||
for (size_t i = 0; i < ObjectsReceived.Num(); i++)
|
||||
{
|
||||
if (ObjectsReceived[i])
|
||||
ProgressMade++;
|
||||
}
|
||||
|
||||
return ProgressMade / ObjectsReceived.Num();
|
||||
}
|
||||
+6
-3
@@ -3,18 +3,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "SpeckleUnrealLayer.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(BlueprintType)
|
||||
class SPECKLEUNREAL_API USpeckleUnrealLayer : public UObject
|
||||
class SPECKLEUNREAL_API ASpeckleUnrealLayer : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(VisibleAnywhere)
|
||||
USceneComponent* Scene;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Speckle")
|
||||
FString LayerName;
|
||||
|
||||
@@ -27,7 +30,7 @@ public:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Speckle")
|
||||
int32 ObjectCount;
|
||||
|
||||
USpeckleUnrealLayer();
|
||||
ASpeckleUnrealLayer();
|
||||
|
||||
void Init(FString NewLayerName, int32 NewStartIndex, int32 NewObjectCount);
|
||||
};
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
|
||||
bool RandomColorsPerLayer;
|
||||
|
||||
TArray<USpeckleUnrealLayer*> SpeckleUnrealLayers;
|
||||
TArray<ASpeckleUnrealLayer*> SpeckleUnrealLayers;
|
||||
|
||||
/*Assign this function to call when the GET request processes sucessfully*/
|
||||
void OnStreamResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
|
||||
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
// logs
|
||||
#include "Engine/Engine.h"
|
||||
|
||||
// json manipulation
|
||||
#include "Dom/JsonObject.h"
|
||||
#include "Dom/JsonValue.h"
|
||||
#include "Serialization/JsonReader.h"
|
||||
#include "Serialization/JsonSerializer.h"
|
||||
|
||||
// web requests
|
||||
#include "Runtime/Online/HTTP/Public/Http.h"
|
||||
|
||||
#include "SpeckleUnrealMesh.h"
|
||||
#include "SpeckleUnrealLayer.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/NoExportTypes.h"
|
||||
#include "SpeckleUnrealReceiver.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(BlueprintType)
|
||||
class SPECKLEUNREAL_API USpeckleUnrealReceiver : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
FHttpModule* Http;
|
||||
|
||||
/* The actual HTTP call */
|
||||
UFUNCTION(BlueprintCallable, Category = "Speckle")
|
||||
void ReceiveStream();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Speckle")
|
||||
float GetStreamProgress();
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
|
||||
FString ServerUrl {
|
||||
"https://hestia.speckle.works/api/"
|
||||
};
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
|
||||
FString StreamID {
|
||||
""
|
||||
};
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
|
||||
FString AuthToken {
|
||||
""
|
||||
};
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
|
||||
TSubclassOf<ASpeckleUnrealMesh> MeshActor;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
|
||||
UMaterialInterface* DefaultMeshMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Speckle")
|
||||
bool RandomColorsPerLayer;
|
||||
|
||||
TArray<ASpeckleUnrealLayer*> SpeckleUnrealLayers;
|
||||
|
||||
/*Assign this function to call when the GET request processes sucessfully*/
|
||||
void OnStreamResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
|
||||
|
||||
// Sets default values for this actor's properties
|
||||
USpeckleUnrealReceiver();
|
||||
|
||||
protected:
|
||||
|
||||
UWorld* World;
|
||||
|
||||
float ScaleFactor;
|
||||
|
||||
TArray<bool> ObjectsReceived;
|
||||
|
||||
int32 LayerIndex;
|
||||
int32 CurrentObjectIndex;
|
||||
|
||||
void SetUpGetRequest(TSharedRef<IHttpRequest> Request);
|
||||
|
||||
void GetStreamObjects(int32 objectCount);
|
||||
|
||||
void OnStreamObjectResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
|
||||
};
|
||||
Reference in New Issue
Block a user