react-native-cesium 1.2.3 → 1.2.4
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 +100 -27
- package/android/CMakeLists.txt +1 -2
- package/android/src/main/cpp/CesiumBridgeAndroid.cpp +264 -130
- package/android/src/main/cpp/CesiumBridgeAndroid.h +70 -27
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/CesiumBridgeJNI.kt +68 -44
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/HybridCesiumView.kt +160 -187
- package/cpp/engine/CameraIntegrator.cpp +374 -0
- package/cpp/engine/CameraIntegrator.hpp +146 -0
- package/cpp/engine/EngineTunables.hpp +78 -31
- package/cpp/engine/GlobeCamera.cpp +17 -6
- package/cpp/engine/GlobeCamera.hpp +11 -8
- package/cpp/engine/test/CameraIntegratorTest.cpp +205 -0
- package/cpp/engine/test/build_and_run.sh +27 -0
- package/example/README.md +1 -1
- package/ios/CesiumBridge.h +53 -28
- package/ios/CesiumBridge.mm +172 -86
- package/ios/HybridCesiumView.swift +213 -145
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts +77 -13
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.cpp +90 -9
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.hpp +19 -3
- package/nitrogen/generated/android/c++/views/JHybridCesiumViewStateUpdater.cpp +20 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/HybridCesiumViewSpec.kt +57 -3
- package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Bridge.hpp +9 -9
- package/nitrogen/generated/ios/c++/HybridCesiumViewSpecSwift.hpp +82 -9
- package/nitrogen/generated/ios/c++/views/HybridCesiumViewComponent.mm +25 -0
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec.swift +14 -3
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec_cxx.swift +210 -16
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.cpp +19 -3
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.hpp +20 -4
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.cpp +55 -0
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.hpp +5 -0
- package/nitrogen/generated/shared/json/CesiumViewConfig.json +5 -0
- package/package.json +1 -1
- package/src/specs/cesium-view.nitro.ts +93 -14
- package/cpp/engine/CameraSmoother.cpp +0 -68
- package/cpp/engine/CameraSmoother.hpp +0 -28
- package/cpp/engine/CameraTargetState.cpp +0 -205
- package/cpp/engine/CameraTargetState.hpp +0 -126
|
@@ -16,11 +16,22 @@ static constexpr double kFarPlane = 50000000.0;
|
|
|
16
16
|
static constexpr double kMinVfov = 20.0;
|
|
17
17
|
static constexpr double kMaxVfov = 100.0;
|
|
18
18
|
|
|
19
|
-
GlobeCamera::GlobeCamera() {
|
|
19
|
+
GlobeCamera::GlobeCamera() {
|
|
20
|
+
params_.verticalFov = std::clamp(params_.verticalFov, kMinVfov, kMaxVfov);
|
|
21
|
+
recompute();
|
|
22
|
+
}
|
|
20
23
|
|
|
21
24
|
void GlobeCamera::setParams(const CameraParams& p) {
|
|
22
25
|
std::lock_guard<std::mutex> lk(mutex_);
|
|
23
26
|
params_ = p;
|
|
27
|
+
// A zero (default-init) verticalFov means "leave the previous value";
|
|
28
|
+
// anything else is clamped to the supported range.
|
|
29
|
+
if (p.verticalFov > 0.0) {
|
|
30
|
+
params_.verticalFov = std::clamp(p.verticalFov, kMinVfov, kMaxVfov);
|
|
31
|
+
} else {
|
|
32
|
+
// Restore the existing value rather than letting a zero overwrite it.
|
|
33
|
+
params_.verticalFov = std::clamp(params_.verticalFov, kMinVfov, kMaxVfov);
|
|
34
|
+
}
|
|
24
35
|
dirty_ = true;
|
|
25
36
|
}
|
|
26
37
|
|
|
@@ -31,12 +42,12 @@ CameraParams GlobeCamera::getParams() const {
|
|
|
31
42
|
|
|
32
43
|
void GlobeCamera::setVerticalFovDegrees(double degrees) {
|
|
33
44
|
std::lock_guard<std::mutex> lk(mutex_);
|
|
34
|
-
|
|
45
|
+
params_.verticalFov = std::clamp(degrees, kMinVfov, kMaxVfov);
|
|
35
46
|
}
|
|
36
47
|
|
|
37
48
|
double GlobeCamera::getVerticalFovDegrees() const {
|
|
38
49
|
std::lock_guard<std::mutex> lk(mutex_);
|
|
39
|
-
return
|
|
50
|
+
return params_.verticalFov;
|
|
40
51
|
}
|
|
41
52
|
|
|
42
53
|
void GlobeCamera::recompute() const {
|
|
@@ -151,7 +162,7 @@ GlobeCamera::computeViewState(double w, double h) const {
|
|
|
151
162
|
recompute();
|
|
152
163
|
|
|
153
164
|
double aspect = w / std::max(h, 1.0);
|
|
154
|
-
double vfov = glm::radians(
|
|
165
|
+
double vfov = glm::radians(params_.verticalFov);
|
|
155
166
|
double hfov = 2.0 * std::atan(std::tan(vfov * 0.5) * aspect);
|
|
156
167
|
|
|
157
168
|
return Cesium3DTilesSelection::ViewState(
|
|
@@ -168,7 +179,7 @@ glm::mat4 GlobeCamera::computeVPMatrix(double w, double h) const {
|
|
|
168
179
|
fullView[0], fullView[1], fullView[2], glm::dvec4(0.0, 0.0, 0.0, 1.0)));
|
|
169
180
|
|
|
170
181
|
double aspect = w / std::max(h, 1.0);
|
|
171
|
-
double vfov = glm::radians(
|
|
182
|
+
double vfov = glm::radians(params_.verticalFov);
|
|
172
183
|
double tanHalfV = std::tan(vfov * 0.5);
|
|
173
184
|
double tanHalfH = tanHalfV * aspect;
|
|
174
185
|
|
|
@@ -193,7 +204,7 @@ glm::dmat4 GlobeCamera::computeVPMatrixDouble(double w, double h) const {
|
|
|
193
204
|
fullView[0], fullView[1], fullView[2], glm::dvec4(0.0, 0.0, 0.0, 1.0));
|
|
194
205
|
|
|
195
206
|
double aspect = w / std::max(h, 1.0);
|
|
196
|
-
double vfov = glm::radians(
|
|
207
|
+
double vfov = glm::radians(params_.verticalFov);
|
|
197
208
|
double tanHalfV = std::tan(vfov * 0.5);
|
|
198
209
|
double tanHalfH = tanHalfV * aspect;
|
|
199
210
|
|
|
@@ -11,12 +11,16 @@
|
|
|
11
11
|
namespace reactnativecesium {
|
|
12
12
|
|
|
13
13
|
struct CameraParams {
|
|
14
|
-
double latitude
|
|
15
|
-
double longitude
|
|
16
|
-
double altitude
|
|
17
|
-
double heading
|
|
18
|
-
double pitch
|
|
19
|
-
double roll
|
|
14
|
+
double latitude = 46.10;
|
|
15
|
+
double longitude = 7.80;
|
|
16
|
+
double altitude = 5500.0;
|
|
17
|
+
double heading = 220.0;
|
|
18
|
+
double pitch = -10.0;
|
|
19
|
+
double roll = 0.0;
|
|
20
|
+
/// Vertical field of view in degrees. Clamped to [kMinVfov, kMaxVfov] by
|
|
21
|
+
/// GlobeCamera when written. Zero means "leave the previous value" — used
|
|
22
|
+
/// by partial constructors that don't want to opine on FOV.
|
|
23
|
+
double verticalFov = 60.0;
|
|
20
24
|
/// Camera-space rotation applied after HPR (unit quaternion; w,x,y,z).
|
|
21
25
|
glm::dquat viewCorrection{1.0, 0.0, 0.0, 0.0};
|
|
22
26
|
};
|
|
@@ -28,6 +32,7 @@ public:
|
|
|
28
32
|
void setParams(const CameraParams& params);
|
|
29
33
|
CameraParams getParams() const;
|
|
30
34
|
|
|
35
|
+
/// Convenience helper — equivalent to mutating only verticalFov via setParams.
|
|
31
36
|
void setVerticalFovDegrees(double degrees);
|
|
32
37
|
double getVerticalFovDegrees() const;
|
|
33
38
|
|
|
@@ -56,8 +61,6 @@ private:
|
|
|
56
61
|
mutable std::mutex mutex_;
|
|
57
62
|
CameraParams params_;
|
|
58
63
|
|
|
59
|
-
double verticalFovDeg_ = 60.0;
|
|
60
|
-
|
|
61
64
|
mutable bool dirty_ = true;
|
|
62
65
|
mutable glm::dvec3 ecefPosition_{0.0};
|
|
63
66
|
mutable glm::dvec3 direction_{0.0, 1.0, 0.0};
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
// Self-contained host harness for CameraIntegrator. NOT compiled into the
|
|
2
|
+
// library — invoked manually by maintainers:
|
|
3
|
+
//
|
|
4
|
+
// $ bash cpp/engine/test/build_and_run.sh
|
|
5
|
+
//
|
|
6
|
+
// The integrator uses steady_clock internally, so the harness mixes real
|
|
7
|
+
// sleeps with calls — total wall-clock runtime is ~3 seconds.
|
|
8
|
+
//
|
|
9
|
+
// Each test prints PASS / FAIL with a short diagnostic. Exit code is the
|
|
10
|
+
// number of failures.
|
|
11
|
+
|
|
12
|
+
#include "../CameraIntegrator.hpp"
|
|
13
|
+
#include "../EngineTunables.hpp"
|
|
14
|
+
|
|
15
|
+
#include <chrono>
|
|
16
|
+
#include <cmath>
|
|
17
|
+
#include <cstdio>
|
|
18
|
+
#include <cstdlib>
|
|
19
|
+
#include <thread>
|
|
20
|
+
|
|
21
|
+
using namespace reactnativecesium;
|
|
22
|
+
|
|
23
|
+
static int g_failures = 0;
|
|
24
|
+
|
|
25
|
+
#define CHECK(cond, label) \
|
|
26
|
+
do { \
|
|
27
|
+
if (!(cond)) { \
|
|
28
|
+
std::fprintf(stderr, "FAIL [%s]: %s (line %d)\n", \
|
|
29
|
+
label, #cond, __LINE__); \
|
|
30
|
+
++g_failures; \
|
|
31
|
+
} else { \
|
|
32
|
+
std::fprintf(stderr, "PASS [%s]\n", label); \
|
|
33
|
+
} \
|
|
34
|
+
} while (0)
|
|
35
|
+
|
|
36
|
+
static bool approxEq(double a, double b, double tol) {
|
|
37
|
+
return std::fabs(a - b) <= tol;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Sleep a few ms then call step() so the integrator advances along the
|
|
41
|
+
// learned velocity. Returns the latest actual.
|
|
42
|
+
static CameraParams stepFor(CameraIntegrator& integ, int totalMs, int tickMs = 16) {
|
|
43
|
+
CameraParams out;
|
|
44
|
+
for (int t = 0; t < totalMs; t += tickMs) {
|
|
45
|
+
std::this_thread::sleep_for(std::chrono::milliseconds(tickMs));
|
|
46
|
+
out = integ.step();
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 1. Step input: a single setter call should move the value toward the
|
|
52
|
+
// target by α × residual (no further movement until another measurement).
|
|
53
|
+
// Demand is preserved through getDemand() regardless.
|
|
54
|
+
static void testStepInput() {
|
|
55
|
+
CameraParams seed;
|
|
56
|
+
seed.altitude = 100.0;
|
|
57
|
+
CameraIntegrator integ(seed);
|
|
58
|
+
|
|
59
|
+
integ.setAltitude(200.0);
|
|
60
|
+
auto out = stepFor(integ, 80);
|
|
61
|
+
|
|
62
|
+
// Single shot: should be between 100 and 200, much closer to value+α*residual
|
|
63
|
+
CHECK(out.altitude > 100.0 && out.altitude < 200.0, "step_input.between");
|
|
64
|
+
CHECK(approxEq(integ.getDemand().altitude, 200.0, 1e-9),
|
|
65
|
+
"step_input.demand_preserved");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 2. Repeated setter at constant velocity. Simulates a 10 Hz altitude feed
|
|
69
|
+
// climbing at 5 m/s. After enough samples, actual altitude should track
|
|
70
|
+
// demand to within a fraction of one inter-arrival delta.
|
|
71
|
+
static void testConstantVelocity() {
|
|
72
|
+
CameraIntegrator integ;
|
|
73
|
+
integ.teleport({}); // default seed: alt=5500
|
|
74
|
+
|
|
75
|
+
const double climbMps = 5.0;
|
|
76
|
+
const double dtSampleSec = 0.1;
|
|
77
|
+
const int numSamples = 25; // 2.5s of feed
|
|
78
|
+
|
|
79
|
+
double demandAlt = 5500.0;
|
|
80
|
+
for (int i = 0; i < numSamples; ++i) {
|
|
81
|
+
std::this_thread::sleep_for(std::chrono::milliseconds(
|
|
82
|
+
static_cast<int>(dtSampleSec * 1000)));
|
|
83
|
+
demandAlt += climbMps * dtSampleSec;
|
|
84
|
+
integ.setAltitude(demandAlt);
|
|
85
|
+
// A few render ticks between samples.
|
|
86
|
+
for (int k = 0; k < 6; ++k) {
|
|
87
|
+
std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
|
88
|
+
integ.step();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
auto actual = integ.getActual();
|
|
92
|
+
// Allow a tracking lag of one full sample delta.
|
|
93
|
+
CHECK(approxEq(actual.altitude, demandAlt, climbMps * dtSampleSec * 2.0),
|
|
94
|
+
"const_vel.tracks");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 3. Rate cap bounds a single noisy heading spike.
|
|
98
|
+
static void testRateCap() {
|
|
99
|
+
CameraIntegrator integ;
|
|
100
|
+
CameraRateCaps caps;
|
|
101
|
+
caps.maxYawRateDegSec = 90.0;
|
|
102
|
+
integ.setRateCaps(caps);
|
|
103
|
+
|
|
104
|
+
integ.teleport({}); // default heading=220
|
|
105
|
+
|
|
106
|
+
// 10 calm samples at 220° to settle.
|
|
107
|
+
for (int i = 0; i < 10; ++i) {
|
|
108
|
+
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
|
109
|
+
integ.setHeading(220.0);
|
|
110
|
+
integ.step();
|
|
111
|
+
}
|
|
112
|
+
// Single 110° spike.
|
|
113
|
+
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
|
114
|
+
integ.setHeading(330.0);
|
|
115
|
+
auto out = integ.step();
|
|
116
|
+
// Without a cap a 110° step would produce v ≈ 110 / 0.02 = 5500 deg/s
|
|
117
|
+
// and the next step() would extrapolate by v*dt = 5500*0.02 = 110°.
|
|
118
|
+
// With the 90 deg/s cap, the change in this single frame is at most
|
|
119
|
+
// 90 * 0.02 ≈ 1.8° beyond the α*residual jump (~66°).
|
|
120
|
+
CHECK(std::fabs(out.heading - 220.0) < 90.0, "rate_cap.bounded");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 4. dt clamp prevents a stale velocity vector from jumping after a long
|
|
124
|
+
// pause. We feed a 30 deg/s heading rate, then wait 5 real seconds with no
|
|
125
|
+
// further measurements, and check that the next step() only advances by
|
|
126
|
+
// kMaxFrameDtSec * velocity.
|
|
127
|
+
static void testLongPause() {
|
|
128
|
+
CameraIntegrator integ;
|
|
129
|
+
integ.teleport({});
|
|
130
|
+
// Build a yaw rate.
|
|
131
|
+
for (int i = 1; i <= 10; ++i) {
|
|
132
|
+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
133
|
+
integ.setHeading(220.0 + 3.0 * i);
|
|
134
|
+
integ.step();
|
|
135
|
+
}
|
|
136
|
+
auto beforePause = integ.getActual();
|
|
137
|
+
// Long real-time pause with no setters and no steps.
|
|
138
|
+
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
|
|
139
|
+
auto out = integ.step();
|
|
140
|
+
// dt was clamped to 0.1 s, so heading advanced by at most
|
|
141
|
+
// velocity * 0.1 s. With v ≈ 30 deg/s, that's at most 3°.
|
|
142
|
+
CHECK(std::fabs(out.heading - beforePause.heading) < 10.0,
|
|
143
|
+
"long_pause.dt_clamped");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 5. Gesture-end bleed. A 60 Hz worklet streams ramping heading values for
|
|
147
|
+
// ~250 ms (simulating an active pan), then stops emitting entirely.
|
|
148
|
+
// Without the silence-aware velocity bleed the integrator would extrapolate
|
|
149
|
+
// the last learned velocity forever; with the bleed, motion should die in
|
|
150
|
+
// well under a second.
|
|
151
|
+
static void testGestureEndBleed() {
|
|
152
|
+
CameraIntegrator integ;
|
|
153
|
+
integ.teleport({});
|
|
154
|
+
|
|
155
|
+
// Active "gesture": 16 ms cadence, +0.5° heading per frame (= 31 deg/s).
|
|
156
|
+
double demand = 220.0;
|
|
157
|
+
for (int i = 0; i < 16; ++i) {
|
|
158
|
+
std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
|
159
|
+
demand += 0.5;
|
|
160
|
+
integ.setHeading(demand);
|
|
161
|
+
integ.step();
|
|
162
|
+
}
|
|
163
|
+
const double duringHeading = integ.getActual().heading;
|
|
164
|
+
|
|
165
|
+
// "Release": no more setters, just render ticks at 60 Hz.
|
|
166
|
+
CameraParams out;
|
|
167
|
+
for (int i = 0; i < 60; ++i) {
|
|
168
|
+
std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
|
169
|
+
out = integ.step();
|
|
170
|
+
}
|
|
171
|
+
const double endHeading = out.heading;
|
|
172
|
+
// Drift during the 1-second silence should be small — the integrator
|
|
173
|
+
// should have given up on the learned 31 deg/s rate well before the end.
|
|
174
|
+
CHECK(std::fabs(endHeading - duringHeading) < 5.0,
|
|
175
|
+
"gesture_end_bleed.stops");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// 6. Terrain clamp write-back — clampActualAltitude raises actual without
|
|
179
|
+
// touching demand.
|
|
180
|
+
static void testTerrainClamp() {
|
|
181
|
+
CameraIntegrator integ;
|
|
182
|
+
CameraParams seed;
|
|
183
|
+
seed.altitude = 100.0;
|
|
184
|
+
integ.teleport(seed);
|
|
185
|
+
integ.clampActualAltitude(150.0);
|
|
186
|
+
auto demand = integ.getDemand();
|
|
187
|
+
auto actual = integ.getActual();
|
|
188
|
+
CHECK(approxEq(actual.altitude, 150.0, 1e-6), "terrain_clamp.actual_raised");
|
|
189
|
+
CHECK(approxEq(demand.altitude, 100.0, 1e-6), "terrain_clamp.demand_preserved");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
int main() {
|
|
193
|
+
testStepInput();
|
|
194
|
+
testConstantVelocity();
|
|
195
|
+
testRateCap();
|
|
196
|
+
testLongPause();
|
|
197
|
+
testGestureEndBleed();
|
|
198
|
+
testTerrainClamp();
|
|
199
|
+
if (g_failures == 0) {
|
|
200
|
+
std::fprintf(stderr, "\nALL TESTS PASSED.\n");
|
|
201
|
+
} else {
|
|
202
|
+
std::fprintf(stderr, "\n%d TEST(S) FAILED.\n", g_failures);
|
|
203
|
+
}
|
|
204
|
+
return g_failures;
|
|
205
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Compile and run CameraIntegratorTest against the iOS simulator-slice headers
|
|
3
|
+
# from the vendored Cesium Native XCFramework. Lightweight smoke test —
|
|
4
|
+
# not part of the production build.
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
|
|
9
|
+
HEADERS="$ROOT/vendor/ios/CesiumNative.xcframework/ios-arm64-simulator/Headers"
|
|
10
|
+
|
|
11
|
+
if [[ ! -d "$HEADERS" ]]; then
|
|
12
|
+
echo "Cesium Native headers not found at $HEADERS"
|
|
13
|
+
echo "Run 'npm run update && CESIUM_BUILD_ONLY=ios npm run build' first."
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
OUT="$(mktemp -d)"
|
|
18
|
+
echo "Building into $OUT..."
|
|
19
|
+
|
|
20
|
+
xcrun -sdk macosx clang++ -std=c++20 -O0 -g \
|
|
21
|
+
-DGLM_FORCE_DEPTH_ZERO_TO_ONE=1 \
|
|
22
|
+
-I"$ROOT/cpp" -I"$HEADERS" \
|
|
23
|
+
-o "$OUT/cit" \
|
|
24
|
+
"$ROOT/cpp/engine/CameraIntegrator.cpp" \
|
|
25
|
+
"$ROOT/cpp/engine/test/CameraIntegratorTest.cpp"
|
|
26
|
+
|
|
27
|
+
"$OUT/cit"
|
package/example/README.md
CHANGED
|
@@ -6,7 +6,7 @@ This app is the reference integration for `react-native-cesium`. For the current
|
|
|
6
6
|
|
|
7
7
|
- rendering `CesiumView` inside a React Native screen
|
|
8
8
|
- wiring a Nitro `hybridRef`
|
|
9
|
-
- driving the camera
|
|
9
|
+
- driving the camera through the per-DoF setters (`setPosition`, `setAltitude`, `setHeading`, `setAttitude`) from a Reanimated worklet — see [`hooks/useCameraController.ts`](./hooks/useCameraController.ts)
|
|
10
10
|
- receiving runtime telemetry through `onMetrics`
|
|
11
11
|
- showing Cesium attribution text from `creditsPlainText`
|
|
12
12
|
|
package/ios/CesiumBridge.h
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
NS_ASSUME_NONNULL_BEGIN
|
|
5
5
|
|
|
6
|
-
// Thin Obj-C++ shell for the iOS side. All cross-platform logic (
|
|
7
|
-
//
|
|
8
|
-
//
|
|
6
|
+
// Thin Obj-C++ shell for the iOS side. All cross-platform logic (per-DoF
|
|
7
|
+
// camera integrator, FPS / metrics aggregation, credit-HTML stripping) lives
|
|
8
|
+
// in shared C++ next to CesiumEngine.
|
|
9
9
|
@interface CesiumBridge : NSObject
|
|
10
10
|
|
|
11
11
|
- (instancetype)initWithMetalLayer:(CAMetalLayer *)layer
|
|
@@ -15,32 +15,46 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
15
15
|
|
|
16
16
|
- (void)updateIonAccessToken:(NSString *)token assetId:(int64_t)assetId;
|
|
17
17
|
- (void)updateImageryAssetId:(int64_t)assetId;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
- (void)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
18
|
+
|
|
19
|
+
// ── Per-DoF camera demand setters ────────────────────────────────────────
|
|
20
|
+
// Each call records the measurement with the current native steady_clock
|
|
21
|
+
// time and performs one α-β update against the predicted state at that
|
|
22
|
+
// instant. Pitch / roll are bundled because they typically come from a
|
|
23
|
+
// single IMU sample.
|
|
24
|
+
- (void)setPositionLatitude:(double)lat longitude:(double)lon;
|
|
25
|
+
- (void)setAltitude:(double)alt;
|
|
26
|
+
- (void)setHeadingDeg:(double)deg;
|
|
27
|
+
- (void)setAttitudePitch:(double)pitch roll:(double)roll;
|
|
28
|
+
- (void)setViewCorrectionW:(double)qw x:(double)qx y:(double)qy z:(double)qz;
|
|
29
|
+
|
|
30
|
+
/// Hard scene jump — resets every DoF (value + velocity + demand) atomically.
|
|
31
|
+
- (void)teleportLatitude:(double)lat
|
|
32
|
+
longitude:(double)lon
|
|
33
|
+
altitude:(double)alt
|
|
34
|
+
heading:(double)heading
|
|
35
|
+
pitch:(double)pitch
|
|
36
|
+
roll:(double)roll
|
|
37
|
+
verticalFovDeg:(double)vfov;
|
|
38
|
+
|
|
35
39
|
- (void)resize:(int)width height:(int)height;
|
|
36
40
|
- (BOOL)shouldRenderNextFrame;
|
|
37
41
|
- (void)markNeedsRender;
|
|
38
|
-
- (
|
|
42
|
+
/// Render one frame. `nowSeconds` is wall-clock seconds (steady_clock) used
|
|
43
|
+
/// by the integrator to extrapolate every DoF forward.
|
|
44
|
+
- (void)renderFrameAt:(double)nowSeconds;
|
|
39
45
|
- (void)shutdown;
|
|
40
46
|
|
|
41
47
|
// Camera / globe
|
|
42
48
|
- (void)setVerticalFovDeg:(double)degrees;
|
|
43
49
|
|
|
50
|
+
/// Runtime rate caps (0 = uncapped). See EngineTunables for compile-time
|
|
51
|
+
/// defaults.
|
|
52
|
+
- (void)setRateCapsYaw:(double)yawDegSec
|
|
53
|
+
pitch:(double)pitchDegSec
|
|
54
|
+
roll:(double)rollDegSec
|
|
55
|
+
climb:(double)climbMps
|
|
56
|
+
groundSpeed:(double)groundMps;
|
|
57
|
+
|
|
44
58
|
// Tileset tuning (runtime-mutable; no full rebuild)
|
|
45
59
|
- (void)setMaximumScreenSpaceError:(double)v;
|
|
46
60
|
- (void)setMaximumSimultaneousTileLoads:(int32_t)v;
|
|
@@ -73,13 +87,24 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
73
87
|
@property (nonatomic, readonly) BOOL metricsTlsConfigured;
|
|
74
88
|
@property (nonatomic, readonly, copy) NSString *metricsCreditsPlainText;
|
|
75
89
|
|
|
76
|
-
|
|
77
|
-
- (double)
|
|
78
|
-
- (double)
|
|
79
|
-
- (double)
|
|
80
|
-
- (double)
|
|
81
|
-
- (double)
|
|
82
|
-
- (double)
|
|
90
|
+
// ── Actual camera readback (what was rendered most recently) ────────────
|
|
91
|
+
- (double)readActualLatitude;
|
|
92
|
+
- (double)readActualLongitude;
|
|
93
|
+
- (double)readActualAltitude;
|
|
94
|
+
- (double)readActualHeading;
|
|
95
|
+
- (double)readActualPitch;
|
|
96
|
+
- (double)readActualRoll;
|
|
97
|
+
- (double)readActualVerticalFovDeg;
|
|
98
|
+
|
|
99
|
+
// ── Demand camera readback (what the consumer last asked for) ───────────
|
|
100
|
+
- (double)readDemandLatitude;
|
|
101
|
+
- (double)readDemandLongitude;
|
|
102
|
+
- (double)readDemandAltitude;
|
|
103
|
+
- (double)readDemandHeading;
|
|
104
|
+
- (double)readDemandPitch;
|
|
105
|
+
- (double)readDemandRoll;
|
|
106
|
+
- (double)readDemandVerticalFovDeg;
|
|
107
|
+
|
|
83
108
|
- (double)readViewCorrectionW;
|
|
84
109
|
- (double)readViewCorrectionX;
|
|
85
110
|
- (double)readViewCorrectionY;
|