react-native-cesium 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE +12 -0
- package/README.md +308 -0
- package/ReactNativeCesium.podspec +54 -0
- package/android/CMakeLists.txt +146 -0
- package/android/build.gradle +178 -0
- package/android/fix-prefab.gradle +51 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +5 -0
- package/android/src/main/assets/cacert.pem +3529 -0
- package/android/src/main/cpp/CesiumBridgeAndroid.cpp +487 -0
- package/android/src/main/cpp/CesiumBridgeAndroid.h +94 -0
- package/android/src/main/cpp/cpp-adapter.cpp +17 -0
- package/android/src/main/cpp/vulkan/VulkanBackend.cpp +1781 -0
- package/android/src/main/cpp/vulkan/VulkanBackend.h +190 -0
- package/android/src/main/cpp/vulkan/shaders/sky.frag +86 -0
- package/android/src/main/cpp/vulkan/shaders/sky.vert +9 -0
- package/android/src/main/cpp/vulkan/shaders/terrain.frag +144 -0
- package/android/src/main/cpp/vulkan/shaders/terrain.vert +25 -0
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/CesiumBridgeJNI.kt +84 -0
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/HybridCesiumView.kt +225 -0
- package/android/src/main/java/com/reactnativecesium/ReactNativeCesiumPackage.kt +28 -0
- package/cpp/engine/CesiumEngine.cpp +413 -0
- package/cpp/engine/CesiumEngine.hpp +90 -0
- package/cpp/engine/DeletionQueue.cpp +28 -0
- package/cpp/engine/DeletionQueue.hpp +28 -0
- package/cpp/engine/GlobeCamera.cpp +181 -0
- package/cpp/engine/GlobeCamera.hpp +64 -0
- package/cpp/engine/GltfToMesh.cpp +154 -0
- package/cpp/engine/GltfToMesh.hpp +20 -0
- package/cpp/engine/ResourcePreparer.cpp +224 -0
- package/cpp/engine/ResourcePreparer.hpp +96 -0
- package/cpp/engine/TaskProcessor.cpp +61 -0
- package/cpp/engine/TaskProcessor.hpp +43 -0
- package/cpp/engine/TileLifecycleManager.cpp +30 -0
- package/cpp/engine/TileLifecycleManager.hpp +25 -0
- package/cpp/fmt/format.h +9 -0
- package/cpp/renderer/IGPUBackend.hpp +22 -0
- package/cpp/renderer/RenderTypes.hpp +112 -0
- package/cpp/renderer/ShaderTypes.hpp +29 -0
- package/example/README.md +43 -0
- package/example/react-native-cesium-example.jpg +0 -0
- package/ios/CesiumBridge.h +55 -0
- package/ios/CesiumBridge.mm +393 -0
- package/ios/HybridCesiumView.swift +299 -0
- package/ios/ReactNativeCesium-umbrella.h +16 -0
- package/ios/metal/MetalBackend.h +82 -0
- package/ios/metal/MetalBackend.mm +839 -0
- package/ios/react_native_cesium_ensure_native.rb +12 -0
- package/ios/react_native_cesium_post_install.rb +30 -0
- package/lib/commonjs/CesiumView.js +13 -0
- package/lib/commonjs/CesiumView.js.map +1 -0
- package/lib/commonjs/index.js +13 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/specs/cesium-view.nitro.js +6 -0
- package/lib/commonjs/specs/cesium-view.nitro.js.map +1 -0
- package/lib/module/CesiumView.js +9 -0
- package/lib/module/CesiumView.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/specs/cesium-view.nitro.js +4 -0
- package/lib/module/specs/cesium-view.nitro.js.map +1 -0
- package/lib/typescript/src/CesiumView.d.ts +5 -0
- package/lib/typescript/src/CesiumView.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts +43 -0
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts.map +1 -0
- package/nitro.json +30 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/ReactNativeCesium+autolinking.cmake +83 -0
- package/nitrogen/generated/android/ReactNativeCesium+autolinking.gradle +27 -0
- package/nitrogen/generated/android/ReactNativeCesiumOnLoad.cpp +58 -0
- package/nitrogen/generated/android/ReactNativeCesiumOnLoad.hpp +34 -0
- package/nitrogen/generated/android/c++/JCameraState.hpp +81 -0
- package/nitrogen/generated/android/c++/JCesiumMetrics.hpp +81 -0
- package/nitrogen/generated/android/c++/JFunc_void_CesiumMetrics.hpp +78 -0
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.cpp +178 -0
- package/nitrogen/generated/android/c++/JHybridCesiumViewSpec.hpp +83 -0
- package/nitrogen/generated/android/c++/views/JHybridCesiumViewStateUpdater.cpp +92 -0
- package/nitrogen/generated/android/c++/views/JHybridCesiumViewStateUpdater.hpp +49 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/CameraState.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/CesiumMetrics.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/Func_void_CesiumMetrics.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/HybridCesiumViewSpec.kt +126 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/ReactNativeCesiumOnLoad.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/views/HybridCesiumViewManager.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativecesium/views/HybridCesiumViewStateUpdater.kt +23 -0
- package/nitrogen/generated/ios/ReactNativeCesium+autolinking.rb +60 -0
- package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Bridge.cpp +57 -0
- package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Bridge.hpp +164 -0
- package/nitrogen/generated/ios/ReactNativeCesium-Swift-Cxx-Umbrella.hpp +53 -0
- package/nitrogen/generated/ios/ReactNativeCesiumAutolinking.mm +33 -0
- package/nitrogen/generated/ios/ReactNativeCesiumAutolinking.swift +26 -0
- package/nitrogen/generated/ios/c++/HybridCesiumViewSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridCesiumViewSpecSwift.hpp +157 -0
- package/nitrogen/generated/ios/c++/views/HybridCesiumViewComponent.mm +167 -0
- package/nitrogen/generated/ios/swift/CameraState.swift +59 -0
- package/nitrogen/generated/ios/swift/CesiumMetrics.swift +59 -0
- package/nitrogen/generated/ios/swift/Func_void_CameraState.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_CesiumMetrics.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec.swift +65 -0
- package/nitrogen/generated/ios/swift/HybridCesiumViewSpec_cxx.swift +306 -0
- package/nitrogen/generated/shared/c++/CameraState.hpp +107 -0
- package/nitrogen/generated/shared/c++/CesiumMetrics.hpp +107 -0
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.cpp +42 -0
- package/nitrogen/generated/shared/c++/HybridCesiumViewSpec.hpp +90 -0
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.cpp +182 -0
- package/nitrogen/generated/shared/c++/views/HybridCesiumViewComponent.hpp +122 -0
- package/nitrogen/generated/shared/json/CesiumViewConfig.json +19 -0
- package/package.json +140 -0
- package/react-native.config.js +16 -0
- package/scripts/cesium/build.mjs +901 -0
- package/scripts/cesium/clean.mjs +35 -0
- package/scripts/cesium/clone.mjs +32 -0
- package/scripts/cesium/ensure-native.mjs +116 -0
- package/scripts/cesium/vcpkg-ports/zstd/fix-emscripten-and-clang-cl.patch +31 -0
- package/scripts/cesium/vcpkg-ports/zstd/fix-windows-rc-compile.patch +13 -0
- package/scripts/cesium/vcpkg-ports/zstd/no-static-suffix.patch +13 -0
- package/scripts/cesium/vcpkg-ports/zstd/portfile.cmake +77 -0
- package/scripts/cesium/vcpkg-ports/zstd/usage +4 -0
- package/scripts/cesium/vcpkg-ports/zstd/vcpkg.json +23 -0
- package/scripts/cesium/vcpkg-triplets/arm64-ios-simulator.cmake +10 -0
- package/scripts/cesium/vcpkg-triplets/arm64-ios.cmake +14 -0
- package/src/CesiumView.tsx +13 -0
- package/src/index.ts +7 -0
- package/src/specs/cesium-view.nitro.ts +51 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
package com.margelo.nitro.reactnativecesium
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.view.Choreographer
|
|
5
|
+
import android.view.SurfaceHolder
|
|
6
|
+
import android.view.SurfaceView
|
|
7
|
+
import android.view.View
|
|
8
|
+
import com.margelo.nitro.core.Promise
|
|
9
|
+
import java.io.File
|
|
10
|
+
import java.io.FileOutputStream
|
|
11
|
+
|
|
12
|
+
class HybridCesiumView(private val appContext: Context) : HybridCesiumViewSpec() {
|
|
13
|
+
private val surfaceView = SurfaceView(appContext)
|
|
14
|
+
private var bridge: CesiumBridgeJNI? = null
|
|
15
|
+
private var metricsFrameCounter = 0
|
|
16
|
+
private var idleProbeAccumulator = 0.0
|
|
17
|
+
private var usingLowRefreshRate = false
|
|
18
|
+
private var lastFrameTimeNanos = 0L
|
|
19
|
+
private var lastPushedCamera: CameraState? = null
|
|
20
|
+
private var renderLoopActive = false
|
|
21
|
+
|
|
22
|
+
override var ionAccessToken: String = ""
|
|
23
|
+
set(value) {
|
|
24
|
+
field = value
|
|
25
|
+
bridge?.updateIonAccessToken(value, ionAssetId.toLong())
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
override var ionAssetId: Double = 1.0
|
|
29
|
+
set(value) {
|
|
30
|
+
field = value
|
|
31
|
+
bridge?.updateIonAccessToken(ionAccessToken, value.toLong())
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
override var initialCamera: CameraState = CameraState(
|
|
35
|
+
latitude = 46.15,
|
|
36
|
+
longitude = 7.35,
|
|
37
|
+
altitude = 12000.0,
|
|
38
|
+
heading = 129.0,
|
|
39
|
+
pitch = -45.0,
|
|
40
|
+
roll = 0.0,
|
|
41
|
+
verticalFovDeg = 60.0,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
override var pauseRendering: Boolean = false
|
|
45
|
+
set(value) {
|
|
46
|
+
field = value
|
|
47
|
+
if (!value) {
|
|
48
|
+
bridge?.markNeedsRender()
|
|
49
|
+
scheduleNextFrame()
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
override var maximumScreenSpaceError: Double = 32.0
|
|
54
|
+
set(value) { field = value; bridge?.setMaxSSE(value) }
|
|
55
|
+
|
|
56
|
+
override var maximumSimultaneousTileLoads: Double = 12.0
|
|
57
|
+
set(value) { field = value; bridge?.setMaxSimLoads(value.toInt()) }
|
|
58
|
+
|
|
59
|
+
override var loadingDescendantLimit: Double = 20.0
|
|
60
|
+
set(value) { field = value; bridge?.setLoadDescLim(value.toInt()) }
|
|
61
|
+
|
|
62
|
+
override var msaaSampleCount: Double = 1.0
|
|
63
|
+
set(value) { field = value; bridge?.setMsaa(value.toInt()) }
|
|
64
|
+
|
|
65
|
+
override var ionImageryAssetId: Double = 1.0
|
|
66
|
+
set(value) { field = value; bridge?.updateImageryAssetId(value.toLong()) }
|
|
67
|
+
|
|
68
|
+
override var onMetrics: ((metrics: CesiumMetrics) -> Unit)? = null
|
|
69
|
+
|
|
70
|
+
override val view: View get() = surfaceView
|
|
71
|
+
|
|
72
|
+
private val frameCallback = Choreographer.FrameCallback { frameTimeNanos ->
|
|
73
|
+
renderLoopActive = false
|
|
74
|
+
if (pauseRendering || bridge == null) return@FrameCallback
|
|
75
|
+
|
|
76
|
+
val dt = if (lastFrameTimeNanos > 0) {
|
|
77
|
+
(frameTimeNanos - lastFrameTimeNanos).coerceAtLeast(1_000_000L) / 1_000_000_000.0
|
|
78
|
+
} else {
|
|
79
|
+
1.0 / 60.0
|
|
80
|
+
}
|
|
81
|
+
lastFrameTimeNanos = frameTimeNanos
|
|
82
|
+
|
|
83
|
+
val shouldRender = bridge?.shouldRenderNextFrame() ?: false
|
|
84
|
+
if (shouldRender) {
|
|
85
|
+
usingLowRefreshRate = false
|
|
86
|
+
idleProbeAccumulator = 0.0
|
|
87
|
+
bridge?.renderFrame(dt)
|
|
88
|
+
} else {
|
|
89
|
+
usingLowRefreshRate = true
|
|
90
|
+
idleProbeAccumulator += dt
|
|
91
|
+
if (idleProbeAccumulator >= 0.25) {
|
|
92
|
+
idleProbeAccumulator = 0.0
|
|
93
|
+
bridge?.markNeedsRender()
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
metricsFrameCounter++
|
|
98
|
+
if (metricsFrameCounter >= 20) {
|
|
99
|
+
metricsFrameCounter = 0
|
|
100
|
+
val b = bridge ?: return@FrameCallback
|
|
101
|
+
val cb = onMetrics ?: return@FrameCallback
|
|
102
|
+
cb(CesiumMetrics(
|
|
103
|
+
fps = b.getMetricsFps(),
|
|
104
|
+
tilesRendered = b.getMetricsTilesRendered().toDouble(),
|
|
105
|
+
tilesLoading = b.getMetricsTilesLoading().toDouble(),
|
|
106
|
+
tilesVisited = b.getMetricsTilesVisited().toDouble(),
|
|
107
|
+
ionTokenConfigured = b.getMetricsIonTokenConfigured(),
|
|
108
|
+
tilesetReady = b.getMetricsTilesetReady(),
|
|
109
|
+
creditsPlainText = b.getMetricsCreditsPlainText(),
|
|
110
|
+
))
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
scheduleNextFrame()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private val surfaceCallback = object : SurfaceHolder.Callback {
|
|
117
|
+
override fun surfaceCreated(holder: SurfaceHolder) {
|
|
118
|
+
val surface = holder.surface
|
|
119
|
+
val w = surfaceView.width
|
|
120
|
+
val h = surfaceView.height
|
|
121
|
+
if (w <= 0 || h <= 0) return
|
|
122
|
+
|
|
123
|
+
val b = CesiumBridgeJNI()
|
|
124
|
+
val cacheDir = appContext.cacheDir.absolutePath
|
|
125
|
+
val cacertPath = extractCacert()
|
|
126
|
+
b.init(surface, w, h, cacheDir, cacertPath)
|
|
127
|
+
bridge = b
|
|
128
|
+
|
|
129
|
+
syncPropsTobridge()
|
|
130
|
+
if (ionAccessToken.isNotEmpty()) {
|
|
131
|
+
b.updateIonAccessToken(ionAccessToken, ionAssetId.toLong())
|
|
132
|
+
}
|
|
133
|
+
pushCameraIfChanged(initialCamera)
|
|
134
|
+
if (ionImageryAssetId != 1.0) {
|
|
135
|
+
b.updateImageryAssetId(ionImageryAssetId.toLong())
|
|
136
|
+
}
|
|
137
|
+
b.setMsaa(msaaSampleCount.toInt())
|
|
138
|
+
|
|
139
|
+
lastFrameTimeNanos = 0L
|
|
140
|
+
scheduleNextFrame()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
|
|
144
|
+
bridge?.resize(width, height)
|
|
145
|
+
bridge?.markNeedsRender()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
override fun surfaceDestroyed(holder: SurfaceHolder) {
|
|
149
|
+
bridge?.shutdown()
|
|
150
|
+
bridge?.destroy()
|
|
151
|
+
bridge = null
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
init {
|
|
156
|
+
surfaceView.holder.addCallback(surfaceCallback)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
override fun getCameraState(): Promise<CameraState> {
|
|
160
|
+
val b = bridge ?: return Promise.resolved(initialCamera)
|
|
161
|
+
return Promise.resolved(CameraState(
|
|
162
|
+
latitude = b.getCameraLat(),
|
|
163
|
+
longitude = b.getCameraLon(),
|
|
164
|
+
altitude = b.getCameraAlt(),
|
|
165
|
+
heading = b.getCameraHeading(),
|
|
166
|
+
pitch = b.getCameraPitch(),
|
|
167
|
+
roll = b.getCameraRoll(),
|
|
168
|
+
verticalFovDeg = b.getVerticalFovDeg(),
|
|
169
|
+
))
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
override fun setCamera(camera: CameraState) {
|
|
173
|
+
initialCamera = camera
|
|
174
|
+
pushCameraIfChanged(camera)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private fun pushCameraIfChanged(camera: CameraState) {
|
|
178
|
+
val b = bridge ?: return
|
|
179
|
+
val last = lastPushedCamera
|
|
180
|
+
if (last != null &&
|
|
181
|
+
last.latitude == camera.latitude &&
|
|
182
|
+
last.longitude == camera.longitude &&
|
|
183
|
+
last.altitude == camera.altitude &&
|
|
184
|
+
last.heading == camera.heading &&
|
|
185
|
+
last.pitch == camera.pitch &&
|
|
186
|
+
last.roll == camera.roll &&
|
|
187
|
+
last.verticalFovDeg == camera.verticalFovDeg) {
|
|
188
|
+
return
|
|
189
|
+
}
|
|
190
|
+
lastPushedCamera = camera
|
|
191
|
+
b.updateCamera(camera.latitude, camera.longitude, camera.altitude,
|
|
192
|
+
camera.heading, camera.pitch, camera.roll)
|
|
193
|
+
b.setVerticalFovDeg(camera.verticalFovDeg)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private fun syncPropsTobridge() {
|
|
197
|
+
bridge?.setMaxSSE(maximumScreenSpaceError)
|
|
198
|
+
bridge?.setMaxSimLoads(maximumSimultaneousTileLoads.toInt())
|
|
199
|
+
bridge?.setLoadDescLim(loadingDescendantLimit.toInt())
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private fun scheduleNextFrame() {
|
|
203
|
+
if (renderLoopActive || pauseRendering || bridge == null) return
|
|
204
|
+
renderLoopActive = true
|
|
205
|
+
Choreographer.getInstance().postFrameCallback(frameCallback)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private fun extractCacert(): String {
|
|
209
|
+
val outFile = File(appContext.cacheDir, "cacert.pem")
|
|
210
|
+
try {
|
|
211
|
+
appContext.assets.open("cacert.pem").use { input ->
|
|
212
|
+
// Re-extract if the cached copy is missing or a different size to the
|
|
213
|
+
// bundled asset (handles the file being updated across app versions).
|
|
214
|
+
val assetSize = input.available().toLong()
|
|
215
|
+
if (!outFile.exists() || outFile.length() != assetSize) {
|
|
216
|
+
FileOutputStream(outFile).use { output -> input.copyTo(output) }
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
} catch (_: Exception) {
|
|
220
|
+
// cacert.pem not bundled as asset — libcurl will use system certs
|
|
221
|
+
return if (outFile.exists()) outFile.absolutePath else ""
|
|
222
|
+
}
|
|
223
|
+
return outFile.absolutePath
|
|
224
|
+
}
|
|
225
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package com.reactnativecesium;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.NativeModule;
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
5
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager;
|
|
7
|
+
import com.facebook.react.BaseReactPackage;
|
|
8
|
+
import com.margelo.nitro.reactnativecesium.ReactNativeCesiumOnLoad;
|
|
9
|
+
import com.margelo.nitro.reactnativecesium.views.HybridCesiumViewManager;
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
public class ReactNativeCesiumPackage : BaseReactPackage() {
|
|
13
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? = null
|
|
14
|
+
|
|
15
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider = ReactModuleInfoProvider { emptyMap() }
|
|
16
|
+
|
|
17
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
18
|
+
val viewManagers = ArrayList<ViewManager<*, *>>()
|
|
19
|
+
viewManagers.add(HybridCesiumViewManager())
|
|
20
|
+
return viewManagers
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
companion object {
|
|
24
|
+
init {
|
|
25
|
+
ReactNativeCesiumOnLoad.initializeNative();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
#ifndef NDEBUG
|
|
2
|
+
# define NDEBUG
|
|
3
|
+
# define CESIUM_ENGINE_UNDEF_NDEBUG
|
|
4
|
+
#endif
|
|
5
|
+
|
|
6
|
+
#include "CesiumEngine.hpp"
|
|
7
|
+
|
|
8
|
+
#include <Cesium3DTilesContent/registerAllTileContentTypes.h>
|
|
9
|
+
#include <Cesium3DTilesSelection/BoundingVolume.h>
|
|
10
|
+
#include <Cesium3DTilesSelection/Tile.h>
|
|
11
|
+
#include <Cesium3DTilesSelection/Tileset.h>
|
|
12
|
+
#include <Cesium3DTilesSelection/TilesetExternals.h>
|
|
13
|
+
#include <Cesium3DTilesSelection/TilesetOptions.h>
|
|
14
|
+
#include <CesiumGeospatial/BoundingRegion.h>
|
|
15
|
+
#include <CesiumGeospatial/GlobeRectangle.h>
|
|
16
|
+
#include <CesiumAsync/CachingAssetAccessor.h>
|
|
17
|
+
#include <CesiumAsync/SqliteCache.h>
|
|
18
|
+
#include <CesiumCurl/CurlAssetAccessor.h>
|
|
19
|
+
#include <CesiumRasterOverlays/IonRasterOverlay.h>
|
|
20
|
+
#include <CesiumUtility/CreditSystem.h>
|
|
21
|
+
#include <CesiumUtility/IntrusivePointer.h>
|
|
22
|
+
|
|
23
|
+
#ifdef CESIUM_ENGINE_UNDEF_NDEBUG
|
|
24
|
+
# undef NDEBUG
|
|
25
|
+
# undef CESIUM_ENGINE_UNDEF_NDEBUG
|
|
26
|
+
#endif
|
|
27
|
+
|
|
28
|
+
#include <spdlog/spdlog.h>
|
|
29
|
+
#include <glm/gtc/matrix_inverse.hpp>
|
|
30
|
+
#include <glm/gtc/matrix_transform.hpp>
|
|
31
|
+
|
|
32
|
+
#include <algorithm>
|
|
33
|
+
#include <cmath>
|
|
34
|
+
|
|
35
|
+
namespace reactnativecesium {
|
|
36
|
+
|
|
37
|
+
CesiumEngine::CesiumEngine()
|
|
38
|
+
: taskProcessor_(std::make_shared<TaskProcessor>(4)),
|
|
39
|
+
asyncSystem_(taskProcessor_) {
|
|
40
|
+
Cesium3DTilesContent::registerAllTileContentTypes();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
CesiumEngine::~CesiumEngine() { shutdown(); }
|
|
44
|
+
|
|
45
|
+
bool CesiumEngine::tilesetOptionsMatch(const EngineConfig& a,
|
|
46
|
+
const EngineConfig& b) const {
|
|
47
|
+
return a.maximumScreenSpaceError == b.maximumScreenSpaceError &&
|
|
48
|
+
a.maximumSimultaneousTileLoads == b.maximumSimultaneousTileLoads &&
|
|
49
|
+
a.loadingDescendantLimit == b.loadingDescendantLimit;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
void CesiumEngine::buildEllipsoidMesh() {
|
|
53
|
+
// Tessellate a WGS84 ellipsoid slightly inset so terrain tiles (at true
|
|
54
|
+
// surface height) reliably overdraw it via the reversed-Z depth test.
|
|
55
|
+
constexpr int nLon = 128;
|
|
56
|
+
constexpr int nLat = 64;
|
|
57
|
+
|
|
58
|
+
constexpr double a_full = 6378137.0;
|
|
59
|
+
constexpr double b_full = 6356752.31424518;
|
|
60
|
+
constexpr double inset = 20.0;
|
|
61
|
+
const double a = a_full - inset;
|
|
62
|
+
const double b = b_full - inset;
|
|
63
|
+
|
|
64
|
+
ellipsoidPositions_.clear();
|
|
65
|
+
ellipsoidIndices_.clear();
|
|
66
|
+
ellipsoidPositions_.reserve(static_cast<size_t>((nLat + 1) * nLon));
|
|
67
|
+
ellipsoidIndices_.reserve(static_cast<size_t>(nLat * nLon * 6));
|
|
68
|
+
|
|
69
|
+
for (int lat = 0; lat <= nLat; ++lat) {
|
|
70
|
+
const double phi = M_PI * (static_cast<double>(lat) / nLat - 0.5);
|
|
71
|
+
const double cosPhi = std::cos(phi);
|
|
72
|
+
const double sinPhi = std::sin(phi);
|
|
73
|
+
for (int lon = 0; lon < nLon; ++lon) {
|
|
74
|
+
const double theta = 2.0 * M_PI * static_cast<double>(lon) / nLon;
|
|
75
|
+
ellipsoidPositions_.push_back({
|
|
76
|
+
a * cosPhi * std::cos(theta),
|
|
77
|
+
a * cosPhi * std::sin(theta),
|
|
78
|
+
b * sinPhi
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
for (int lat = 0; lat < nLat; ++lat) {
|
|
84
|
+
for (int lon = 0; lon < nLon; ++lon) {
|
|
85
|
+
const uint32_t v00 = static_cast<uint32_t>(lat * nLon + lon);
|
|
86
|
+
const uint32_t v10 = static_cast<uint32_t>(lat * nLon + (lon + 1) % nLon);
|
|
87
|
+
const uint32_t v01 = static_cast<uint32_t>((lat + 1) * nLon + lon);
|
|
88
|
+
const uint32_t v11 = static_cast<uint32_t>((lat + 1) * nLon + (lon + 1) % nLon);
|
|
89
|
+
ellipsoidIndices_.push_back(v00); ellipsoidIndices_.push_back(v10); ellipsoidIndices_.push_back(v11);
|
|
90
|
+
ellipsoidIndices_.push_back(v00); ellipsoidIndices_.push_back(v11); ellipsoidIndices_.push_back(v01);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Append the fallback ellipsoid as a draw.
|
|
96
|
+
// RTC convention for the fallback: the tile's "RTC centre" is the camera
|
|
97
|
+
// position itself, so local positions == old camera-relative positions. The
|
|
98
|
+
// per-draw MVP is therefore the same rotation-only VP used before RTC was
|
|
99
|
+
// introduced, keeping the fallback on the same code path.
|
|
100
|
+
void CesiumEngine::appendEllipsoidDraws(FrameResult& result) const {
|
|
101
|
+
if (ellipsoidPositions_.empty() || ellipsoidIndices_.empty()) return;
|
|
102
|
+
|
|
103
|
+
const glm::dvec3 cameraPos = camera_.getECEFPosition();
|
|
104
|
+
const size_t baseVertex = result.localPositions.size() / 3;
|
|
105
|
+
const uint32_t indexByteOff =
|
|
106
|
+
static_cast<uint32_t>(result.indices.size() * sizeof(uint32_t));
|
|
107
|
+
const size_t vertexCount = ellipsoidPositions_.size();
|
|
108
|
+
|
|
109
|
+
result.localPositions.resize(result.localPositions.size() + vertexCount * 3);
|
|
110
|
+
result.altitudes.resize(result.altitudes.size() + vertexCount);
|
|
111
|
+
result.uvs.resize(result.uvs.size() + vertexCount * 2);
|
|
112
|
+
|
|
113
|
+
float* posOut = result.localPositions.data() + baseVertex * 3;
|
|
114
|
+
float* altOut = result.altitudes.data() + baseVertex;
|
|
115
|
+
float* uvOut = result.uvs.data() + baseVertex * 2;
|
|
116
|
+
|
|
117
|
+
for (const auto& posEcef : ellipsoidPositions_) {
|
|
118
|
+
// Local position = ECEF - camera (same as old eye-relative, since camera is the RTC centre).
|
|
119
|
+
const glm::dvec3 local = posEcef - cameraPos;
|
|
120
|
+
*posOut++ = static_cast<float>(local.x);
|
|
121
|
+
*posOut++ = static_cast<float>(local.y);
|
|
122
|
+
*posOut++ = static_cast<float>(local.z);
|
|
123
|
+
// Fallback geoid should represent land by default when terrain tiles are not
|
|
124
|
+
// loaded yet, so keep altitude at sea level for hypsometric land colouring.
|
|
125
|
+
*altOut++ = 0.0f;
|
|
126
|
+
*uvOut++ = 0.5f;
|
|
127
|
+
*uvOut++ = 0.5f;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const size_t indexOffset = result.indices.size();
|
|
131
|
+
result.indices.resize(indexOffset + ellipsoidIndices_.size());
|
|
132
|
+
uint32_t* indexOut = result.indices.data() + indexOffset;
|
|
133
|
+
for (uint32_t idx : ellipsoidIndices_) {
|
|
134
|
+
*indexOut++ = static_cast<uint32_t>(baseVertex) + idx;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
DrawPrimitive draw;
|
|
138
|
+
draw.indexByteOffset = indexByteOff;
|
|
139
|
+
draw.indexCount = static_cast<uint32_t>(ellipsoidIndices_.size());
|
|
140
|
+
draw.hasUVs = false;
|
|
141
|
+
draw.isEllipsoidFallback = true;
|
|
142
|
+
draw.overlayTexture = nullptr;
|
|
143
|
+
// Ellipsoid RTC centre = camera → local pos = eye-relative → use the
|
|
144
|
+
// rotation-only VP (identical to the pre-RTC vertex transform).
|
|
145
|
+
draw.mvpMatrix = result.vpMatrix;
|
|
146
|
+
draw.rtcCenterEcef = result.cameraEcef;
|
|
147
|
+
result.draws.push_back(draw);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
void CesiumEngine::initialize(const EngineConfig& config) {
|
|
151
|
+
config_ = config;
|
|
152
|
+
|
|
153
|
+
auto logger = spdlog::default_logger();
|
|
154
|
+
|
|
155
|
+
CesiumCurl::CurlAssetAccessorOptions curlOpts;
|
|
156
|
+
if (!config.tlsCaBundlePath.empty()) {
|
|
157
|
+
curlOpts.certificateFile = config.tlsCaBundlePath;
|
|
158
|
+
}
|
|
159
|
+
auto curlAccessor = std::make_shared<CesiumCurl::CurlAssetAccessor>(curlOpts);
|
|
160
|
+
|
|
161
|
+
if (!config.cacheDatabasePath.empty()) {
|
|
162
|
+
auto cache = std::make_shared<CesiumAsync::SqliteCache>(
|
|
163
|
+
logger, config.cacheDatabasePath, 4096);
|
|
164
|
+
assetAccessor_ = std::make_shared<CesiumAsync::CachingAssetAccessor>(
|
|
165
|
+
logger, curlAccessor, cache);
|
|
166
|
+
} else {
|
|
167
|
+
assetAccessor_ = curlAccessor;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
resourcePreparer_ = std::make_shared<ResourcePreparer>(lifecycle_);
|
|
171
|
+
|
|
172
|
+
if (!creditSystem_) {
|
|
173
|
+
creditSystem_ = std::make_shared<CesiumUtility::CreditSystem>();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
buildEllipsoidMesh();
|
|
177
|
+
createTileset(config.ionAccessToken, config.ionAssetId);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
void CesiumEngine::shutdown() {
|
|
181
|
+
destroyTileset();
|
|
182
|
+
creditSystem_.reset();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
void CesiumEngine::updateConfig(const EngineConfig& config) {
|
|
186
|
+
const bool needRebuild =
|
|
187
|
+
config.ionAccessToken != config_.ionAccessToken ||
|
|
188
|
+
config.ionAssetId != config_.ionAssetId ||
|
|
189
|
+
!tilesetOptionsMatch(config, config_);
|
|
190
|
+
|
|
191
|
+
config_ = config;
|
|
192
|
+
|
|
193
|
+
if (!needRebuild) return;
|
|
194
|
+
|
|
195
|
+
destroyTileset();
|
|
196
|
+
if (!config_.ionAccessToken.empty()) {
|
|
197
|
+
createTileset(config_.ionAccessToken, config_.ionAssetId, currentImageryAssetId_);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
void CesiumEngine::createTileset(const std::string& token,
|
|
202
|
+
int64_t assetId,
|
|
203
|
+
int64_t imageryAssetId) {
|
|
204
|
+
if (token.empty()) return;
|
|
205
|
+
|
|
206
|
+
if (!creditSystem_) {
|
|
207
|
+
creditSystem_ = std::make_shared<CesiumUtility::CreditSystem>();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
auto logger = spdlog::default_logger();
|
|
211
|
+
|
|
212
|
+
Cesium3DTilesSelection::TilesetExternals externals{
|
|
213
|
+
assetAccessor_, resourcePreparer_, asyncSystem_, creditSystem_,
|
|
214
|
+
logger, nullptr};
|
|
215
|
+
|
|
216
|
+
Cesium3DTilesSelection::TilesetOptions opts;
|
|
217
|
+
opts.maximumCachedBytes = 256 * 1024 * 1024;
|
|
218
|
+
opts.maximumSimultaneousTileLoads =
|
|
219
|
+
static_cast<uint32_t>(std::max(0, config_.maximumSimultaneousTileLoads));
|
|
220
|
+
opts.loadingDescendantLimit =
|
|
221
|
+
static_cast<uint32_t>(std::max(1, config_.loadingDescendantLimit));
|
|
222
|
+
opts.maximumScreenSpaceError =
|
|
223
|
+
std::max(1.0, config_.maximumScreenSpaceError);
|
|
224
|
+
opts.preloadAncestors = true;
|
|
225
|
+
opts.preloadSiblings = true;
|
|
226
|
+
opts.forbidHoles = true;
|
|
227
|
+
opts.contentOptions.enableWaterMask = true;
|
|
228
|
+
|
|
229
|
+
tileset_ = std::make_unique<Cesium3DTilesSelection::Tileset>(
|
|
230
|
+
externals, assetId, token, opts);
|
|
231
|
+
|
|
232
|
+
if (imageryAssetId != 1) {
|
|
233
|
+
CesiumUtility::IntrusivePointer<CesiumRasterOverlays::RasterOverlay> ov =
|
|
234
|
+
new CesiumRasterOverlays::IonRasterOverlay("imagery", imageryAssetId, token);
|
|
235
|
+
tileset_->getOverlays().add(ov);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
void CesiumEngine::destroyTileset() {
|
|
240
|
+
tileset_.reset();
|
|
241
|
+
taskProcessor_->waitUntilIdle();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
void CesiumEngine::setImageryAssetId(int64_t assetId) {
|
|
245
|
+
if (config_.ionAccessToken.empty()) return;
|
|
246
|
+
currentImageryAssetId_ = assetId;
|
|
247
|
+
destroyTileset();
|
|
248
|
+
createTileset(config_.ionAccessToken, config_.ionAssetId, assetId);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
void CesiumEngine::updateFrame(double w, double h, FrameResult& result) {
|
|
252
|
+
result.localPositions.clear();
|
|
253
|
+
result.altitudes.clear();
|
|
254
|
+
result.uvs.clear();
|
|
255
|
+
result.indices.clear();
|
|
256
|
+
result.draws.clear();
|
|
257
|
+
result.creditHtmlLines.clear();
|
|
258
|
+
|
|
259
|
+
result.ionTokenConfigured = !config_.ionAccessToken.empty();
|
|
260
|
+
result.tilesetActive = (tileset_ != nullptr);
|
|
261
|
+
result.verticalFovDeg = camera_.getVerticalFovDegrees();
|
|
262
|
+
|
|
263
|
+
const glm::dvec3 cameraPos = camera_.getECEFPosition();
|
|
264
|
+
result.cameraEcef = glm::vec3(cameraPos);
|
|
265
|
+
|
|
266
|
+
// Rotation-only VP (float) — used by the sky shader and the ellipsoid fallback.
|
|
267
|
+
result.vpMatrix = camera_.computeVPMatrix(w, h);
|
|
268
|
+
result.invVP = glm::inverse(result.vpMatrix);
|
|
269
|
+
|
|
270
|
+
// Double-precision rotation-only VP — used to build per-tile MVP matrices
|
|
271
|
+
// so the camera↔tile-centre translation is resolved in double before the
|
|
272
|
+
// final cast to float32.
|
|
273
|
+
const glm::dmat4 vpDouble = camera_.computeVPMatrixDouble(w, h);
|
|
274
|
+
|
|
275
|
+
if (!tileset_) {
|
|
276
|
+
appendEllipsoidDraws(result);
|
|
277
|
+
lifecycle_.advanceFrame();
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
result.localPositions.reserve(512 * 1024);
|
|
282
|
+
result.altitudes.reserve(512 * 1024 / 3);
|
|
283
|
+
result.uvs.reserve(512 * 1024 * 2);
|
|
284
|
+
result.indices.reserve(3 * 1024 * 1024);
|
|
285
|
+
|
|
286
|
+
asyncSystem_.dispatchMainThreadTasks();
|
|
287
|
+
|
|
288
|
+
// Ellipsoid fallback is appended first so real terrain tiles (drawn later)
|
|
289
|
+
// overdraw it via the reversed-Z depth test.
|
|
290
|
+
appendEllipsoidDraws(result);
|
|
291
|
+
|
|
292
|
+
const auto viewState = camera_.computeViewState(w, h);
|
|
293
|
+
const auto& updateResult = tileset_->updateView({viewState});
|
|
294
|
+
|
|
295
|
+
if (creditSystem_) {
|
|
296
|
+
const CesiumUtility::CreditsSnapshot& snap =
|
|
297
|
+
creditSystem_->getSnapshot(CesiumUtility::CreditFilteringMode::UniqueHtml);
|
|
298
|
+
for (const auto& c : snap.currentCredits) {
|
|
299
|
+
const std::string& html = creditSystem_->getHtml(c);
|
|
300
|
+
if (html.empty()) continue;
|
|
301
|
+
if (html.find("Error: Invalid Credit") != std::string::npos) continue;
|
|
302
|
+
result.creditHtmlLines.push_back(html);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
for (const auto& tile : updateResult.tilesToRenderThisFrame) {
|
|
307
|
+
if (!tile) continue;
|
|
308
|
+
|
|
309
|
+
const auto* renderContent = tile->getContent().getRenderContent();
|
|
310
|
+
if (!renderContent) continue;
|
|
311
|
+
|
|
312
|
+
const auto* res = static_cast<const TileGPUResources*>(
|
|
313
|
+
renderContent->getRenderResources());
|
|
314
|
+
if (!res) continue;
|
|
315
|
+
|
|
316
|
+
lifecycle_.stampTileUsed(const_cast<TileGPUResources*>(res));
|
|
317
|
+
|
|
318
|
+
glm::vec4 wmTileBounds(0.0f);
|
|
319
|
+
const auto& bv = tile->getBoundingVolume();
|
|
320
|
+
const CesiumGeospatial::BoundingRegion* bRegion =
|
|
321
|
+
Cesium3DTilesSelection::getBoundingRegionFromBoundingVolume(bv);
|
|
322
|
+
if (bRegion) {
|
|
323
|
+
const auto& rect = bRegion->getRectangle();
|
|
324
|
+
wmTileBounds = glm::vec4(
|
|
325
|
+
static_cast<float>(rect.getWest()),
|
|
326
|
+
static_cast<float>(rect.getSouth()),
|
|
327
|
+
static_cast<float>(rect.getEast()),
|
|
328
|
+
static_cast<float>(rect.getNorth()));
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
for (const auto& prim : res->primitives) {
|
|
332
|
+
if (prim.indices.empty() || prim.localPositions.empty()) continue;
|
|
333
|
+
|
|
334
|
+
const size_t baseVertex = result.localPositions.size() / 3;
|
|
335
|
+
const uint32_t indexByteOff =
|
|
336
|
+
static_cast<uint32_t>(result.indices.size() * sizeof(uint32_t));
|
|
337
|
+
const size_t vertexCount = prim.localPositions.size();
|
|
338
|
+
const bool hasPrimUVs =
|
|
339
|
+
!prim.uvs.empty() && prim.uvs.size() == vertexCount;
|
|
340
|
+
|
|
341
|
+
// ── RTC: copy tile-local positions & altitudes ────────────────────────
|
|
342
|
+
// Positions are already relative to prim.rtcCenter (small float values).
|
|
343
|
+
// Altitudes are computed in double in GltfToMesh — sub-millimetre precision.
|
|
344
|
+
result.localPositions.resize(result.localPositions.size() + vertexCount * 3);
|
|
345
|
+
result.altitudes.resize(result.altitudes.size() + vertexCount);
|
|
346
|
+
result.uvs.resize(result.uvs.size() + vertexCount * 2);
|
|
347
|
+
|
|
348
|
+
float* posOut = result.localPositions.data() + baseVertex * 3;
|
|
349
|
+
float* altOut = result.altitudes.data() + baseVertex;
|
|
350
|
+
float* uvOut = result.uvs.data() + baseVertex * 2;
|
|
351
|
+
|
|
352
|
+
for (size_t vi = 0; vi < vertexCount; ++vi) {
|
|
353
|
+
const glm::vec3& lp = prim.localPositions[vi];
|
|
354
|
+
*posOut++ = lp.x;
|
|
355
|
+
*posOut++ = lp.y;
|
|
356
|
+
*posOut++ = lp.z;
|
|
357
|
+
*altOut++ = prim.altitudes.empty() ? 0.0f : prim.altitudes[vi];
|
|
358
|
+
if (hasPrimUVs) {
|
|
359
|
+
*uvOut++ = prim.uvs[vi].x;
|
|
360
|
+
*uvOut++ = prim.uvs[vi].y;
|
|
361
|
+
} else {
|
|
362
|
+
*uvOut++ = 0.5f;
|
|
363
|
+
*uvOut++ = 0.5f;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
for (uint32_t idx : prim.indices) {
|
|
368
|
+
result.indices.push_back(static_cast<uint32_t>(baseVertex) + idx);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// ── RTC: per-tile MVP matrix (double → float) ─────────────────────────
|
|
372
|
+
// Compute the camera-relative offset of the tile's RTC centre in double
|
|
373
|
+
// and bake it into the MVP matrix before casting to float32. This means
|
|
374
|
+
// the large camera↔tile translation is resolved with double precision;
|
|
375
|
+
// the vertex shader only ever adds small tile-local offsets on top of it.
|
|
376
|
+
const glm::dvec3 rtcCamRel =
|
|
377
|
+
prim.rtcCenter - glm::dvec3(cameraPos);
|
|
378
|
+
const glm::dmat4 translateD =
|
|
379
|
+
glm::translate(glm::dmat4(1.0), rtcCamRel);
|
|
380
|
+
const glm::mat4 perTileMVP =
|
|
381
|
+
glm::mat4(vpDouble * translateD);
|
|
382
|
+
|
|
383
|
+
DrawPrimitive draw;
|
|
384
|
+
draw.indexByteOffset = indexByteOff;
|
|
385
|
+
draw.indexCount = static_cast<uint32_t>(prim.indices.size());
|
|
386
|
+
draw.hasUVs = hasPrimUVs;
|
|
387
|
+
draw.overlayTexture = res->overlayTexture;
|
|
388
|
+
draw.overlayTranslation = res->overlayTranslation;
|
|
389
|
+
draw.overlayScale = res->overlayScale;
|
|
390
|
+
draw.waterMaskTexture = res->waterMaskTexture;
|
|
391
|
+
draw.isOnlyWater = res->isOnlyWater;
|
|
392
|
+
draw.wmTileBounds = wmTileBounds;
|
|
393
|
+
draw.wmTranslation = res->wmTranslation;
|
|
394
|
+
draw.wmScale = res->wmScale;
|
|
395
|
+
draw.mvpMatrix = perTileMVP;
|
|
396
|
+
draw.rtcCenterEcef = glm::vec3(prim.rtcCenter);
|
|
397
|
+
result.draws.push_back(draw);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
result.tilesRendered = static_cast<int>(updateResult.tilesToRenderThisFrame.size());
|
|
402
|
+
result.tilesLoading = updateResult.workerThreadTileLoadQueueLength +
|
|
403
|
+
updateResult.mainThreadTileLoadQueueLength;
|
|
404
|
+
result.tilesVisited = static_cast<int>(updateResult.tilesVisited);
|
|
405
|
+
const auto params = camera_.getParams();
|
|
406
|
+
result.cameraLat = params.latitude;
|
|
407
|
+
result.cameraLon = params.longitude;
|
|
408
|
+
result.cameraAlt = params.altitude;
|
|
409
|
+
|
|
410
|
+
lifecycle_.advanceFrame();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
} // namespace reactnativecesium
|