react-native-cesium 1.2.2 → 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.
Files changed (40) hide show
  1. package/README.md +100 -26
  2. package/android/CMakeLists.txt +1 -2
  3. package/android/src/main/cpp/CesiumBridgeAndroid.cpp +264 -130
  4. package/android/src/main/cpp/CesiumBridgeAndroid.h +70 -27
  5. package/android/src/main/java/com/margelo/nitro/reactnativecesium/CesiumBridgeJNI.kt +68 -44
  6. package/android/src/main/java/com/margelo/nitro/reactnativecesium/HybridCesiumView.kt +160 -187
  7. package/cpp/engine/CameraIntegrator.cpp +374 -0
  8. package/cpp/engine/CameraIntegrator.hpp +146 -0
  9. package/cpp/engine/CesiumEngine.cpp +3 -1
  10. package/cpp/engine/EngineTunables.hpp +80 -21
  11. package/cpp/engine/GlobeCamera.cpp +17 -6
  12. package/cpp/engine/GlobeCamera.hpp +11 -8
  13. package/cpp/engine/test/CameraIntegratorTest.cpp +205 -0
  14. package/cpp/engine/test/build_and_run.sh +27 -0
  15. package/example/README.md +1 -1
  16. package/ios/CesiumBridge.h +53 -28
  17. package/ios/CesiumBridge.mm +172 -86
  18. package/ios/HybridCesiumView.swift +213 -145
  19. package/lib/typescript/src/specs/cesium-view.nitro.d.ts +77 -13
  20. package/lib/typescript/src/specs/cesium-view.nitro.d.ts.map +1 -1
  21. package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.cpp +90 -9
  22. package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.hpp +19 -3
  23. package/nitrogen/generated/android/c++/views/JHybridCesiumViewStateUpdater.cpp +20 -0
  24. package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/HybridCesiumViewSpec.kt +57 -3
  25. package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Bridge.hpp +9 -9
  26. package/nitrogen/generated/ios/c++/HybridCesiumViewSpecSwift.hpp +82 -9
  27. package/nitrogen/generated/ios/c++/views/HybridCesiumViewComponent.mm +25 -0
  28. package/nitrogen/generated/ios/swift/HybridCesiumViewSpec.swift +14 -3
  29. package/nitrogen/generated/ios/swift/HybridCesiumViewSpec_cxx.swift +210 -16
  30. package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.cpp +19 -3
  31. package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.hpp +20 -4
  32. package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.cpp +55 -0
  33. package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.hpp +5 -0
  34. package/nitrogen/generated/shared/json/CesiumViewConfig.json +5 -0
  35. package/package.json +2 -2
  36. package/src/specs/cesium-view.nitro.ts +93 -14
  37. package/cpp/engine/CameraSmoother.cpp +0 -71
  38. package/cpp/engine/CameraSmoother.hpp +0 -25
  39. package/cpp/engine/CameraTargetState.cpp +0 -140
  40. package/cpp/engine/CameraTargetState.hpp +0 -103
@@ -532,6 +532,126 @@ open class HybridCesiumViewSpec_cxx {
532
532
  }
533
533
  }
534
534
 
535
+ public final var maxYawRateDegSec: bridge.std__optional_double_ {
536
+ @inline(__always)
537
+ get {
538
+ return { () -> bridge.std__optional_double_ in
539
+ if let __unwrappedValue = self.__implementation.maxYawRateDegSec {
540
+ return bridge.create_std__optional_double_(__unwrappedValue)
541
+ } else {
542
+ return .init()
543
+ }
544
+ }()
545
+ }
546
+ @inline(__always)
547
+ set {
548
+ self.__implementation.maxYawRateDegSec = { () -> Double? in
549
+ if bridge.has_value_std__optional_double_(newValue) {
550
+ let __unwrapped = bridge.get_std__optional_double_(newValue)
551
+ return __unwrapped
552
+ } else {
553
+ return nil
554
+ }
555
+ }()
556
+ }
557
+ }
558
+
559
+ public final var maxPitchRateDegSec: bridge.std__optional_double_ {
560
+ @inline(__always)
561
+ get {
562
+ return { () -> bridge.std__optional_double_ in
563
+ if let __unwrappedValue = self.__implementation.maxPitchRateDegSec {
564
+ return bridge.create_std__optional_double_(__unwrappedValue)
565
+ } else {
566
+ return .init()
567
+ }
568
+ }()
569
+ }
570
+ @inline(__always)
571
+ set {
572
+ self.__implementation.maxPitchRateDegSec = { () -> Double? in
573
+ if bridge.has_value_std__optional_double_(newValue) {
574
+ let __unwrapped = bridge.get_std__optional_double_(newValue)
575
+ return __unwrapped
576
+ } else {
577
+ return nil
578
+ }
579
+ }()
580
+ }
581
+ }
582
+
583
+ public final var maxRollRateDegSec: bridge.std__optional_double_ {
584
+ @inline(__always)
585
+ get {
586
+ return { () -> bridge.std__optional_double_ in
587
+ if let __unwrappedValue = self.__implementation.maxRollRateDegSec {
588
+ return bridge.create_std__optional_double_(__unwrappedValue)
589
+ } else {
590
+ return .init()
591
+ }
592
+ }()
593
+ }
594
+ @inline(__always)
595
+ set {
596
+ self.__implementation.maxRollRateDegSec = { () -> Double? in
597
+ if bridge.has_value_std__optional_double_(newValue) {
598
+ let __unwrapped = bridge.get_std__optional_double_(newValue)
599
+ return __unwrapped
600
+ } else {
601
+ return nil
602
+ }
603
+ }()
604
+ }
605
+ }
606
+
607
+ public final var maxClimbRateMps: bridge.std__optional_double_ {
608
+ @inline(__always)
609
+ get {
610
+ return { () -> bridge.std__optional_double_ in
611
+ if let __unwrappedValue = self.__implementation.maxClimbRateMps {
612
+ return bridge.create_std__optional_double_(__unwrappedValue)
613
+ } else {
614
+ return .init()
615
+ }
616
+ }()
617
+ }
618
+ @inline(__always)
619
+ set {
620
+ self.__implementation.maxClimbRateMps = { () -> Double? in
621
+ if bridge.has_value_std__optional_double_(newValue) {
622
+ let __unwrapped = bridge.get_std__optional_double_(newValue)
623
+ return __unwrapped
624
+ } else {
625
+ return nil
626
+ }
627
+ }()
628
+ }
629
+ }
630
+
631
+ public final var maxGroundSpeedMps: bridge.std__optional_double_ {
632
+ @inline(__always)
633
+ get {
634
+ return { () -> bridge.std__optional_double_ in
635
+ if let __unwrappedValue = self.__implementation.maxGroundSpeedMps {
636
+ return bridge.create_std__optional_double_(__unwrappedValue)
637
+ } else {
638
+ return .init()
639
+ }
640
+ }()
641
+ }
642
+ @inline(__always)
643
+ set {
644
+ self.__implementation.maxGroundSpeedMps = { () -> Double? in
645
+ if bridge.has_value_std__optional_double_(newValue) {
646
+ let __unwrapped = bridge.get_std__optional_double_(newValue)
647
+ return __unwrapped
648
+ } else {
649
+ return nil
650
+ }
651
+ }()
652
+ }
653
+ }
654
+
535
655
  public final var onMetrics: bridge.std__optional_std__function_void_const_CesiumMetrics_____metrics______ {
536
656
  @inline(__always)
537
657
  get {
@@ -566,28 +686,20 @@ open class HybridCesiumViewSpec_cxx {
566
686
 
567
687
  // Methods
568
688
  @inline(__always)
569
- public final func getCameraState() -> bridge.Result_std__shared_ptr_Promise_CameraState___ {
689
+ public final func setPosition(latitude: Double, longitude: Double) -> bridge.Result_void_ {
570
690
  do {
571
- let __result = try self.__implementation.getCameraState()
572
- let __resultCpp = { () -> bridge.std__shared_ptr_Promise_CameraState__ in
573
- let __promise = bridge.create_std__shared_ptr_Promise_CameraState__()
574
- let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_CameraState__(__promise)
575
- __result
576
- .then({ __result in __promiseHolder.resolve(__result) })
577
- .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
578
- return __promise
579
- }()
580
- return bridge.create_Result_std__shared_ptr_Promise_CameraState___(__resultCpp)
691
+ try self.__implementation.setPosition(latitude: latitude, longitude: longitude)
692
+ return bridge.create_Result_void_()
581
693
  } catch (let __error) {
582
694
  let __exceptionPtr = __error.toCpp()
583
- return bridge.create_Result_std__shared_ptr_Promise_CameraState___(__exceptionPtr)
695
+ return bridge.create_Result_void_(__exceptionPtr)
584
696
  }
585
697
  }
586
698
 
587
699
  @inline(__always)
588
- public final func setCamera(camera: CameraState) -> bridge.Result_void_ {
700
+ public final func setAltitude(altitudeMeters: Double) -> bridge.Result_void_ {
589
701
  do {
590
- try self.__implementation.setCamera(camera: camera)
702
+ try self.__implementation.setAltitude(altitudeMeters: altitudeMeters)
591
703
  return bridge.create_Result_void_()
592
704
  } catch (let __error) {
593
705
  let __exceptionPtr = __error.toCpp()
@@ -596,9 +708,9 @@ open class HybridCesiumViewSpec_cxx {
596
708
  }
597
709
 
598
710
  @inline(__always)
599
- public final func setCameraQuaternion(camera: CameraState, viewCorrection: Quaternion) -> bridge.Result_void_ {
711
+ public final func setHeading(headingDeg: Double) -> bridge.Result_void_ {
600
712
  do {
601
- try self.__implementation.setCameraQuaternion(camera: camera, viewCorrection: viewCorrection)
713
+ try self.__implementation.setHeading(headingDeg: headingDeg)
602
714
  return bridge.create_Result_void_()
603
715
  } catch (let __error) {
604
716
  let __exceptionPtr = __error.toCpp()
@@ -606,6 +718,88 @@ open class HybridCesiumViewSpec_cxx {
606
718
  }
607
719
  }
608
720
 
721
+ @inline(__always)
722
+ public final func setAttitude(pitchDeg: Double, rollDeg: Double) -> bridge.Result_void_ {
723
+ do {
724
+ try self.__implementation.setAttitude(pitchDeg: pitchDeg, rollDeg: rollDeg)
725
+ return bridge.create_Result_void_()
726
+ } catch (let __error) {
727
+ let __exceptionPtr = __error.toCpp()
728
+ return bridge.create_Result_void_(__exceptionPtr)
729
+ }
730
+ }
731
+
732
+ @inline(__always)
733
+ public final func setViewCorrection(q: Quaternion) -> bridge.Result_void_ {
734
+ do {
735
+ try self.__implementation.setViewCorrection(q: q)
736
+ return bridge.create_Result_void_()
737
+ } catch (let __error) {
738
+ let __exceptionPtr = __error.toCpp()
739
+ return bridge.create_Result_void_(__exceptionPtr)
740
+ }
741
+ }
742
+
743
+ @inline(__always)
744
+ public final func setVerticalFov(deg: Double) -> bridge.Result_void_ {
745
+ do {
746
+ try self.__implementation.setVerticalFov(deg: deg)
747
+ return bridge.create_Result_void_()
748
+ } catch (let __error) {
749
+ let __exceptionPtr = __error.toCpp()
750
+ return bridge.create_Result_void_(__exceptionPtr)
751
+ }
752
+ }
753
+
754
+ @inline(__always)
755
+ public final func teleport(camera: CameraState) -> bridge.Result_void_ {
756
+ do {
757
+ try self.__implementation.teleport(camera: camera)
758
+ return bridge.create_Result_void_()
759
+ } catch (let __error) {
760
+ let __exceptionPtr = __error.toCpp()
761
+ return bridge.create_Result_void_(__exceptionPtr)
762
+ }
763
+ }
764
+
765
+ @inline(__always)
766
+ public final func getActualCamera() -> bridge.Result_std__shared_ptr_Promise_CameraState___ {
767
+ do {
768
+ let __result = try self.__implementation.getActualCamera()
769
+ let __resultCpp = { () -> bridge.std__shared_ptr_Promise_CameraState__ in
770
+ let __promise = bridge.create_std__shared_ptr_Promise_CameraState__()
771
+ let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_CameraState__(__promise)
772
+ __result
773
+ .then({ __result in __promiseHolder.resolve(__result) })
774
+ .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
775
+ return __promise
776
+ }()
777
+ return bridge.create_Result_std__shared_ptr_Promise_CameraState___(__resultCpp)
778
+ } catch (let __error) {
779
+ let __exceptionPtr = __error.toCpp()
780
+ return bridge.create_Result_std__shared_ptr_Promise_CameraState___(__exceptionPtr)
781
+ }
782
+ }
783
+
784
+ @inline(__always)
785
+ public final func getDemandCamera() -> bridge.Result_std__shared_ptr_Promise_CameraState___ {
786
+ do {
787
+ let __result = try self.__implementation.getDemandCamera()
788
+ let __resultCpp = { () -> bridge.std__shared_ptr_Promise_CameraState__ in
789
+ let __promise = bridge.create_std__shared_ptr_Promise_CameraState__()
790
+ let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_CameraState__(__promise)
791
+ __result
792
+ .then({ __result in __promiseHolder.resolve(__result) })
793
+ .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
794
+ return __promise
795
+ }()
796
+ return bridge.create_Result_std__shared_ptr_Promise_CameraState___(__resultCpp)
797
+ } catch (let __error) {
798
+ let __exceptionPtr = __error.toCpp()
799
+ return bridge.create_Result_std__shared_ptr_Promise_CameraState___(__exceptionPtr)
800
+ }
801
+ }
802
+
609
803
  @inline(__always)
610
804
  public final func getViewCorrection() -> bridge.Result_std__shared_ptr_Promise_Quaternion___ {
611
805
  do {
@@ -58,11 +58,27 @@ namespace margelo::nitro::reactnativecesium {
58
58
  prototype.registerHybridSetter("taskProcessorThreads", &HybridCesiumViewSpec::setTaskProcessorThreads);
59
59
  prototype.registerHybridGetter("minAltitudeAboveTerrain", &HybridCesiumViewSpec::getMinAltitudeAboveTerrain);
60
60
  prototype.registerHybridSetter("minAltitudeAboveTerrain", &HybridCesiumViewSpec::setMinAltitudeAboveTerrain);
61
+ prototype.registerHybridGetter("maxYawRateDegSec", &HybridCesiumViewSpec::getMaxYawRateDegSec);
62
+ prototype.registerHybridSetter("maxYawRateDegSec", &HybridCesiumViewSpec::setMaxYawRateDegSec);
63
+ prototype.registerHybridGetter("maxPitchRateDegSec", &HybridCesiumViewSpec::getMaxPitchRateDegSec);
64
+ prototype.registerHybridSetter("maxPitchRateDegSec", &HybridCesiumViewSpec::setMaxPitchRateDegSec);
65
+ prototype.registerHybridGetter("maxRollRateDegSec", &HybridCesiumViewSpec::getMaxRollRateDegSec);
66
+ prototype.registerHybridSetter("maxRollRateDegSec", &HybridCesiumViewSpec::setMaxRollRateDegSec);
67
+ prototype.registerHybridGetter("maxClimbRateMps", &HybridCesiumViewSpec::getMaxClimbRateMps);
68
+ prototype.registerHybridSetter("maxClimbRateMps", &HybridCesiumViewSpec::setMaxClimbRateMps);
69
+ prototype.registerHybridGetter("maxGroundSpeedMps", &HybridCesiumViewSpec::getMaxGroundSpeedMps);
70
+ prototype.registerHybridSetter("maxGroundSpeedMps", &HybridCesiumViewSpec::setMaxGroundSpeedMps);
61
71
  prototype.registerHybridGetter("onMetrics", &HybridCesiumViewSpec::getOnMetrics);
62
72
  prototype.registerHybridSetter("onMetrics", &HybridCesiumViewSpec::setOnMetrics);
63
- prototype.registerHybridMethod("getCameraState", &HybridCesiumViewSpec::getCameraState);
64
- prototype.registerHybridMethod("setCamera", &HybridCesiumViewSpec::setCamera);
65
- prototype.registerHybridMethod("setCameraQuaternion", &HybridCesiumViewSpec::setCameraQuaternion);
73
+ prototype.registerHybridMethod("setPosition", &HybridCesiumViewSpec::setPosition);
74
+ prototype.registerHybridMethod("setAltitude", &HybridCesiumViewSpec::setAltitude);
75
+ prototype.registerHybridMethod("setHeading", &HybridCesiumViewSpec::setHeading);
76
+ prototype.registerHybridMethod("setAttitude", &HybridCesiumViewSpec::setAttitude);
77
+ prototype.registerHybridMethod("setViewCorrection", &HybridCesiumViewSpec::setViewCorrection);
78
+ prototype.registerHybridMethod("setVerticalFov", &HybridCesiumViewSpec::setVerticalFov);
79
+ prototype.registerHybridMethod("teleport", &HybridCesiumViewSpec::teleport);
80
+ prototype.registerHybridMethod("getActualCamera", &HybridCesiumViewSpec::getActualCamera);
81
+ prototype.registerHybridMethod("getDemandCamera", &HybridCesiumViewSpec::getDemandCamera);
66
82
  prototype.registerHybridMethod("getViewCorrection", &HybridCesiumViewSpec::getViewCorrection);
67
83
  });
68
84
  }
@@ -25,8 +25,8 @@ namespace margelo::nitro::reactnativecesium { struct Quaternion; }
25
25
  #include <optional>
26
26
  #include "CesiumMetrics.hpp"
27
27
  #include <functional>
28
- #include <NitroModules/Promise.hpp>
29
28
  #include "Quaternion.hpp"
29
+ #include <NitroModules/Promise.hpp>
30
30
 
31
31
  namespace margelo::nitro::reactnativecesium {
32
32
 
@@ -99,14 +99,30 @@ namespace margelo::nitro::reactnativecesium {
99
99
  virtual void setTaskProcessorThreads(std::optional<double> taskProcessorThreads) = 0;
100
100
  virtual std::optional<double> getMinAltitudeAboveTerrain() = 0;
101
101
  virtual void setMinAltitudeAboveTerrain(std::optional<double> minAltitudeAboveTerrain) = 0;
102
+ virtual std::optional<double> getMaxYawRateDegSec() = 0;
103
+ virtual void setMaxYawRateDegSec(std::optional<double> maxYawRateDegSec) = 0;
104
+ virtual std::optional<double> getMaxPitchRateDegSec() = 0;
105
+ virtual void setMaxPitchRateDegSec(std::optional<double> maxPitchRateDegSec) = 0;
106
+ virtual std::optional<double> getMaxRollRateDegSec() = 0;
107
+ virtual void setMaxRollRateDegSec(std::optional<double> maxRollRateDegSec) = 0;
108
+ virtual std::optional<double> getMaxClimbRateMps() = 0;
109
+ virtual void setMaxClimbRateMps(std::optional<double> maxClimbRateMps) = 0;
110
+ virtual std::optional<double> getMaxGroundSpeedMps() = 0;
111
+ virtual void setMaxGroundSpeedMps(std::optional<double> maxGroundSpeedMps) = 0;
102
112
  virtual std::optional<std::function<void(const CesiumMetrics& /* metrics */)>> getOnMetrics() = 0;
103
113
  virtual void setOnMetrics(const std::optional<std::function<void(const CesiumMetrics& /* metrics */)>>& onMetrics) = 0;
104
114
 
105
115
  public:
106
116
  // Methods
107
- virtual std::shared_ptr<Promise<CameraState>> getCameraState() = 0;
108
- virtual void setCamera(const CameraState& camera) = 0;
109
- virtual void setCameraQuaternion(const CameraState& camera, const Quaternion& viewCorrection) = 0;
117
+ virtual void setPosition(double latitude, double longitude) = 0;
118
+ virtual void setAltitude(double altitudeMeters) = 0;
119
+ virtual void setHeading(double headingDeg) = 0;
120
+ virtual void setAttitude(double pitchDeg, double rollDeg) = 0;
121
+ virtual void setViewCorrection(const Quaternion& q) = 0;
122
+ virtual void setVerticalFov(double deg) = 0;
123
+ virtual void teleport(const CameraState& camera) = 0;
124
+ virtual std::shared_ptr<Promise<CameraState>> getActualCamera() = 0;
125
+ virtual std::shared_ptr<Promise<CameraState>> getDemandCamera() = 0;
110
126
  virtual std::shared_ptr<Promise<Quaternion>> getViewCorrection() = 0;
111
127
 
112
128
  protected:
@@ -246,6 +246,56 @@ namespace margelo::nitro::reactnativecesium::views {
246
246
  throw std::runtime_error(std::string("CesiumView.minAltitudeAboveTerrain: ") + exc.what());
247
247
  }
248
248
  }()),
249
+ maxYawRateDegSec([&]() -> CachedProp<std::optional<double>> {
250
+ try {
251
+ const react::RawValue* rawValue = rawProps.at("maxYawRateDegSec", nullptr, nullptr);
252
+ if (rawValue == nullptr) return sourceProps.maxYawRateDegSec;
253
+ const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
254
+ return CachedProp<std::optional<double>>::fromRawValue(*runtime, value, sourceProps.maxYawRateDegSec);
255
+ } catch (const std::exception& exc) {
256
+ throw std::runtime_error(std::string("CesiumView.maxYawRateDegSec: ") + exc.what());
257
+ }
258
+ }()),
259
+ maxPitchRateDegSec([&]() -> CachedProp<std::optional<double>> {
260
+ try {
261
+ const react::RawValue* rawValue = rawProps.at("maxPitchRateDegSec", nullptr, nullptr);
262
+ if (rawValue == nullptr) return sourceProps.maxPitchRateDegSec;
263
+ const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
264
+ return CachedProp<std::optional<double>>::fromRawValue(*runtime, value, sourceProps.maxPitchRateDegSec);
265
+ } catch (const std::exception& exc) {
266
+ throw std::runtime_error(std::string("CesiumView.maxPitchRateDegSec: ") + exc.what());
267
+ }
268
+ }()),
269
+ maxRollRateDegSec([&]() -> CachedProp<std::optional<double>> {
270
+ try {
271
+ const react::RawValue* rawValue = rawProps.at("maxRollRateDegSec", nullptr, nullptr);
272
+ if (rawValue == nullptr) return sourceProps.maxRollRateDegSec;
273
+ const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
274
+ return CachedProp<std::optional<double>>::fromRawValue(*runtime, value, sourceProps.maxRollRateDegSec);
275
+ } catch (const std::exception& exc) {
276
+ throw std::runtime_error(std::string("CesiumView.maxRollRateDegSec: ") + exc.what());
277
+ }
278
+ }()),
279
+ maxClimbRateMps([&]() -> CachedProp<std::optional<double>> {
280
+ try {
281
+ const react::RawValue* rawValue = rawProps.at("maxClimbRateMps", nullptr, nullptr);
282
+ if (rawValue == nullptr) return sourceProps.maxClimbRateMps;
283
+ const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
284
+ return CachedProp<std::optional<double>>::fromRawValue(*runtime, value, sourceProps.maxClimbRateMps);
285
+ } catch (const std::exception& exc) {
286
+ throw std::runtime_error(std::string("CesiumView.maxClimbRateMps: ") + exc.what());
287
+ }
288
+ }()),
289
+ maxGroundSpeedMps([&]() -> CachedProp<std::optional<double>> {
290
+ try {
291
+ const react::RawValue* rawValue = rawProps.at("maxGroundSpeedMps", nullptr, nullptr);
292
+ if (rawValue == nullptr) return sourceProps.maxGroundSpeedMps;
293
+ const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
294
+ return CachedProp<std::optional<double>>::fromRawValue(*runtime, value, sourceProps.maxGroundSpeedMps);
295
+ } catch (const std::exception& exc) {
296
+ throw std::runtime_error(std::string("CesiumView.maxGroundSpeedMps: ") + exc.what());
297
+ }
298
+ }()),
249
299
  onMetrics([&]() -> CachedProp<std::optional<std::function<void(const CesiumMetrics& /* metrics */)>>> {
250
300
  try {
251
301
  const react::RawValue* rawValue = rawProps.at("onMetrics", nullptr, nullptr);
@@ -291,6 +341,11 @@ namespace margelo::nitro::reactnativecesium::views {
291
341
  case hashString("sqliteCacheMaxRows"): return true;
292
342
  case hashString("taskProcessorThreads"): return true;
293
343
  case hashString("minAltitudeAboveTerrain"): return true;
344
+ case hashString("maxYawRateDegSec"): return true;
345
+ case hashString("maxPitchRateDegSec"): return true;
346
+ case hashString("maxRollRateDegSec"): return true;
347
+ case hashString("maxClimbRateMps"): return true;
348
+ case hashString("maxGroundSpeedMps"): return true;
294
349
  case hashString("onMetrics"): return true;
295
350
  case hashString("hybridRef"): return true;
296
351
  default: return false;
@@ -66,6 +66,11 @@ namespace margelo::nitro::reactnativecesium::views {
66
66
  CachedProp<std::optional<double>> sqliteCacheMaxRows;
67
67
  CachedProp<std::optional<double>> taskProcessorThreads;
68
68
  CachedProp<std::optional<double>> minAltitudeAboveTerrain;
69
+ CachedProp<std::optional<double>> maxYawRateDegSec;
70
+ CachedProp<std::optional<double>> maxPitchRateDegSec;
71
+ CachedProp<std::optional<double>> maxRollRateDegSec;
72
+ CachedProp<std::optional<double>> maxClimbRateMps;
73
+ CachedProp<std::optional<double>> maxGroundSpeedMps;
69
74
  CachedProp<std::optional<std::function<void(const CesiumMetrics& /* metrics */)>>> onMetrics;
70
75
  CachedProp<std::optional<std::function<void(const std::shared_ptr<HybridCesiumViewSpec>& /* ref */)>>> hybridRef;
71
76
 
@@ -26,6 +26,11 @@
26
26
  "sqliteCacheMaxRows": true,
27
27
  "taskProcessorThreads": true,
28
28
  "minAltitudeAboveTerrain": true,
29
+ "maxYawRateDegSec": true,
30
+ "maxPitchRateDegSec": true,
31
+ "maxRollRateDegSec": true,
32
+ "maxClimbRateMps": true,
33
+ "maxGroundSpeedMps": true,
29
34
  "onMetrics": true,
30
35
  "hybridRef": true
31
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-cesium",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "Experimental Cesium rendering for React Native via Nitro (iOS/Metal today; Android planned)",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/module/index.js",
@@ -79,7 +79,7 @@
79
79
  "conventional-changelog-conventionalcommits": "^9.3.1",
80
80
  "nitrogen": "0.35.6",
81
81
  "react": "19.2.3",
82
- "react-native": "0.85.2",
82
+ "react-native": "0.85.3",
83
83
  "react-native-builder-bob": "^0.41.0",
84
84
  "semantic-release": "^25.0.3",
85
85
  "typescript": "^5.9.3"
@@ -4,7 +4,10 @@ import type {
4
4
  HybridViewMethods,
5
5
  } from 'react-native-nitro-modules'
6
6
 
7
- /** Snapshot of the native camera for persistence / sync with React state. */
7
+ /**
8
+ * Snapshot of the native camera for persistence / sync with React state.
9
+ * Returned by `getActualCamera()` and `getDemandCamera()`.
10
+ */
8
11
  export interface CameraState {
9
12
  latitude: number
10
13
  longitude: number
@@ -16,8 +19,9 @@ export interface CameraState {
16
19
  }
17
20
 
18
21
  /**
19
- * Unit quaternion (w + xi + yj + zk). Used for camera-space view correction.
20
- * Non-unit values are normalized on the native side.
22
+ * Unit quaternion (w + xi + yj + zk). Used for camera-space view correction
23
+ * applied after HPR (boresight / HUD alignment). Non-unit values are
24
+ * normalised on the native side.
21
25
  */
22
26
  export interface Quaternion {
23
27
  w: number
@@ -42,7 +46,11 @@ export interface CesiumMetrics {
42
46
  export interface CesiumViewProps extends HybridViewProps {
43
47
  ionAccessToken: string
44
48
  ionAssetId: number
45
- /** Construction-time seed camera. Use `setCamera()` for runtime updates. */
49
+ /**
50
+ * Initial camera applied via `teleport(...)` once when the native bridge is
51
+ * created. Subsequent prop writes are ignored — use the per-DoF setters or
52
+ * `teleport(...)` for runtime updates.
53
+ */
46
54
  initialCamera: CameraState
47
55
  pauseRendering: boolean
48
56
  maximumScreenSpaceError: number
@@ -52,7 +60,7 @@ export interface CesiumViewProps extends HybridViewProps {
52
60
  msaaSampleCount: number
53
61
  ionImageryAssetId: number
54
62
 
55
- // ── Optional perf / quality knobs (added in 1.1) ─────────────────────
63
+ // ── Optional perf / quality knobs ────────────────────────────────────────
56
64
  /** RAM budget for live tileset, in mebibytes. Default 256. */
57
65
  maximumCachedMiB?: number
58
66
  /** Pre-load ancestor tiles around the visible set (smoother panning, more loads). Default true. */
@@ -85,23 +93,94 @@ export interface CesiumViewProps extends HybridViewProps {
85
93
  */
86
94
  minAltitudeAboveTerrain?: number
87
95
 
96
+ // ── Optional rate caps (flight-sim feel) ─────────────────────────────────
97
+ // All defaults: 0 = uncapped. Override per-screen to enforce a maximum
98
+ // angular / linear speed on the integrator's per-DoF velocity. Useful when
99
+ // your sensor feed is noisy and you would rather drop the change than
100
+ // visually whip the camera.
101
+ /** Maximum yaw rate (degrees per second). 0 = uncapped. */
102
+ maxYawRateDegSec?: number
103
+ /** Maximum pitch rate (degrees per second). 0 = uncapped. */
104
+ maxPitchRateDegSec?: number
105
+ /** Maximum roll rate (degrees per second). 0 = uncapped. */
106
+ maxRollRateDegSec?: number
107
+ /** Maximum climb / descent rate (metres per second). 0 = uncapped. */
108
+ maxClimbRateMps?: number
109
+ /** Maximum horizontal ground speed (metres per second). 0 = uncapped. */
110
+ maxGroundSpeedMps?: number
111
+
88
112
  onMetrics?: (metrics: CesiumMetrics) => void
89
113
  }
90
114
 
115
+ /**
116
+ * Per-DoF camera control. Every setter records the measurement with the
117
+ * native steady_clock time of arrival and feeds it into an α-β tracker
118
+ * (constant-velocity predictor) that owns both demand and actual state.
119
+ *
120
+ * All setters are synchronous and thread-safe. Calling them from a
121
+ * Reanimated worklet via a Nitro `hybridRef` is the supported path for
122
+ * high-frequency updates; the worklet thread takes the integrator's mutex
123
+ * briefly and returns immediately.
124
+ *
125
+ * Getters return Promises and should be called from the JS thread (e.g. a
126
+ * `useEffect` or a throttled HUD update), not from a worklet.
127
+ */
91
128
  export interface CesiumViewMethods extends HybridViewMethods {
92
- /** Returns the current native camera state. */
93
- getCameraState(): Promise<CameraState>
94
129
  /**
95
- * Runtime camera control (heading/pitch/roll + position + VFOV).
96
- * Does not change the view-correction quaternion; use `setCameraQuaternion` to set that.
130
+ * New geographic position demand (latitude / longitude in degrees). Use
131
+ * for GPS or scripted position updates. Latitude is clamped to ±90 by the
132
+ * integrator; longitude is continuous (no wrap normalisation) so the
133
+ * shortest-arc residual maths stays correct across the antimeridian.
134
+ */
135
+ setPosition(latitude: number, longitude: number): void
136
+
137
+ /** New altitude demand (metres above mean sea level). */
138
+ setAltitude(altitudeMeters: number): void
139
+
140
+ /** New heading demand (degrees, 0 = north, increasing clockwise). */
141
+ setHeading(headingDeg: number): void
142
+
143
+ /**
144
+ * New attitude demand (pitch and roll in degrees). Bundled because almost
145
+ * every IMU emits them together — but you can pass the previous value for
146
+ * either axis if you only have one of them.
97
147
  */
98
- setCamera(camera: CameraState): void
148
+ setAttitude(pitchDeg: number, rollDeg: number): void
149
+
150
+ /**
151
+ * New camera-space rotation applied after HPR (unit quaternion). Use for
152
+ * boresight calibration or screen-fixed HUD alignment. SLERPed toward the
153
+ * latest demand each frame.
154
+ */
155
+ setViewCorrection(q: Quaternion): void
156
+
157
+ /** New vertical field-of-view demand (degrees). Clamped to 20..100. */
158
+ setVerticalFov(deg: number): void
159
+
160
+ /**
161
+ * Atomically reset every DoF to the given camera state (value, velocity
162
+ * and demand all snap to the target). Bypasses the integrator entirely;
163
+ * use for `Fly to coordinate` actions or initial seeding from saved
164
+ * state.
165
+ */
166
+ teleport(camera: CameraState): void
167
+
168
+ /**
169
+ * Most recent camera that was rendered (post-integration). This is what
170
+ * the user is currently looking at and is what a HUD overlay should
171
+ * mirror. Differs from `getDemandCamera()` while a glide is in progress
172
+ * or when the terrain-floor clamp has raised the altitude.
173
+ */
174
+ getActualCamera(): Promise<CameraState>
175
+
99
176
  /**
100
- * Same fields as `setCamera`, plus a camera-space rotation applied after HPR
101
- * (e.g. boresight / HUD alignment). See README.
177
+ * What the consumer last asked for (per-DoF demand). Useful for
178
+ * diagnostics or for showing the requested camera alongside the rendered
179
+ * one.
102
180
  */
103
- setCameraQuaternion(camera: CameraState, viewCorrection: Quaternion): void
104
- /** Current view-correction quaternion (identity if never set via `setCameraQuaternion`). */
181
+ getDemandCamera(): Promise<CameraState>
182
+
183
+ /** Current view-correction quaternion (smoothed toward the latest demand). */
105
184
  getViewCorrection(): Promise<Quaternion>
106
185
  }
107
186
 
@@ -1,71 +0,0 @@
1
- #include "CameraSmoother.hpp"
2
-
3
- #include "EngineTunables.hpp"
4
-
5
- #include <cmath>
6
-
7
- namespace reactnativecesium {
8
-
9
- namespace {
10
-
11
- inline double lerpAngleDeg(double a, double b, double t) {
12
- // Wraps difference to [-180, 180] before applying the mix factor so we
13
- // always rotate the short way around the unit circle.
14
- double diff = std::fmod(b - a + 540.0, 360.0) - 180.0;
15
- return a + diff * t;
16
- }
17
-
18
- inline double angleDeltaAbsDeg(double a, double b) {
19
- return std::abs(std::fmod(b - a + 540.0, 360.0) - 180.0);
20
- }
21
-
22
- inline double quatDotAbs(const glm::dquat& a, const glm::dquat& b) {
23
- return std::abs(glm::dot(glm::normalize(a), glm::normalize(b)));
24
- }
25
-
26
- } // namespace
27
-
28
- CameraParams CameraSmoother::step(
29
- const CameraParams& current, const CameraParams& target, double dt) {
30
- CameraParams next = current;
31
-
32
- // lat/lon: snap directly to the target.
33
- // CameraTargetState::snapshot() already produces a linearly-interpolated
34
- // position that advances at constant speed between position fixes, so
35
- // snapping here gives smooth, constant-velocity motion with no ease-in/out.
36
- next.latitude = target.latitude;
37
- next.longitude = target.longitude;
38
-
39
- const double aAlt = 1.0 - std::exp(-tunables::kSmoothAltitude * dt);
40
- const double aHdg = 1.0 - std::exp(-tunables::kSmoothHeading * dt);
41
- const double aPitch = 1.0 - std::exp(-tunables::kSmoothPitch * dt);
42
- const double aRoll = 1.0 - std::exp(-tunables::kSmoothRoll * dt);
43
- const double aViewQ = 1.0 - std::exp(-tunables::kSmoothViewCorr * dt);
44
-
45
- next.altitude = current.altitude + aAlt * (target.altitude - current.altitude);
46
- next.heading = lerpAngleDeg(current.heading, target.heading, aHdg);
47
- next.pitch = lerpAngleDeg(current.pitch, target.pitch, aPitch);
48
- next.roll = lerpAngleDeg(current.roll, target.roll, aRoll);
49
-
50
- glm::dquat cq = glm::normalize(current.viewCorrection);
51
- glm::dquat tq = glm::normalize(target.viewCorrection);
52
- if (glm::dot(cq, tq) < 0.0) tq = -tq;
53
- next.viewCorrection = glm::normalize(glm::slerp(cq, tq, aViewQ));
54
-
55
- // Eventually-exact convergence: snap once the residual is sub-epsilon.
56
- if (std::abs(target.altitude - next.altitude) <= tunables::kEpsAltitudeMeters)
57
- next.altitude = target.altitude;
58
- if (angleDeltaAbsDeg(next.heading, target.heading) <= tunables::kEpsAngleDeg)
59
- next.heading = target.heading;
60
- if (angleDeltaAbsDeg(next.pitch, target.pitch) <= tunables::kEpsAngleDeg)
61
- next.pitch = target.pitch;
62
- if (angleDeltaAbsDeg(next.roll, target.roll) <= tunables::kEpsAngleDeg)
63
- next.roll = target.roll;
64
- if ((1.0 - quatDotAbs(next.viewCorrection, target.viewCorrection))
65
- <= tunables::kEpsQuatDot)
66
- next.viewCorrection = target.viewCorrection;
67
-
68
- return next;
69
- }
70
-
71
- } // namespace reactnativecesium