Skip to content

Commit

Permalink
Merge pull request #1432 from CesiumGS/custom-ellipsoid
Browse files Browse the repository at this point in the history
Add support for custom ellipsoids
  • Loading branch information
csciguy8 committed Jun 28, 2024
2 parents 3663041 + 27d80a7 commit 0c619da
Show file tree
Hide file tree
Showing 30 changed files with 908 additions and 180 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

### ? - ?

##### Additions :tada:
- Cesium for Unreal now supports using non-WGS84 ellipsoids.
- An `UCesiumEllipsoid` asset should be specified on the `Ellipsoid` field of an `ACesiumGeoreference`.
- To create a `UCesiumEllipsoid` asset, right-click in the Content Drawer and select "Data Asset" under "Miscellaneous." Choose "Cesium Ellipsoid" from the menu that appears.

##### Fixes :wrench:

- Removed unnecessary alpha check when selecting translucent base materials.
Expand Down
Binary file added Content/WGS84.uasset
Binary file not shown.
103 changes: 70 additions & 33 deletions Source/CesiumEditor/Private/CesiumGlobeAnchorCustomization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "DetailCategoryBuilder.h"
#include "DetailLayoutBuilder.h"
#include "IDetailGroup.h"
#include "Widgets/SToolTip.h"

FName FCesiumGlobeAnchorCustomization::RegisteredLayoutName;

Expand Down Expand Up @@ -201,32 +202,63 @@ void UCesiumGlobeAnchorDerivedProperties::PostEditChangeProperty(
this->GlobeAnchor->Modify();
this->GlobeAnchor->MoveToEarthCenteredEarthFixedPosition(
FVector(this->X, this->Y, this->Z));
} else if (
propertyName == GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Longitude) ||
propertyName == GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Latitude) ||
propertyName == GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Height)) {
this->GlobeAnchor->Modify();
this->GlobeAnchor->MoveToLongitudeLatitudeHeight(
FVector(this->Longitude, this->Latitude, this->Height));
} else if (
propertyName ==
GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Pitch) ||
propertyName ==
GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Yaw) ||
propertyName ==
GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Roll)) {
this->GlobeAnchor->Modify();
this->GlobeAnchor->SetEastSouthUpRotation(
FRotator(this->Pitch, this->Yaw, this->Roll).Quaternion());
} else if (true) {
if (propertyName == GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Longitude) ||
propertyName == GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Latitude) ||
propertyName == GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Height)) {
this->GlobeAnchor->Modify();
this->GlobeAnchor->MoveToLongitudeLatitudeHeight(
FVector(this->Longitude, this->Latitude, this->Height));
} else if (
propertyName == GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Pitch) ||
propertyName ==
GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Yaw) ||
propertyName == GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Roll)) {
this->GlobeAnchor->Modify();
this->GlobeAnchor->SetEastSouthUpRotation(
FRotator(this->Pitch, this->Yaw, this->Roll).Quaternion());
}
}
}

bool UCesiumGlobeAnchorDerivedProperties::CanEditChange(
const FProperty* InProperty) const {
const FName Name = InProperty->GetFName();

// Valid georeference, nothing to disable
if (IsValid(this->GlobeAnchor->ResolveGeoreference())) {
return true;
}

return Name != GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Longitude) &&
Name != GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Latitude) &&
Name != GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Height) &&
Name != GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Pitch) &&
Name != GET_MEMBER_NAME_CHECKED(
UCesiumGlobeAnchorDerivedProperties,
Yaw) &&
Name !=
GET_MEMBER_NAME_CHECKED(UCesiumGlobeAnchorDerivedProperties, Roll);
}

void UCesiumGlobeAnchorDerivedProperties::Initialize(
UCesiumGlobeAnchorComponent* GlobeAnchorComponent) {
this->GlobeAnchor = GlobeAnchorComponent;
Expand All @@ -240,16 +272,21 @@ void UCesiumGlobeAnchorDerivedProperties::Tick(float DeltaTime) {
this->Y = position.Y;
this->Z = position.Z;

FVector llh = this->GlobeAnchor->GetLongitudeLatitudeHeight();
this->Longitude = llh.X;
this->Latitude = llh.Y;
this->Height = llh.Z;

FQuat rotation = this->GlobeAnchor->GetEastSouthUpRotation();
FRotator rotator = rotation.Rotator();
this->Roll = rotator.Roll;
this->Pitch = rotator.Pitch;
this->Yaw = rotator.Yaw;
// We can't transform the GlobeAnchor's ECEF coordinates back to
// cartographic & rotation without a valid georeference to know what
// ellipsoid to use.
if (IsValid(this->GlobeAnchor->ResolveGeoreference())) {
FVector llh = this->GlobeAnchor->GetLongitudeLatitudeHeight();
this->Longitude = llh.X;
this->Latitude = llh.Y;
this->Height = llh.Z;

FQuat rotation = this->GlobeAnchor->GetEastSouthUpRotation();
FRotator rotator = rotation.Rotator();
this->Roll = rotator.Roll;
this->Pitch = rotator.Pitch;
this->Yaw = rotator.Yaw;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ class UCesiumGlobeAnchorDerivedProperties : public UObject,

virtual void PostEditChangeProperty(
struct FPropertyChangedEvent& PropertyChangedEvent) override;
virtual bool CanEditChange(const FProperty* InProperty) const override;

void Initialize(UCesiumGlobeAnchorComponent* GlobeAnchor);

Expand Down
51 changes: 43 additions & 8 deletions Source/CesiumRuntime/Private/Cesium3DTileset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ ACesiumGeoreference* ACesium3DTileset::ResolveGeoreference() {
this->ResolvedGeoreference->OnGeoreferenceUpdated.AddUniqueDynamic(
pRoot,
&UCesium3DTilesetRoot::HandleGeoreferenceUpdated);
this->ResolvedGeoreference->OnEllipsoidChanged.AddUniqueDynamic(
this,
&ACesium3DTileset::HandleOnGeoreferenceEllipsoidChanged);

// Update existing tile positions, if any.
pRoot->HandleGeoreferenceUpdated();
Expand Down Expand Up @@ -471,10 +474,14 @@ void ACesium3DTileset::OnFocusEditorViewportOnThis() {
*this->GetName());

struct CalculateECEFCameraPosition {
const CesiumGeospatial::Ellipsoid& ellipsoid;

glm::dvec3 operator()(const CesiumGeometry::BoundingSphere& sphere) {
const glm::dvec3& center = sphere.getCenter();
glm::dmat4 ENU =
CesiumGeospatial::GlobeTransforms::eastNorthUpToFixedFrame(center);
CesiumGeospatial::GlobeTransforms::eastNorthUpToFixedFrame(
center,
ellipsoid);
glm::dvec3 offset =
sphere.getRadius() *
glm::normalize(
Expand All @@ -487,7 +494,9 @@ void ACesium3DTileset::OnFocusEditorViewportOnThis() {
operator()(const CesiumGeometry::OrientedBoundingBox& orientedBoundingBox) {
const glm::dvec3& center = orientedBoundingBox.getCenter();
glm::dmat4 ENU =
CesiumGeospatial::GlobeTransforms::eastNorthUpToFixedFrame(center);
CesiumGeospatial::GlobeTransforms::eastNorthUpToFixedFrame(
center,
ellipsoid);
const glm::dmat3& halfAxes = orientedBoundingBox.getHalfAxes();
glm::dvec3 offset =
glm::length(halfAxes[0] + halfAxes[1] + halfAxes[2]) *
Expand Down Expand Up @@ -525,9 +534,12 @@ void ACesium3DTileset::OnFocusEditorViewportOnThis() {

ACesiumGeoreference* pGeoreference = this->ResolveGeoreference();

const CesiumGeospatial::Ellipsoid& ellipsoid =
pGeoreference->GetEllipsoid()->GetNativeEllipsoid();

// calculate unreal camera position
glm::dvec3 ecefCameraPosition =
std::visit(CalculateECEFCameraPosition{}, boundingVolume);
std::visit(CalculateECEFCameraPosition{ellipsoid}, boundingVolume);
FVector unrealCameraPosition =
pGeoreference->TransformEarthCenteredEarthFixedPositionToUnreal(
VecMath::createVector(ecefCameraPosition));
Expand Down Expand Up @@ -591,6 +603,13 @@ void ACesium3DTileset::UpdateTransformFromCesium() {
}
}

void ACesium3DTileset::HandleOnGeoreferenceEllipsoidChanged(
UCesiumEllipsoid* OldEllipsoid,
UCesiumEllipsoid* NewEllpisoid) {
UE_LOG(LogCesium, Warning, TEXT("Ellipsoid changed"));
this->RefreshTileset();
}

// Called when the game starts or when spawned
void ACesium3DTileset::BeginPlay() {
Super::BeginPlay();
Expand Down Expand Up @@ -708,8 +727,13 @@ class UnrealResourcePreparer
&(*this->_pActor->_metadataDescription_DEPRECATED);
}

const CesiumGeospatial::Ellipsoid& ellipsoid = tileLoadResult.ellipsoid;

TUniquePtr<UCesiumGltfComponent::HalfConstructed> pHalf =
UCesiumGltfComponent::CreateOffGameThread(transform, options);
UCesiumGltfComponent::CreateOffGameThread(
transform,
options,
ellipsoid);

return asyncSystem.createResolvedFuture(
Cesium3DTilesSelection::TileLoadResultAndRenderResources{
Expand Down Expand Up @@ -1052,6 +1076,9 @@ void ACesium3DTileset::LoadTileset() {
this->BoundingVolumePoolComponent->initPool(this->OcclusionPoolSize);
}

CesiumGeospatial::Ellipsoid pNativeEllipsoid =
this->ResolveGeoreference()->GetEllipsoid()->GetNativeEllipsoid();

ACesiumCreditSystem* pCreditSystem = this->ResolvedCreditSystem;

Cesium3DTilesSelection::TilesetExternals externals{
Expand All @@ -1072,6 +1099,8 @@ void ACesium3DTileset::LoadTileset() {

Cesium3DTilesSelection::TilesetOptions options;

options.ellipsoid = pNativeEllipsoid;

options.enableOcclusionCulling =
GetDefault<UCesiumRuntimeSettings>()
->EnableExperimentalOcclusionCullingFeature &&
Expand Down Expand Up @@ -1545,7 +1574,8 @@ std::vector<FCesiumCamera> ACesium3DTileset::GetSceneCaptures() const {
/*static*/ Cesium3DTilesSelection::ViewState
ACesium3DTileset::CreateViewStateFromViewParameters(
const FCesiumCamera& camera,
const glm::dmat4& unrealWorldToTileset) {
const glm::dmat4& unrealWorldToTileset,
UCesiumEllipsoid* ellipsoid) {

double horizontalFieldOfView =
FMath::DegreesToRadians(camera.FieldOfViewDegrees);
Expand Down Expand Up @@ -1595,7 +1625,8 @@ ACesium3DTileset::CreateViewStateFromViewParameters(
tilesetCameraUp,
size,
horizontalFieldOfView,
verticalFieldOfView);
verticalFieldOfView,
ellipsoid->GetNativeEllipsoid());
}

#if WITH_EDITOR
Expand Down Expand Up @@ -2044,10 +2075,14 @@ void ACesium3DTileset::Tick(float DeltaTime) {
return;
}

UCesiumEllipsoid* ellipsoid = this->ResolveGeoreference()->GetEllipsoid();

std::vector<Cesium3DTilesSelection::ViewState> frustums;
for (const FCesiumCamera& camera : cameras) {
frustums.push_back(
CreateViewStateFromViewParameters(camera, unrealWorldToCesiumTileset));
frustums.push_back(CreateViewStateFromViewParameters(
camera,
unrealWorldToCesiumTileset,
ellipsoid));
}

const Cesium3DTilesSelection::ViewUpdateResult* pResult;
Expand Down
Loading

0 comments on commit 0c619da

Please sign in to comment.