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.
Files changed (129) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +12 -0
  3. package/README.md +308 -0
  4. package/ReactNativeCesium.podspec +54 -0
  5. package/android/CMakeLists.txt +146 -0
  6. package/android/build.gradle +178 -0
  7. package/android/fix-prefab.gradle +51 -0
  8. package/android/gradle.properties +5 -0
  9. package/android/src/main/AndroidManifest.xml +5 -0
  10. package/android/src/main/assets/cacert.pem +3529 -0
  11. package/android/src/main/cpp/CesiumBridgeAndroid.cpp +487 -0
  12. package/android/src/main/cpp/CesiumBridgeAndroid.h +94 -0
  13. package/android/src/main/cpp/cpp-adapter.cpp +17 -0
  14. package/android/src/main/cpp/vulkan/VulkanBackend.cpp +1781 -0
  15. package/android/src/main/cpp/vulkan/VulkanBackend.h +190 -0
  16. package/android/src/main/cpp/vulkan/shaders/sky.frag +86 -0
  17. package/android/src/main/cpp/vulkan/shaders/sky.vert +9 -0
  18. package/android/src/main/cpp/vulkan/shaders/terrain.frag +144 -0
  19. package/android/src/main/cpp/vulkan/shaders/terrain.vert +25 -0
  20. package/android/src/main/java/com/margelo/nitro/reactnativecesium/CesiumBridgeJNI.kt +84 -0
  21. package/android/src/main/java/com/margelo/nitro/reactnativecesium/HybridCesiumView.kt +225 -0
  22. package/android/src/main/java/com/reactnativecesium/ReactNativeCesiumPackage.kt +28 -0
  23. package/cpp/engine/CesiumEngine.cpp +413 -0
  24. package/cpp/engine/CesiumEngine.hpp +90 -0
  25. package/cpp/engine/DeletionQueue.cpp +28 -0
  26. package/cpp/engine/DeletionQueue.hpp +28 -0
  27. package/cpp/engine/GlobeCamera.cpp +181 -0
  28. package/cpp/engine/GlobeCamera.hpp +64 -0
  29. package/cpp/engine/GltfToMesh.cpp +154 -0
  30. package/cpp/engine/GltfToMesh.hpp +20 -0
  31. package/cpp/engine/ResourcePreparer.cpp +224 -0
  32. package/cpp/engine/ResourcePreparer.hpp +96 -0
  33. package/cpp/engine/TaskProcessor.cpp +61 -0
  34. package/cpp/engine/TaskProcessor.hpp +43 -0
  35. package/cpp/engine/TileLifecycleManager.cpp +30 -0
  36. package/cpp/engine/TileLifecycleManager.hpp +25 -0
  37. package/cpp/fmt/format.h +9 -0
  38. package/cpp/renderer/IGPUBackend.hpp +22 -0
  39. package/cpp/renderer/RenderTypes.hpp +112 -0
  40. package/cpp/renderer/ShaderTypes.hpp +29 -0
  41. package/example/README.md +43 -0
  42. package/example/react-native-cesium-example.jpg +0 -0
  43. package/ios/CesiumBridge.h +55 -0
  44. package/ios/CesiumBridge.mm +393 -0
  45. package/ios/HybridCesiumView.swift +299 -0
  46. package/ios/ReactNativeCesium-umbrella.h +16 -0
  47. package/ios/metal/MetalBackend.h +82 -0
  48. package/ios/metal/MetalBackend.mm +839 -0
  49. package/ios/react_native_cesium_ensure_native.rb +12 -0
  50. package/ios/react_native_cesium_post_install.rb +30 -0
  51. package/lib/commonjs/CesiumView.js +13 -0
  52. package/lib/commonjs/CesiumView.js.map +1 -0
  53. package/lib/commonjs/index.js +13 -0
  54. package/lib/commonjs/index.js.map +1 -0
  55. package/lib/commonjs/package.json +1 -0
  56. package/lib/commonjs/specs/cesium-view.nitro.js +6 -0
  57. package/lib/commonjs/specs/cesium-view.nitro.js.map +1 -0
  58. package/lib/module/CesiumView.js +9 -0
  59. package/lib/module/CesiumView.js.map +1 -0
  60. package/lib/module/index.js +4 -0
  61. package/lib/module/index.js.map +1 -0
  62. package/lib/module/specs/cesium-view.nitro.js +4 -0
  63. package/lib/module/specs/cesium-view.nitro.js.map +1 -0
  64. package/lib/typescript/src/CesiumView.d.ts +5 -0
  65. package/lib/typescript/src/CesiumView.d.ts.map +1 -0
  66. package/lib/typescript/src/index.d.ts +3 -0
  67. package/lib/typescript/src/index.d.ts.map +1 -0
  68. package/lib/typescript/src/specs/cesium-view.nitro.d.ts +43 -0
  69. package/lib/typescript/src/specs/cesium-view.nitro.d.ts.map +1 -0
  70. package/nitro.json +30 -0
  71. package/nitrogen/generated/.gitattributes +1 -0
  72. package/nitrogen/generated/android/ReactNativeCesium+autolinking.cmake +83 -0
  73. package/nitrogen/generated/android/ReactNativeCesium+autolinking.gradle +27 -0
  74. package/nitrogen/generated/android/ReactNativeCesiumOnLoad.cpp +58 -0
  75. package/nitrogen/generated/android/ReactNativeCesiumOnLoad.hpp +34 -0
  76. package/nitrogen/generated/android/c++/JCameraState.hpp +81 -0
  77. package/nitrogen/generated/android/c++/JCesiumMetrics.hpp +81 -0
  78. package/nitrogen/generated/android/c++/JFunc_void_CesiumMetrics.hpp +78 -0
  79. package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.cpp +178 -0
  80. package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.hpp +83 -0
  81. package/nitrogen/generated/android/c++/views/JHybridCesiumViewStateUpdater.cpp +92 -0
  82. package/nitrogen/generated/android/c++/views/JHybridCesiumViewStateUpdater.hpp +49 -0
  83. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/CameraState.kt +56 -0
  84. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/CesiumMetrics.kt +56 -0
  85. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/Func_void_CesiumMetrics.kt +80 -0
  86. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/HybridCesiumViewSpec.kt +126 -0
  87. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/ReactNativeCesiumOnLoad.kt +35 -0
  88. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/views/HybridCesiumViewManager.kt +80 -0
  89. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/views/HybridCesiumViewStateUpdater.kt +23 -0
  90. package/nitrogen/generated/ios/ReactNativeCesium+autolinking.rb +60 -0
  91. package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Bridge.cpp +57 -0
  92. package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Bridge.hpp +164 -0
  93. package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Umbrella.hpp +53 -0
  94. package/nitrogen/generated/ios/ReactNativeCesiumAutolinking.mm +33 -0
  95. package/nitrogen/generated/ios/ReactNativeCesiumAutolinking.swift +26 -0
  96. package/nitrogen/generated/ios/c++/HybridCesiumViewSpecSwift.cpp +11 -0
  97. package/nitrogen/generated/ios/c++/HybridCesiumViewSpecSwift.hpp +157 -0
  98. package/nitrogen/generated/ios/c++/views/HybridCesiumViewComponent.mm +167 -0
  99. package/nitrogen/generated/ios/swift/CameraState.swift +59 -0
  100. package/nitrogen/generated/ios/swift/CesiumMetrics.swift +59 -0
  101. package/nitrogen/generated/ios/swift/Func_void_CameraState.swift +46 -0
  102. package/nitrogen/generated/ios/swift/Func_void_CesiumMetrics.swift +46 -0
  103. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
  104. package/nitrogen/generated/ios/swift/HybridCesiumViewSpec.swift +65 -0
  105. package/nitrogen/generated/ios/swift/HybridCesiumViewSpec_cxx.swift +306 -0
  106. package/nitrogen/generated/shared/c++/CameraState.hpp +107 -0
  107. package/nitrogen/generated/shared/c++/CesiumMetrics.hpp +107 -0
  108. package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.cpp +42 -0
  109. package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.hpp +90 -0
  110. package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.cpp +182 -0
  111. package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.hpp +122 -0
  112. package/nitrogen/generated/shared/json/CesiumViewConfig.json +19 -0
  113. package/package.json +140 -0
  114. package/react-native.config.js +16 -0
  115. package/scripts/cesium/build.mjs +901 -0
  116. package/scripts/cesium/clean.mjs +35 -0
  117. package/scripts/cesium/clone.mjs +32 -0
  118. package/scripts/cesium/ensure-native.mjs +116 -0
  119. package/scripts/cesium/vcpkg-ports/zstd/fix-emscripten-and-clang-cl.patch +31 -0
  120. package/scripts/cesium/vcpkg-ports/zstd/fix-windows-rc-compile.patch +13 -0
  121. package/scripts/cesium/vcpkg-ports/zstd/no-static-suffix.patch +13 -0
  122. package/scripts/cesium/vcpkg-ports/zstd/portfile.cmake +77 -0
  123. package/scripts/cesium/vcpkg-ports/zstd/usage +4 -0
  124. package/scripts/cesium/vcpkg-ports/zstd/vcpkg.json +23 -0
  125. package/scripts/cesium/vcpkg-triplets/arm64-ios-simulator.cmake +10 -0
  126. package/scripts/cesium/vcpkg-triplets/arm64-ios.cmake +14 -0
  127. package/src/CesiumView.tsx +13 -0
  128. package/src/index.ts +7 -0
  129. package/src/specs/cesium-view.nitro.ts +51 -0
@@ -0,0 +1,487 @@
1
+ #include "CesiumBridgeAndroid.h"
2
+
3
+ #include "engine/CesiumEngine.hpp"
4
+ #include "vulkan/VulkanBackend.h"
5
+
6
+ #include <android/native_window_jni.h>
7
+ #include <android/log.h>
8
+
9
+ #include <cmath>
10
+ #include <regex>
11
+ #include <sstream>
12
+
13
+ #define LOG_TAG "CesiumBridge"
14
+ #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
15
+ #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
16
+
17
+ // Per-DOF smoothing constants (match iOS CesiumBridge.mm)
18
+ static const double kSmoothAlt = 25.0;
19
+ static const double kSmoothHdg = 30.0;
20
+ static const double kSmoothRoll = 50.0;
21
+ static const double kSmoothPitch = 50.0;
22
+ static const double kEpsLatLon = 1e-7;
23
+ static const double kEpsAlt = 0.1;
24
+ static const double kEpsAngleDeg = 0.05;
25
+
26
+ static double lerpAngleDeg(double a, double b, double t) {
27
+ double diff = std::fmod(b - a + 540.0, 360.0) - 180.0;
28
+ return a + diff * t;
29
+ }
30
+
31
+ static double angleDeltaAbsDeg(double a, double b) {
32
+ return std::abs(std::fmod(b - a + 540.0, 360.0) - 180.0);
33
+ }
34
+
35
+ static std::string stripHtmlToPlain(const std::string& html) {
36
+ if (html.empty()) return "";
37
+ static const std::regex tagRx("<[^>]+>");
38
+ std::string plain = std::regex_replace(html, tagRx, " ");
39
+ static const std::regex wsRx("\\s+");
40
+ plain = std::regex_replace(plain, wsRx, " ");
41
+ // Trim
42
+ size_t start = plain.find_first_not_of(" \t\n\r");
43
+ size_t end = plain.find_last_not_of(" \t\n\r");
44
+ if (start == std::string::npos) return "";
45
+ return plain.substr(start, end - start + 1);
46
+ }
47
+
48
+ void CesiumBridgeAndroid::init(JNIEnv* env, jobject surface, int width, int height,
49
+ const std::string& cacheDir, const std::string& cacertPath) {
50
+ cacheDir_ = cacheDir;
51
+ cacertPath_ = cacertPath;
52
+ viewportWidth_ = width;
53
+ viewportHeight_ = height;
54
+
55
+ ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
56
+ if (!window) {
57
+ LOGE("Failed to get ANativeWindow from Surface");
58
+ return;
59
+ }
60
+
61
+ vulkanBackend_ = std::make_unique<reactnativecesium::VulkanBackend>();
62
+ vulkanBackend_->initialize(window, width, height);
63
+
64
+ frameResult_ = std::make_unique<reactnativecesium::FrameResult>();
65
+ buildEngine();
66
+ initialized_ = true;
67
+ forceRenderNextFrame_ = true;
68
+
69
+ LOGI("CesiumBridgeAndroid initialized %dx%d", width, height);
70
+ }
71
+
72
+ void CesiumBridgeAndroid::buildEngine() {
73
+ reactnativecesium::EngineConfig cfg;
74
+ cfg.ionAccessToken = ionAccessToken_;
75
+ cfg.ionAssetId = ionTilesetAssetId_;
76
+ cfg.cacheDatabasePath = cacheDir_.empty() ? "" : cacheDir_ + "/cesium_cache.db";
77
+ cfg.tlsCaBundlePath = cacertPath_;
78
+ cfg.maximumScreenSpaceError = std::max(1.0, maxSSE_);
79
+ cfg.maximumSimultaneousTileLoads = static_cast<int32_t>(std::max(0.0, std::round(maxSimLoads_)));
80
+ cfg.loadingDescendantLimit = static_cast<int32_t>(std::max(1.0, std::round(loadDescLim_)));
81
+
82
+ engine_ = std::make_unique<reactnativecesium::CesiumEngine>();
83
+ engine_->initialize(cfg);
84
+
85
+ auto params = engine_->camera().getParams();
86
+ camTargetLat_ = params.latitude;
87
+ camTargetLon_ = params.longitude;
88
+ camTargetAlt_ = params.altitude;
89
+ camTargetHeading_ = params.heading;
90
+ camTargetPitch_ = params.pitch;
91
+ camTargetRoll_ = params.roll;
92
+
93
+ auto* backendPtr = vulkanBackend_.get();
94
+ engine_->getResourcePreparer()->setGPUTextureCreator(
95
+ [backendPtr](const uint8_t* pixels, int32_t w, int32_t h) -> void* {
96
+ return backendPtr->createRasterTexture(pixels, w, h);
97
+ });
98
+ engine_->getResourcePreparer()->setGPUTextureDeleter(
99
+ [backendPtr](void* tex) {
100
+ if (tex) backendPtr->freeRasterTexture(tex);
101
+ });
102
+ engine_->getResourcePreparer()->setWaterMaskTextureCreator(
103
+ [backendPtr](const uint8_t* pixels, int32_t w, int32_t h) -> void* {
104
+ return backendPtr->createWaterMaskTexture(pixels, w, h);
105
+ });
106
+ engine_->getResourcePreparer()->setWaterMaskTextureDeleter(
107
+ [backendPtr](void* tex) {
108
+ if (tex) backendPtr->freeWaterMaskTexture(tex);
109
+ });
110
+ }
111
+
112
+ void CesiumBridgeAndroid::shutdown() {
113
+ if (engine_) engine_->shutdown();
114
+ if (vulkanBackend_) vulkanBackend_->shutdown();
115
+ initialized_ = false;
116
+ }
117
+
118
+ void CesiumBridgeAndroid::resize(int width, int height) {
119
+ viewportWidth_ = width;
120
+ viewportHeight_ = height;
121
+ if (vulkanBackend_) vulkanBackend_->resize(width, height);
122
+ forceRenderNextFrame_ = true;
123
+ }
124
+
125
+ void CesiumBridgeAndroid::updateIonAccessToken(const std::string& token, int64_t assetId) {
126
+ if (!initialized_) return;
127
+ ionAccessToken_ = token;
128
+ ionTilesetAssetId_ = assetId;
129
+
130
+ reactnativecesium::EngineConfig cfg;
131
+ cfg.ionAccessToken = ionAccessToken_;
132
+ cfg.ionAssetId = ionTilesetAssetId_;
133
+ cfg.cacheDatabasePath = cacheDir_.empty() ? "" : cacheDir_ + "/cesium_cache.db";
134
+ cfg.tlsCaBundlePath = cacertPath_;
135
+ cfg.maximumScreenSpaceError = std::max(1.0, maxSSE_);
136
+ cfg.maximumSimultaneousTileLoads = static_cast<int32_t>(std::max(0.0, std::round(maxSimLoads_)));
137
+ cfg.loadingDescendantLimit = static_cast<int32_t>(std::max(1.0, std::round(loadDescLim_)));
138
+
139
+ engine_->updateConfig(cfg);
140
+ forceRenderNextFrame_ = true;
141
+ }
142
+
143
+ void CesiumBridgeAndroid::updateImageryAssetId(int64_t assetId) {
144
+ if (!initialized_) return;
145
+ engine_->setImageryAssetId(assetId);
146
+ forceRenderNextFrame_ = true;
147
+ }
148
+
149
+ void CesiumBridgeAndroid::updateCamera(double lat, double lon, double alt,
150
+ double heading, double pitch, double roll) {
151
+ if (!initialized_) return;
152
+ camTargetLat_ = lat;
153
+ camTargetLon_ = lon;
154
+ camTargetAlt_ = alt;
155
+ camTargetHeading_ = heading;
156
+ camTargetPitch_ = pitch;
157
+ camTargetRoll_ = roll;
158
+ forceRenderNextFrame_ = true;
159
+ }
160
+
161
+ void CesiumBridgeAndroid::setVerticalFovDeg(double degrees) {
162
+ if (!initialized_) return;
163
+ engine_->camera().setVerticalFovDegrees(degrees);
164
+ forceRenderNextFrame_ = true;
165
+ }
166
+
167
+ void CesiumBridgeAndroid::setMaximumScreenSpaceError(double v) {
168
+ maxSSE_ = v;
169
+ if (!initialized_) return;
170
+ reactnativecesium::EngineConfig cfg;
171
+ cfg.ionAccessToken = ionAccessToken_;
172
+ cfg.ionAssetId = ionTilesetAssetId_;
173
+ cfg.cacheDatabasePath = cacheDir_.empty() ? "" : cacheDir_ + "/cesium_cache.db";
174
+ cfg.tlsCaBundlePath = cacertPath_;
175
+ cfg.maximumScreenSpaceError = std::max(1.0, maxSSE_);
176
+ cfg.maximumSimultaneousTileLoads = static_cast<int32_t>(std::max(0.0, std::round(maxSimLoads_)));
177
+ cfg.loadingDescendantLimit = static_cast<int32_t>(std::max(1.0, std::round(loadDescLim_)));
178
+ engine_->updateConfig(cfg);
179
+ forceRenderNextFrame_ = true;
180
+ }
181
+
182
+ void CesiumBridgeAndroid::setMaximumSimultaneousTileLoads(int v) {
183
+ maxSimLoads_ = static_cast<double>(v);
184
+ if (!initialized_) return;
185
+ setMaximumScreenSpaceError(maxSSE_); // reuses config rebuild path
186
+ }
187
+
188
+ void CesiumBridgeAndroid::setLoadingDescendantLimit(int v) {
189
+ loadDescLim_ = static_cast<double>(v);
190
+ if (!initialized_) return;
191
+ setMaximumScreenSpaceError(maxSSE_);
192
+ }
193
+
194
+ void CesiumBridgeAndroid::setMsaaSampleCount(int samples) {
195
+ if (vulkanBackend_) vulkanBackend_->setMsaaSampleCount(samples);
196
+ forceRenderNextFrame_ = true;
197
+ }
198
+
199
+ void CesiumBridgeAndroid::markNeedsRender() {
200
+ forceRenderNextFrame_ = true;
201
+ }
202
+
203
+ bool CesiumBridgeAndroid::shouldRenderNextFrame() {
204
+ if (!initialized_ || !engine_) return false;
205
+
206
+ const auto cur = engine_->camera().getParams();
207
+ const bool cameraDirty =
208
+ std::abs(camTargetLat_ - cur.latitude) > kEpsLatLon ||
209
+ std::abs(camTargetLon_ - cur.longitude) > kEpsLatLon ||
210
+ std::abs(camTargetAlt_ - cur.altitude) > kEpsAlt ||
211
+ angleDeltaAbsDeg(cur.heading, camTargetHeading_) > kEpsAngleDeg ||
212
+ angleDeltaAbsDeg(cur.pitch, camTargetPitch_) > kEpsAngleDeg ||
213
+ angleDeltaAbsDeg(cur.roll, camTargetRoll_) > kEpsAngleDeg;
214
+
215
+ return forceRenderNextFrame_ ||
216
+ frameResult_->tilesLoading > 0 ||
217
+ !frameResult_->tilesetActive ||
218
+ cameraDirty;
219
+ }
220
+
221
+ void CesiumBridgeAndroid::renderFrame(double dt) {
222
+ if (!initialized_) return;
223
+
224
+ auto cur = engine_->camera().getParams();
225
+
226
+ // Smooth follower: track camera target per DOF (same as iOS)
227
+ cur.latitude = camTargetLat_;
228
+ cur.longitude = camTargetLon_;
229
+
230
+ const double aAlt = 1.0 - std::exp(-kSmoothAlt * dt);
231
+ const double aHdg = 1.0 - std::exp(-kSmoothHdg * dt);
232
+ const double aPitch = 1.0 - std::exp(-kSmoothPitch * dt);
233
+ const double aRoll = 1.0 - std::exp(-kSmoothRoll * dt);
234
+
235
+ cur.altitude = cur.altitude + aAlt * (camTargetAlt_ - cur.altitude);
236
+ cur.heading = lerpAngleDeg(cur.heading, camTargetHeading_, aHdg);
237
+ cur.pitch = lerpAngleDeg(cur.pitch, camTargetPitch_, aPitch);
238
+ cur.roll = lerpAngleDeg(cur.roll, camTargetRoll_, aRoll);
239
+
240
+ if (std::abs(camTargetAlt_ - cur.altitude) <= kEpsAlt)
241
+ cur.altitude = camTargetAlt_;
242
+ if (angleDeltaAbsDeg(cur.heading, camTargetHeading_) <= kEpsAngleDeg)
243
+ cur.heading = camTargetHeading_;
244
+ if (angleDeltaAbsDeg(cur.pitch, camTargetPitch_) <= kEpsAngleDeg)
245
+ cur.pitch = camTargetPitch_;
246
+ if (angleDeltaAbsDeg(cur.roll, camTargetRoll_) <= kEpsAngleDeg)
247
+ cur.roll = camTargetRoll_;
248
+
249
+ engine_->camera().setParams(cur);
250
+ engine_->updateFrame(viewportWidth_, viewportHeight_, *frameResult_);
251
+
252
+ const double instFps = (dt > 1e-6) ? (1.0 / dt) : 0.0;
253
+ fpsEma_ = (fpsEma_ <= 1e-6) ? instFps : (fpsEma_ * 0.85 + instFps * 0.15);
254
+
255
+ if (++metricsTick_ >= 20) {
256
+ metricsTick_ = 0;
257
+ metricsFps_ = fpsEma_;
258
+ metricsTilesRendered_ = frameResult_->tilesRendered;
259
+ metricsTilesLoading_ = frameResult_->tilesLoading;
260
+ metricsTilesVisited_ = frameResult_->tilesVisited;
261
+ metricsIonTokenConfigured_ = frameResult_->ionTokenConfigured;
262
+ metricsTilesetReady_ = frameResult_->tilesetActive;
263
+
264
+ if (!frameResult_->creditHtmlLines.empty()) {
265
+ std::string joined;
266
+ for (const auto& html : frameResult_->creditHtmlLines) {
267
+ if (!joined.empty()) joined += "|";
268
+ joined += html;
269
+ }
270
+ if (joined != lastCreditHtmlJoined_) {
271
+ lastCreditHtmlJoined_ = joined;
272
+ std::string credits;
273
+ for (const auto& html : frameResult_->creditHtmlLines) {
274
+ std::string chunk = stripHtmlToPlain(html);
275
+ if (chunk.empty()) continue;
276
+ if (!credits.empty()) credits += " · ";
277
+ credits += chunk;
278
+ }
279
+ metricsCreditsPlainText_ = credits;
280
+ }
281
+ } else {
282
+ lastCreditHtmlJoined_.clear();
283
+ metricsCreditsPlainText_.clear();
284
+ }
285
+ }
286
+
287
+ reactnativecesium::FrameParams params;
288
+ vulkanBackend_->beginFrame(params);
289
+ vulkanBackend_->drawScene(*frameResult_);
290
+ vulkanBackend_->endFrame();
291
+ forceRenderNextFrame_ = false;
292
+ }
293
+
294
+ double CesiumBridgeAndroid::readCameraLatitude() {
295
+ return engine_ ? engine_->camera().getParams().latitude : 0.0;
296
+ }
297
+ double CesiumBridgeAndroid::readCameraLongitude() {
298
+ return engine_ ? engine_->camera().getParams().longitude : 0.0;
299
+ }
300
+ double CesiumBridgeAndroid::readCameraAltitude() {
301
+ return engine_ ? engine_->camera().getParams().altitude : 0.0;
302
+ }
303
+ double CesiumBridgeAndroid::readCameraHeading() {
304
+ return engine_ ? engine_->camera().getParams().heading : 0.0;
305
+ }
306
+ double CesiumBridgeAndroid::readCameraPitch() {
307
+ return engine_ ? engine_->camera().getParams().pitch : 0.0;
308
+ }
309
+ double CesiumBridgeAndroid::readCameraRoll() {
310
+ return engine_ ? engine_->camera().getParams().roll : 0.0;
311
+ }
312
+ double CesiumBridgeAndroid::readVerticalFovDeg() {
313
+ return engine_ ? engine_->camera().getVerticalFovDegrees() : 60.0;
314
+ }
315
+
316
+ // ── JNI native method implementations ──────────────────────────────────────────
317
+
318
+ static CesiumBridgeAndroid* getBridge(jlong ptr) {
319
+ return reinterpret_cast<CesiumBridgeAndroid*>(ptr);
320
+ }
321
+
322
+ extern "C" {
323
+
324
+ JNIEXPORT jlong JNICALL
325
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeCreate(JNIEnv*, jobject) {
326
+ return reinterpret_cast<jlong>(new CesiumBridgeAndroid());
327
+ }
328
+
329
+ JNIEXPORT void JNICALL
330
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeInit(
331
+ JNIEnv* env, jobject, jlong ptr, jobject surface, jint w, jint h,
332
+ jstring cacheDir, jstring cacertPath) {
333
+ const char* cacheDirC = env->GetStringUTFChars(cacheDir, nullptr);
334
+ const char* cacertC = env->GetStringUTFChars(cacertPath, nullptr);
335
+ getBridge(ptr)->init(env, surface, w, h, cacheDirC, cacertC);
336
+ env->ReleaseStringUTFChars(cacheDir, cacheDirC);
337
+ env->ReleaseStringUTFChars(cacertPath, cacertC);
338
+ }
339
+
340
+ JNIEXPORT void JNICALL
341
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeShutdown(JNIEnv*, jobject, jlong ptr) {
342
+ getBridge(ptr)->shutdown();
343
+ }
344
+
345
+ JNIEXPORT void JNICALL
346
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeDestroy(JNIEnv*, jobject, jlong ptr) {
347
+ delete getBridge(ptr);
348
+ }
349
+
350
+ JNIEXPORT void JNICALL
351
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeResize(JNIEnv*, jobject, jlong ptr, jint w, jint h) {
352
+ getBridge(ptr)->resize(w, h);
353
+ }
354
+
355
+ JNIEXPORT void JNICALL
356
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeUpdateIonAccessToken(
357
+ JNIEnv* env, jobject, jlong ptr, jstring token, jlong assetId) {
358
+ const char* tokenC = env->GetStringUTFChars(token, nullptr);
359
+ getBridge(ptr)->updateIonAccessToken(tokenC, assetId);
360
+ env->ReleaseStringUTFChars(token, tokenC);
361
+ }
362
+
363
+ JNIEXPORT void JNICALL
364
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeUpdateImageryAssetId(
365
+ JNIEnv*, jobject, jlong ptr, jlong assetId) {
366
+ getBridge(ptr)->updateImageryAssetId(assetId);
367
+ }
368
+
369
+ JNIEXPORT void JNICALL
370
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeUpdateCamera(
371
+ JNIEnv*, jobject, jlong ptr, jdouble lat, jdouble lon, jdouble alt,
372
+ jdouble heading, jdouble pitch, jdouble roll) {
373
+ getBridge(ptr)->updateCamera(lat, lon, alt, heading, pitch, roll);
374
+ }
375
+
376
+ JNIEXPORT void JNICALL
377
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetVerticalFovDeg(
378
+ JNIEnv*, jobject, jlong ptr, jdouble deg) {
379
+ getBridge(ptr)->setVerticalFovDeg(deg);
380
+ }
381
+
382
+ JNIEXPORT void JNICALL
383
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetMaxSSE(JNIEnv*, jobject, jlong ptr, jdouble v) {
384
+ getBridge(ptr)->setMaximumScreenSpaceError(v);
385
+ }
386
+
387
+ JNIEXPORT void JNICALL
388
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetMaxSimLoads(JNIEnv*, jobject, jlong ptr, jint v) {
389
+ getBridge(ptr)->setMaximumSimultaneousTileLoads(v);
390
+ }
391
+
392
+ JNIEXPORT void JNICALL
393
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetLoadDescLim(JNIEnv*, jobject, jlong ptr, jint v) {
394
+ getBridge(ptr)->setLoadingDescendantLimit(v);
395
+ }
396
+
397
+ JNIEXPORT void JNICALL
398
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetMsaa(JNIEnv*, jobject, jlong ptr, jint v) {
399
+ getBridge(ptr)->setMsaaSampleCount(v);
400
+ }
401
+
402
+ JNIEXPORT void JNICALL
403
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeMarkNeedsRender(JNIEnv*, jobject, jlong ptr) {
404
+ getBridge(ptr)->markNeedsRender();
405
+ }
406
+
407
+ JNIEXPORT jboolean JNICALL
408
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeShouldRenderNextFrame(JNIEnv*, jobject, jlong ptr) {
409
+ return getBridge(ptr)->shouldRenderNextFrame() ? JNI_TRUE : JNI_FALSE;
410
+ }
411
+
412
+ JNIEXPORT void JNICALL
413
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeRenderFrame(JNIEnv*, jobject, jlong ptr, jdouble dt) {
414
+ getBridge(ptr)->renderFrame(dt);
415
+ }
416
+
417
+ JNIEXPORT jdouble JNICALL
418
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetCameraLat(JNIEnv*, jobject, jlong ptr) {
419
+ return getBridge(ptr)->readCameraLatitude();
420
+ }
421
+
422
+ JNIEXPORT jdouble JNICALL
423
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetCameraLon(JNIEnv*, jobject, jlong ptr) {
424
+ return getBridge(ptr)->readCameraLongitude();
425
+ }
426
+
427
+ JNIEXPORT jdouble JNICALL
428
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetCameraAlt(JNIEnv*, jobject, jlong ptr) {
429
+ return getBridge(ptr)->readCameraAltitude();
430
+ }
431
+
432
+ JNIEXPORT jdouble JNICALL
433
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetCameraHeading(JNIEnv*, jobject, jlong ptr) {
434
+ return getBridge(ptr)->readCameraHeading();
435
+ }
436
+
437
+ JNIEXPORT jdouble JNICALL
438
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetCameraPitch(JNIEnv*, jobject, jlong ptr) {
439
+ return getBridge(ptr)->readCameraPitch();
440
+ }
441
+
442
+ JNIEXPORT jdouble JNICALL
443
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetCameraRoll(JNIEnv*, jobject, jlong ptr) {
444
+ return getBridge(ptr)->readCameraRoll();
445
+ }
446
+
447
+ JNIEXPORT jdouble JNICALL
448
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetVerticalFovDeg(JNIEnv*, jobject, jlong ptr) {
449
+ return getBridge(ptr)->readVerticalFovDeg();
450
+ }
451
+
452
+ JNIEXPORT jdouble JNICALL
453
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetMetricsFps(JNIEnv*, jobject, jlong ptr) {
454
+ return getBridge(ptr)->metricsFps();
455
+ }
456
+
457
+ JNIEXPORT jint JNICALL
458
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetMetricsTilesRendered(JNIEnv*, jobject, jlong ptr) {
459
+ return getBridge(ptr)->metricsTilesRendered();
460
+ }
461
+
462
+ JNIEXPORT jint JNICALL
463
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetMetricsTilesLoading(JNIEnv*, jobject, jlong ptr) {
464
+ return getBridge(ptr)->metricsTilesLoading();
465
+ }
466
+
467
+ JNIEXPORT jint JNICALL
468
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetMetricsTilesVisited(JNIEnv*, jobject, jlong ptr) {
469
+ return getBridge(ptr)->metricsTilesVisited();
470
+ }
471
+
472
+ JNIEXPORT jboolean JNICALL
473
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetMetricsIonTokenConfigured(JNIEnv*, jobject, jlong ptr) {
474
+ return getBridge(ptr)->metricsIonTokenConfigured() ? JNI_TRUE : JNI_FALSE;
475
+ }
476
+
477
+ JNIEXPORT jboolean JNICALL
478
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetMetricsTilesetReady(JNIEnv*, jobject, jlong ptr) {
479
+ return getBridge(ptr)->metricsTilesetReady() ? JNI_TRUE : JNI_FALSE;
480
+ }
481
+
482
+ JNIEXPORT jstring JNICALL
483
+ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetMetricsCreditsPlainText(JNIEnv* env, jobject, jlong ptr) {
484
+ return env->NewStringUTF(getBridge(ptr)->metricsCreditsPlainText().c_str());
485
+ }
486
+
487
+ } // extern "C"
@@ -0,0 +1,94 @@
1
+ #pragma once
2
+
3
+ #include <jni.h>
4
+ #include <memory>
5
+ #include <string>
6
+
7
+ namespace reactnativecesium {
8
+ class VulkanBackend;
9
+ class CesiumEngine;
10
+ struct FrameResult;
11
+ struct CameraParams;
12
+ }
13
+
14
+ struct CesiumBridgeAndroid {
15
+ void init(JNIEnv* env, jobject surface, int width, int height,
16
+ const std::string& cacheDir, const std::string& cacertPath);
17
+ void shutdown();
18
+
19
+ void resize(int width, int height);
20
+
21
+ void updateIonAccessToken(const std::string& token, int64_t assetId);
22
+ void updateImageryAssetId(int64_t assetId);
23
+ void updateCamera(double lat, double lon, double alt,
24
+ double heading, double pitch, double roll);
25
+ void setVerticalFovDeg(double degrees);
26
+ void setMaximumScreenSpaceError(double v);
27
+ void setMaximumSimultaneousTileLoads(int v);
28
+ void setLoadingDescendantLimit(int v);
29
+ void setMsaaSampleCount(int samples);
30
+
31
+ void markNeedsRender();
32
+ bool shouldRenderNextFrame();
33
+ void renderFrame(double dt);
34
+
35
+ // Camera readback
36
+ double readCameraLatitude();
37
+ double readCameraLongitude();
38
+ double readCameraAltitude();
39
+ double readCameraHeading();
40
+ double readCameraPitch();
41
+ double readCameraRoll();
42
+ double readVerticalFovDeg();
43
+
44
+ // Metrics
45
+ double metricsFps() const { return metricsFps_; }
46
+ int metricsTilesRendered() const { return metricsTilesRendered_; }
47
+ int metricsTilesLoading() const { return metricsTilesLoading_; }
48
+ int metricsTilesVisited() const { return metricsTilesVisited_; }
49
+ bool metricsIonTokenConfigured() const { return metricsIonTokenConfigured_; }
50
+ bool metricsTilesetReady() const { return metricsTilesetReady_; }
51
+ const std::string& metricsCreditsPlainText() const { return metricsCreditsPlainText_; }
52
+
53
+ private:
54
+ void buildEngine();
55
+ reactnativecesium::CameraParams makeCamTarget();
56
+
57
+ std::unique_ptr<reactnativecesium::VulkanBackend> vulkanBackend_;
58
+ std::unique_ptr<reactnativecesium::CesiumEngine> engine_;
59
+ std::unique_ptr<reactnativecesium::FrameResult> frameResult_;
60
+
61
+ int viewportWidth_ = 0;
62
+ int viewportHeight_ = 0;
63
+ bool initialized_ = false;
64
+
65
+ std::string cacheDir_;
66
+ std::string cacertPath_;
67
+ std::string ionAccessToken_;
68
+ int64_t ionTilesetAssetId_ = 1;
69
+
70
+ double maxSSE_ = 32.0;
71
+ double maxSimLoads_ = 12.0;
72
+ double loadDescLim_ = 20.0;
73
+
74
+ // Camera demand target
75
+ double camTargetLat_ = 46.15;
76
+ double camTargetLon_ = 7.35;
77
+ double camTargetAlt_ = 12000.0;
78
+ double camTargetHeading_ = 129.0;
79
+ double camTargetPitch_ = -45.0;
80
+ double camTargetRoll_ = 0.0;
81
+ bool forceRenderNextFrame_ = true;
82
+
83
+ // Metrics
84
+ double fpsEma_ = 0.0;
85
+ int metricsTick_ = 0;
86
+ double metricsFps_ = 0.0;
87
+ int metricsTilesRendered_ = 0;
88
+ int metricsTilesLoading_ = 0;
89
+ int metricsTilesVisited_ = 0;
90
+ bool metricsIonTokenConfigured_ = false;
91
+ bool metricsTilesetReady_ = false;
92
+ std::string metricsCreditsPlainText_;
93
+ std::string lastCreditHtmlJoined_;
94
+ };
@@ -0,0 +1,17 @@
1
+ #include <jni.h>
2
+ #include <fbjni/fbjni.h>
3
+ #include <vulkan/vulkan.h>
4
+
5
+ #include "ReactNativeCesiumOnLoad.hpp"
6
+
7
+ #include <Cesium3DTilesContent/registerAllTileContentTypes.h>
8
+
9
+ static const uint32_t kCesiumVulkanApiVersion = VK_MAKE_VERSION(1, 1, 0);
10
+
11
+ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
12
+ (void)kCesiumVulkanApiVersion;
13
+ Cesium3DTilesContent::registerAllTileContentTypes();
14
+ return facebook::jni::initialize(vm, []() {
15
+ margelo::nitro::reactnativecesium::registerAllNatives();
16
+ });
17
+ }