react-native-cesium 1.0.6 → 1.2.0
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/README.md +64 -11
- package/ReactNativeCesium.podspec +1 -1
- package/android/CMakeLists.txt +5 -3
- package/android/src/main/cpp/CesiumBridgeAndroid.cpp +197 -227
- package/android/src/main/cpp/CesiumBridgeAndroid.h +48 -49
- package/android/src/main/cpp/cpp-adapter.cpp +2 -2
- package/android/src/main/cpp/vulkan/VulkanBackend.cpp +1010 -569
- package/android/src/main/cpp/vulkan/VulkanBackend.h +121 -12
- package/android/src/main/cpp/vulkan/shaders/sky.frag +20 -10
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/CesiumBridgeJNI.kt +28 -0
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/HybridCesiumView.kt +295 -58
- package/cpp/engine/CameraSmoother.cpp +99 -0
- package/cpp/engine/CameraSmoother.hpp +29 -0
- package/cpp/engine/CameraTargetState.cpp +49 -0
- package/cpp/engine/CameraTargetState.hpp +121 -0
- package/cpp/engine/CesiumEngine.cpp +206 -60
- package/cpp/engine/CesiumEngine.hpp +77 -10
- package/cpp/engine/EngineTunables.hpp +79 -0
- package/cpp/engine/GeoidConverter.cpp +36 -0
- package/cpp/engine/GeoidConverter.hpp +10 -0
- package/cpp/engine/GlobeCamera.cpp +7 -2
- package/cpp/engine/MetricsAggregator.cpp +71 -0
- package/cpp/engine/MetricsAggregator.hpp +54 -0
- package/cpp/engine/TileLifecycleManager.cpp +0 -12
- package/cpp/engine/TileLifecycleManager.hpp +0 -3
- package/cpp/third_party/egm96/EGM96.c +289 -0
- package/cpp/third_party/egm96/EGM96.h +45 -0
- package/cpp/third_party/egm96/EGM96_data.h +65372 -0
- package/ios/CesiumBridge.h +24 -5
- package/ios/CesiumBridge.mm +149 -271
- package/ios/HybridCesiumView.swift +197 -40
- package/ios/metal/MetalBackend.mm +72 -23
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts +26 -0
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JCesiumMetrics.hpp +5 -1
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.cpp +109 -1
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.hpp +24 -0
- package/nitrogen/generated/android/c++/views/JHybridCesiumViewStateUpdater.cpp +48 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/CameraState.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/CesiumMetrics.kt +32 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/HybridCesiumViewSpec.kt +72 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/Quaternion.kt +19 -0
- package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Bridge.hpp +30 -0
- package/nitrogen/generated/ios/c++/HybridCesiumViewSpecSwift.hpp +85 -1
- package/nitrogen/generated/ios/c++/views/HybridCesiumViewComponent.mm +60 -0
- package/nitrogen/generated/ios/swift/CesiumMetrics.swift +7 -2
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec.swift +12 -0
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec_cxx.swift +288 -0
- package/nitrogen/generated/shared/c++/CesiumMetrics.hpp +5 -1
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.cpp +24 -0
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.hpp +25 -1
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.cpp +132 -0
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.hpp +13 -1
- package/nitrogen/generated/shared/json/CesiumViewConfig.json +12 -0
- package/package.json +4 -4
- package/scripts/cesium/clone.mjs +1 -1
- package/src/specs/cesium-view.nitro.ts +29 -0
- package/cpp/engine/DeletionQueue.cpp +0 -28
- package/cpp/engine/DeletionQueue.hpp +0 -28
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#include "CesiumBridgeAndroid.h"
|
|
2
2
|
|
|
3
|
-
#include "engine/
|
|
3
|
+
#include "engine/CameraSmoother.hpp"
|
|
4
|
+
#include "engine/EngineTunables.hpp"
|
|
4
5
|
#include "vulkan/VulkanBackend.h"
|
|
5
6
|
|
|
6
7
|
#include <android/native_window_jni.h>
|
|
@@ -8,55 +9,18 @@
|
|
|
8
9
|
|
|
9
10
|
#include <glm/gtc/quaternion.hpp>
|
|
10
11
|
|
|
12
|
+
#include <algorithm>
|
|
11
13
|
#include <cmath>
|
|
12
|
-
#include <regex>
|
|
13
|
-
#include <sstream>
|
|
14
14
|
|
|
15
15
|
#define LOG_TAG "CesiumBridge"
|
|
16
16
|
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
|
|
17
17
|
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
|
|
18
18
|
|
|
19
|
-
// Per-DOF smoothing constants (match iOS CesiumBridge.mm)
|
|
20
|
-
static const double kSmoothAlt = 25.0;
|
|
21
|
-
static const double kSmoothHdg = 30.0;
|
|
22
|
-
static const double kSmoothRoll = 50.0;
|
|
23
|
-
static const double kSmoothPitch = 50.0;
|
|
24
|
-
static const double kSmoothViewCorr = 50.0;
|
|
25
|
-
static const double kEpsLatLon = 1e-7;
|
|
26
|
-
static const double kEpsAlt = 0.1;
|
|
27
|
-
static const double kEpsAngleDeg = 0.05;
|
|
28
|
-
static const double kEpsQuatDot = 1e-8;
|
|
29
|
-
|
|
30
|
-
static double quatDotAbs(const glm::dquat& a, const glm::dquat& b) {
|
|
31
|
-
return std::abs(glm::dot(glm::normalize(a), glm::normalize(b)));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
static double lerpAngleDeg(double a, double b, double t) {
|
|
35
|
-
double diff = std::fmod(b - a + 540.0, 360.0) - 180.0;
|
|
36
|
-
return a + diff * t;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
static double angleDeltaAbsDeg(double a, double b) {
|
|
40
|
-
return std::abs(std::fmod(b - a + 540.0, 360.0) - 180.0);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
static std::string stripHtmlToPlain(const std::string& html) {
|
|
44
|
-
if (html.empty()) return "";
|
|
45
|
-
static const std::regex tagRx("<[^>]+>");
|
|
46
|
-
std::string plain = std::regex_replace(html, tagRx, " ");
|
|
47
|
-
static const std::regex wsRx("\\s+");
|
|
48
|
-
plain = std::regex_replace(plain, wsRx, " ");
|
|
49
|
-
// Trim
|
|
50
|
-
size_t start = plain.find_first_not_of(" \t\n\r");
|
|
51
|
-
size_t end = plain.find_last_not_of(" \t\n\r");
|
|
52
|
-
if (start == std::string::npos) return "";
|
|
53
|
-
return plain.substr(start, end - start + 1);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
19
|
void CesiumBridgeAndroid::init(JNIEnv* env, jobject surface, int width, int height,
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
20
|
+
const std::string& cacheDir,
|
|
21
|
+
const std::string& cacertPath) {
|
|
22
|
+
config_.cacheDatabasePath = cacheDir.empty() ? "" : cacheDir + "/cesium_cache.db";
|
|
23
|
+
config_.tlsCaBundlePath = cacertPath;
|
|
60
24
|
viewportWidth_ = width;
|
|
61
25
|
viewportHeight_ = height;
|
|
62
26
|
|
|
@@ -67,40 +31,22 @@ void CesiumBridgeAndroid::init(JNIEnv* env, jobject surface, int width, int heig
|
|
|
67
31
|
}
|
|
68
32
|
|
|
69
33
|
vulkanBackend_ = std::make_unique<reactnativecesium::VulkanBackend>();
|
|
34
|
+
vulkanBackend_->setCacheDir(cacheDir);
|
|
70
35
|
vulkanBackend_->initialize(window, width, height);
|
|
71
36
|
|
|
72
37
|
frameResult_ = std::make_unique<reactnativecesium::FrameResult>();
|
|
73
38
|
buildEngine();
|
|
74
39
|
initialized_ = true;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
LOGI("CesiumBridgeAndroid initialized %dx%d", width, height);
|
|
40
|
+
target_.requestForceRender();
|
|
78
41
|
}
|
|
79
42
|
|
|
80
43
|
void CesiumBridgeAndroid::buildEngine() {
|
|
81
|
-
reactnativecesium::EngineConfig cfg;
|
|
82
|
-
cfg.ionAccessToken = ionAccessToken_;
|
|
83
|
-
cfg.ionAssetId = ionTilesetAssetId_;
|
|
84
|
-
cfg.cacheDatabasePath = cacheDir_.empty() ? "" : cacheDir_ + "/cesium_cache.db";
|
|
85
|
-
cfg.tlsCaBundlePath = cacertPath_;
|
|
86
|
-
cfg.maximumScreenSpaceError = std::max(1.0, maxSSE_);
|
|
87
|
-
cfg.maximumSimultaneousTileLoads = static_cast<int32_t>(std::max(0.0, std::round(maxSimLoads_)));
|
|
88
|
-
cfg.loadingDescendantLimit = static_cast<int32_t>(std::max(1.0, std::round(loadDescLim_)));
|
|
89
|
-
|
|
90
44
|
engine_ = std::make_unique<reactnativecesium::CesiumEngine>();
|
|
91
|
-
engine_->initialize(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
camTargetAlt_ = params.altitude;
|
|
97
|
-
camTargetHeading_ = params.heading;
|
|
98
|
-
camTargetPitch_ = params.pitch;
|
|
99
|
-
camTargetRoll_ = params.roll;
|
|
100
|
-
camTargetViewQw_ = params.viewCorrection.w;
|
|
101
|
-
camTargetViewQx_ = params.viewCorrection.x;
|
|
102
|
-
camTargetViewQy_ = params.viewCorrection.y;
|
|
103
|
-
camTargetViewQz_ = params.viewCorrection.z;
|
|
45
|
+
engine_->initialize(config_);
|
|
46
|
+
|
|
47
|
+
// Seed the demand target from the engine's initial camera so the first
|
|
48
|
+
// frame is not a "snap from default" jump.
|
|
49
|
+
target_.setAll(engine_->camera().getParams());
|
|
104
50
|
|
|
105
51
|
auto* backendPtr = vulkanBackend_.get();
|
|
106
52
|
engine_->getResourcePreparer()->setGPUTextureCreator(
|
|
@@ -121,6 +67,12 @@ void CesiumBridgeAndroid::buildEngine() {
|
|
|
121
67
|
});
|
|
122
68
|
}
|
|
123
69
|
|
|
70
|
+
void CesiumBridgeAndroid::applyEngineConfig() {
|
|
71
|
+
if (!engine_) return;
|
|
72
|
+
engine_->updateConfig(config_);
|
|
73
|
+
target_.requestForceRender();
|
|
74
|
+
}
|
|
75
|
+
|
|
124
76
|
void CesiumBridgeAndroid::shutdown() {
|
|
125
77
|
if (engine_) engine_->shutdown();
|
|
126
78
|
if (vulkanBackend_) vulkanBackend_->shutdown();
|
|
@@ -131,213 +83,178 @@ void CesiumBridgeAndroid::resize(int width, int height) {
|
|
|
131
83
|
viewportWidth_ = width;
|
|
132
84
|
viewportHeight_ = height;
|
|
133
85
|
if (vulkanBackend_) vulkanBackend_->resize(width, height);
|
|
134
|
-
|
|
86
|
+
target_.requestForceRender();
|
|
135
87
|
}
|
|
136
88
|
|
|
137
|
-
void CesiumBridgeAndroid::updateIonAccessToken(const std::string& token,
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
reactnativecesium::EngineConfig cfg;
|
|
143
|
-
cfg.ionAccessToken = ionAccessToken_;
|
|
144
|
-
cfg.ionAssetId = ionTilesetAssetId_;
|
|
145
|
-
cfg.cacheDatabasePath = cacheDir_.empty() ? "" : cacheDir_ + "/cesium_cache.db";
|
|
146
|
-
cfg.tlsCaBundlePath = cacertPath_;
|
|
147
|
-
cfg.maximumScreenSpaceError = std::max(1.0, maxSSE_);
|
|
148
|
-
cfg.maximumSimultaneousTileLoads = static_cast<int32_t>(std::max(0.0, std::round(maxSimLoads_)));
|
|
149
|
-
cfg.loadingDescendantLimit = static_cast<int32_t>(std::max(1.0, std::round(loadDescLim_)));
|
|
150
|
-
|
|
151
|
-
engine_->updateConfig(cfg);
|
|
152
|
-
forceRenderNextFrame_ = true;
|
|
89
|
+
void CesiumBridgeAndroid::updateIonAccessToken(const std::string& token,
|
|
90
|
+
int64_t assetId) {
|
|
91
|
+
config_.ionAccessToken = token;
|
|
92
|
+
config_.ionAssetId = assetId;
|
|
93
|
+
if (initialized_) applyEngineConfig();
|
|
153
94
|
}
|
|
154
95
|
|
|
155
96
|
void CesiumBridgeAndroid::updateImageryAssetId(int64_t assetId) {
|
|
156
|
-
|
|
157
|
-
engine_
|
|
158
|
-
|
|
97
|
+
config_.ionImageryAssetId = (assetId <= 0) ? 1 : assetId;
|
|
98
|
+
if (initialized_ && engine_) {
|
|
99
|
+
engine_->setImageryAssetId(config_.ionImageryAssetId);
|
|
100
|
+
target_.requestForceRender();
|
|
101
|
+
}
|
|
159
102
|
}
|
|
160
103
|
|
|
161
104
|
void CesiumBridgeAndroid::updateCamera(double lat, double lon, double alt,
|
|
162
|
-
|
|
105
|
+
double heading, double pitch, double roll) {
|
|
163
106
|
if (!initialized_) return;
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// Does not change camTargetViewQ* (view correction target).
|
|
171
|
-
forceRenderNextFrame_ = true;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
void CesiumBridgeAndroid::updateCameraQuaternion(double lat, double lon, double alt,
|
|
175
|
-
double heading, double pitch, double roll,
|
|
176
|
-
double qw, double qx, double qy, double qz) {
|
|
107
|
+
target_.setHpr(lat, lon, alt, heading, pitch, roll);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
void CesiumBridgeAndroid::updateCameraQuaternion(
|
|
111
|
+
double lat, double lon, double alt, double heading, double pitch,
|
|
112
|
+
double roll, double qw, double qx, double qy, double qz) {
|
|
177
113
|
if (!initialized_) return;
|
|
178
|
-
|
|
179
|
-
camTargetLon_ = lon;
|
|
180
|
-
camTargetAlt_ = alt;
|
|
181
|
-
camTargetHeading_ = heading;
|
|
182
|
-
camTargetPitch_ = pitch;
|
|
183
|
-
camTargetRoll_ = roll;
|
|
114
|
+
target_.setHpr(lat, lon, alt, heading, pitch, roll);
|
|
184
115
|
const double ql2 = qw * qw + qx * qx + qy * qy + qz * qz;
|
|
185
|
-
glm::dquat
|
|
116
|
+
glm::dquat q;
|
|
186
117
|
if (ql2 < 1e-20) {
|
|
187
118
|
q = glm::dquat(1.0, 0.0, 0.0, 0.0);
|
|
188
119
|
} else {
|
|
189
120
|
const double inv = 1.0 / std::sqrt(ql2);
|
|
190
121
|
q = glm::dquat(qw * inv, qx * inv, qy * inv, qz * inv);
|
|
191
122
|
}
|
|
192
|
-
|
|
193
|
-
camTargetViewQx_ = q.x;
|
|
194
|
-
camTargetViewQy_ = q.y;
|
|
195
|
-
camTargetViewQz_ = q.z;
|
|
196
|
-
forceRenderNextFrame_ = true;
|
|
123
|
+
target_.setViewCorrection(q);
|
|
197
124
|
}
|
|
198
125
|
|
|
199
126
|
void CesiumBridgeAndroid::setVerticalFovDeg(double degrees) {
|
|
200
127
|
if (!initialized_) return;
|
|
201
128
|
engine_->camera().setVerticalFovDegrees(degrees);
|
|
202
|
-
|
|
129
|
+
target_.requestForceRender();
|
|
203
130
|
}
|
|
204
131
|
|
|
205
132
|
void CesiumBridgeAndroid::setMaximumScreenSpaceError(double v) {
|
|
206
|
-
|
|
207
|
-
if (
|
|
208
|
-
reactnativecesium::EngineConfig cfg;
|
|
209
|
-
cfg.ionAccessToken = ionAccessToken_;
|
|
210
|
-
cfg.ionAssetId = ionTilesetAssetId_;
|
|
211
|
-
cfg.cacheDatabasePath = cacheDir_.empty() ? "" : cacheDir_ + "/cesium_cache.db";
|
|
212
|
-
cfg.tlsCaBundlePath = cacertPath_;
|
|
213
|
-
cfg.maximumScreenSpaceError = std::max(1.0, maxSSE_);
|
|
214
|
-
cfg.maximumSimultaneousTileLoads = static_cast<int32_t>(std::max(0.0, std::round(maxSimLoads_)));
|
|
215
|
-
cfg.loadingDescendantLimit = static_cast<int32_t>(std::max(1.0, std::round(loadDescLim_)));
|
|
216
|
-
engine_->updateConfig(cfg);
|
|
217
|
-
forceRenderNextFrame_ = true;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
void CesiumBridgeAndroid::setMaximumSimultaneousTileLoads(int v) {
|
|
221
|
-
maxSimLoads_ = static_cast<double>(v);
|
|
222
|
-
if (!initialized_) return;
|
|
223
|
-
setMaximumScreenSpaceError(maxSSE_); // reuses config rebuild path
|
|
133
|
+
config_.maximumScreenSpaceError = v;
|
|
134
|
+
if (initialized_) applyEngineConfig();
|
|
224
135
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
136
|
+
void CesiumBridgeAndroid::setMaximumSimultaneousTileLoads(int32_t v) {
|
|
137
|
+
config_.maximumSimultaneousTileLoads = v;
|
|
138
|
+
if (initialized_) applyEngineConfig();
|
|
139
|
+
}
|
|
140
|
+
void CesiumBridgeAndroid::setLoadingDescendantLimit(int32_t v) {
|
|
141
|
+
config_.loadingDescendantLimit = v;
|
|
142
|
+
if (initialized_) applyEngineConfig();
|
|
230
143
|
}
|
|
231
144
|
|
|
232
145
|
void CesiumBridgeAndroid::setMsaaSampleCount(int samples) {
|
|
233
146
|
if (vulkanBackend_) vulkanBackend_->setMsaaSampleCount(samples);
|
|
234
|
-
|
|
147
|
+
target_.requestForceRender();
|
|
235
148
|
}
|
|
236
149
|
|
|
237
|
-
void CesiumBridgeAndroid::
|
|
238
|
-
|
|
150
|
+
void CesiumBridgeAndroid::setMaximumCachedMiB(int32_t v) {
|
|
151
|
+
config_.maximumCachedBytes =
|
|
152
|
+
static_cast<int64_t>(std::max(16, v)) * 1024LL * 1024LL;
|
|
153
|
+
if (initialized_) applyEngineConfig();
|
|
154
|
+
}
|
|
155
|
+
void CesiumBridgeAndroid::setPreloadAncestors(bool v) {
|
|
156
|
+
config_.preloadAncestors = v;
|
|
157
|
+
if (initialized_) applyEngineConfig();
|
|
158
|
+
}
|
|
159
|
+
void CesiumBridgeAndroid::setPreloadSiblings(bool v) {
|
|
160
|
+
config_.preloadSiblings = v;
|
|
161
|
+
if (initialized_) applyEngineConfig();
|
|
162
|
+
}
|
|
163
|
+
void CesiumBridgeAndroid::setForbidHoles(bool v) {
|
|
164
|
+
config_.forbidHoles = v;
|
|
165
|
+
if (initialized_) applyEngineConfig();
|
|
166
|
+
}
|
|
167
|
+
void CesiumBridgeAndroid::setEnableWaterMask(bool v) {
|
|
168
|
+
config_.enableWaterMask = v;
|
|
169
|
+
if (initialized_) applyEngineConfig();
|
|
170
|
+
}
|
|
171
|
+
void CesiumBridgeAndroid::setEnableFogCulling(bool v) {
|
|
172
|
+
config_.enableFogCulling = v;
|
|
173
|
+
if (initialized_) applyEngineConfig();
|
|
174
|
+
}
|
|
175
|
+
void CesiumBridgeAndroid::setEnforceCulledScreenSpaceError(bool v) {
|
|
176
|
+
config_.enforceCulledScreenSpaceError = v;
|
|
177
|
+
if (initialized_) applyEngineConfig();
|
|
178
|
+
}
|
|
179
|
+
void CesiumBridgeAndroid::setCulledScreenSpaceError(double v) {
|
|
180
|
+
config_.culledScreenSpaceError = v;
|
|
181
|
+
if (initialized_) applyEngineConfig();
|
|
182
|
+
}
|
|
183
|
+
void CesiumBridgeAndroid::setEnableLodTransitionPeriod(bool v) {
|
|
184
|
+
config_.enableLodTransitionPeriod = v;
|
|
185
|
+
if (initialized_) applyEngineConfig();
|
|
186
|
+
}
|
|
187
|
+
void CesiumBridgeAndroid::setLodTransitionLength(double v) {
|
|
188
|
+
config_.lodTransitionLength = v;
|
|
189
|
+
if (initialized_) applyEngineConfig();
|
|
190
|
+
}
|
|
191
|
+
void CesiumBridgeAndroid::setSqliteCacheMaxRows(int32_t v) {
|
|
192
|
+
// Re-creating SqliteCache requires a tileset rebuild, so we only honour the
|
|
193
|
+
// value on next init.
|
|
194
|
+
config_.sqliteCacheMaxRows = std::max(64, v);
|
|
195
|
+
}
|
|
196
|
+
void CesiumBridgeAndroid::setTaskProcessorThreads(int32_t v) {
|
|
197
|
+
// Worker pool is sized once per CesiumEngine. We mirror it for the next
|
|
198
|
+
// initialize().
|
|
199
|
+
config_.taskProcessorThreads = std::max(0, v);
|
|
239
200
|
}
|
|
240
201
|
|
|
202
|
+
void CesiumBridgeAndroid::markNeedsRender() { target_.requestForceRender(); }
|
|
203
|
+
|
|
241
204
|
bool CesiumBridgeAndroid::shouldRenderNextFrame() {
|
|
242
205
|
if (!initialized_ || !engine_) return false;
|
|
243
206
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
207
|
+
if (target_.consumeForceRender()) {
|
|
208
|
+
// Force-render request observed: keep it sticky for one frame so we make
|
|
209
|
+
// it through to the actual GPU encode below.
|
|
210
|
+
target_.requestForceRender();
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
if (frameResult_->tilesLoading > 0 || !frameResult_->tilesetActive) {
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
// Keep rendering at full speed until we have actual terrain tiles loaded.
|
|
217
|
+
// This ensures tiles start loading immediately instead of falling into idle
|
|
218
|
+
// mode (250ms intervals) before any content appears.
|
|
219
|
+
if (frameResult_->tilesRendered < 5) {
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
if (target_.isDirty()) {
|
|
223
|
+
const auto cur = engine_->camera().getParams();
|
|
224
|
+
const auto tgt = target_.snapshot();
|
|
225
|
+
if (reactnativecesium::CameraTargetState::deltaExceedsEpsilon(cur, tgt)) {
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
target_.clearDirty();
|
|
229
|
+
}
|
|
230
|
+
return false;
|
|
259
231
|
}
|
|
260
232
|
|
|
261
233
|
void CesiumBridgeAndroid::renderFrame(double dt) {
|
|
262
234
|
if (!initialized_) return;
|
|
263
235
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
cur.latitude = camTargetLat_;
|
|
268
|
-
cur.longitude = camTargetLon_;
|
|
269
|
-
|
|
270
|
-
const double aAlt = 1.0 - std::exp(-kSmoothAlt * dt);
|
|
271
|
-
const double aHdg = 1.0 - std::exp(-kSmoothHdg * dt);
|
|
272
|
-
const double aPitch = 1.0 - std::exp(-kSmoothPitch * dt);
|
|
273
|
-
const double aRoll = 1.0 - std::exp(-kSmoothRoll * dt);
|
|
274
|
-
const double aViewQ = 1.0 - std::exp(-kSmoothViewCorr * dt);
|
|
275
|
-
|
|
276
|
-
cur.altitude = cur.altitude + aAlt * (camTargetAlt_ - cur.altitude);
|
|
277
|
-
cur.heading = lerpAngleDeg(cur.heading, camTargetHeading_, aHdg);
|
|
278
|
-
cur.pitch = lerpAngleDeg(cur.pitch, camTargetPitch_, aPitch);
|
|
279
|
-
cur.roll = lerpAngleDeg(cur.roll, camTargetRoll_, aRoll);
|
|
280
|
-
|
|
281
|
-
glm::dquat cq = glm::normalize(cur.viewCorrection);
|
|
282
|
-
glm::dquat tq = glm::normalize(glm::dquat(camTargetViewQw_, camTargetViewQx_, camTargetViewQy_, camTargetViewQz_));
|
|
283
|
-
if (glm::dot(cq, tq) < 0.0)
|
|
284
|
-
tq = -tq;
|
|
285
|
-
cur.viewCorrection = glm::normalize(glm::slerp(cq, tq, aViewQ));
|
|
286
|
-
|
|
287
|
-
if (std::abs(camTargetAlt_ - cur.altitude) <= kEpsAlt)
|
|
288
|
-
cur.altitude = camTargetAlt_;
|
|
289
|
-
if (angleDeltaAbsDeg(cur.heading, camTargetHeading_) <= kEpsAngleDeg)
|
|
290
|
-
cur.heading = camTargetHeading_;
|
|
291
|
-
if (angleDeltaAbsDeg(cur.pitch, camTargetPitch_) <= kEpsAngleDeg)
|
|
292
|
-
cur.pitch = camTargetPitch_;
|
|
293
|
-
if (angleDeltaAbsDeg(cur.roll, camTargetRoll_) <= kEpsAngleDeg)
|
|
294
|
-
cur.roll = camTargetRoll_;
|
|
295
|
-
if ((1.0 - quatDotAbs(cur.viewCorrection, tq)) <= kEpsQuatDot)
|
|
296
|
-
cur.viewCorrection = tq;
|
|
297
|
-
|
|
298
|
-
engine_->camera().setParams(cur);
|
|
299
|
-
engine_->updateFrame(viewportWidth_, viewportHeight_, *frameResult_);
|
|
236
|
+
// Consume the force-render flag here (it may have been re-armed by
|
|
237
|
+
// shouldRenderNextFrame; either way we're rendering this frame).
|
|
238
|
+
(void)target_.consumeForceRender();
|
|
300
239
|
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
metricsIonTokenConfigured_ = frameResult_->ionTokenConfigured;
|
|
311
|
-
metricsTilesetReady_ = frameResult_->tilesetActive;
|
|
312
|
-
|
|
313
|
-
if (!frameResult_->creditHtmlLines.empty()) {
|
|
314
|
-
std::string joined;
|
|
315
|
-
for (const auto& html : frameResult_->creditHtmlLines) {
|
|
316
|
-
if (!joined.empty()) joined += "|";
|
|
317
|
-
joined += html;
|
|
318
|
-
}
|
|
319
|
-
if (joined != lastCreditHtmlJoined_) {
|
|
320
|
-
lastCreditHtmlJoined_ = joined;
|
|
321
|
-
std::string credits;
|
|
322
|
-
for (const auto& html : frameResult_->creditHtmlLines) {
|
|
323
|
-
std::string chunk = stripHtmlToPlain(html);
|
|
324
|
-
if (chunk.empty()) continue;
|
|
325
|
-
if (!credits.empty()) credits += " · ";
|
|
326
|
-
credits += chunk;
|
|
327
|
-
}
|
|
328
|
-
metricsCreditsPlainText_ = credits;
|
|
329
|
-
}
|
|
330
|
-
} else {
|
|
331
|
-
lastCreditHtmlJoined_.clear();
|
|
332
|
-
metricsCreditsPlainText_.clear();
|
|
333
|
-
}
|
|
240
|
+
const auto cur = engine_->camera().getParams();
|
|
241
|
+
const auto tgt = target_.snapshot();
|
|
242
|
+
const auto smooth = reactnativecesium::CameraSmoother::step(
|
|
243
|
+
cur, tgt, dt, target_.recentIntervalSec());
|
|
244
|
+
engine_->camera().setParams(smooth);
|
|
245
|
+
|
|
246
|
+
// If we converged, clear the dirty flag so the next idle vsync can early-out.
|
|
247
|
+
if (!reactnativecesium::CameraTargetState::deltaExceedsEpsilon(smooth, tgt)) {
|
|
248
|
+
target_.clearDirty();
|
|
334
249
|
}
|
|
335
250
|
|
|
251
|
+
engine_->updateFrame(viewportWidth_, viewportHeight_, *frameResult_);
|
|
252
|
+
metrics_.tick(dt, *frameResult_, !config_.tlsCaBundlePath.empty());
|
|
253
|
+
|
|
336
254
|
reactnativecesium::FrameParams params;
|
|
337
255
|
vulkanBackend_->beginFrame(params);
|
|
338
256
|
vulkanBackend_->drawScene(*frameResult_);
|
|
339
257
|
vulkanBackend_->endFrame();
|
|
340
|
-
forceRenderNextFrame_ = false;
|
|
341
258
|
}
|
|
342
259
|
|
|
343
260
|
double CesiumBridgeAndroid::readCameraLatitude() {
|
|
@@ -361,7 +278,6 @@ double CesiumBridgeAndroid::readCameraRoll() {
|
|
|
361
278
|
double CesiumBridgeAndroid::readVerticalFovDeg() {
|
|
362
279
|
return engine_ ? engine_->camera().getVerticalFovDegrees() : 60.0;
|
|
363
280
|
}
|
|
364
|
-
|
|
365
281
|
double CesiumBridgeAndroid::readViewCorrectionW() {
|
|
366
282
|
return engine_ ? engine_->camera().getParams().viewCorrection.w : 1.0;
|
|
367
283
|
}
|
|
@@ -566,9 +482,63 @@ Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetMetricsTileset
|
|
|
566
482
|
return getBridge(ptr)->metricsTilesetReady() ? JNI_TRUE : JNI_FALSE;
|
|
567
483
|
}
|
|
568
484
|
|
|
485
|
+
JNIEXPORT jboolean JNICALL
|
|
486
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetMetricsTlsConfigured(JNIEnv*, jobject, jlong ptr) {
|
|
487
|
+
return getBridge(ptr)->metricsTlsConfigured() ? JNI_TRUE : JNI_FALSE;
|
|
488
|
+
}
|
|
489
|
+
|
|
569
490
|
JNIEXPORT jstring JNICALL
|
|
570
491
|
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeGetMetricsCreditsPlainText(JNIEnv* env, jobject, jlong ptr) {
|
|
571
492
|
return env->NewStringUTF(getBridge(ptr)->metricsCreditsPlainText().c_str());
|
|
572
493
|
}
|
|
573
494
|
|
|
495
|
+
JNIEXPORT void JNICALL
|
|
496
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetMaximumCachedMiB(JNIEnv*, jobject, jlong ptr, jint v) {
|
|
497
|
+
getBridge(ptr)->setMaximumCachedMiB(v);
|
|
498
|
+
}
|
|
499
|
+
JNIEXPORT void JNICALL
|
|
500
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetPreloadAncestors(JNIEnv*, jobject, jlong ptr, jboolean v) {
|
|
501
|
+
getBridge(ptr)->setPreloadAncestors(v == JNI_TRUE);
|
|
502
|
+
}
|
|
503
|
+
JNIEXPORT void JNICALL
|
|
504
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetPreloadSiblings(JNIEnv*, jobject, jlong ptr, jboolean v) {
|
|
505
|
+
getBridge(ptr)->setPreloadSiblings(v == JNI_TRUE);
|
|
506
|
+
}
|
|
507
|
+
JNIEXPORT void JNICALL
|
|
508
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetForbidHoles(JNIEnv*, jobject, jlong ptr, jboolean v) {
|
|
509
|
+
getBridge(ptr)->setForbidHoles(v == JNI_TRUE);
|
|
510
|
+
}
|
|
511
|
+
JNIEXPORT void JNICALL
|
|
512
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetEnableWaterMask(JNIEnv*, jobject, jlong ptr, jboolean v) {
|
|
513
|
+
getBridge(ptr)->setEnableWaterMask(v == JNI_TRUE);
|
|
514
|
+
}
|
|
515
|
+
JNIEXPORT void JNICALL
|
|
516
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetEnableFogCulling(JNIEnv*, jobject, jlong ptr, jboolean v) {
|
|
517
|
+
getBridge(ptr)->setEnableFogCulling(v == JNI_TRUE);
|
|
518
|
+
}
|
|
519
|
+
JNIEXPORT void JNICALL
|
|
520
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetEnforceCulledScreenSpaceError(JNIEnv*, jobject, jlong ptr, jboolean v) {
|
|
521
|
+
getBridge(ptr)->setEnforceCulledScreenSpaceError(v == JNI_TRUE);
|
|
522
|
+
}
|
|
523
|
+
JNIEXPORT void JNICALL
|
|
524
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetCulledScreenSpaceError(JNIEnv*, jobject, jlong ptr, jdouble v) {
|
|
525
|
+
getBridge(ptr)->setCulledScreenSpaceError(v);
|
|
526
|
+
}
|
|
527
|
+
JNIEXPORT void JNICALL
|
|
528
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetEnableLodTransitionPeriod(JNIEnv*, jobject, jlong ptr, jboolean v) {
|
|
529
|
+
getBridge(ptr)->setEnableLodTransitionPeriod(v == JNI_TRUE);
|
|
530
|
+
}
|
|
531
|
+
JNIEXPORT void JNICALL
|
|
532
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetLodTransitionLength(JNIEnv*, jobject, jlong ptr, jdouble v) {
|
|
533
|
+
getBridge(ptr)->setLodTransitionLength(v);
|
|
534
|
+
}
|
|
535
|
+
JNIEXPORT void JNICALL
|
|
536
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetSqliteCacheMaxRows(JNIEnv*, jobject, jlong ptr, jint v) {
|
|
537
|
+
getBridge(ptr)->setSqliteCacheMaxRows(v);
|
|
538
|
+
}
|
|
539
|
+
JNIEXPORT void JNICALL
|
|
540
|
+
Java_com_margelo_nitro_reactnativecesium_CesiumBridgeJNI_nativeSetTaskProcessorThreads(JNIEnv*, jobject, jlong ptr, jint v) {
|
|
541
|
+
getBridge(ptr)->setTaskProcessorThreads(v);
|
|
542
|
+
}
|
|
543
|
+
|
|
574
544
|
} // extern "C"
|
|
@@ -4,13 +4,21 @@
|
|
|
4
4
|
#include <memory>
|
|
5
5
|
#include <string>
|
|
6
6
|
|
|
7
|
+
#include "engine/CameraTargetState.hpp"
|
|
8
|
+
#include "engine/CesiumEngine.hpp"
|
|
9
|
+
#include "engine/MetricsAggregator.hpp"
|
|
10
|
+
|
|
7
11
|
namespace reactnativecesium {
|
|
8
12
|
class VulkanBackend;
|
|
9
|
-
class CesiumEngine;
|
|
10
13
|
struct FrameResult;
|
|
11
|
-
|
|
12
|
-
}
|
|
14
|
+
} // namespace reactnativecesium
|
|
13
15
|
|
|
16
|
+
// Thin Android shell. All cross-platform logic (camera demand state +
|
|
17
|
+
// smoothing, FPS / metrics aggregation, credit HTML stripping) lives in
|
|
18
|
+
// shared C++ next to CesiumEngine. This class only owns:
|
|
19
|
+
// - the JNI/window surface,
|
|
20
|
+
// - the Vulkan backend instance, and
|
|
21
|
+
// - the EngineConfig snapshot mirrored from JS props.
|
|
14
22
|
struct CesiumBridgeAndroid {
|
|
15
23
|
void init(JNIEnv* env, jobject surface, int width, int height,
|
|
16
24
|
const std::string& cacheDir, const std::string& cacertPath);
|
|
@@ -27,10 +35,24 @@ struct CesiumBridgeAndroid {
|
|
|
27
35
|
double qw, double qx, double qy, double qz);
|
|
28
36
|
void setVerticalFovDeg(double degrees);
|
|
29
37
|
void setMaximumScreenSpaceError(double v);
|
|
30
|
-
void setMaximumSimultaneousTileLoads(
|
|
31
|
-
void setLoadingDescendantLimit(
|
|
38
|
+
void setMaximumSimultaneousTileLoads(int32_t v);
|
|
39
|
+
void setLoadingDescendantLimit(int32_t v);
|
|
32
40
|
void setMsaaSampleCount(int samples);
|
|
33
41
|
|
|
42
|
+
// Optional knobs (default values mirror EngineConfig defaults).
|
|
43
|
+
void setMaximumCachedMiB(int32_t v);
|
|
44
|
+
void setPreloadAncestors(bool v);
|
|
45
|
+
void setPreloadSiblings(bool v);
|
|
46
|
+
void setForbidHoles(bool v);
|
|
47
|
+
void setEnableWaterMask(bool v);
|
|
48
|
+
void setEnableFogCulling(bool v);
|
|
49
|
+
void setEnforceCulledScreenSpaceError(bool v);
|
|
50
|
+
void setCulledScreenSpaceError(double v);
|
|
51
|
+
void setEnableLodTransitionPeriod(bool v);
|
|
52
|
+
void setLodTransitionLength(double v);
|
|
53
|
+
void setSqliteCacheMaxRows(int32_t v);
|
|
54
|
+
void setTaskProcessorThreads(int32_t v);
|
|
55
|
+
|
|
34
56
|
void markNeedsRender();
|
|
35
57
|
bool shouldRenderNextFrame();
|
|
36
58
|
void renderFrame(double dt);
|
|
@@ -48,57 +70,34 @@ struct CesiumBridgeAndroid {
|
|
|
48
70
|
double readViewCorrectionY();
|
|
49
71
|
double readViewCorrectionZ();
|
|
50
72
|
|
|
51
|
-
// Metrics
|
|
52
|
-
double metricsFps()
|
|
53
|
-
int metricsTilesRendered()
|
|
54
|
-
int metricsTilesLoading()
|
|
55
|
-
int metricsTilesVisited()
|
|
56
|
-
bool metricsIonTokenConfigured() const { return
|
|
57
|
-
bool metricsTilesetReady()
|
|
58
|
-
|
|
73
|
+
// Metrics readback (delegated to MetricsAggregator)
|
|
74
|
+
double metricsFps() const { return metrics_.latest().fps; }
|
|
75
|
+
int metricsTilesRendered() const { return metrics_.latest().tilesRendered; }
|
|
76
|
+
int metricsTilesLoading() const { return metrics_.latest().tilesLoading; }
|
|
77
|
+
int metricsTilesVisited() const { return metrics_.latest().tilesVisited; }
|
|
78
|
+
bool metricsIonTokenConfigured() const { return metrics_.latest().ionTokenConfigured; }
|
|
79
|
+
bool metricsTilesetReady() const { return metrics_.latest().tilesetReady; }
|
|
80
|
+
bool metricsTlsConfigured() const { return metrics_.latest().tlsConfigured; }
|
|
81
|
+
const std::string& metricsCreditsPlainText() const {
|
|
82
|
+
return metrics_.latest().creditsPlainText;
|
|
83
|
+
}
|
|
59
84
|
|
|
60
85
|
private:
|
|
61
86
|
void buildEngine();
|
|
87
|
+
// Push the current `config_` state to the live engine (runtime-mutable
|
|
88
|
+
// fields go through tileset_->getOptions(); token/asset id changes force
|
|
89
|
+
// a tileset rebuild).
|
|
90
|
+
void applyEngineConfig();
|
|
62
91
|
|
|
63
92
|
std::unique_ptr<reactnativecesium::VulkanBackend> vulkanBackend_;
|
|
64
93
|
std::unique_ptr<reactnativecesium::CesiumEngine> engine_;
|
|
65
94
|
std::unique_ptr<reactnativecesium::FrameResult> frameResult_;
|
|
66
95
|
|
|
67
|
-
int
|
|
68
|
-
int
|
|
69
|
-
bool initialized_
|
|
70
|
-
|
|
71
|
-
std::string cacheDir_;
|
|
72
|
-
std::string cacertPath_;
|
|
73
|
-
std::string ionAccessToken_;
|
|
74
|
-
int64_t ionTilesetAssetId_ = 1;
|
|
75
|
-
|
|
76
|
-
double maxSSE_ = 32.0;
|
|
77
|
-
double maxSimLoads_ = 12.0;
|
|
78
|
-
double loadDescLim_ = 20.0;
|
|
79
|
-
|
|
80
|
-
// Camera demand target
|
|
81
|
-
double camTargetLat_ = 46.15;
|
|
82
|
-
double camTargetLon_ = 7.35;
|
|
83
|
-
double camTargetAlt_ = 12000.0;
|
|
84
|
-
double camTargetHeading_ = 129.0;
|
|
85
|
-
double camTargetPitch_ = -45.0;
|
|
86
|
-
double camTargetRoll_ = 0.0;
|
|
87
|
-
double camTargetViewQw_ = 1.0;
|
|
88
|
-
double camTargetViewQx_ = 0.0;
|
|
89
|
-
double camTargetViewQy_ = 0.0;
|
|
90
|
-
double camTargetViewQz_ = 0.0;
|
|
91
|
-
bool forceRenderNextFrame_ = true;
|
|
96
|
+
int viewportWidth_ = 0;
|
|
97
|
+
int viewportHeight_ = 0;
|
|
98
|
+
bool initialized_ = false;
|
|
92
99
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
double metricsFps_ = 0.0;
|
|
97
|
-
int metricsTilesRendered_ = 0;
|
|
98
|
-
int metricsTilesLoading_ = 0;
|
|
99
|
-
int metricsTilesVisited_ = 0;
|
|
100
|
-
bool metricsIonTokenConfigured_ = false;
|
|
101
|
-
bool metricsTilesetReady_ = false;
|
|
102
|
-
std::string metricsCreditsPlainText_;
|
|
103
|
-
std::string lastCreditHtmlJoined_;
|
|
100
|
+
reactnativecesium::EngineConfig config_;
|
|
101
|
+
reactnativecesium::CameraTargetState target_;
|
|
102
|
+
reactnativecesium::MetricsAggregator metrics_;
|
|
104
103
|
};
|