react-native-cesium 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE +12 -0
- package/README.md +308 -0
- package/ReactNativeCesium.podspec +54 -0
- package/android/CMakeLists.txt +146 -0
- package/android/build.gradle +178 -0
- package/android/fix-prefab.gradle +51 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +5 -0
- package/android/src/main/assets/cacert.pem +3529 -0
- package/android/src/main/cpp/CesiumBridgeAndroid.cpp +487 -0
- package/android/src/main/cpp/CesiumBridgeAndroid.h +94 -0
- package/android/src/main/cpp/cpp-adapter.cpp +17 -0
- package/android/src/main/cpp/vulkan/VulkanBackend.cpp +1781 -0
- package/android/src/main/cpp/vulkan/VulkanBackend.h +190 -0
- package/android/src/main/cpp/vulkan/shaders/sky.frag +86 -0
- package/android/src/main/cpp/vulkan/shaders/sky.vert +9 -0
- package/android/src/main/cpp/vulkan/shaders/terrain.frag +144 -0
- package/android/src/main/cpp/vulkan/shaders/terrain.vert +25 -0
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/CesiumBridgeJNI.kt +84 -0
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/HybridCesiumView.kt +225 -0
- package/android/src/main/java/com/reactnativecesium/ReactNativeCesiumPackage.kt +28 -0
- package/cpp/engine/CesiumEngine.cpp +413 -0
- package/cpp/engine/CesiumEngine.hpp +90 -0
- package/cpp/engine/DeletionQueue.cpp +28 -0
- package/cpp/engine/DeletionQueue.hpp +28 -0
- package/cpp/engine/GlobeCamera.cpp +181 -0
- package/cpp/engine/GlobeCamera.hpp +64 -0
- package/cpp/engine/GltfToMesh.cpp +154 -0
- package/cpp/engine/GltfToMesh.hpp +20 -0
- package/cpp/engine/ResourcePreparer.cpp +224 -0
- package/cpp/engine/ResourcePreparer.hpp +96 -0
- package/cpp/engine/TaskProcessor.cpp +61 -0
- package/cpp/engine/TaskProcessor.hpp +43 -0
- package/cpp/engine/TileLifecycleManager.cpp +30 -0
- package/cpp/engine/TileLifecycleManager.hpp +25 -0
- package/cpp/fmt/format.h +9 -0
- package/cpp/renderer/IGPUBackend.hpp +22 -0
- package/cpp/renderer/RenderTypes.hpp +112 -0
- package/cpp/renderer/ShaderTypes.hpp +29 -0
- package/example/README.md +43 -0
- package/example/react-native-cesium-example.jpg +0 -0
- package/ios/CesiumBridge.h +55 -0
- package/ios/CesiumBridge.mm +393 -0
- package/ios/HybridCesiumView.swift +299 -0
- package/ios/ReactNativeCesium-umbrella.h +16 -0
- package/ios/metal/MetalBackend.h +82 -0
- package/ios/metal/MetalBackend.mm +839 -0
- package/ios/react_native_cesium_ensure_native.rb +12 -0
- package/ios/react_native_cesium_post_install.rb +30 -0
- package/lib/commonjs/CesiumView.js +13 -0
- package/lib/commonjs/CesiumView.js.map +1 -0
- package/lib/commonjs/index.js +13 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/specs/cesium-view.nitro.js +6 -0
- package/lib/commonjs/specs/cesium-view.nitro.js.map +1 -0
- package/lib/module/CesiumView.js +9 -0
- package/lib/module/CesiumView.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/specs/cesium-view.nitro.js +4 -0
- package/lib/module/specs/cesium-view.nitro.js.map +1 -0
- package/lib/typescript/src/CesiumView.d.ts +5 -0
- package/lib/typescript/src/CesiumView.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts +43 -0
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts.map +1 -0
- package/nitro.json +30 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/ReactNativeCesium+autolinking.cmake +83 -0
- package/nitrogen/generated/android/ReactNativeCesium+autolinking.gradle +27 -0
- package/nitrogen/generated/android/ReactNativeCesiumOnLoad.cpp +58 -0
- package/nitrogen/generated/android/ReactNativeCesiumOnLoad.hpp +34 -0
- package/nitrogen/generated/android/c++/JCameraState.hpp +81 -0
- package/nitrogen/generated/android/c++/JCesiumMetrics.hpp +81 -0
- package/nitrogen/generated/android/c++/JFunc_void_CesiumMetrics.hpp +78 -0
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.cpp +178 -0
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.hpp +83 -0
- package/nitrogen/generated/android/c++/views/JHybridCesiumViewStateUpdater.cpp +92 -0
- package/nitrogen/generated/android/c++/views/JHybridCesiumViewStateUpdater.hpp +49 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/CameraState.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/CesiumMetrics.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/Func_void_CesiumMetrics.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/HybridCesiumViewSpec.kt +126 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/ReactNativeCesiumOnLoad.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/views/HybridCesiumViewManager.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/views/HybridCesiumViewStateUpdater.kt +23 -0
- package/nitrogen/generated/ios/ReactNativeCesium+autolinking.rb +60 -0
- package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Bridge.cpp +57 -0
- package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Bridge.hpp +164 -0
- package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Umbrella.hpp +53 -0
- package/nitrogen/generated/ios/ReactNativeCesiumAutolinking.mm +33 -0
- package/nitrogen/generated/ios/ReactNativeCesiumAutolinking.swift +26 -0
- package/nitrogen/generated/ios/c++/HybridCesiumViewSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridCesiumViewSpecSwift.hpp +157 -0
- package/nitrogen/generated/ios/c++/views/HybridCesiumViewComponent.mm +167 -0
- package/nitrogen/generated/ios/swift/CameraState.swift +59 -0
- package/nitrogen/generated/ios/swift/CesiumMetrics.swift +59 -0
- package/nitrogen/generated/ios/swift/Func_void_CameraState.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_CesiumMetrics.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec.swift +65 -0
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec_cxx.swift +306 -0
- package/nitrogen/generated/shared/c++/CameraState.hpp +107 -0
- package/nitrogen/generated/shared/c++/CesiumMetrics.hpp +107 -0
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.cpp +42 -0
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.hpp +90 -0
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.cpp +182 -0
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.hpp +122 -0
- package/nitrogen/generated/shared/json/CesiumViewConfig.json +19 -0
- package/package.json +140 -0
- package/react-native.config.js +16 -0
- package/scripts/cesium/build.mjs +901 -0
- package/scripts/cesium/clean.mjs +35 -0
- package/scripts/cesium/clone.mjs +32 -0
- package/scripts/cesium/ensure-native.mjs +116 -0
- package/scripts/cesium/vcpkg-ports/zstd/fix-emscripten-and-clang-cl.patch +31 -0
- package/scripts/cesium/vcpkg-ports/zstd/fix-windows-rc-compile.patch +13 -0
- package/scripts/cesium/vcpkg-ports/zstd/no-static-suffix.patch +13 -0
- package/scripts/cesium/vcpkg-ports/zstd/portfile.cmake +77 -0
- package/scripts/cesium/vcpkg-ports/zstd/usage +4 -0
- package/scripts/cesium/vcpkg-ports/zstd/vcpkg.json +23 -0
- package/scripts/cesium/vcpkg-triplets/arm64-ios-simulator.cmake +10 -0
- package/scripts/cesium/vcpkg-triplets/arm64-ios.cmake +14 -0
- package/src/CesiumView.tsx +13 -0
- package/src/index.ts +7 -0
- package/src/specs/cesium-view.nitro.ts +51 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "../renderer/RenderTypes.hpp"
|
|
4
|
+
#include "GlobeCamera.hpp"
|
|
5
|
+
#include "ResourcePreparer.hpp"
|
|
6
|
+
#include "TaskProcessor.hpp"
|
|
7
|
+
#include "TileLifecycleManager.hpp"
|
|
8
|
+
|
|
9
|
+
#include <CesiumAsync/AsyncSystem.h>
|
|
10
|
+
#include <CesiumAsync/IAssetAccessor.h>
|
|
11
|
+
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <string>
|
|
14
|
+
|
|
15
|
+
namespace Cesium3DTilesSelection {
|
|
16
|
+
class Tileset;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
namespace CesiumUtility {
|
|
20
|
+
class CreditSystem;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
namespace reactnativecesium {
|
|
24
|
+
|
|
25
|
+
struct EngineConfig {
|
|
26
|
+
std::string ionAccessToken;
|
|
27
|
+
int64_t ionAssetId = 1;
|
|
28
|
+
std::string cacheDatabasePath;
|
|
29
|
+
std::string tlsCaBundlePath;
|
|
30
|
+
double maximumScreenSpaceError = 32.0;
|
|
31
|
+
int32_t maximumSimultaneousTileLoads = 12;
|
|
32
|
+
int32_t loadingDescendantLimit = 20;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
class CesiumEngine {
|
|
36
|
+
public:
|
|
37
|
+
CesiumEngine();
|
|
38
|
+
~CesiumEngine();
|
|
39
|
+
|
|
40
|
+
CesiumEngine(const CesiumEngine&) = delete;
|
|
41
|
+
CesiumEngine& operator=(const CesiumEngine&) = delete;
|
|
42
|
+
|
|
43
|
+
void initialize(const EngineConfig& config);
|
|
44
|
+
void shutdown();
|
|
45
|
+
void updateConfig(const EngineConfig& config);
|
|
46
|
+
|
|
47
|
+
void updateFrame(double viewportWidth, double viewportHeight, FrameResult& result);
|
|
48
|
+
|
|
49
|
+
void setImageryAssetId(int64_t assetId);
|
|
50
|
+
|
|
51
|
+
GlobeCamera& camera() { return camera_; }
|
|
52
|
+
const GlobeCamera& camera() const { return camera_; }
|
|
53
|
+
|
|
54
|
+
ResourcePreparer* getResourcePreparer() const { return resourcePreparer_.get(); }
|
|
55
|
+
|
|
56
|
+
private:
|
|
57
|
+
void createTileset(const std::string& token,
|
|
58
|
+
int64_t assetId,
|
|
59
|
+
int64_t imageryAssetId = 1);
|
|
60
|
+
void destroyTileset();
|
|
61
|
+
|
|
62
|
+
bool tilesetOptionsMatch(const EngineConfig& a, const EngineConfig& b) const;
|
|
63
|
+
|
|
64
|
+
// Builds a tessellated WGS84 ellipsoid mesh (inset ~20 m) used as a
|
|
65
|
+
// permanent background so flat terrain is always visible even when tiles
|
|
66
|
+
// are absent or not yet loaded.
|
|
67
|
+
void buildEllipsoidMesh();
|
|
68
|
+
void appendEllipsoidDraws(FrameResult& result) const;
|
|
69
|
+
|
|
70
|
+
EngineConfig config_;
|
|
71
|
+
|
|
72
|
+
std::shared_ptr<TaskProcessor> taskProcessor_;
|
|
73
|
+
std::shared_ptr<CesiumAsync::IAssetAccessor> assetAccessor_;
|
|
74
|
+
CesiumAsync::AsyncSystem asyncSystem_;
|
|
75
|
+
std::shared_ptr<ResourcePreparer> resourcePreparer_;
|
|
76
|
+
std::shared_ptr<CesiumUtility::CreditSystem> creditSystem_;
|
|
77
|
+
|
|
78
|
+
std::unique_ptr<Cesium3DTilesSelection::Tileset> tileset_;
|
|
79
|
+
|
|
80
|
+
int64_t currentImageryAssetId_ = 1;
|
|
81
|
+
|
|
82
|
+
GlobeCamera camera_;
|
|
83
|
+
TileLifecycleManager lifecycle_;
|
|
84
|
+
|
|
85
|
+
// Pre-computed fallback ellipsoid geometry (ECEF, absolute).
|
|
86
|
+
std::vector<glm::dvec3> ellipsoidPositions_;
|
|
87
|
+
std::vector<uint32_t> ellipsoidIndices_;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
} // namespace reactnativecesium
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#include "DeletionQueue.hpp"
|
|
2
|
+
|
|
3
|
+
namespace reactnativecesium {
|
|
4
|
+
|
|
5
|
+
void DeletionQueue::enqueue(TileGPUResources* resources, uint64_t currentFrame) {
|
|
6
|
+
if (!resources) return;
|
|
7
|
+
queue_.push_back({resources, currentFrame});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
void DeletionQueue::processFrame(uint64_t currentFrame) {
|
|
11
|
+
int disposed = 0;
|
|
12
|
+
while (!queue_.empty() && disposed < MAX_DISPOSALS_PER_FRAME) {
|
|
13
|
+
auto& front = queue_.front();
|
|
14
|
+
if (currentFrame - front.enqueueFrame < MIN_FRAME_DELAY) break;
|
|
15
|
+
delete front.resources;
|
|
16
|
+
queue_.pop_front();
|
|
17
|
+
++disposed;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
void DeletionQueue::flush() {
|
|
22
|
+
while (!queue_.empty()) {
|
|
23
|
+
delete queue_.front().resources;
|
|
24
|
+
queue_.pop_front();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
} // namespace reactnativecesium
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "../renderer/RenderTypes.hpp"
|
|
4
|
+
|
|
5
|
+
#include <cstdint>
|
|
6
|
+
#include <deque>
|
|
7
|
+
|
|
8
|
+
namespace reactnativecesium {
|
|
9
|
+
|
|
10
|
+
// CPU-only resource deletion with a frame delay (avoids deleting in-flight data).
|
|
11
|
+
class DeletionQueue {
|
|
12
|
+
public:
|
|
13
|
+
static constexpr uint64_t MIN_FRAME_DELAY = 3;
|
|
14
|
+
static constexpr int MAX_DISPOSALS_PER_FRAME = 8;
|
|
15
|
+
|
|
16
|
+
void enqueue(TileGPUResources* resources, uint64_t currentFrame);
|
|
17
|
+
void processFrame(uint64_t currentFrame);
|
|
18
|
+
void flush();
|
|
19
|
+
|
|
20
|
+
private:
|
|
21
|
+
struct Entry {
|
|
22
|
+
TileGPUResources* resources;
|
|
23
|
+
uint64_t enqueueFrame;
|
|
24
|
+
};
|
|
25
|
+
std::deque<Entry> queue_;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
} // namespace reactnativecesium
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#include "GlobeCamera.hpp"
|
|
2
|
+
|
|
3
|
+
#include <CesiumGeospatial/GlobeTransforms.h>
|
|
4
|
+
|
|
5
|
+
#include <glm/gtc/matrix_transform.hpp>
|
|
6
|
+
|
|
7
|
+
#include <algorithm>
|
|
8
|
+
#include <cmath>
|
|
9
|
+
|
|
10
|
+
namespace reactnativecesium {
|
|
11
|
+
|
|
12
|
+
static constexpr double kNearPlane = 1.0;
|
|
13
|
+
static constexpr double kFarPlane = 50000000.0;
|
|
14
|
+
static constexpr double kMinVfov = 20.0;
|
|
15
|
+
static constexpr double kMaxVfov = 100.0;
|
|
16
|
+
|
|
17
|
+
GlobeCamera::GlobeCamera() { recompute(); }
|
|
18
|
+
|
|
19
|
+
void GlobeCamera::setParams(const CameraParams& p) {
|
|
20
|
+
std::lock_guard<std::mutex> lk(mutex_);
|
|
21
|
+
params_ = p;
|
|
22
|
+
dirty_ = true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
CameraParams GlobeCamera::getParams() const {
|
|
26
|
+
std::lock_guard<std::mutex> lk(mutex_);
|
|
27
|
+
return params_;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void GlobeCamera::setVerticalFovDegrees(double degrees) {
|
|
31
|
+
std::lock_guard<std::mutex> lk(mutex_);
|
|
32
|
+
verticalFovDeg_ = std::clamp(degrees, kMinVfov, kMaxVfov);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
double GlobeCamera::getVerticalFovDegrees() const {
|
|
36
|
+
std::lock_guard<std::mutex> lk(mutex_);
|
|
37
|
+
return verticalFovDeg_;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void GlobeCamera::recompute() const {
|
|
41
|
+
if (!dirty_) return;
|
|
42
|
+
dirty_ = false;
|
|
43
|
+
|
|
44
|
+
const auto& ellipsoid = CesiumGeospatial::Ellipsoid::WGS84;
|
|
45
|
+
CesiumGeospatial::Cartographic carto(glm::radians(params_.longitude),
|
|
46
|
+
glm::radians(params_.latitude),
|
|
47
|
+
params_.altitude);
|
|
48
|
+
ecefPosition_ = ellipsoid.cartographicToCartesian(carto);
|
|
49
|
+
|
|
50
|
+
glm::dmat4 enuToECEF =
|
|
51
|
+
CesiumGeospatial::GlobeTransforms::eastNorthUpToFixedFrame(
|
|
52
|
+
ecefPosition_, ellipsoid);
|
|
53
|
+
|
|
54
|
+
glm::dvec3 east = glm::normalize(glm::dvec3(enuToECEF[0]));
|
|
55
|
+
glm::dvec3 north = glm::normalize(glm::dvec3(enuToECEF[1]));
|
|
56
|
+
glm::dvec3 upENU = glm::normalize(glm::dvec3(enuToECEF[2]));
|
|
57
|
+
|
|
58
|
+
double hdgRad = glm::radians(params_.heading);
|
|
59
|
+
double pitchRad = glm::radians(params_.pitch);
|
|
60
|
+
double rollRad = glm::radians(params_.roll);
|
|
61
|
+
|
|
62
|
+
// 1. Heading: forward and right in the horizontal plane.
|
|
63
|
+
glm::dvec3 fwdH = north * std::cos(hdgRad) + east * std::sin(hdgRad);
|
|
64
|
+
glm::dvec3 right = glm::normalize(glm::cross(fwdH, upENU));
|
|
65
|
+
|
|
66
|
+
// 2. Pitch: rotate fwdH and upENU around the fixed right axis.
|
|
67
|
+
// Works for any pitch (full 360° loop) — no cross(fwd, upENU) singularity.
|
|
68
|
+
glm::dvec3 fwd = fwdH * std::cos(pitchRad) + upENU * std::sin(pitchRad);
|
|
69
|
+
glm::dvec3 camUp = -fwdH * std::sin(pitchRad) + upENU * std::cos(pitchRad);
|
|
70
|
+
|
|
71
|
+
// 3. Roll: rotate right and camUp around fwd.
|
|
72
|
+
if (std::abs(rollRad) > 1e-6) {
|
|
73
|
+
glm::dvec3 rolledRight = right * std::cos(rollRad) + camUp * std::sin(rollRad);
|
|
74
|
+
camUp = glm::normalize(glm::cross(rolledRight, fwd));
|
|
75
|
+
right = glm::normalize(rolledRight);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
direction_ = fwd;
|
|
79
|
+
up_ = camUp;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
glm::dvec3 GlobeCamera::getECEFPosition() const {
|
|
83
|
+
std::lock_guard<std::mutex> lk(mutex_);
|
|
84
|
+
recompute();
|
|
85
|
+
return ecefPosition_;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
void GlobeCamera::computeHeadingPitchToward(double targetLatDeg,
|
|
89
|
+
double targetLonDeg,
|
|
90
|
+
double targetAltMeters,
|
|
91
|
+
double& outHeadingDeg,
|
|
92
|
+
double& outPitchDeg) const {
|
|
93
|
+
std::lock_guard<std::mutex> lk(mutex_);
|
|
94
|
+
recompute();
|
|
95
|
+
|
|
96
|
+
const auto& ellipsoid = CesiumGeospatial::Ellipsoid::WGS84;
|
|
97
|
+
CesiumGeospatial::Cartographic targetCarto(
|
|
98
|
+
glm::radians(targetLonDeg),
|
|
99
|
+
glm::radians(targetLatDeg),
|
|
100
|
+
targetAltMeters);
|
|
101
|
+
glm::dvec3 targetEcef = ellipsoid.cartographicToCartesian(targetCarto);
|
|
102
|
+
glm::dvec3 dirEcef = glm::normalize(targetEcef - ecefPosition_);
|
|
103
|
+
|
|
104
|
+
glm::dmat4 enuToECEF =
|
|
105
|
+
CesiumGeospatial::GlobeTransforms::eastNorthUpToFixedFrame(
|
|
106
|
+
ecefPosition_, ellipsoid);
|
|
107
|
+
glm::dvec3 east = glm::normalize(glm::dvec3(enuToECEF[0]));
|
|
108
|
+
glm::dvec3 north = glm::normalize(glm::dvec3(enuToECEF[1]));
|
|
109
|
+
glm::dvec3 upENU = glm::normalize(glm::dvec3(enuToECEF[2]));
|
|
110
|
+
|
|
111
|
+
const double dEast = glm::dot(dirEcef, east);
|
|
112
|
+
const double dNorth = glm::dot(dirEcef, north);
|
|
113
|
+
const double dUp = glm::dot(dirEcef, upENU);
|
|
114
|
+
const double horiz = std::sqrt(dEast * dEast + dNorth * dNorth);
|
|
115
|
+
|
|
116
|
+
outHeadingDeg = glm::degrees(std::atan2(dEast, dNorth));
|
|
117
|
+
outPitchDeg = glm::degrees(std::atan2(dUp, horiz));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
Cesium3DTilesSelection::ViewState
|
|
121
|
+
GlobeCamera::computeViewState(double w, double h) const {
|
|
122
|
+
std::lock_guard<std::mutex> lk(mutex_);
|
|
123
|
+
recompute();
|
|
124
|
+
|
|
125
|
+
double aspect = w / std::max(h, 1.0);
|
|
126
|
+
double vfov = glm::radians(verticalFovDeg_);
|
|
127
|
+
double hfov = 2.0 * std::atan(std::tan(vfov * 0.5) * aspect);
|
|
128
|
+
|
|
129
|
+
return Cesium3DTilesSelection::ViewState(
|
|
130
|
+
ecefPosition_, direction_, up_,
|
|
131
|
+
glm::dvec2(w, h), hfov, vfov);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
glm::mat4 GlobeCamera::computeVPMatrix(double w, double h) const {
|
|
135
|
+
std::lock_guard<std::mutex> lk(mutex_);
|
|
136
|
+
recompute();
|
|
137
|
+
|
|
138
|
+
glm::dmat4 fullView = glm::lookAt(ecefPosition_, ecefPosition_ + direction_, up_);
|
|
139
|
+
glm::mat4 viewRot = glm::mat4(glm::dmat4(
|
|
140
|
+
fullView[0], fullView[1], fullView[2], glm::dvec4(0.0, 0.0, 0.0, 1.0)));
|
|
141
|
+
|
|
142
|
+
double aspect = w / std::max(h, 1.0);
|
|
143
|
+
double vfov = glm::radians(verticalFovDeg_);
|
|
144
|
+
double tanHalfV = std::tan(vfov * 0.5);
|
|
145
|
+
double tanHalfH = tanHalfV * aspect;
|
|
146
|
+
|
|
147
|
+
float f = static_cast<float>(kNearPlane);
|
|
148
|
+
glm::mat4 proj(0.0f);
|
|
149
|
+
proj[0][0] = static_cast<float>(1.0 / tanHalfH);
|
|
150
|
+
proj[1][1] = static_cast<float>(1.0 / tanHalfV);
|
|
151
|
+
proj[2][3] = -1.0f;
|
|
152
|
+
proj[3][2] = f;
|
|
153
|
+
|
|
154
|
+
return proj * viewRot;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
glm::dmat4 GlobeCamera::computeVPMatrixDouble(double w, double h) const {
|
|
158
|
+
std::lock_guard<std::mutex> lk(mutex_);
|
|
159
|
+
recompute();
|
|
160
|
+
|
|
161
|
+
// Rotation-only view (camera-at-origin, ECEF-oriented) — same structure as
|
|
162
|
+
// computeVPMatrix but all operations stay in double.
|
|
163
|
+
glm::dmat4 fullView = glm::lookAt(ecefPosition_, ecefPosition_ + direction_, up_);
|
|
164
|
+
glm::dmat4 viewRot(
|
|
165
|
+
fullView[0], fullView[1], fullView[2], glm::dvec4(0.0, 0.0, 0.0, 1.0));
|
|
166
|
+
|
|
167
|
+
double aspect = w / std::max(h, 1.0);
|
|
168
|
+
double vfov = glm::radians(verticalFovDeg_);
|
|
169
|
+
double tanHalfV = std::tan(vfov * 0.5);
|
|
170
|
+
double tanHalfH = tanHalfV * aspect;
|
|
171
|
+
|
|
172
|
+
glm::dmat4 proj(0.0);
|
|
173
|
+
proj[0][0] = 1.0 / tanHalfH;
|
|
174
|
+
proj[1][1] = 1.0 / tanHalfV;
|
|
175
|
+
proj[2][3] = -1.0;
|
|
176
|
+
proj[3][2] = kNearPlane;
|
|
177
|
+
|
|
178
|
+
return proj * viewRot;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
} // namespace reactnativecesium
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <CesiumGeospatial/Cartographic.h>
|
|
4
|
+
#include <CesiumGeospatial/Ellipsoid.h>
|
|
5
|
+
#include <Cesium3DTilesSelection/ViewState.h>
|
|
6
|
+
|
|
7
|
+
#include <glm/glm.hpp>
|
|
8
|
+
#include <mutex>
|
|
9
|
+
|
|
10
|
+
namespace reactnativecesium {
|
|
11
|
+
|
|
12
|
+
struct CameraParams {
|
|
13
|
+
double latitude = 46.10;
|
|
14
|
+
double longitude = 7.80;
|
|
15
|
+
double altitude = 5500.0;
|
|
16
|
+
double heading = 220.0;
|
|
17
|
+
double pitch = -10.0;
|
|
18
|
+
double roll = 0.0;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
class GlobeCamera {
|
|
22
|
+
public:
|
|
23
|
+
GlobeCamera();
|
|
24
|
+
|
|
25
|
+
void setParams(const CameraParams& params);
|
|
26
|
+
CameraParams getParams() const;
|
|
27
|
+
|
|
28
|
+
void setVerticalFovDegrees(double degrees);
|
|
29
|
+
double getVerticalFovDegrees() const;
|
|
30
|
+
|
|
31
|
+
/// Bearing / tilt to look from the current camera position toward |target*| (degrees).
|
|
32
|
+
void computeHeadingPitchToward(double targetLatDeg,
|
|
33
|
+
double targetLonDeg,
|
|
34
|
+
double targetAltMeters,
|
|
35
|
+
double& outHeadingDeg,
|
|
36
|
+
double& outPitchDeg) const;
|
|
37
|
+
|
|
38
|
+
Cesium3DTilesSelection::ViewState
|
|
39
|
+
computeViewState(double viewportWidth, double viewportHeight) const;
|
|
40
|
+
|
|
41
|
+
glm::dvec3 getECEFPosition() const;
|
|
42
|
+
|
|
43
|
+
glm::mat4 computeVPMatrix(double viewportWidth, double viewportHeight) const;
|
|
44
|
+
|
|
45
|
+
// Double-precision rotation-only VP matrix (same projection, no translation).
|
|
46
|
+
// Used by CesiumEngine to build per-tile MVP = vpDouble * translate(rtcCenter-camera)
|
|
47
|
+
// entirely in double before casting the result to float32 for the GPU.
|
|
48
|
+
glm::dmat4 computeVPMatrixDouble(double viewportWidth, double viewportHeight) const;
|
|
49
|
+
|
|
50
|
+
private:
|
|
51
|
+
void recompute() const;
|
|
52
|
+
|
|
53
|
+
mutable std::mutex mutex_;
|
|
54
|
+
CameraParams params_;
|
|
55
|
+
|
|
56
|
+
double verticalFovDeg_ = 60.0;
|
|
57
|
+
|
|
58
|
+
mutable bool dirty_ = true;
|
|
59
|
+
mutable glm::dvec3 ecefPosition_{0.0};
|
|
60
|
+
mutable glm::dvec3 direction_{0.0, 1.0, 0.0};
|
|
61
|
+
mutable glm::dvec3 up_{0.0, 0.0, 1.0};
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
} // namespace reactnativecesium
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#include "GltfToMesh.hpp"
|
|
2
|
+
|
|
3
|
+
#include <CesiumGltf/AccessorView.h>
|
|
4
|
+
#include <CesiumGltf/AccessorUtility.h>
|
|
5
|
+
#include <CesiumGltf/VertexAttributeSemantics.h>
|
|
6
|
+
#include <CesiumGltfContent/GltfUtilities.h>
|
|
7
|
+
|
|
8
|
+
#include <glm/gtc/matrix_transform.hpp>
|
|
9
|
+
#include <glm/gtc/quaternion.hpp>
|
|
10
|
+
|
|
11
|
+
#include <cmath>
|
|
12
|
+
#include <cstring>
|
|
13
|
+
|
|
14
|
+
namespace reactnativecesium {
|
|
15
|
+
|
|
16
|
+
// Double-precision Bowring iterative geodetic height.
|
|
17
|
+
// Both subtracted terms are ~6.4e6 m, but in double (52-bit mantissa) the
|
|
18
|
+
// catastrophic cancellation leaves ~1 nm residual — effectively exact.
|
|
19
|
+
static double ellipsoidHeightDouble(const glm::dvec3& p) {
|
|
20
|
+
constexpr double a = 6378137.0;
|
|
21
|
+
constexpr double b = 6356752.31424518;
|
|
22
|
+
constexpr double e2 = 1.0 - (b * b) / (a * a);
|
|
23
|
+
constexpr double ep2 = (a * a - b * b) / (b * b);
|
|
24
|
+
|
|
25
|
+
const double pxy = std::sqrt(p.x * p.x + p.y * p.y);
|
|
26
|
+
if (pxy < 1e-10) return std::abs(p.z) - b;
|
|
27
|
+
|
|
28
|
+
const double theta = std::atan2(p.z * a, pxy * b);
|
|
29
|
+
const double st = std::sin(theta), ct = std::cos(theta);
|
|
30
|
+
const double lat = std::atan2(p.z + ep2 * b * st * st * st,
|
|
31
|
+
pxy - e2 * a * ct * ct * ct);
|
|
32
|
+
const double sinLat = std::sin(lat);
|
|
33
|
+
const double N = a / std::sqrt(1.0 - e2 * sinLat * sinLat);
|
|
34
|
+
return pxy / std::cos(lat) - N;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
std::vector<TilePrimitive>
|
|
38
|
+
GltfToMesh::convert(const CesiumGltf::Model& model,
|
|
39
|
+
const glm::dmat4& tileTransform) {
|
|
40
|
+
std::vector<TilePrimitive> results;
|
|
41
|
+
|
|
42
|
+
// Apply CESIUM_RTC and glTF Y-up adjustment.
|
|
43
|
+
glm::dmat4 rootTransform = tileTransform;
|
|
44
|
+
rootTransform = CesiumGltfContent::GltfUtilities::applyRtcCenter(model, rootTransform);
|
|
45
|
+
rootTransform = CesiumGltfContent::GltfUtilities::applyGltfUpAxisTransform(model, rootTransform);
|
|
46
|
+
|
|
47
|
+
model.forEachPrimitiveInScene(
|
|
48
|
+
-1,
|
|
49
|
+
[&results, &rootTransform](
|
|
50
|
+
const CesiumGltf::Model& gltf,
|
|
51
|
+
const CesiumGltf::Node& /*node*/,
|
|
52
|
+
const CesiumGltf::Mesh& /*mesh*/,
|
|
53
|
+
const CesiumGltf::MeshPrimitive& primitive,
|
|
54
|
+
const glm::dmat4& nodeTransform) {
|
|
55
|
+
|
|
56
|
+
switch (primitive.mode) {
|
|
57
|
+
case CesiumGltf::MeshPrimitive::Mode::TRIANGLES:
|
|
58
|
+
case CesiumGltf::MeshPrimitive::Mode::TRIANGLE_STRIP:
|
|
59
|
+
case CesiumGltf::MeshPrimitive::Mode::TRIANGLE_FAN:
|
|
60
|
+
break;
|
|
61
|
+
default:
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const CesiumGltf::PositionAccessorType posAccessor =
|
|
66
|
+
CesiumGltf::getPositionAccessorView(gltf, primitive);
|
|
67
|
+
if (posAccessor.status() != CesiumGltf::AccessorViewStatus::Valid ||
|
|
68
|
+
posAccessor.size() <= 0)
|
|
69
|
+
return;
|
|
70
|
+
|
|
71
|
+
const glm::dmat4 worldTransform = rootTransform * nodeTransform;
|
|
72
|
+
const int64_t vertexCount = posAccessor.size();
|
|
73
|
+
|
|
74
|
+
// RTC centre = translation column of the world transform.
|
|
75
|
+
// After applyRtcCenter this is the tile's ECEF centre embedded by
|
|
76
|
+
// Cesium Native (the RTC_CENTER GLTF extension value).
|
|
77
|
+
const glm::dvec3 rtcCenter(worldTransform[3]);
|
|
78
|
+
|
|
79
|
+
TilePrimitive prim;
|
|
80
|
+
prim.rtcCenter = rtcCenter;
|
|
81
|
+
prim.localPositions.reserve(static_cast<size_t>(vertexCount));
|
|
82
|
+
prim.altitudes.reserve(static_cast<size_t>(vertexCount));
|
|
83
|
+
|
|
84
|
+
for (int64_t i = 0; i < vertexCount; ++i) {
|
|
85
|
+
const auto& p = posAccessor[i];
|
|
86
|
+
const glm::dvec3 gltfLocal(p.value[0], p.value[1], p.value[2]);
|
|
87
|
+
// Absolute ECEF in double precision.
|
|
88
|
+
const glm::dvec3 ecef(worldTransform * glm::dvec4(gltfLocal, 1.0));
|
|
89
|
+
// Tile-local position (small float, retains full float32 precision
|
|
90
|
+
// because it is relative to the nearby tile centre, not the origin).
|
|
91
|
+
prim.localPositions.push_back(glm::vec3(ecef - rtcCenter));
|
|
92
|
+
// Altitude computed in double — sub-millimetre accuracy.
|
|
93
|
+
prim.altitudes.push_back(static_cast<float>(ellipsoidHeightDouble(ecef)));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Overlay UV coordinates (_CESIUMOVERLAY_0).
|
|
97
|
+
const auto uvIt = primitive.attributes.find("_CESIUMOVERLAY_0");
|
|
98
|
+
if (uvIt != primitive.attributes.end() && uvIt->second >= 0) {
|
|
99
|
+
CesiumGltf::AccessorView<CesiumGltf::AccessorTypes::VEC2<float>> uvView(gltf, uvIt->second);
|
|
100
|
+
if (uvView.status() == CesiumGltf::AccessorViewStatus::Valid &&
|
|
101
|
+
uvView.size() == vertexCount) {
|
|
102
|
+
prim.uvs.reserve(static_cast<size_t>(vertexCount));
|
|
103
|
+
for (int64_t i = 0; i < vertexCount; ++i) {
|
|
104
|
+
prim.uvs.push_back(glm::vec2(uvView[i].value[0], uvView[i].value[1]));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Expand index buffer → flat uint32 triangle list.
|
|
110
|
+
const CesiumGltf::IndexAccessorType idxAccessor =
|
|
111
|
+
CesiumGltf::getIndexAccessorView(gltf, primitive);
|
|
112
|
+
|
|
113
|
+
const int64_t srcIdxCount =
|
|
114
|
+
(primitive.indices >= 0)
|
|
115
|
+
? std::visit(CesiumGltf::CountFromAccessor{}, idxAccessor)
|
|
116
|
+
: vertexCount;
|
|
117
|
+
|
|
118
|
+
int64_t faceCount = 0;
|
|
119
|
+
switch (primitive.mode) {
|
|
120
|
+
case CesiumGltf::MeshPrimitive::Mode::TRIANGLES:
|
|
121
|
+
faceCount = srcIdxCount / 3;
|
|
122
|
+
break;
|
|
123
|
+
case CesiumGltf::MeshPrimitive::Mode::TRIANGLE_STRIP:
|
|
124
|
+
case CesiumGltf::MeshPrimitive::Mode::TRIANGLE_FAN:
|
|
125
|
+
faceCount = std::max<int64_t>(0, srcIdxCount - 2);
|
|
126
|
+
break;
|
|
127
|
+
default:
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
prim.indices.reserve(static_cast<size_t>(faceCount * 3));
|
|
132
|
+
for (int64_t fi = 0; fi < faceCount; ++fi) {
|
|
133
|
+
const std::array<int64_t, 3> face = std::visit(
|
|
134
|
+
CesiumGltf::IndicesForFaceFromAccessor{
|
|
135
|
+
fi, vertexCount, primitive.mode},
|
|
136
|
+
idxAccessor);
|
|
137
|
+
if (face[0] < 0 || face[1] < 0 || face[2] < 0 ||
|
|
138
|
+
face[0] >= vertexCount || face[1] >= vertexCount ||
|
|
139
|
+
face[2] >= vertexCount)
|
|
140
|
+
continue;
|
|
141
|
+
prim.indices.push_back(static_cast<uint32_t>(face[0]));
|
|
142
|
+
prim.indices.push_back(static_cast<uint32_t>(face[1]));
|
|
143
|
+
prim.indices.push_back(static_cast<uint32_t>(face[2]));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!prim.indices.empty()) {
|
|
147
|
+
results.push_back(std::move(prim));
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
return results;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
} // namespace reactnativecesium
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "../renderer/RenderTypes.hpp"
|
|
4
|
+
|
|
5
|
+
#include <CesiumGltf/Model.h>
|
|
6
|
+
#include <glm/glm.hpp>
|
|
7
|
+
|
|
8
|
+
#include <vector>
|
|
9
|
+
|
|
10
|
+
namespace reactnativecesium {
|
|
11
|
+
|
|
12
|
+
class GltfToMesh {
|
|
13
|
+
public:
|
|
14
|
+
// Convert a glTF model + tile world transform into a list of primitives.
|
|
15
|
+
// All vertex positions are transformed to absolute ECEF in double precision.
|
|
16
|
+
static std::vector<TilePrimitive>
|
|
17
|
+
convert(const CesiumGltf::Model& model, const glm::dmat4& tileTransform);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
} // namespace reactnativecesium
|