Skip to content
Snippets Groups Projects
Commit e47e0f4c authored by Patric Ljung's avatar Patric Ljung
Browse files

Implemented DomeDisplayComponent that uses ProceduralMeshComponent to produce...

Implemented DomeDisplayComponent that uses ProceduralMeshComponent to produce a Dome Mesh with UV-mapping. Also added materials for the dome display, still a test texture and no video. Tangents are yet not computed for the vertices, might need to create multiple points at the top to get proper tangents.
parent b2317ce8
No related branches found
No related tags found
No related merge requests found
File added
File added
File added
File added
No preview for this file type
No preview for this file type
......@@ -4,3 +4,5 @@
#include "Modules/ModuleManager.h"
IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, DomeViewerVR, "DomeViewerVR" );
DEFINE_LOG_CATEGORY(DomeViewer);
......@@ -4,3 +4,4 @@
#include "CoreMinimal.h"
DECLARE_LOG_CATEGORY_EXTERN(DomeViewer, Verbose, All);
// 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;
}
// 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;
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment