diff --git a/Content/Interaction/DomeDispay_BP.uasset b/Content/Interaction/DomeDispay_BP.uasset new file mode 100644 index 0000000000000000000000000000000000000000..c6a526e2e4dbad357b3a515bc76ab3b1d8c92db9 --- /dev/null +++ b/Content/Interaction/DomeDispay_BP.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2928cfb222bb8eb20fa8885353effd679e621e3bc974773803ef2ae67bb554f5 +size 34674 diff --git a/Content/Interaction/FulldomeMasterGrid.uasset b/Content/Interaction/FulldomeMasterGrid.uasset new file mode 100644 index 0000000000000000000000000000000000000000..2d145b39430a9f4adcb44355a0c29356c95c364f --- /dev/null +++ b/Content/Interaction/FulldomeMasterGrid.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8b6848483e3fcaccda4667e35437ca10de414700ef071eb3229cc4ebded5162 +size 1996778 diff --git a/Content/Interaction/MI_DomeDisplayGeneric.uasset b/Content/Interaction/MI_DomeDisplayGeneric.uasset new file mode 100644 index 0000000000000000000000000000000000000000..3e925d479aabfb46126b813522bdfa8024f5e375 --- /dev/null +++ b/Content/Interaction/MI_DomeDisplayGeneric.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4eab88f1f0d7a3b2d02fe5ea604f1cef5214f20fc4ae3007e5fb4f817d969320 +size 132242 diff --git a/Content/Interaction/M_DomeDisplay.uasset b/Content/Interaction/M_DomeDisplay.uasset new file mode 100644 index 0000000000000000000000000000000000000000..859ae9c02f754808010a12ae799bd4e57c7600bf --- /dev/null +++ b/Content/Interaction/M_DomeDisplay.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:251fddde1ec9572bd5236ffb6bcca5b75468fd6e3bb15f6ff9dbfe91f3ff13e8 +size 103358 diff --git a/Content/Levels/ViewerMain.umap b/Content/Levels/ViewerMain.umap index bbef24363cb6fcdf00ca3c15a32604beb4839b12..04109777cc0956326c2faf722ce44010cf99f9ab 100644 --- a/Content/Levels/ViewerMain.umap +++ b/Content/Levels/ViewerMain.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3aa7ddaf955bb854612b90c4bb6db93af855222f0c36f080773bc0ed412609f -size 639326 +oid sha256:d5c22f25887f895a877ce9bd4418164898405ceec6eb8e9bcacc7d4ff0e4d9f1 +size 5042957 diff --git a/Content/Levels/ViewerMain_BuiltData.uasset b/Content/Levels/ViewerMain_BuiltData.uasset index d5f0195db966373c9019841118ba5632cb78ae71..185789077d91560ab2965f3725ab32266c6a6f97 100644 --- a/Content/Levels/ViewerMain_BuiltData.uasset +++ b/Content/Levels/ViewerMain_BuiltData.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:861f079ee62fb01f4d1a07378770a6b8b52e489e03da56c175d4a60a99c81371 +oid sha256:c2490fe53943792e9bcb8351d8f426c540a75d69e2633887bc8360497e92be3b size 1134373 diff --git a/Source/DomeViewerVR/DomeViewerVR.cpp b/Source/DomeViewerVR/DomeViewerVR.cpp index 7463fa938a1839f5a9bf618da8ad553d6252e8da..f2adc9438c42b995d48e86f897de43c6bedf5e94 100644 --- a/Source/DomeViewerVR/DomeViewerVR.cpp +++ b/Source/DomeViewerVR/DomeViewerVR.cpp @@ -4,3 +4,5 @@ #include "Modules/ModuleManager.h" IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, DomeViewerVR, "DomeViewerVR" ); + +DEFINE_LOG_CATEGORY(DomeViewer); diff --git a/Source/DomeViewerVR/DomeViewerVR.h b/Source/DomeViewerVR/DomeViewerVR.h index 90aad9e7e22f143662bdcb74de4ca59ffc4f7321..e991e40bbd7ca2fa24463fdfb1615101be3131ab 100644 --- a/Source/DomeViewerVR/DomeViewerVR.h +++ b/Source/DomeViewerVR/DomeViewerVR.h @@ -4,3 +4,4 @@ #include "CoreMinimal.h" +DECLARE_LOG_CATEGORY_EXTERN(DomeViewer, Verbose, All); diff --git a/Source/DomeViewerVR/Private/DomeDisplayComponent.cpp b/Source/DomeViewerVR/Private/DomeDisplayComponent.cpp index 2437c1d827cf4f490b6c67d87b5513c762ff3922..f5645e0ecc6117f319ad65177cb612bcba23f2c7 100644 --- a/Source/DomeViewerVR/Private/DomeDisplayComponent.cpp +++ b/Source/DomeViewerVR/Private/DomeDisplayComponent.cpp @@ -1,5 +1,155 @@ -// Fill out your copyright notice in the Description page of Project Settings. +// Copyright 2019 Patric Ljung +// Linkoping University, Media and Information Technology, Visualization Center C +// License: BSD-3-Clause (https://opensource.org/licenses/BSD-3-Clause) #include "DomeDisplayComponent.h" +#include "Math/UnrealMath.h" +#include "DomeViewerVR.h" // For the log category +//UDomeDisplayComponent::UDomeDisplayComponent(const FObjectInitializer & ObjectInitializer) +//: Super(ObjectInitializer) +//{ +// Radius = 750.0f; +// TiltAngle = 27.0f; +// HemisphereDegrees = 170.0f; +// MeshEdgeDegrees = 3.6f; +// Material = nullptr; +// +// BuildDomeMesh(); +// +// bUseComplexAsSimpleCollision = true; // Since it is concave +// +// CreateMeshSection(0, MeshVerts, MeshTris, MeshNormals, MeshUVs, MeshColors, MeshTangents, true); +//} + +UDomeDisplayComponent::UDomeDisplayComponent() +{ + Radius = 750.0f; + TiltAngle = 27.0f; + HemisphereDegrees = 170.0f; + MeshEdgeDegrees = 3.6f; + Material = nullptr; + + DomeMesh = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("DomeMesh")); + DomeMesh->SetupAttachment(this); + + //BuildDomeMesh(); + + //bUseComplexAsSimpleCollision = true; // Since it is concave + + //CreateMeshSection(0, MeshVerts, MeshTris, MeshNormals, MeshUVs, MeshColors, MeshTangents, true); +} + +UDomeDisplayComponent::~UDomeDisplayComponent() +{ + Material = nullptr; +} + +#define PI_2 (2.0f * PI) + +void UDomeDisplayComponent::BuildDomeMesh() +{ + int numLatSections = 1 + int(HemisphereDegrees / MeshEdgeDegrees / 2.0f); + int numLonSections = 1 + int(360.0f / MeshEdgeDegrees); + + // DEBUG: Just make it simpler for debugging + //numLatSections = 2; + + UE_LOG(DomeViewer, Display, TEXT("BuildDomeMesh: LatSections %d, LonSections: %d"), numLatSections, numLonSections); + + const FVector forward = FVector(1.0f, 0.0f, 0.0f); + const FVector right = FVector(0.0f, 1.0f, 0.0f); + const FVector up = FVector(0.0f, 0.0f, 1.0f); + + int numVerts = 1 + numLatSections * numLonSections; + MeshVerts.Reserve(numVerts); + MeshUVs.Reserve(numVerts); + MeshTris.Reserve(3*numVerts); // TODO: Resolve real number of triangles + + const float deltaLatRads = (PI * HemisphereDegrees / 360.0f) / float(numLatSections - 1); + const float deltaLonRads = PI_2 / float(numLonSections); + + // Compute the vertices, starting at top + MeshVerts.Add(up * Radius); + MeshNormals.Add(-up); + //MeshTangents.Add(right); + + for (int latIdx = 1; latIdx < numLatSections; ++latIdx) + { + float latAngle = latIdx * deltaLatRads; + float latSin = sin(latAngle); + float latCos = cos(latAngle); + FVector upLoc = up * latCos; + + for (int lonIdx = 0; lonIdx < numLonSections; ++lonIdx) + { + float lonSin = sin(lonIdx * PI_2 / numLonSections); + float lonCos = cos(lonIdx * PI_2 / numLonSections); + FVector unitDir(forward * (latSin * lonCos) + + right * (latSin * lonSin) + upLoc); + MeshVerts.Add(unitDir * Radius); + MeshNormals.Add(-unitDir); + } + } + + // Compute mesh UVs, starting at the center + const FVector2D uvCenter(0.5f, 0.5f); + MeshUVs.Add(uvCenter); + + for (int latIdx = 1; latIdx < numLatSections; ++latIdx) + { + float uvRadius = 0.5f * float(latIdx) / float(numLatSections - 1); + + for (int lonIdx = 0; lonIdx < numLonSections; ++lonIdx) + { + float lonAngle = lonIdx * deltaLonRads; + MeshUVs.Add(uvCenter + uvRadius * FVector2D(sin(lonAngle), cos(lonAngle))); + } + } + + // Compute the triangle indices + // ... first the cap + for (int lonIdx = 0; lonIdx < numLonSections; ++lonIdx) + { + // Counter clock-wise, triangle fan + MeshTris.Add(1 + lonIdx); + MeshTris.Add(1 + ((lonIdx + 1) % numLonSections)); + MeshTris.Add(0); + } + // ... then the rest + for (int latIdx = 1; latIdx < numLatSections - 1; ++latIdx) + { + int32 topBase = 1 + (latIdx - 1) * numLonSections; + int32 bottomBase = 1 + latIdx * numLonSections; + + for (int lonIdx = 0; lonIdx < numLonSections; ++lonIdx) + { + // Make quads, two triangles + // Counter clock-wise + MeshTris.Add(bottomBase + lonIdx); + MeshTris.Add(bottomBase + (lonIdx + 1) % numLonSections); + MeshTris.Add(topBase + lonIdx); + + MeshTris.Add(bottomBase + (lonIdx + 1) % numLonSections); + MeshTris.Add(topBase + (lonIdx + 1) % numLonSections); + MeshTris.Add(topBase + lonIdx); + } + } +} + +bool UDomeDisplayComponent::UpdateDomeMesh() +{ + BuildDomeMesh(); + + DomeMesh->CreateMeshSection(0, MeshVerts, MeshTris, MeshNormals, MeshUVs, MeshColors, MeshTangents, false); + + if (Material != nullptr) + { + DomeMesh->SetMaterial(0, Material); + } + + DomeMesh->SetRelativeRotation(FRotator(-TiltAngle, 0.0f, 0.0f)); + + return true; +} diff --git a/Source/DomeViewerVR/Public/DomeDisplayComponent.h b/Source/DomeViewerVR/Public/DomeDisplayComponent.h index 0b9a05a817a7412d5d9308a0a408271c375c5df4..818b226b54f442cca67ddef92a2c619a1fd4c002 100644 --- a/Source/DomeViewerVR/Public/DomeDisplayComponent.h +++ b/Source/DomeViewerVR/Public/DomeDisplayComponent.h @@ -1,17 +1,69 @@ -// Fill out your copyright notice in the Description page of Project Settings. +// Copyright 2019 Patric Ljung +// Linkoping University, Media and Information Technology, Visualization Center C +// License: BSD-3-Clause (https://opensource.org/licenses/BSD-3-Clause) #pragma once #include "CoreMinimal.h" #include "ProceduralMeshComponent.h" +// TODO: Move to .cpp file and provide forward declaration here instead +#include "Materials/MaterialInterface.h" + #include "DomeDisplayComponent.generated.h" /** * */ -UCLASS() -class DOMEVIEWERVR_API UDomeDisplayComponent : public UProceduralMeshComponent +UCLASS(BlueprintType, Category = "Dome", + Meta = (BlueprintSpawnableComponent, Tooltip = "A component that dynamically creates a UV-mapped dome hemisphere mesh")) +class DOMEVIEWERVR_API UDomeDisplayComponent : public USceneComponent { GENERATED_BODY() +public: + UDomeDisplayComponent(); + ~UDomeDisplayComponent(); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dome", + Meta = (Tooltip = "The radius of the dome")) + float Radius; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dome", + Meta = (Tooltip = "How many degrees is the dome tilted forward")) + float TiltAngle; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dome", + Meta = (Tooltip = "How many degrees the hemisphere spans, 180 degrees makes it a full hemishphere")) + float HemisphereDegrees; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dome", + Meta = (Tooltip = "Mesh resolution, degrees per bottom edge")) + float MeshEdgeDegrees; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Dome", + Meta = (Tooltip = "Dome display mesh material")) + UMaterialInterface * Material; + +// UPROPERTY(EditAnywhere, BlueprintRead, Category = "Dome", +// Meta = (Tooltip = "Dome display mesh material")) + UPROPERTY() + UProceduralMeshComponent * DomeMesh; + +public: + UFUNCTION(BlueprintCallable, Category = "Dome", + Meta = (Tooltip = "Update the dome mesh using current settings")) + bool UpdateDomeMesh(); + +protected: + // TODO: Add method to capture editor changes and call BuildDomeMesh + + void BuildDomeMesh(); + + TArray<FVector> MeshVerts; + TArray<int32> MeshTris; + TArray<FVector> MeshNormals; + TArray<FVector2D> MeshUVs; + TArray<FColor> MeshColors; + TArray<FProcMeshTangent> MeshTangents; + };