@aguacerowx/react-native 0.0.27 → 0.0.29
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 +126 -126
- package/aguacerowx-react-native.podspec +38 -38
- package/android/build.gradle +107 -107
- package/android/src/main/AndroidManifest.xml +6 -6
- package/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
- package/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +672 -672
- package/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
- package/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
- package/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
- package/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
- package/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
- package/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
- package/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
- package/android/src/main/res/raw/fragment_shader.glsl +161 -161
- package/android/src/main/res/raw/vertex_shader.glsl +19 -19
- package/index.js +2 -2
- package/ios/AguaceroPackage.m +18 -18
- package/ios/FragmentUniforms.swift +15 -15
- package/ios/GridRenderLayer.swift +1043 -1043
- package/ios/GridRenderLayerBridge.swift +37 -37
- package/ios/GridRenderLayerManager.mm +157 -157
- package/ios/GridRenderLayerView.h +30 -30
- package/ios/GridRenderLayerView.m +256 -256
- package/ios/InspectorDataCache.swift +65 -65
- package/ios/InspectorModule.m +9 -9
- package/ios/InspectorModule.swift +63 -63
- package/ios/Shaders.metal +190 -190
- package/ios/WeatherFrameProcessorModule.m +15 -15
- package/ios/WeatherFrameProcessorModule.swift +103 -103
- package/lib/commonjs/README.md +126 -126
- package/lib/commonjs/aguacerowx-react-native.podspec +38 -38
- package/lib/commonjs/android/build.gradle +107 -107
- package/lib/commonjs/android/src/main/AndroidManifest.xml +6 -6
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +672 -672
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
- package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
- package/lib/commonjs/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
- package/lib/commonjs/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
- package/lib/commonjs/android/src/main/res/raw/fragment_shader.glsl +161 -161
- package/lib/commonjs/android/src/main/res/raw/vertex_shader.glsl +19 -19
- package/lib/commonjs/babel.config.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ios/AguaceroPackage.m +18 -18
- package/lib/commonjs/ios/FragmentUniforms.swift +15 -15
- package/lib/commonjs/ios/GridRenderLayer.swift +1043 -1043
- package/lib/commonjs/ios/GridRenderLayerBridge.swift +37 -37
- package/lib/commonjs/ios/GridRenderLayerManager.mm +157 -157
- package/lib/commonjs/ios/GridRenderLayerView.h +30 -30
- package/lib/commonjs/ios/GridRenderLayerView.m +256 -256
- package/lib/commonjs/ios/InspectorDataCache.swift +65 -65
- package/lib/commonjs/ios/InspectorModule.m +9 -9
- package/lib/commonjs/ios/InspectorModule.swift +63 -63
- package/lib/commonjs/ios/Shaders.metal +190 -190
- package/lib/commonjs/ios/WeatherFrameProcessorModule.m +15 -15
- package/lib/commonjs/ios/WeatherFrameProcessorModule.swift +103 -103
- package/lib/commonjs/package.json +72 -72
- package/lib/commonjs/react-native-builder-bob.config.js.map +1 -1
- package/lib/commonjs/scripts/compile-shaders.js.map +1 -1
- package/lib/commonjs/scripts/compile-shaders.sh +38 -38
- package/lib/commonjs/src/AguaceroContext.js.map +1 -1
- package/lib/commonjs/src/GridRenderLayer.js.map +1 -1
- package/lib/commonjs/src/GridRenderLayerNativeComponent.js.map +1 -1
- package/lib/commonjs/src/MapManager.js +64 -4
- package/lib/commonjs/src/MapManager.js.map +1 -1
- package/lib/commonjs/src/MapRegistry.js.map +1 -1
- package/lib/commonjs/src/StyleApplicator.js +6 -6
- package/lib/commonjs/src/StyleApplicator.js.map +1 -1
- package/lib/commonjs/src/WeatherLayerManager.js +11 -3
- package/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
- package/lib/commonjs/tsconfig.json +23 -23
- package/lib/module/README.md +126 -126
- package/lib/module/aguacerowx-react-native.podspec +38 -38
- package/lib/module/android/build.gradle +107 -107
- package/lib/module/android/src/main/AndroidManifest.xml +6 -6
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +672 -672
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
- package/lib/module/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
- package/lib/module/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
- package/lib/module/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
- package/lib/module/android/src/main/res/raw/fragment_shader.glsl +161 -161
- package/lib/module/android/src/main/res/raw/vertex_shader.glsl +19 -19
- package/lib/module/babel.config.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/ios/AguaceroPackage.m +18 -18
- package/lib/module/ios/FragmentUniforms.swift +15 -15
- package/lib/module/ios/GridRenderLayer.swift +1043 -1043
- package/lib/module/ios/GridRenderLayerBridge.swift +37 -37
- package/lib/module/ios/GridRenderLayerManager.mm +157 -157
- package/lib/module/ios/GridRenderLayerView.h +30 -30
- package/lib/module/ios/GridRenderLayerView.m +256 -256
- package/lib/module/ios/InspectorDataCache.swift +65 -65
- package/lib/module/ios/InspectorModule.m +9 -9
- package/lib/module/ios/InspectorModule.swift +63 -63
- package/lib/module/ios/Shaders.metal +190 -190
- package/lib/module/ios/WeatherFrameProcessorModule.m +15 -15
- package/lib/module/ios/WeatherFrameProcessorModule.swift +103 -103
- package/lib/module/lib/commonjs/README.md +126 -126
- package/lib/module/lib/commonjs/aguacerowx-react-native.podspec +38 -38
- package/lib/module/lib/commonjs/babel.config.js.map +1 -1
- package/lib/module/lib/commonjs/index.js.map +1 -1
- package/lib/module/lib/commonjs/package.json +72 -72
- package/lib/module/lib/commonjs/react-native-builder-bob.config.js.map +1 -1
- package/lib/module/lib/commonjs/scripts/compile-shaders.js.map +1 -1
- package/lib/module/lib/commonjs/src/AguaceroContext.js.map +1 -1
- package/lib/module/lib/commonjs/src/GridRenderLayer.js.map +1 -1
- package/lib/module/lib/commonjs/src/GridRenderLayerNativeComponent.js.map +1 -1
- package/lib/module/lib/commonjs/src/MapManager.js +64 -4
- package/lib/module/lib/commonjs/src/MapManager.js.map +1 -1
- package/lib/module/lib/commonjs/src/MapRegistry.js.map +1 -1
- package/lib/module/lib/commonjs/src/StyleApplicator.js +6 -6
- package/lib/module/lib/commonjs/src/StyleApplicator.js.map +1 -1
- package/lib/module/lib/commonjs/src/WeatherLayerManager.js +11 -3
- package/lib/module/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
- package/lib/module/lib/commonjs/tsconfig.json +23 -23
- package/lib/module/package.json +72 -72
- package/lib/module/react-native-builder-bob.config.js.map +1 -1
- package/lib/module/scripts/compile-shaders.js.map +1 -1
- package/lib/module/scripts/compile-shaders.sh +38 -38
- package/lib/module/src/AguaceroContext.js.map +1 -1
- package/lib/module/src/GridRenderLayer.js.map +1 -1
- package/lib/module/src/GridRenderLayerNativeComponent.js.map +1 -1
- package/lib/module/src/MapManager.js +65 -4
- package/lib/module/src/MapManager.js.map +1 -1
- package/lib/module/src/MapRegistry.js.map +1 -1
- package/lib/module/src/StyleApplicator.js +6 -6
- package/lib/module/src/StyleApplicator.js.map +1 -1
- package/lib/module/src/WeatherLayerManager.js +11 -3
- package/lib/module/src/WeatherLayerManager.js.map +1 -1
- package/lib/module/tsconfig.json +23 -23
- package/lib/typescript/src/MapManager.d.ts +1 -7
- package/lib/typescript/src/MapManager.d.ts.map +1 -1
- package/lib/typescript/src/WeatherLayerManager.d.ts.map +1 -1
- package/package.json +72 -72
- package/src/AguaceroContext.js +3 -3
- package/src/GridRenderLayer.js +217 -217
- package/src/GridRenderLayerNativeComponent.ts +15 -15
- package/src/MapManager.js +218 -155
- package/src/MapRegistry.js +34 -34
- package/src/StyleApplicator.js +240 -240
- package/src/WeatherLayerManager.js +1028 -1020
- package/android/build/.transforms/42e9b8fa82d77a1c205db5bf0d0ed519/results.bin +0 -1
- package/android/build/.transforms/42e9b8fa82d77a1c205db5bf0d0ed519/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/results.bin +0 -1
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/AguaceroPackage.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/BuildConfig.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayer.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayerView.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderManager.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/InspectorModule.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/ShaderUtils.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/WeatherFrameProcessorModule.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.dex +0 -0
- package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
- package/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
- package/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
- package/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
- package/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
- package/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
- package/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
- package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
- package/android/build/generated/source/codegen/schema.json +0 -1
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
- package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
- package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
- package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
- package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
- package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
- package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
- package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
- package/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
- package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
- package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
- package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
- package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
- package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
- package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
- package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
- package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
- package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -162
- package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId2 +0 -0
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/lib/commonjs/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
- package/lib/commonjs/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
- package/lib/commonjs/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
- package/lib/commonjs/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
- package/lib/commonjs/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
- package/lib/commonjs/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
- package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
- package/lib/commonjs/android/build/generated/source/codegen/schema.json +0 -1
- package/lib/commonjs/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
- package/lib/commonjs/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
- package/lib/commonjs/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
- package/lib/commonjs/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
- package/lib/commonjs/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/lib/commonjs/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/lib/commonjs/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
- package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
- package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
- package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
- package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
- package/lib/commonjs/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
- package/lib/commonjs/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
- package/lib/commonjs/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
- package/lib/commonjs/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
- package/lib/commonjs/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/lib/commonjs/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
- package/lib/commonjs/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
- package/lib/commonjs/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
- package/lib/commonjs/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
- package/lib/commonjs/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
- package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
- package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
- package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -162
- package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/lib/commonjs/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/lib/commonjs/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
- package/lib/commonjs/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
- package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
- package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
- package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId2 +0 -0
- package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/lib/module/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
- package/lib/module/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
- package/lib/module/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
- package/lib/module/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
- package/lib/module/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
- package/lib/module/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
- package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
- package/lib/module/android/build/generated/source/codegen/schema.json +0 -1
- package/lib/module/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
- package/lib/module/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
- package/lib/module/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
- package/lib/module/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
- package/lib/module/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/lib/module/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/lib/module/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
- package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
- package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
- package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
- package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
- package/lib/module/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
- package/lib/module/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
- package/lib/module/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
- package/lib/module/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
- package/lib/module/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/lib/module/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
- package/lib/module/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
- package/lib/module/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
- package/lib/module/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
- package/lib/module/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
- package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
- package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
- package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -162
- package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
- package/lib/module/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/lib/module/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
- package/lib/module/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
- package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId0 +0 -0
- package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId1 +0 -0
- package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId2 +0 -0
- package/lib/module/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/lib/module/lib/commonjs/android/build.gradle +0 -108
- package/lib/module/lib/commonjs/android/src/main/AndroidManifest.xml +0 -7
- package/lib/module/lib/commonjs/ios/AguaceroPackage.m +0 -19
- package/lib/module/lib/commonjs/ios/FragmentUniforms.swift +0 -16
- package/lib/module/lib/commonjs/ios/GridRenderLayer.swift +0 -1043
- package/lib/module/lib/commonjs/ios/GridRenderLayerBridge.swift +0 -38
- package/lib/module/lib/commonjs/ios/GridRenderLayerManager.mm +0 -158
- package/lib/module/lib/commonjs/ios/GridRenderLayerView.h +0 -31
- package/lib/module/lib/commonjs/ios/GridRenderLayerView.m +0 -257
- package/lib/module/lib/commonjs/ios/InspectorDataCache.swift +0 -66
- package/lib/module/lib/commonjs/ios/InspectorModule.m +0 -10
- package/lib/module/lib/commonjs/ios/InspectorModule.swift +0 -64
- package/lib/module/lib/commonjs/ios/Shaders.metal +0 -191
- package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.m +0 -16
- package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.swift +0 -104
- package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-device.metallib +0 -0
- package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
- package/lib/module/lib/commonjs/ios/generated/AguaceroWxReactNativeSpec-generated.mm +0 -0
- package/lib/module/lib/commonjs/ios/generated/AguaceroWxReactNativeSpec.h +0 -0
- package/lib/module/lib/commonjs/scripts/compile-shaders.sh +0 -39
|
@@ -1,1043 +1,1043 @@
|
|
|
1
|
-
import Foundation
|
|
2
|
-
import MapboxMaps
|
|
3
|
-
import Metal
|
|
4
|
-
import libzstd
|
|
5
|
-
import simd
|
|
6
|
-
|
|
7
|
-
// MARK: - Swift-only wrapper for CustomLayerHost conformance
|
|
8
|
-
@objc internal final class GridRenderLayerHost: NSObject, CustomLayerHost {
|
|
9
|
-
weak var layer: GridRenderLayer?
|
|
10
|
-
|
|
11
|
-
init(layer: GridRenderLayer) {
|
|
12
|
-
self.layer = layer
|
|
13
|
-
super.init()
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
func renderingWillStart(_ metalDevice: MTLDevice, colorPixelFormat: UInt, depthStencilPixelFormat: UInt) {
|
|
17
|
-
layer?.internalRenderingWillStart(metalDevice, colorPixelFormat: colorPixelFormat, depthStencilPixelFormat: depthStencilPixelFormat)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
func render(_ parameters: CustomLayerRenderParameters, mtlCommandBuffer: MTLCommandBuffer, mtlRenderPassDescriptor: MTLRenderPassDescriptor) {
|
|
21
|
-
layer?.internalRender(parameters, mtlCommandBuffer: mtlCommandBuffer, mtlRenderPassDescriptor: mtlRenderPassDescriptor)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
func renderingWillEnd() {
|
|
25
|
-
layer?.internalRenderingWillEnd()
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
@objc(GridRenderLayer)
|
|
30
|
-
public class GridRenderLayer: NSObject {
|
|
31
|
-
|
|
32
|
-
// MARK: - Properties
|
|
33
|
-
|
|
34
|
-
public var id: String
|
|
35
|
-
@objc internal var hostWrapper: GridRenderLayerHost!
|
|
36
|
-
|
|
37
|
-
// Metal objects
|
|
38
|
-
private var device: MTLDevice!
|
|
39
|
-
private var commandQueue: MTLCommandQueue!
|
|
40
|
-
private var pipelineState: MTLRenderPipelineState!
|
|
41
|
-
private var vertexBuffer: MTLBuffer?
|
|
42
|
-
private var indexBuffer: MTLBuffer?
|
|
43
|
-
private var dataTexture: MTLTexture?
|
|
44
|
-
private var colormapTexture: MTLTexture?
|
|
45
|
-
private var dataSamplerState: MTLSamplerState!
|
|
46
|
-
private var colormapSamplerState: MTLSamplerState!
|
|
47
|
-
private var isDataSamplerLinear: Bool = false
|
|
48
|
-
|
|
49
|
-
private var pendingColormapUpdate: String?
|
|
50
|
-
private var pendingDataUpdate: (data: String, nx: NSNumber, ny: NSNumber, scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: String)?
|
|
51
|
-
private var pendingGeometryUpdate: (corners: [String: Any], gridDef: [String: Any])?
|
|
52
|
-
|
|
53
|
-
// Layer state
|
|
54
|
-
private var indexCount: Int = 0
|
|
55
|
-
private var uniforms = FragmentUniforms(
|
|
56
|
-
opacity: 1.0,
|
|
57
|
-
dataRange: SIMD2<Float>(0.0, 1.0),
|
|
58
|
-
scale: 1.0,
|
|
59
|
-
offset: 0.0,
|
|
60
|
-
missingQuantized: 127.0,
|
|
61
|
-
textureSize: SIMD2<Float>(0.0, 0.0),
|
|
62
|
-
smoothing: 1,
|
|
63
|
-
scaleType: 0,
|
|
64
|
-
isPtype: 0,
|
|
65
|
-
isMRMS: 0
|
|
66
|
-
)
|
|
67
|
-
private var isVisible = false
|
|
68
|
-
private var pendingActiveFrameKey: String?
|
|
69
|
-
private let inspectorCache = InspectorDataCache.shared
|
|
70
|
-
private struct FrameMetadata {
|
|
71
|
-
let texture: MTLTexture
|
|
72
|
-
let scale: Float
|
|
73
|
-
let offset: Float
|
|
74
|
-
let missing: Float
|
|
75
|
-
let scaleType: Int
|
|
76
|
-
let nx: Float
|
|
77
|
-
let ny: Float
|
|
78
|
-
let filePath: String
|
|
79
|
-
let originalScale: Float
|
|
80
|
-
let originalOffset: Float
|
|
81
|
-
}
|
|
82
|
-
private var frameCache: [String: FrameMetadata] = [:]
|
|
83
|
-
private let frameProcessingQueue = DispatchQueue(label: "com.aguacero.frame-processing", qos: .userInitiated, attributes: .concurrent)
|
|
84
|
-
private let semaphore = DispatchSemaphore(value: 8)
|
|
85
|
-
|
|
86
|
-
private struct VertexInfo {
|
|
87
|
-
var mercX: Float
|
|
88
|
-
var mercY: Float
|
|
89
|
-
var texU: Float
|
|
90
|
-
var texV: Float
|
|
91
|
-
var index: UInt16
|
|
92
|
-
}
|
|
93
|
-
@objc
|
|
94
|
-
public init(id: String) {
|
|
95
|
-
self.id = id
|
|
96
|
-
super.init()
|
|
97
|
-
self.hostWrapper = GridRenderLayerHost(layer: self)
|
|
98
|
-
print("🟢 [GridRenderLayer] Initialized with ID: \(id)")
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
@objc public func getHostWrapper() -> Any {
|
|
102
|
-
return self.hostWrapper as Any
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// MARK: - Public Methods (called from Manager)
|
|
106
|
-
|
|
107
|
-
@objc public func setOpacity(value: Float) {
|
|
108
|
-
self.uniforms.opacity = value
|
|
109
|
-
print("🟢 [GridRenderLayer] Set opacity: \(value)")
|
|
110
|
-
// ADD THIS: Force the map to repaint to show the opacity change immediately.
|
|
111
|
-
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
@objc public func setDataRange(value: [NSNumber]) {
|
|
115
|
-
self.uniforms.dataRange = SIMD2<Float>(value[0].floatValue, value[1].floatValue)
|
|
116
|
-
print("🟢 [GridRenderLayer] Set data range: \(value)")
|
|
117
|
-
// ADD THIS: Force the map to repaint to show the data range change immediately.
|
|
118
|
-
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
@objc public func setSmoothing(value: Bool) {
|
|
122
|
-
self.uniforms.smoothing = value ? 1 : 0
|
|
123
|
-
print("🟢 [GridRenderLayer] Set smoothing: \(value)")
|
|
124
|
-
// ADD THIS: Force the map to repaint to show the smoothing change immediately.
|
|
125
|
-
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
@objc(setIsMRMSWithIsMRMS:)
|
|
129
|
-
public func setIsMRMS(isMRMS: Bool) {
|
|
130
|
-
self.uniforms.isMRMS = isMRMS ? 1 : 0
|
|
131
|
-
print("🟢 [GridRenderLayer] Set isMRMS: \(isMRMS)")
|
|
132
|
-
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// ADD THIS METHOD
|
|
136
|
-
@objc(setVariableWithVariable:)
|
|
137
|
-
public func setVariable(variable: String) {
|
|
138
|
-
let isPtypeVar = (variable == "ptypeRefl" || variable == "ptypeRate")
|
|
139
|
-
self.uniforms.isPtype = isPtypeVar ? 1 : 0
|
|
140
|
-
print("🟢 [GridRenderLayer] Set variable: \(variable), isPtype set to: \(self.uniforms.isPtype)")
|
|
141
|
-
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
@objc public func clear() {
|
|
145
|
-
self.isVisible = false
|
|
146
|
-
self.inspectorCache.clear()
|
|
147
|
-
print("🟢 [GridRenderLayer] Cleared")
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
@objc public func updateDataParameters(scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: NSNumber) { // ADD scaleType parameter
|
|
151
|
-
// Update both the inspector cache AND the rendering uniforms
|
|
152
|
-
self.uniforms.scale = scale.floatValue
|
|
153
|
-
self.uniforms.offset = offset.floatValue
|
|
154
|
-
self.uniforms.missingQuantized = missing.floatValue
|
|
155
|
-
self.uniforms.scaleType = Int32(scaleType.intValue) // ADD THIS
|
|
156
|
-
|
|
157
|
-
inspectorCache.update(
|
|
158
|
-
data: inspectorCache.lastDecompressedData,
|
|
159
|
-
nx: inspectorCache.nx,
|
|
160
|
-
ny: inspectorCache.ny,
|
|
161
|
-
scale: scale.floatValue,
|
|
162
|
-
offset: offset.floatValue,
|
|
163
|
-
missing: missing.floatValue,
|
|
164
|
-
scaleType: scaleType.intValue // ADD THIS
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
print("🟢 [GridRenderLayer] Updated data parameters - scale: \(scale), offset: \(offset), missing: \(missing), scaleType: \(scaleType)")
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
@objc public func updateColormapTexture(colormapAsBase64: String) {
|
|
171
|
-
guard let device = self.device else {
|
|
172
|
-
pendingColormapUpdate = colormapAsBase64
|
|
173
|
-
return
|
|
174
|
-
}
|
|
175
|
-
guard let data = Data(base64Encoded: colormapAsBase64) else { return }
|
|
176
|
-
let textureDescriptor = MTLTextureDescriptor()
|
|
177
|
-
textureDescriptor.pixelFormat = .rgba8Unorm
|
|
178
|
-
textureDescriptor.width = 256
|
|
179
|
-
textureDescriptor.height = 1
|
|
180
|
-
textureDescriptor.usage = .shaderRead
|
|
181
|
-
guard let texture = device.makeTexture(descriptor: textureDescriptor) else { return }
|
|
182
|
-
texture.replace(
|
|
183
|
-
region: MTLRegionMake2D(0, 0, 256, 1),
|
|
184
|
-
mipmapLevel: 0,
|
|
185
|
-
withBytes: (data as NSData).bytes,
|
|
186
|
-
bytesPerRow: 256 * 4
|
|
187
|
-
)
|
|
188
|
-
self.colormapTexture = texture
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
@objc(clearGpuCache)
|
|
192
|
-
public func clearGpuCache() {
|
|
193
|
-
frameProcessingQueue.async { [weak self] in
|
|
194
|
-
self?.frameCache.removeAll()
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
private func processRawData(fileData: Data) -> Data? {
|
|
199
|
-
guard let decompressedDeltas = self.decompressZstd(data: fileData) else {
|
|
200
|
-
print("❌ [GridRenderLayer] Failed to decompress zstd data")
|
|
201
|
-
return nil
|
|
202
|
-
}
|
|
203
|
-
let reconstructedData = self.reconstructData(decompressedDeltas: decompressedDeltas)
|
|
204
|
-
let finalTextureBytes = self.transformData(finalData: reconstructedData)
|
|
205
|
-
return finalTextureBytes
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
private func createTextureFromBytes(bytes: Data, nx: Int, ny: Int) -> MTLTexture? {
|
|
209
|
-
guard let device = self.device else { return nil }
|
|
210
|
-
let textureDescriptor = MTLTextureDescriptor()
|
|
211
|
-
textureDescriptor.pixelFormat = .r8Unorm
|
|
212
|
-
textureDescriptor.width = nx
|
|
213
|
-
textureDescriptor.height = ny
|
|
214
|
-
textureDescriptor.usage = .shaderRead
|
|
215
|
-
|
|
216
|
-
guard let texture = device.makeTexture(descriptor: textureDescriptor) else { return nil }
|
|
217
|
-
texture.replace(
|
|
218
|
-
region: MTLRegionMake2D(0, 0, nx, ny),
|
|
219
|
-
mipmapLevel: 0,
|
|
220
|
-
withBytes: (bytes as NSData).bytes,
|
|
221
|
-
bytesPerRow: nx
|
|
222
|
-
)
|
|
223
|
-
return texture
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
private func updateInspectorCache(filePath: String, nx: Int, ny: Int, scale: Float, offset: Float, missing: Float, scaleType: Int) {
|
|
227
|
-
// This is now called from frameProcessingQueue, so we can do the work synchronously
|
|
228
|
-
guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else {
|
|
229
|
-
print("❌ [Inspector] FATAL: Failed to read file data from path.")
|
|
230
|
-
self.inspectorCache.clear()
|
|
231
|
-
return
|
|
232
|
-
}
|
|
233
|
-
print("💡 [Inspector] 2. Successfully read \(fileData.count) bytes from file.")
|
|
234
|
-
|
|
235
|
-
guard let decompressedDeltas = self.decompressZstd(data: fileData) else {
|
|
236
|
-
print("❌ [Inspector] FATAL: Failed to decompress Zstd data.")
|
|
237
|
-
self.inspectorCache.clear()
|
|
238
|
-
return
|
|
239
|
-
}
|
|
240
|
-
print("💡 [Inspector] 3. Successfully decompressed data.")
|
|
241
|
-
|
|
242
|
-
let reconstructedData = self.reconstructData(decompressedDeltas: decompressedDeltas)
|
|
243
|
-
print("💡 [Inspector] 4. Reconstructed data with \(reconstructedData.count) bytes.")
|
|
244
|
-
|
|
245
|
-
self.inspectorCache.update(
|
|
246
|
-
data: reconstructedData,
|
|
247
|
-
nx: nx,
|
|
248
|
-
ny: ny,
|
|
249
|
-
scale: scale,
|
|
250
|
-
offset: offset,
|
|
251
|
-
missing: missing,
|
|
252
|
-
scaleType: scaleType
|
|
253
|
-
)
|
|
254
|
-
|
|
255
|
-
print("💡 [Inspector] 5. ✅ Cache updated successfully with scaleType=\(scaleType)")
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
@objc(setActiveFrameWithCacheKey:)
|
|
259
|
-
public func setActiveFrame(cacheKey: String) {
|
|
260
|
-
if let frame = frameCache[cacheKey] {
|
|
261
|
-
print("⚡️ [GridRenderLayer] Cache HIT for key: \(cacheKey). Swapping texture.")
|
|
262
|
-
|
|
263
|
-
self.dataTexture = frame.texture
|
|
264
|
-
self.uniforms.scale = frame.scale
|
|
265
|
-
self.uniforms.offset = frame.offset
|
|
266
|
-
self.uniforms.missingQuantized = frame.missing
|
|
267
|
-
self.uniforms.textureSize = SIMD2<Float>(frame.nx, frame.ny)
|
|
268
|
-
self.uniforms.scaleType = Int32(frame.scaleType)
|
|
269
|
-
|
|
270
|
-
self.isVisible = true
|
|
271
|
-
self.pendingActiveFrameKey = nil
|
|
272
|
-
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
273
|
-
|
|
274
|
-
// Update inspector cache on background thread since we already have the frame data
|
|
275
|
-
frameProcessingQueue.async { [weak self] in
|
|
276
|
-
self?.updateInspectorCache(
|
|
277
|
-
filePath: frame.filePath,
|
|
278
|
-
nx: Int(frame.nx),
|
|
279
|
-
ny: Int(frame.ny),
|
|
280
|
-
scale: frame.scale,
|
|
281
|
-
offset: frame.offset,
|
|
282
|
-
missing: frame.missing,
|
|
283
|
-
scaleType: frame.scaleType
|
|
284
|
-
)
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
} else {
|
|
288
|
-
print("⚠️ [GridRenderLayer] setActiveFrame cache MISS for key: \(cacheKey). Will apply when primed.")
|
|
289
|
-
self.pendingActiveFrameKey = cacheKey
|
|
290
|
-
self.isVisible = false
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
@objc(primeGpuCacheWithFrameInfo:)
|
|
294
|
-
public func primeGpuCache(frameInfo: [String: [String: Any]]) {
|
|
295
|
-
let group = DispatchGroup()
|
|
296
|
-
|
|
297
|
-
if (frameInfo.count > 1) {
|
|
298
|
-
print("🟡 [GridRenderLayer] Starting to prime \(frameInfo.count) textures with concurrent processing...")
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
for (cacheKey, info) in frameInfo {
|
|
302
|
-
group.enter()
|
|
303
|
-
|
|
304
|
-
frameProcessingQueue.async { [weak self] in
|
|
305
|
-
guard let self = self else {
|
|
306
|
-
group.leave()
|
|
307
|
-
return
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
self.semaphore.wait()
|
|
311
|
-
defer {
|
|
312
|
-
self.semaphore.signal()
|
|
313
|
-
group.leave()
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if self.frameCache[cacheKey] != nil { return }
|
|
317
|
-
|
|
318
|
-
guard let filePath = info["filePath"] as? String,
|
|
319
|
-
let nx = info["nx"] as? NSNumber,
|
|
320
|
-
let ny = info["ny"] as? NSNumber,
|
|
321
|
-
let scale = info["scale"] as? NSNumber,
|
|
322
|
-
let offset = info["offset"] as? NSNumber,
|
|
323
|
-
let missing = info["missing"] as? NSNumber,
|
|
324
|
-
let scaleTypeStr = info["scaleType"] as? String,
|
|
325
|
-
let originalScale = info["originalScale"] as? NSNumber,
|
|
326
|
-
let originalOffset = info["originalOffset"] as? NSNumber
|
|
327
|
-
else {
|
|
328
|
-
print("❌ [GridRenderLayer] Skipping prime for \(cacheKey), missing data.")
|
|
329
|
-
return
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// Process data OFF the main thread
|
|
333
|
-
guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
|
|
334
|
-
let finalTextureBytes = self.processRawData(fileData: fileData)
|
|
335
|
-
else {
|
|
336
|
-
print("❌ [GridRenderLayer] Failed to process data for \(cacheKey)")
|
|
337
|
-
return
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// Create texture on main thread
|
|
341
|
-
DispatchQueue.main.async { [weak self] in
|
|
342
|
-
guard let self = self else { return }
|
|
343
|
-
|
|
344
|
-
if let texture = self.createTextureFromBytes(bytes: finalTextureBytes, nx: nx.intValue, ny: ny.intValue) {
|
|
345
|
-
let metadata = FrameMetadata(
|
|
346
|
-
texture: texture,
|
|
347
|
-
scale: scale.floatValue,
|
|
348
|
-
offset: offset.floatValue,
|
|
349
|
-
missing: missing.floatValue,
|
|
350
|
-
scaleType: (scaleTypeStr == "sqrt") ? 1 : 0,
|
|
351
|
-
nx: nx.floatValue,
|
|
352
|
-
ny: ny.floatValue,
|
|
353
|
-
filePath: filePath,
|
|
354
|
-
originalScale: originalScale.floatValue,
|
|
355
|
-
originalOffset: originalOffset.floatValue
|
|
356
|
-
)
|
|
357
|
-
self.frameCache[cacheKey] = metadata
|
|
358
|
-
|
|
359
|
-
if let pendingKey = self.pendingActiveFrameKey, pendingKey == cacheKey {
|
|
360
|
-
print("👍 [GridRenderLayer] The pending frame is now ready. Activating it.")
|
|
361
|
-
self.setActiveFrame(cacheKey: pendingKey)
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
group.notify(queue: .main) {
|
|
369
|
-
if (frameInfo.count > 1) {
|
|
370
|
-
print("🎉 [GridRenderLayer] All \(frameInfo.count) frames have been processed and cached.")
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
@objc public func updateDataTexture(data: String, nx: NSNumber, ny: NSNumber, scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: String) {
|
|
376
|
-
print("🚀 [GridRenderLayer] FAST LANE: updateDataTexture called for initial frame...")
|
|
377
|
-
|
|
378
|
-
let filePath = data
|
|
379
|
-
|
|
380
|
-
frameProcessingQueue.async { [weak self] in
|
|
381
|
-
guard let self = self else { return }
|
|
382
|
-
|
|
383
|
-
guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
|
|
384
|
-
let finalTextureBytes = self.processRawData(fileData: fileData)
|
|
385
|
-
else {
|
|
386
|
-
print("❌ [GridRenderLayer] FAST LANE: Failed to process initial frame data.")
|
|
387
|
-
return
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
DispatchQueue.main.async { [weak self] in
|
|
391
|
-
guard let self = self, let texture = self.createTextureFromBytes(bytes: finalTextureBytes, nx: nx.intValue, ny: ny.intValue) else {
|
|
392
|
-
return
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
self.dataTexture = texture
|
|
396
|
-
self.uniforms.scale = scale.floatValue
|
|
397
|
-
self.uniforms.offset = offset.floatValue
|
|
398
|
-
self.uniforms.missingQuantized = missing.floatValue
|
|
399
|
-
self.uniforms.scaleType = Int32((scaleType == "sqrt") ? 1 : 0)
|
|
400
|
-
self.uniforms.textureSize = SIMD2<Float>(nx.floatValue, ny.floatValue)
|
|
401
|
-
|
|
402
|
-
self.isVisible = true
|
|
403
|
-
print("✅ [GridRenderLayer] FAST LANE: Initial frame processed and displayed.")
|
|
404
|
-
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
405
|
-
|
|
406
|
-
self.updateInspectorCache(
|
|
407
|
-
filePath: filePath,
|
|
408
|
-
nx: nx.intValue,
|
|
409
|
-
ny: ny.intValue,
|
|
410
|
-
scale: scale.floatValue,
|
|
411
|
-
offset: offset.floatValue,
|
|
412
|
-
missing: missing.floatValue,
|
|
413
|
-
scaleType: (scaleType == "sqrt") ? 1 : 0
|
|
414
|
-
)
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
@objc public func updateGeometry(corners: [String: Any], gridDef: [String: Any]) {
|
|
420
|
-
guard self.device != nil else {
|
|
421
|
-
print("⚠️ [GridRenderLayer] Device not ready yet, storing geometry for later")
|
|
422
|
-
pendingGeometryUpdate = (corners: corners, gridDef: gridDef)
|
|
423
|
-
return
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
print(" Device is ready, processing geometry immediately")
|
|
427
|
-
|
|
428
|
-
DispatchQueue.global(qos: .userInitiated).async {
|
|
429
|
-
print(" 🔄 Generating geometry on background thread")
|
|
430
|
-
|
|
431
|
-
var vertices: [Float] = []
|
|
432
|
-
var indices: [UInt16] = []
|
|
433
|
-
|
|
434
|
-
self.generateGeometryData(gridDef: gridDef, vertices: &vertices, indices: &indices)
|
|
435
|
-
|
|
436
|
-
if vertices.isEmpty || indices.isEmpty {
|
|
437
|
-
print("❌ [GridRenderLayer] No geometry generated")
|
|
438
|
-
return
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
self.indexCount = indices.count
|
|
442
|
-
|
|
443
|
-
DispatchQueue.main.async {
|
|
444
|
-
print(" 🎨 Creating buffers on main thread")
|
|
445
|
-
|
|
446
|
-
self.vertexBuffer = self.device.makeBuffer(bytes: vertices, length: vertices.count * MemoryLayout<Float>.size, options: [])
|
|
447
|
-
self.indexBuffer = self.device.makeBuffer(bytes: indices, length: indices.count * MemoryLayout<UInt16>.size, options: [])
|
|
448
|
-
|
|
449
|
-
print("🟢 [GridRenderLayer] Geometry updated: \(vertices.count/4) vertices, \(indices.count/3) triangles")
|
|
450
|
-
print(" vertexBuffer: \(self.vertexBuffer != nil)")
|
|
451
|
-
print(" indexBuffer: \(self.indexBuffer != nil)")
|
|
452
|
-
print(" indexCount: \(self.indexCount)")
|
|
453
|
-
|
|
454
|
-
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
private func decompressZstd(data: Data) -> Data? {
|
|
460
|
-
let decompressedSize = data.withUnsafeBytes { ptr in
|
|
461
|
-
ZSTD_getFrameContentSize(ptr.baseAddress, data.count)
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
guard Int64(bitPattern: decompressedSize) > 0 else {
|
|
465
|
-
print("❌ [GridRenderLayer] Could not determine decompressed size")
|
|
466
|
-
return nil
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
var decompressedData = Data(count: Int(decompressedSize))
|
|
470
|
-
|
|
471
|
-
let result = decompressedData.withUnsafeMutableBytes { decompressedPtr -> Int in
|
|
472
|
-
data.withUnsafeBytes { compressedPtr -> Int in
|
|
473
|
-
let returnValue = ZSTD_decompress(
|
|
474
|
-
decompressedPtr.baseAddress,
|
|
475
|
-
Int(decompressedSize),
|
|
476
|
-
compressedPtr.baseAddress,
|
|
477
|
-
data.count
|
|
478
|
-
)
|
|
479
|
-
return Int(returnValue)
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
guard result > 0 && result == decompressedData.count else {
|
|
484
|
-
if result > 0 {
|
|
485
|
-
let size_t_result = size_t(result)
|
|
486
|
-
if let errorName = ZSTD_getErrorName(size_t_result) {
|
|
487
|
-
let errorString = String(cString: errorName)
|
|
488
|
-
print("❌ [GridRenderLayer] Zstd decompression failed: \(errorString)")
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
return nil
|
|
492
|
-
}
|
|
493
|
-
return decompressedData
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
// MARK: - Private Helper Methods
|
|
497
|
-
|
|
498
|
-
private func reconstructData(decompressedDeltas: Data) -> Data {
|
|
499
|
-
guard !decompressedDeltas.isEmpty else { return Data() }
|
|
500
|
-
var reconstructedData = Data(count: decompressedDeltas.count)
|
|
501
|
-
reconstructedData[0] = decompressedDeltas[0]
|
|
502
|
-
for i in 1..<decompressedDeltas.count {
|
|
503
|
-
reconstructedData[i] = UInt8(Int8(bitPattern: reconstructedData[i-1]) &+ Int8(bitPattern: decompressedDeltas[i]))
|
|
504
|
-
}
|
|
505
|
-
return reconstructedData
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
private func transformData(finalData: Data) -> Data {
|
|
509
|
-
var transformedData = Data(count: finalData.count)
|
|
510
|
-
for i in 0..<finalData.count {
|
|
511
|
-
transformedData[i] = UInt8(Int16(Int8(bitPattern: finalData[i])) + 128)
|
|
512
|
-
}
|
|
513
|
-
return transformedData
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
private func isLCCType(gridDef: [String: Any]) -> Bool {
|
|
517
|
-
if let type = gridDef["type"] as? String {
|
|
518
|
-
return type == "lambert_conformal_conic"
|
|
519
|
-
}
|
|
520
|
-
return false
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
private func generateLCCGeometry(gridDef: [String: Any], vertices: inout [Float], indices: inout [UInt16]) {
|
|
524
|
-
guard let gridParams = gridDef["grid_params"] as? [String: Any],
|
|
525
|
-
let projParams = gridDef["proj_params"] as? [String: Any],
|
|
526
|
-
let nx = gridParams["nx"] as? Int,
|
|
527
|
-
let ny = gridParams["ny"] as? Int,
|
|
528
|
-
let dx = gridParams["dx"] as? Double,
|
|
529
|
-
let dy = gridParams["dy"] as? Double,
|
|
530
|
-
let x_origin = gridParams["x_origin"] as? Double,
|
|
531
|
-
let y_origin = gridParams["y_origin"] as? Double else {
|
|
532
|
-
return
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
let subdivisions = 60
|
|
536
|
-
let TILE_SIZE: Double = 512.0
|
|
537
|
-
|
|
538
|
-
let x_min = x_origin
|
|
539
|
-
let y_max = y_origin
|
|
540
|
-
let x_max = x_origin + Double(nx - 1) * dx
|
|
541
|
-
let y_min = y_origin + Double(ny - 1) * dy
|
|
542
|
-
|
|
543
|
-
var vertexGrid: [[VertexInfo?]] = Array(repeating: Array(repeating: nil, count: subdivisions + 1), count: subdivisions + 1)
|
|
544
|
-
var validVertexCount: UInt16 = 0
|
|
545
|
-
|
|
546
|
-
// Generate vertices
|
|
547
|
-
for row in 0...subdivisions {
|
|
548
|
-
for col in 0...subdivisions {
|
|
549
|
-
let t_x = Double(col) / Double(subdivisions)
|
|
550
|
-
let t_y = Double(row) / Double(subdivisions)
|
|
551
|
-
|
|
552
|
-
let proj_x = x_min + t_x * (x_max - x_min)
|
|
553
|
-
let proj_y = y_max + t_y * (y_min - y_max)
|
|
554
|
-
|
|
555
|
-
// Convert LCC projection coordinates to lat/lon
|
|
556
|
-
if let (lon, lat) = lccToLonLat(i: proj_x, j: proj_y, gridDef: gridDef) {
|
|
557
|
-
// Convert lat/lon to Mercator
|
|
558
|
-
let mercX_normalized = (lon + 180.0) / 360.0
|
|
559
|
-
let clampedLat = max(-85.05112878, min(85.05112878, lat))
|
|
560
|
-
let sinLatitude = sin(clampedLat * .pi / 180.0)
|
|
561
|
-
let mercY_normalized = 0.5 - log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * .pi)
|
|
562
|
-
|
|
563
|
-
let mercX = mercX_normalized * TILE_SIZE
|
|
564
|
-
let mercY = mercY_normalized * TILE_SIZE
|
|
565
|
-
|
|
566
|
-
// Check for invalid values
|
|
567
|
-
if !mercX.isFinite || !mercY.isFinite {
|
|
568
|
-
vertexGrid[row][col] = nil
|
|
569
|
-
continue
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
let tex_u = Float(t_x)
|
|
573
|
-
let tex_v = Float(t_y)
|
|
574
|
-
|
|
575
|
-
let vInfo = VertexInfo(
|
|
576
|
-
mercX: Float(mercX),
|
|
577
|
-
mercY: Float(mercY),
|
|
578
|
-
texU: tex_u,
|
|
579
|
-
texV: tex_v,
|
|
580
|
-
index: validVertexCount
|
|
581
|
-
)
|
|
582
|
-
|
|
583
|
-
vertexGrid[row][col] = vInfo
|
|
584
|
-
|
|
585
|
-
vertices.append(Float(mercX))
|
|
586
|
-
vertices.append(Float(mercY))
|
|
587
|
-
vertices.append(tex_u)
|
|
588
|
-
vertices.append(tex_v)
|
|
589
|
-
|
|
590
|
-
validVertexCount += 1
|
|
591
|
-
} else {
|
|
592
|
-
vertexGrid[row][col] = nil
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
if vertices.isEmpty {
|
|
598
|
-
print("❌ [LCC Geometry] No valid vertices generated")
|
|
599
|
-
return
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
// Generate indices
|
|
603
|
-
for row in 0..<subdivisions {
|
|
604
|
-
for col in 0..<subdivisions {
|
|
605
|
-
guard let topLeft = vertexGrid[row][col],
|
|
606
|
-
let topRight = vertexGrid[row][col + 1],
|
|
607
|
-
let bottomLeft = vertexGrid[row + 1][col],
|
|
608
|
-
let bottomRight = vertexGrid[row + 1][col + 1] else {
|
|
609
|
-
continue
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
indices.append(topLeft.index)
|
|
613
|
-
indices.append(bottomLeft.index)
|
|
614
|
-
indices.append(topRight.index)
|
|
615
|
-
|
|
616
|
-
indices.append(topRight.index)
|
|
617
|
-
indices.append(bottomLeft.index)
|
|
618
|
-
indices.append(bottomRight.index)
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
private func lccToLonLat(i: Double, j: Double, gridDef: [String: Any]) -> (lon: Double, lat: Double)? {
|
|
624
|
-
guard let projParams = gridDef["proj_params"] as? [String: Any],
|
|
625
|
-
let lat_0 = (projParams["lat_0"] as? NSNumber)?.doubleValue,
|
|
626
|
-
let lon_0 = (projParams["lon_0"] as? NSNumber)?.doubleValue,
|
|
627
|
-
let lat_1 = (projParams["lat_1"] as? NSNumber)?.doubleValue,
|
|
628
|
-
let lat_2 = (projParams["lat_2"] as? NSNumber)?.doubleValue,
|
|
629
|
-
let r_earth = (projParams["R"] as? NSNumber)?.doubleValue else {
|
|
630
|
-
print("❌ [LCC Geometry] Failed to extract LCC parameters.")
|
|
631
|
-
return nil
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
let π = Double.pi
|
|
635
|
-
let toRad = π / 180.0
|
|
636
|
-
let toDeg = 180.0 / π
|
|
637
|
-
|
|
638
|
-
let lat1_rad = lat_1 * toRad
|
|
639
|
-
let lat2_rad = lat_2 * toRad
|
|
640
|
-
let lat0_rad = lat_0 * toRad
|
|
641
|
-
let lon0_rad = lon_0 * toRad
|
|
642
|
-
|
|
643
|
-
let n: Double
|
|
644
|
-
if abs(lat_1 - lat_2) < 1e-10 {
|
|
645
|
-
n = sin(lat1_rad)
|
|
646
|
-
} else {
|
|
647
|
-
n = log(cos(lat1_rad) / cos(lat2_rad)) / log(tan(π/4.0 + lat2_rad/2.0) / tan(π/4.0 + lat1_rad/2.0))
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
let F = cos(lat1_rad) * pow(tan(π/4.0 + lat1_rad/2.0), n) / n
|
|
651
|
-
let rho_0 = r_earth * F * pow(tan(π/4.0 + lat0_rad/2.0), -n)
|
|
652
|
-
|
|
653
|
-
let x = i
|
|
654
|
-
let y = j
|
|
655
|
-
|
|
656
|
-
let rho = sqrt(x * x + (rho_0 - y) * (rho_0 - y))
|
|
657
|
-
if rho < 1e-10 {
|
|
658
|
-
return (lon: lon_0, lat: lat_0)
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
let theta = atan2(x, rho_0 - y)
|
|
662
|
-
|
|
663
|
-
let lon = lon0_rad + theta / n
|
|
664
|
-
let lat = 2.0 * atan(pow(r_earth * F / rho, 1.0 / n)) - π/2.0
|
|
665
|
-
|
|
666
|
-
let lonDeg = lon * toDeg
|
|
667
|
-
let latDeg = lat * toDeg
|
|
668
|
-
|
|
669
|
-
if !lonDeg.isFinite || !latDeg.isFinite {
|
|
670
|
-
return nil
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
return (lon: lonDeg, lat: latDeg)
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
private func generateGeometryData(gridDef: [String: Any], vertices: inout [Float], indices: inout [UInt16]) {
|
|
677
|
-
guard let gridParams = gridDef["grid_params"] as? [String: Any] else {
|
|
678
|
-
print("❌ [generateGeometryData] No grid_params found")
|
|
679
|
-
return
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
// Check grid type
|
|
683
|
-
let isGFS = isGFSType(gridParams: gridParams)
|
|
684
|
-
let isLCC = isLCCType(gridDef: gridDef)
|
|
685
|
-
|
|
686
|
-
if isGFS {
|
|
687
|
-
// GFS path remains unchanged
|
|
688
|
-
let subdivisions = 120
|
|
689
|
-
let verticesPerRow = (subdivisions * 3) + 1
|
|
690
|
-
let TILE_SIZE: Double = 512.0
|
|
691
|
-
|
|
692
|
-
for row in 0...subdivisions {
|
|
693
|
-
for col in 0...(subdivisions * 3) {
|
|
694
|
-
let v_interp = Float(row) / Float(subdivisions)
|
|
695
|
-
let u_interp = Float(col) / Float(subdivisions)
|
|
696
|
-
let lon = -540.0 + Double(u_interp) * 1080.0
|
|
697
|
-
let lat = -90.0 + Double(v_interp) * 180.0
|
|
698
|
-
|
|
699
|
-
let merc = lonLatToMercator(lon: lon, lat: lat, tileSize: TILE_SIZE)
|
|
700
|
-
vertices.append(contentsOf: [merc.x, merc.y])
|
|
701
|
-
|
|
702
|
-
let tex_u = Float((lon + 180.0) / 360.0)
|
|
703
|
-
let tex_v = 1.0 - v_interp
|
|
704
|
-
vertices.append(contentsOf: [tex_u, tex_v])
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
for row in 0..<subdivisions {
|
|
709
|
-
for col in 0..<(subdivisions * 3) {
|
|
710
|
-
let tl = UInt16(row * verticesPerRow + col)
|
|
711
|
-
let tr = tl + 1
|
|
712
|
-
let bl = UInt16((row + 1) * verticesPerRow + col)
|
|
713
|
-
let br = bl + 1
|
|
714
|
-
indices.append(contentsOf: [tl, bl, tr, tr, bl, br])
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
return
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
if isLCC {
|
|
721
|
-
print("🗺️ [generateGeometryData] Using LCC projection path")
|
|
722
|
-
generateLCCGeometry(gridDef: gridDef, vertices: &vertices, indices: &indices)
|
|
723
|
-
return
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
// Generic Grid Path (MRMS, regional models, etc.)
|
|
727
|
-
print("🗺️ [generateGeometryData] Using generic regional grid path")
|
|
728
|
-
|
|
729
|
-
let nx = gridParams["nx"] as? Int ?? 0
|
|
730
|
-
let ny = gridParams["ny"] as? Int ?? 0
|
|
731
|
-
let lon_first = gridParams["lon_first"] as? Double ?? 0.0
|
|
732
|
-
let lat_first = gridParams["lat_first"] as? Double ?? 90.0
|
|
733
|
-
let dx = gridParams["dx_degrees"] as? Double ?? 0.0
|
|
734
|
-
let dy = gridParams["dy_degrees"] as? Double ?? 0.0
|
|
735
|
-
let lon_last = gridParams["lon_last"] as? Double ?? (lon_first + Double(nx - 1) * dx)
|
|
736
|
-
let lat_last = gridParams["lat_last"] as? Double ?? (lat_first + Double(ny - 1) * dy)
|
|
737
|
-
|
|
738
|
-
let lat_span = lat_last - lat_first
|
|
739
|
-
let isSouthToNorth = lat_span > 0
|
|
740
|
-
|
|
741
|
-
let data_lon_first_180 = lon_first > 180 ? lon_first - 360 : lon_first
|
|
742
|
-
let data_lon_last_180 = lon_last > 180 ? lon_last - 360 : lon_last
|
|
743
|
-
let data_lon_range = data_lon_last_180 - data_lon_first_180
|
|
744
|
-
|
|
745
|
-
let subdivisions_x = 120
|
|
746
|
-
let subdivisions_y = 60
|
|
747
|
-
let verticesPerRow = subdivisions_x + 1
|
|
748
|
-
let TILE_SIZE: Double = 512.0
|
|
749
|
-
|
|
750
|
-
let worldCopies = (data_lon_range > 300) ? [-1, 0, 1] : [0]
|
|
751
|
-
|
|
752
|
-
for world_copy in worldCopies {
|
|
753
|
-
let vertexStartIndex = UInt16(vertices.count / 4)
|
|
754
|
-
let lon_offset = Double(world_copy) * 360.0
|
|
755
|
-
|
|
756
|
-
for row in 0...subdivisions_y {
|
|
757
|
-
for col in 0...subdivisions_x {
|
|
758
|
-
let v_interp = Float(row) / Float(subdivisions_y)
|
|
759
|
-
let u_interp = Float(col) / Float(subdivisions_x)
|
|
760
|
-
|
|
761
|
-
let vertex_lon = data_lon_first_180 + (Double(u_interp) * data_lon_range)
|
|
762
|
-
let vertex_lat = lat_first + (Double(v_interp) * lat_span)
|
|
763
|
-
|
|
764
|
-
let mercX_normalized = ((vertex_lon + lon_offset) + 180.0) / 360.0
|
|
765
|
-
let clampedLat = max(-85.05112878, min(85.05112878, vertex_lat))
|
|
766
|
-
let sinLatitude = sin(clampedLat * .pi / 180.0)
|
|
767
|
-
let mercY_normalized = 0.5 - log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * .pi)
|
|
768
|
-
let mercX = mercX_normalized * TILE_SIZE
|
|
769
|
-
let mercY = mercY_normalized * TILE_SIZE
|
|
770
|
-
|
|
771
|
-
vertices.append(contentsOf: [Float(mercX), Float(mercY)])
|
|
772
|
-
|
|
773
|
-
let tex_u = u_interp
|
|
774
|
-
let tex_v = isSouthToNorth ? (1.0 - v_interp) : v_interp
|
|
775
|
-
|
|
776
|
-
vertices.append(contentsOf: [tex_u, tex_v])
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
for row in 0..<UInt16(subdivisions_y) {
|
|
781
|
-
for col in 0..<UInt16(subdivisions_x) {
|
|
782
|
-
let tl = vertexStartIndex + row * UInt16(verticesPerRow) + col
|
|
783
|
-
let tr = tl + 1
|
|
784
|
-
let bl = vertexStartIndex + (row + 1) * UInt16(verticesPerRow) + col
|
|
785
|
-
let br = bl + 1
|
|
786
|
-
|
|
787
|
-
if isSouthToNorth {
|
|
788
|
-
indices.append(contentsOf: [tl, bl, tr, tr, bl, br])
|
|
789
|
-
} else {
|
|
790
|
-
indices.append(contentsOf: [tl, tr, bl, bl, tr, br])
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
private func isGFSType(gridParams: [String: Any]) -> Bool {
|
|
798
|
-
return (gridParams["lon_first"] as? Double) == 0.0 &&
|
|
799
|
-
abs((gridParams["lat_first"] as? Double) ?? -1) == 90.0
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
private func lonLatToMercator(lon: Double, lat: Double, tileSize: Double) -> (x: Float, y: Float) {
|
|
803
|
-
let mercX_normalized = (lon + 180.0) / 360.0
|
|
804
|
-
let clampedLat = max(-85.05112878, min(85.05112878, lat))
|
|
805
|
-
let sinLatitude = sin(clampedLat * .pi / 180.0)
|
|
806
|
-
let mercY_normalized = 0.5 - log((1.0 + sinLatitude) / (1.0 - sinLatitude)) / (4.0 * .pi)
|
|
807
|
-
|
|
808
|
-
return (x: Float(mercX_normalized * tileSize), y: Float(mercY_normalized * tileSize))
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
// MARK: - Internal methods for CustomLayerHost (called by wrapper)
|
|
812
|
-
|
|
813
|
-
internal func internalRenderingWillStart(_ metalDevice: MTLDevice, colorPixelFormat: UInt, depthStencilPixelFormat: UInt) {
|
|
814
|
-
print("🟢 [GridRenderLayer] renderingWillStart called")
|
|
815
|
-
self.device = metalDevice
|
|
816
|
-
self.commandQueue = metalDevice.makeCommandQueue()
|
|
817
|
-
|
|
818
|
-
let bundle = Bundle(for: GridRenderLayer.self)
|
|
819
|
-
|
|
820
|
-
// Determine if we're running on simulator or device
|
|
821
|
-
#if targetEnvironment(simulator)
|
|
822
|
-
let metallibName = "Shaders-simulator"
|
|
823
|
-
#else
|
|
824
|
-
let metallibName = "Shaders-device"
|
|
825
|
-
#endif
|
|
826
|
-
|
|
827
|
-
// Try to load pre-compiled metallib for the current platform
|
|
828
|
-
let defaultLibrary: MTLLibrary?
|
|
829
|
-
if let metallibUrl = bundle.url(forResource: metallibName, withExtension: "metallib"),
|
|
830
|
-
let library = try? metalDevice.makeLibrary(URL: metallibUrl) {
|
|
831
|
-
print("✅ [GridRenderLayer] Loaded pre-compiled metallib (\(metallibName))")
|
|
832
|
-
defaultLibrary = library
|
|
833
|
-
}
|
|
834
|
-
// Fall back to compiling from .metal source (for development with npm link)
|
|
835
|
-
else if let metalUrl = bundle.url(forResource: "Shaders", withExtension: "metal"),
|
|
836
|
-
let source = try? String(contentsOf: metalUrl),
|
|
837
|
-
let library = try? metalDevice.makeLibrary(source: source, options: nil) {
|
|
838
|
-
print("✅ [GridRenderLayer] Compiled Metal shader from source")
|
|
839
|
-
defaultLibrary = library
|
|
840
|
-
}
|
|
841
|
-
// Neither worked
|
|
842
|
-
else {
|
|
843
|
-
print("❌ [GridRenderLayer] Could not find or compile Metal shaders")
|
|
844
|
-
print(" Bundle path: \(bundle.bundlePath)")
|
|
845
|
-
return
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
guard let library = defaultLibrary else {
|
|
849
|
-
print("❌ [GridRenderLayer] Failed to create Metal library")
|
|
850
|
-
return
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
let vertexFunction = library.makeFunction(name: "vertex_main")
|
|
854
|
-
let fragmentFunction = library.makeFunction(name: "fragment_main")
|
|
855
|
-
|
|
856
|
-
// Set up vertex descriptor
|
|
857
|
-
let vertexDescriptor = MTLVertexDescriptor()
|
|
858
|
-
vertexDescriptor.attributes[0].format = .float2 // position (x, y)
|
|
859
|
-
vertexDescriptor.attributes[0].offset = 0
|
|
860
|
-
vertexDescriptor.attributes[0].bufferIndex = 0
|
|
861
|
-
|
|
862
|
-
vertexDescriptor.attributes[1].format = .float2 // texCoord (u, v)
|
|
863
|
-
vertexDescriptor.attributes[1].offset = MemoryLayout<Float>.size * 2
|
|
864
|
-
vertexDescriptor.attributes[1].bufferIndex = 0
|
|
865
|
-
|
|
866
|
-
vertexDescriptor.layouts[0].stride = MemoryLayout<Float>.size * 4 // 2 floats for pos + 2 for texCoord
|
|
867
|
-
vertexDescriptor.layouts[0].stepFunction = .perVertex
|
|
868
|
-
|
|
869
|
-
let pipelineDescriptor = MTLRenderPipelineDescriptor()
|
|
870
|
-
pipelineDescriptor.vertexDescriptor = vertexDescriptor
|
|
871
|
-
pipelineDescriptor.vertexFunction = vertexFunction
|
|
872
|
-
pipelineDescriptor.fragmentFunction = fragmentFunction
|
|
873
|
-
|
|
874
|
-
pipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormat(rawValue: colorPixelFormat) ?? .bgra8Unorm
|
|
875
|
-
pipelineDescriptor.depthAttachmentPixelFormat = MTLPixelFormat(rawValue: depthStencilPixelFormat) ?? .depth32Float_stencil8
|
|
876
|
-
pipelineDescriptor.stencilAttachmentPixelFormat = MTLPixelFormat(rawValue: depthStencilPixelFormat) ?? .depth32Float_stencil8
|
|
877
|
-
|
|
878
|
-
pipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
|
|
879
|
-
pipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
|
|
880
|
-
pipelineDescriptor.colorAttachments[0].alphaBlendOperation = .add
|
|
881
|
-
pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
|
|
882
|
-
pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha
|
|
883
|
-
pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
|
|
884
|
-
pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
|
|
885
|
-
|
|
886
|
-
do {
|
|
887
|
-
self.pipelineState = try metalDevice.makeRenderPipelineState(descriptor: pipelineDescriptor)
|
|
888
|
-
} catch {
|
|
889
|
-
print("❌ [GridRenderLayer] Failed to create pipeline state: \(error)")
|
|
890
|
-
return
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
let dataSamplerDesc = MTLSamplerDescriptor()
|
|
894
|
-
dataSamplerDesc.minFilter = .nearest
|
|
895
|
-
dataSamplerDesc.magFilter = .nearest
|
|
896
|
-
self.dataSamplerState = metalDevice.makeSamplerState(descriptor: dataSamplerDesc)
|
|
897
|
-
|
|
898
|
-
let colormapSamplerDesc = MTLSamplerDescriptor()
|
|
899
|
-
colormapSamplerDesc.minFilter = .nearest
|
|
900
|
-
colormapSamplerDesc.magFilter = .nearest
|
|
901
|
-
colormapSamplerDesc.sAddressMode = .clampToEdge
|
|
902
|
-
self.colormapSamplerState = metalDevice.makeSamplerState(descriptor: colormapSamplerDesc)
|
|
903
|
-
|
|
904
|
-
print("🟢 [GridRenderLayer] Metal setup complete")
|
|
905
|
-
|
|
906
|
-
// Process any pending updates that came in before Metal was ready
|
|
907
|
-
if let pendingGeometry = pendingGeometryUpdate {
|
|
908
|
-
print("🟡 [GridRenderLayer] Processing pending geometry update")
|
|
909
|
-
updateGeometry(corners: pendingGeometry.corners, gridDef: pendingGeometry.gridDef)
|
|
910
|
-
pendingGeometryUpdate = nil
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
if let pendingColormap = pendingColormapUpdate {
|
|
914
|
-
print("🟡 [GridRenderLayer] Processing pending colormap update")
|
|
915
|
-
updateColormapTexture(colormapAsBase64: pendingColormap)
|
|
916
|
-
pendingColormapUpdate = nil
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
if let pendingData = pendingDataUpdate {
|
|
920
|
-
print("🟡 [GridRenderLayer] Processing pending data update")
|
|
921
|
-
updateDataTexture(data: pendingData.data, nx: pendingData.nx, ny: pendingData.ny,
|
|
922
|
-
scale: pendingData.scale, offset: pendingData.offset,
|
|
923
|
-
missing: pendingData.missing, scaleType: pendingData.scaleType)
|
|
924
|
-
pendingDataUpdate = nil
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
internal func internalRender(_ parameters: CustomLayerRenderParameters, mtlCommandBuffer: MTLCommandBuffer, mtlRenderPassDescriptor: MTLRenderPassDescriptor) {
|
|
928
|
-
guard isVisible,
|
|
929
|
-
let pipeline = pipelineState,
|
|
930
|
-
let vertices = vertexBuffer,
|
|
931
|
-
let indices = indexBuffer,
|
|
932
|
-
let dataTex = dataTexture,
|
|
933
|
-
let colormapTex = colormapTexture,
|
|
934
|
-
indexCount > 0,
|
|
935
|
-
let encoder = mtlCommandBuffer.makeRenderCommandEncoder(descriptor: mtlRenderPassDescriptor) else {
|
|
936
|
-
|
|
937
|
-
// OPTIMIZATION: Change log message to be more informative and less alarming.
|
|
938
|
-
// This is an expected state during initial load.
|
|
939
|
-
if (pipelineState != nil) { // Only log if Metal is set up
|
|
940
|
-
print("🟡 [GridRenderLayer] internalRender: Waiting for all resources to be ready before drawing.")
|
|
941
|
-
}
|
|
942
|
-
return
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
let needsLinear = (uniforms.smoothing != 0)
|
|
946
|
-
if isDataSamplerLinear != needsLinear {
|
|
947
|
-
let samplerDesc = MTLSamplerDescriptor()
|
|
948
|
-
samplerDesc.minFilter = needsLinear ? .linear : .nearest
|
|
949
|
-
samplerDesc.magFilter = needsLinear ? .linear : .nearest
|
|
950
|
-
dataSamplerState = device.makeSamplerState(descriptor: samplerDesc)
|
|
951
|
-
isDataSamplerLinear = needsLinear
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
// Apply zoom scale transformation
|
|
955
|
-
let zoom = parameters.zoom
|
|
956
|
-
let scale = Float(pow(2.0, zoom))
|
|
957
|
-
|
|
958
|
-
let matrixArray = parameters.projectionMatrix
|
|
959
|
-
var floatArray = matrixArray.map { $0.floatValue }
|
|
960
|
-
|
|
961
|
-
floatArray[0] *= scale // X scale
|
|
962
|
-
floatArray[1] *= scale // X rotation
|
|
963
|
-
floatArray[2] *= scale // X Z-component
|
|
964
|
-
floatArray[3] *= scale // X translation
|
|
965
|
-
floatArray[4] *= scale // Y rotation
|
|
966
|
-
floatArray[5] *= scale // Y scale
|
|
967
|
-
floatArray[6] *= scale // Y Z-component
|
|
968
|
-
floatArray[7] *= scale // Y translation
|
|
969
|
-
floatArray[8] *= scale // Z X-component
|
|
970
|
-
floatArray[9] *= scale // Z Y-component
|
|
971
|
-
floatArray[10] *= scale // Z scale
|
|
972
|
-
floatArray[11] *= scale // Z translation
|
|
973
|
-
|
|
974
|
-
let mvp = matrix_float4x4(
|
|
975
|
-
SIMD4<Float>(floatArray[0], floatArray[1], floatArray[2], floatArray[3]),
|
|
976
|
-
SIMD4<Float>(floatArray[4], floatArray[5], floatArray[6], floatArray[7]),
|
|
977
|
-
SIMD4<Float>(floatArray[8], floatArray[9], floatArray[10], floatArray[11]),
|
|
978
|
-
SIMD4<Float>(floatArray[12], floatArray[13], floatArray[14], floatArray[15])
|
|
979
|
-
)
|
|
980
|
-
|
|
981
|
-
// Add depth state
|
|
982
|
-
let depthStencilDescriptor = MTLDepthStencilDescriptor()
|
|
983
|
-
depthStencilDescriptor.depthCompareFunction = .always
|
|
984
|
-
depthStencilDescriptor.isDepthWriteEnabled = false
|
|
985
|
-
let depthStencilState = device.makeDepthStencilState(descriptor: depthStencilDescriptor)
|
|
986
|
-
|
|
987
|
-
encoder.setRenderPipelineState(pipeline)
|
|
988
|
-
encoder.setDepthStencilState(depthStencilState!)
|
|
989
|
-
encoder.setVertexBuffer(vertices, offset: 0, index: 0)
|
|
990
|
-
encoder.setVertexBytes([mvp], length: MemoryLayout<matrix_float4x4>.size, index: 1)
|
|
991
|
-
|
|
992
|
-
var mutableUniforms = uniforms
|
|
993
|
-
encoder.setFragmentBytes(&mutableUniforms, length: MemoryLayout<FragmentUniforms>.stride, index: 0)
|
|
994
|
-
encoder.setFragmentTexture(dataTex, index: 0)
|
|
995
|
-
encoder.setFragmentTexture(colormapTex, index: 1)
|
|
996
|
-
encoder.setFragmentSamplerState(dataSamplerState, index: 0)
|
|
997
|
-
encoder.setFragmentSamplerState(colormapSamplerState, index: 1)
|
|
998
|
-
|
|
999
|
-
encoder.drawIndexedPrimitives(type: .triangle, indexCount: indexCount, indexType: .uint16, indexBuffer: indices, indexBufferOffset: 0)
|
|
1000
|
-
|
|
1001
|
-
encoder.endEncoding()
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
deinit {
|
|
1005
|
-
print("🔴 [GridRenderLayer] deinit called for layer: \(id)")
|
|
1006
|
-
|
|
1007
|
-
// Clean up all resources
|
|
1008
|
-
frameCache.removeAll()
|
|
1009
|
-
vertexBuffer = nil
|
|
1010
|
-
indexBuffer = nil
|
|
1011
|
-
dataTexture = nil
|
|
1012
|
-
colormapTexture = nil
|
|
1013
|
-
device = nil
|
|
1014
|
-
commandQueue = nil
|
|
1015
|
-
pipelineState = nil
|
|
1016
|
-
dataSamplerState = nil
|
|
1017
|
-
colormapSamplerState = nil
|
|
1018
|
-
|
|
1019
|
-
// Break the reference cycle
|
|
1020
|
-
hostWrapper = nil
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
internal func internalRenderingWillEnd() {
|
|
1024
|
-
print("🟢 [GridRenderLayer] renderingWillEnd called")
|
|
1025
|
-
vertexBuffer = nil
|
|
1026
|
-
indexBuffer = nil
|
|
1027
|
-
dataTexture = nil
|
|
1028
|
-
colormapTexture = nil
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
extension GridRenderLayer {
|
|
1033
|
-
// Override to prevent KVC crashes during cleanup
|
|
1034
|
-
open override func value(forUndefinedKey key: String) -> Any? {
|
|
1035
|
-
print("⚠️ [GridRenderLayer] Attempted to access undefined key: \(key)")
|
|
1036
|
-
return nil
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
open override func setValue(_ value: Any?, forUndefinedKey key: String) {
|
|
1040
|
-
print("⚠️ [GridRenderLayer] Attempted to set undefined key: \(key)")
|
|
1041
|
-
// Silently ignore instead of crashing
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1
|
+
import Foundation
|
|
2
|
+
import MapboxMaps
|
|
3
|
+
import Metal
|
|
4
|
+
import libzstd
|
|
5
|
+
import simd
|
|
6
|
+
|
|
7
|
+
// MARK: - Swift-only wrapper for CustomLayerHost conformance
|
|
8
|
+
@objc internal final class GridRenderLayerHost: NSObject, CustomLayerHost {
|
|
9
|
+
weak var layer: GridRenderLayer?
|
|
10
|
+
|
|
11
|
+
init(layer: GridRenderLayer) {
|
|
12
|
+
self.layer = layer
|
|
13
|
+
super.init()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
func renderingWillStart(_ metalDevice: MTLDevice, colorPixelFormat: UInt, depthStencilPixelFormat: UInt) {
|
|
17
|
+
layer?.internalRenderingWillStart(metalDevice, colorPixelFormat: colorPixelFormat, depthStencilPixelFormat: depthStencilPixelFormat)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func render(_ parameters: CustomLayerRenderParameters, mtlCommandBuffer: MTLCommandBuffer, mtlRenderPassDescriptor: MTLRenderPassDescriptor) {
|
|
21
|
+
layer?.internalRender(parameters, mtlCommandBuffer: mtlCommandBuffer, mtlRenderPassDescriptor: mtlRenderPassDescriptor)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func renderingWillEnd() {
|
|
25
|
+
layer?.internalRenderingWillEnd()
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@objc(GridRenderLayer)
|
|
30
|
+
public class GridRenderLayer: NSObject {
|
|
31
|
+
|
|
32
|
+
// MARK: - Properties
|
|
33
|
+
|
|
34
|
+
public var id: String
|
|
35
|
+
@objc internal var hostWrapper: GridRenderLayerHost!
|
|
36
|
+
|
|
37
|
+
// Metal objects
|
|
38
|
+
private var device: MTLDevice!
|
|
39
|
+
private var commandQueue: MTLCommandQueue!
|
|
40
|
+
private var pipelineState: MTLRenderPipelineState!
|
|
41
|
+
private var vertexBuffer: MTLBuffer?
|
|
42
|
+
private var indexBuffer: MTLBuffer?
|
|
43
|
+
private var dataTexture: MTLTexture?
|
|
44
|
+
private var colormapTexture: MTLTexture?
|
|
45
|
+
private var dataSamplerState: MTLSamplerState!
|
|
46
|
+
private var colormapSamplerState: MTLSamplerState!
|
|
47
|
+
private var isDataSamplerLinear: Bool = false
|
|
48
|
+
|
|
49
|
+
private var pendingColormapUpdate: String?
|
|
50
|
+
private var pendingDataUpdate: (data: String, nx: NSNumber, ny: NSNumber, scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: String)?
|
|
51
|
+
private var pendingGeometryUpdate: (corners: [String: Any], gridDef: [String: Any])?
|
|
52
|
+
|
|
53
|
+
// Layer state
|
|
54
|
+
private var indexCount: Int = 0
|
|
55
|
+
private var uniforms = FragmentUniforms(
|
|
56
|
+
opacity: 1.0,
|
|
57
|
+
dataRange: SIMD2<Float>(0.0, 1.0),
|
|
58
|
+
scale: 1.0,
|
|
59
|
+
offset: 0.0,
|
|
60
|
+
missingQuantized: 127.0,
|
|
61
|
+
textureSize: SIMD2<Float>(0.0, 0.0),
|
|
62
|
+
smoothing: 1,
|
|
63
|
+
scaleType: 0,
|
|
64
|
+
isPtype: 0,
|
|
65
|
+
isMRMS: 0
|
|
66
|
+
)
|
|
67
|
+
private var isVisible = false
|
|
68
|
+
private var pendingActiveFrameKey: String?
|
|
69
|
+
private let inspectorCache = InspectorDataCache.shared
|
|
70
|
+
private struct FrameMetadata {
|
|
71
|
+
let texture: MTLTexture
|
|
72
|
+
let scale: Float
|
|
73
|
+
let offset: Float
|
|
74
|
+
let missing: Float
|
|
75
|
+
let scaleType: Int
|
|
76
|
+
let nx: Float
|
|
77
|
+
let ny: Float
|
|
78
|
+
let filePath: String
|
|
79
|
+
let originalScale: Float
|
|
80
|
+
let originalOffset: Float
|
|
81
|
+
}
|
|
82
|
+
private var frameCache: [String: FrameMetadata] = [:]
|
|
83
|
+
private let frameProcessingQueue = DispatchQueue(label: "com.aguacero.frame-processing", qos: .userInitiated, attributes: .concurrent)
|
|
84
|
+
private let semaphore = DispatchSemaphore(value: 8)
|
|
85
|
+
|
|
86
|
+
private struct VertexInfo {
|
|
87
|
+
var mercX: Float
|
|
88
|
+
var mercY: Float
|
|
89
|
+
var texU: Float
|
|
90
|
+
var texV: Float
|
|
91
|
+
var index: UInt16
|
|
92
|
+
}
|
|
93
|
+
@objc
|
|
94
|
+
public init(id: String) {
|
|
95
|
+
self.id = id
|
|
96
|
+
super.init()
|
|
97
|
+
self.hostWrapper = GridRenderLayerHost(layer: self)
|
|
98
|
+
print("🟢 [GridRenderLayer] Initialized with ID: \(id)")
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@objc public func getHostWrapper() -> Any {
|
|
102
|
+
return self.hostWrapper as Any
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// MARK: - Public Methods (called from Manager)
|
|
106
|
+
|
|
107
|
+
@objc public func setOpacity(value: Float) {
|
|
108
|
+
self.uniforms.opacity = value
|
|
109
|
+
print("🟢 [GridRenderLayer] Set opacity: \(value)")
|
|
110
|
+
// ADD THIS: Force the map to repaint to show the opacity change immediately.
|
|
111
|
+
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@objc public func setDataRange(value: [NSNumber]) {
|
|
115
|
+
self.uniforms.dataRange = SIMD2<Float>(value[0].floatValue, value[1].floatValue)
|
|
116
|
+
print("🟢 [GridRenderLayer] Set data range: \(value)")
|
|
117
|
+
// ADD THIS: Force the map to repaint to show the data range change immediately.
|
|
118
|
+
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@objc public func setSmoothing(value: Bool) {
|
|
122
|
+
self.uniforms.smoothing = value ? 1 : 0
|
|
123
|
+
print("🟢 [GridRenderLayer] Set smoothing: \(value)")
|
|
124
|
+
// ADD THIS: Force the map to repaint to show the smoothing change immediately.
|
|
125
|
+
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@objc(setIsMRMSWithIsMRMS:)
|
|
129
|
+
public func setIsMRMS(isMRMS: Bool) {
|
|
130
|
+
self.uniforms.isMRMS = isMRMS ? 1 : 0
|
|
131
|
+
print("🟢 [GridRenderLayer] Set isMRMS: \(isMRMS)")
|
|
132
|
+
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// ADD THIS METHOD
|
|
136
|
+
@objc(setVariableWithVariable:)
|
|
137
|
+
public func setVariable(variable: String) {
|
|
138
|
+
let isPtypeVar = (variable == "ptypeRefl" || variable == "ptypeRate")
|
|
139
|
+
self.uniforms.isPtype = isPtypeVar ? 1 : 0
|
|
140
|
+
print("🟢 [GridRenderLayer] Set variable: \(variable), isPtype set to: \(self.uniforms.isPtype)")
|
|
141
|
+
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@objc public func clear() {
|
|
145
|
+
self.isVisible = false
|
|
146
|
+
self.inspectorCache.clear()
|
|
147
|
+
print("🟢 [GridRenderLayer] Cleared")
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@objc public func updateDataParameters(scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: NSNumber) { // ADD scaleType parameter
|
|
151
|
+
// Update both the inspector cache AND the rendering uniforms
|
|
152
|
+
self.uniforms.scale = scale.floatValue
|
|
153
|
+
self.uniforms.offset = offset.floatValue
|
|
154
|
+
self.uniforms.missingQuantized = missing.floatValue
|
|
155
|
+
self.uniforms.scaleType = Int32(scaleType.intValue) // ADD THIS
|
|
156
|
+
|
|
157
|
+
inspectorCache.update(
|
|
158
|
+
data: inspectorCache.lastDecompressedData,
|
|
159
|
+
nx: inspectorCache.nx,
|
|
160
|
+
ny: inspectorCache.ny,
|
|
161
|
+
scale: scale.floatValue,
|
|
162
|
+
offset: offset.floatValue,
|
|
163
|
+
missing: missing.floatValue,
|
|
164
|
+
scaleType: scaleType.intValue // ADD THIS
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
print("🟢 [GridRenderLayer] Updated data parameters - scale: \(scale), offset: \(offset), missing: \(missing), scaleType: \(scaleType)")
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
@objc public func updateColormapTexture(colormapAsBase64: String) {
|
|
171
|
+
guard let device = self.device else {
|
|
172
|
+
pendingColormapUpdate = colormapAsBase64
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
guard let data = Data(base64Encoded: colormapAsBase64) else { return }
|
|
176
|
+
let textureDescriptor = MTLTextureDescriptor()
|
|
177
|
+
textureDescriptor.pixelFormat = .rgba8Unorm
|
|
178
|
+
textureDescriptor.width = 256
|
|
179
|
+
textureDescriptor.height = 1
|
|
180
|
+
textureDescriptor.usage = .shaderRead
|
|
181
|
+
guard let texture = device.makeTexture(descriptor: textureDescriptor) else { return }
|
|
182
|
+
texture.replace(
|
|
183
|
+
region: MTLRegionMake2D(0, 0, 256, 1),
|
|
184
|
+
mipmapLevel: 0,
|
|
185
|
+
withBytes: (data as NSData).bytes,
|
|
186
|
+
bytesPerRow: 256 * 4
|
|
187
|
+
)
|
|
188
|
+
self.colormapTexture = texture
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@objc(clearGpuCache)
|
|
192
|
+
public func clearGpuCache() {
|
|
193
|
+
frameProcessingQueue.async { [weak self] in
|
|
194
|
+
self?.frameCache.removeAll()
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private func processRawData(fileData: Data) -> Data? {
|
|
199
|
+
guard let decompressedDeltas = self.decompressZstd(data: fileData) else {
|
|
200
|
+
print("❌ [GridRenderLayer] Failed to decompress zstd data")
|
|
201
|
+
return nil
|
|
202
|
+
}
|
|
203
|
+
let reconstructedData = self.reconstructData(decompressedDeltas: decompressedDeltas)
|
|
204
|
+
let finalTextureBytes = self.transformData(finalData: reconstructedData)
|
|
205
|
+
return finalTextureBytes
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private func createTextureFromBytes(bytes: Data, nx: Int, ny: Int) -> MTLTexture? {
|
|
209
|
+
guard let device = self.device else { return nil }
|
|
210
|
+
let textureDescriptor = MTLTextureDescriptor()
|
|
211
|
+
textureDescriptor.pixelFormat = .r8Unorm
|
|
212
|
+
textureDescriptor.width = nx
|
|
213
|
+
textureDescriptor.height = ny
|
|
214
|
+
textureDescriptor.usage = .shaderRead
|
|
215
|
+
|
|
216
|
+
guard let texture = device.makeTexture(descriptor: textureDescriptor) else { return nil }
|
|
217
|
+
texture.replace(
|
|
218
|
+
region: MTLRegionMake2D(0, 0, nx, ny),
|
|
219
|
+
mipmapLevel: 0,
|
|
220
|
+
withBytes: (bytes as NSData).bytes,
|
|
221
|
+
bytesPerRow: nx
|
|
222
|
+
)
|
|
223
|
+
return texture
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private func updateInspectorCache(filePath: String, nx: Int, ny: Int, scale: Float, offset: Float, missing: Float, scaleType: Int) {
|
|
227
|
+
// This is now called from frameProcessingQueue, so we can do the work synchronously
|
|
228
|
+
guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else {
|
|
229
|
+
print("❌ [Inspector] FATAL: Failed to read file data from path.")
|
|
230
|
+
self.inspectorCache.clear()
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
print("💡 [Inspector] 2. Successfully read \(fileData.count) bytes from file.")
|
|
234
|
+
|
|
235
|
+
guard let decompressedDeltas = self.decompressZstd(data: fileData) else {
|
|
236
|
+
print("❌ [Inspector] FATAL: Failed to decompress Zstd data.")
|
|
237
|
+
self.inspectorCache.clear()
|
|
238
|
+
return
|
|
239
|
+
}
|
|
240
|
+
print("💡 [Inspector] 3. Successfully decompressed data.")
|
|
241
|
+
|
|
242
|
+
let reconstructedData = self.reconstructData(decompressedDeltas: decompressedDeltas)
|
|
243
|
+
print("💡 [Inspector] 4. Reconstructed data with \(reconstructedData.count) bytes.")
|
|
244
|
+
|
|
245
|
+
self.inspectorCache.update(
|
|
246
|
+
data: reconstructedData,
|
|
247
|
+
nx: nx,
|
|
248
|
+
ny: ny,
|
|
249
|
+
scale: scale,
|
|
250
|
+
offset: offset,
|
|
251
|
+
missing: missing,
|
|
252
|
+
scaleType: scaleType
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
print("💡 [Inspector] 5. ✅ Cache updated successfully with scaleType=\(scaleType)")
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
@objc(setActiveFrameWithCacheKey:)
|
|
259
|
+
public func setActiveFrame(cacheKey: String) {
|
|
260
|
+
if let frame = frameCache[cacheKey] {
|
|
261
|
+
print("⚡️ [GridRenderLayer] Cache HIT for key: \(cacheKey). Swapping texture.")
|
|
262
|
+
|
|
263
|
+
self.dataTexture = frame.texture
|
|
264
|
+
self.uniforms.scale = frame.scale
|
|
265
|
+
self.uniforms.offset = frame.offset
|
|
266
|
+
self.uniforms.missingQuantized = frame.missing
|
|
267
|
+
self.uniforms.textureSize = SIMD2<Float>(frame.nx, frame.ny)
|
|
268
|
+
self.uniforms.scaleType = Int32(frame.scaleType)
|
|
269
|
+
|
|
270
|
+
self.isVisible = true
|
|
271
|
+
self.pendingActiveFrameKey = nil
|
|
272
|
+
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
273
|
+
|
|
274
|
+
// Update inspector cache on background thread since we already have the frame data
|
|
275
|
+
frameProcessingQueue.async { [weak self] in
|
|
276
|
+
self?.updateInspectorCache(
|
|
277
|
+
filePath: frame.filePath,
|
|
278
|
+
nx: Int(frame.nx),
|
|
279
|
+
ny: Int(frame.ny),
|
|
280
|
+
scale: frame.scale,
|
|
281
|
+
offset: frame.offset,
|
|
282
|
+
missing: frame.missing,
|
|
283
|
+
scaleType: frame.scaleType
|
|
284
|
+
)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
} else {
|
|
288
|
+
print("⚠️ [GridRenderLayer] setActiveFrame cache MISS for key: \(cacheKey). Will apply when primed.")
|
|
289
|
+
self.pendingActiveFrameKey = cacheKey
|
|
290
|
+
self.isVisible = false
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
@objc(primeGpuCacheWithFrameInfo:)
|
|
294
|
+
public func primeGpuCache(frameInfo: [String: [String: Any]]) {
|
|
295
|
+
let group = DispatchGroup()
|
|
296
|
+
|
|
297
|
+
if (frameInfo.count > 1) {
|
|
298
|
+
print("🟡 [GridRenderLayer] Starting to prime \(frameInfo.count) textures with concurrent processing...")
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
for (cacheKey, info) in frameInfo {
|
|
302
|
+
group.enter()
|
|
303
|
+
|
|
304
|
+
frameProcessingQueue.async { [weak self] in
|
|
305
|
+
guard let self = self else {
|
|
306
|
+
group.leave()
|
|
307
|
+
return
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
self.semaphore.wait()
|
|
311
|
+
defer {
|
|
312
|
+
self.semaphore.signal()
|
|
313
|
+
group.leave()
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if self.frameCache[cacheKey] != nil { return }
|
|
317
|
+
|
|
318
|
+
guard let filePath = info["filePath"] as? String,
|
|
319
|
+
let nx = info["nx"] as? NSNumber,
|
|
320
|
+
let ny = info["ny"] as? NSNumber,
|
|
321
|
+
let scale = info["scale"] as? NSNumber,
|
|
322
|
+
let offset = info["offset"] as? NSNumber,
|
|
323
|
+
let missing = info["missing"] as? NSNumber,
|
|
324
|
+
let scaleTypeStr = info["scaleType"] as? String,
|
|
325
|
+
let originalScale = info["originalScale"] as? NSNumber,
|
|
326
|
+
let originalOffset = info["originalOffset"] as? NSNumber
|
|
327
|
+
else {
|
|
328
|
+
print("❌ [GridRenderLayer] Skipping prime for \(cacheKey), missing data.")
|
|
329
|
+
return
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Process data OFF the main thread
|
|
333
|
+
guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
|
|
334
|
+
let finalTextureBytes = self.processRawData(fileData: fileData)
|
|
335
|
+
else {
|
|
336
|
+
print("❌ [GridRenderLayer] Failed to process data for \(cacheKey)")
|
|
337
|
+
return
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Create texture on main thread
|
|
341
|
+
DispatchQueue.main.async { [weak self] in
|
|
342
|
+
guard let self = self else { return }
|
|
343
|
+
|
|
344
|
+
if let texture = self.createTextureFromBytes(bytes: finalTextureBytes, nx: nx.intValue, ny: ny.intValue) {
|
|
345
|
+
let metadata = FrameMetadata(
|
|
346
|
+
texture: texture,
|
|
347
|
+
scale: scale.floatValue,
|
|
348
|
+
offset: offset.floatValue,
|
|
349
|
+
missing: missing.floatValue,
|
|
350
|
+
scaleType: (scaleTypeStr == "sqrt") ? 1 : 0,
|
|
351
|
+
nx: nx.floatValue,
|
|
352
|
+
ny: ny.floatValue,
|
|
353
|
+
filePath: filePath,
|
|
354
|
+
originalScale: originalScale.floatValue,
|
|
355
|
+
originalOffset: originalOffset.floatValue
|
|
356
|
+
)
|
|
357
|
+
self.frameCache[cacheKey] = metadata
|
|
358
|
+
|
|
359
|
+
if let pendingKey = self.pendingActiveFrameKey, pendingKey == cacheKey {
|
|
360
|
+
print("👍 [GridRenderLayer] The pending frame is now ready. Activating it.")
|
|
361
|
+
self.setActiveFrame(cacheKey: pendingKey)
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
group.notify(queue: .main) {
|
|
369
|
+
if (frameInfo.count > 1) {
|
|
370
|
+
print("🎉 [GridRenderLayer] All \(frameInfo.count) frames have been processed and cached.")
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
@objc public func updateDataTexture(data: String, nx: NSNumber, ny: NSNumber, scale: NSNumber, offset: NSNumber, missing: NSNumber, scaleType: String) {
|
|
376
|
+
print("🚀 [GridRenderLayer] FAST LANE: updateDataTexture called for initial frame...")
|
|
377
|
+
|
|
378
|
+
let filePath = data
|
|
379
|
+
|
|
380
|
+
frameProcessingQueue.async { [weak self] in
|
|
381
|
+
guard let self = self else { return }
|
|
382
|
+
|
|
383
|
+
guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
|
|
384
|
+
let finalTextureBytes = self.processRawData(fileData: fileData)
|
|
385
|
+
else {
|
|
386
|
+
print("❌ [GridRenderLayer] FAST LANE: Failed to process initial frame data.")
|
|
387
|
+
return
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
DispatchQueue.main.async { [weak self] in
|
|
391
|
+
guard let self = self, let texture = self.createTextureFromBytes(bytes: finalTextureBytes, nx: nx.intValue, ny: ny.intValue) else {
|
|
392
|
+
return
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
self.dataTexture = texture
|
|
396
|
+
self.uniforms.scale = scale.floatValue
|
|
397
|
+
self.uniforms.offset = offset.floatValue
|
|
398
|
+
self.uniforms.missingQuantized = missing.floatValue
|
|
399
|
+
self.uniforms.scaleType = Int32((scaleType == "sqrt") ? 1 : 0)
|
|
400
|
+
self.uniforms.textureSize = SIMD2<Float>(nx.floatValue, ny.floatValue)
|
|
401
|
+
|
|
402
|
+
self.isVisible = true
|
|
403
|
+
print("✅ [GridRenderLayer] FAST LANE: Initial frame processed and displayed.")
|
|
404
|
+
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
405
|
+
|
|
406
|
+
self.updateInspectorCache(
|
|
407
|
+
filePath: filePath,
|
|
408
|
+
nx: nx.intValue,
|
|
409
|
+
ny: ny.intValue,
|
|
410
|
+
scale: scale.floatValue,
|
|
411
|
+
offset: offset.floatValue,
|
|
412
|
+
missing: missing.floatValue,
|
|
413
|
+
scaleType: (scaleType == "sqrt") ? 1 : 0
|
|
414
|
+
)
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
@objc public func updateGeometry(corners: [String: Any], gridDef: [String: Any]) {
|
|
420
|
+
guard self.device != nil else {
|
|
421
|
+
print("⚠️ [GridRenderLayer] Device not ready yet, storing geometry for later")
|
|
422
|
+
pendingGeometryUpdate = (corners: corners, gridDef: gridDef)
|
|
423
|
+
return
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
print(" Device is ready, processing geometry immediately")
|
|
427
|
+
|
|
428
|
+
DispatchQueue.global(qos: .userInitiated).async {
|
|
429
|
+
print(" 🔄 Generating geometry on background thread")
|
|
430
|
+
|
|
431
|
+
var vertices: [Float] = []
|
|
432
|
+
var indices: [UInt16] = []
|
|
433
|
+
|
|
434
|
+
self.generateGeometryData(gridDef: gridDef, vertices: &vertices, indices: &indices)
|
|
435
|
+
|
|
436
|
+
if vertices.isEmpty || indices.isEmpty {
|
|
437
|
+
print("❌ [GridRenderLayer] No geometry generated")
|
|
438
|
+
return
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
self.indexCount = indices.count
|
|
442
|
+
|
|
443
|
+
DispatchQueue.main.async {
|
|
444
|
+
print(" 🎨 Creating buffers on main thread")
|
|
445
|
+
|
|
446
|
+
self.vertexBuffer = self.device.makeBuffer(bytes: vertices, length: vertices.count * MemoryLayout<Float>.size, options: [])
|
|
447
|
+
self.indexBuffer = self.device.makeBuffer(bytes: indices, length: indices.count * MemoryLayout<UInt16>.size, options: [])
|
|
448
|
+
|
|
449
|
+
print("🟢 [GridRenderLayer] Geometry updated: \(vertices.count/4) vertices, \(indices.count/3) triangles")
|
|
450
|
+
print(" vertexBuffer: \(self.vertexBuffer != nil)")
|
|
451
|
+
print(" indexBuffer: \(self.indexBuffer != nil)")
|
|
452
|
+
print(" indexCount: \(self.indexCount)")
|
|
453
|
+
|
|
454
|
+
NotificationCenter.default.post(name: NSNotification.Name("TriggerMapRepaint"), object: nil)
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
private func decompressZstd(data: Data) -> Data? {
|
|
460
|
+
let decompressedSize = data.withUnsafeBytes { ptr in
|
|
461
|
+
ZSTD_getFrameContentSize(ptr.baseAddress, data.count)
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
guard Int64(bitPattern: decompressedSize) > 0 else {
|
|
465
|
+
print("❌ [GridRenderLayer] Could not determine decompressed size")
|
|
466
|
+
return nil
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
var decompressedData = Data(count: Int(decompressedSize))
|
|
470
|
+
|
|
471
|
+
let result = decompressedData.withUnsafeMutableBytes { decompressedPtr -> Int in
|
|
472
|
+
data.withUnsafeBytes { compressedPtr -> Int in
|
|
473
|
+
let returnValue = ZSTD_decompress(
|
|
474
|
+
decompressedPtr.baseAddress,
|
|
475
|
+
Int(decompressedSize),
|
|
476
|
+
compressedPtr.baseAddress,
|
|
477
|
+
data.count
|
|
478
|
+
)
|
|
479
|
+
return Int(returnValue)
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
guard result > 0 && result == decompressedData.count else {
|
|
484
|
+
if result > 0 {
|
|
485
|
+
let size_t_result = size_t(result)
|
|
486
|
+
if let errorName = ZSTD_getErrorName(size_t_result) {
|
|
487
|
+
let errorString = String(cString: errorName)
|
|
488
|
+
print("❌ [GridRenderLayer] Zstd decompression failed: \(errorString)")
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return nil
|
|
492
|
+
}
|
|
493
|
+
return decompressedData
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
// MARK: - Private Helper Methods
|
|
497
|
+
|
|
498
|
+
private func reconstructData(decompressedDeltas: Data) -> Data {
|
|
499
|
+
guard !decompressedDeltas.isEmpty else { return Data() }
|
|
500
|
+
var reconstructedData = Data(count: decompressedDeltas.count)
|
|
501
|
+
reconstructedData[0] = decompressedDeltas[0]
|
|
502
|
+
for i in 1..<decompressedDeltas.count {
|
|
503
|
+
reconstructedData[i] = UInt8(Int8(bitPattern: reconstructedData[i-1]) &+ Int8(bitPattern: decompressedDeltas[i]))
|
|
504
|
+
}
|
|
505
|
+
return reconstructedData
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
private func transformData(finalData: Data) -> Data {
|
|
509
|
+
var transformedData = Data(count: finalData.count)
|
|
510
|
+
for i in 0..<finalData.count {
|
|
511
|
+
transformedData[i] = UInt8(Int16(Int8(bitPattern: finalData[i])) + 128)
|
|
512
|
+
}
|
|
513
|
+
return transformedData
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
private func isLCCType(gridDef: [String: Any]) -> Bool {
|
|
517
|
+
if let type = gridDef["type"] as? String {
|
|
518
|
+
return type == "lambert_conformal_conic"
|
|
519
|
+
}
|
|
520
|
+
return false
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
private func generateLCCGeometry(gridDef: [String: Any], vertices: inout [Float], indices: inout [UInt16]) {
|
|
524
|
+
guard let gridParams = gridDef["grid_params"] as? [String: Any],
|
|
525
|
+
let projParams = gridDef["proj_params"] as? [String: Any],
|
|
526
|
+
let nx = gridParams["nx"] as? Int,
|
|
527
|
+
let ny = gridParams["ny"] as? Int,
|
|
528
|
+
let dx = gridParams["dx"] as? Double,
|
|
529
|
+
let dy = gridParams["dy"] as? Double,
|
|
530
|
+
let x_origin = gridParams["x_origin"] as? Double,
|
|
531
|
+
let y_origin = gridParams["y_origin"] as? Double else {
|
|
532
|
+
return
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
let subdivisions = 60
|
|
536
|
+
let TILE_SIZE: Double = 512.0
|
|
537
|
+
|
|
538
|
+
let x_min = x_origin
|
|
539
|
+
let y_max = y_origin
|
|
540
|
+
let x_max = x_origin + Double(nx - 1) * dx
|
|
541
|
+
let y_min = y_origin + Double(ny - 1) * dy
|
|
542
|
+
|
|
543
|
+
var vertexGrid: [[VertexInfo?]] = Array(repeating: Array(repeating: nil, count: subdivisions + 1), count: subdivisions + 1)
|
|
544
|
+
var validVertexCount: UInt16 = 0
|
|
545
|
+
|
|
546
|
+
// Generate vertices
|
|
547
|
+
for row in 0...subdivisions {
|
|
548
|
+
for col in 0...subdivisions {
|
|
549
|
+
let t_x = Double(col) / Double(subdivisions)
|
|
550
|
+
let t_y = Double(row) / Double(subdivisions)
|
|
551
|
+
|
|
552
|
+
let proj_x = x_min + t_x * (x_max - x_min)
|
|
553
|
+
let proj_y = y_max + t_y * (y_min - y_max)
|
|
554
|
+
|
|
555
|
+
// Convert LCC projection coordinates to lat/lon
|
|
556
|
+
if let (lon, lat) = lccToLonLat(i: proj_x, j: proj_y, gridDef: gridDef) {
|
|
557
|
+
// Convert lat/lon to Mercator
|
|
558
|
+
let mercX_normalized = (lon + 180.0) / 360.0
|
|
559
|
+
let clampedLat = max(-85.05112878, min(85.05112878, lat))
|
|
560
|
+
let sinLatitude = sin(clampedLat * .pi / 180.0)
|
|
561
|
+
let mercY_normalized = 0.5 - log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * .pi)
|
|
562
|
+
|
|
563
|
+
let mercX = mercX_normalized * TILE_SIZE
|
|
564
|
+
let mercY = mercY_normalized * TILE_SIZE
|
|
565
|
+
|
|
566
|
+
// Check for invalid values
|
|
567
|
+
if !mercX.isFinite || !mercY.isFinite {
|
|
568
|
+
vertexGrid[row][col] = nil
|
|
569
|
+
continue
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
let tex_u = Float(t_x)
|
|
573
|
+
let tex_v = Float(t_y)
|
|
574
|
+
|
|
575
|
+
let vInfo = VertexInfo(
|
|
576
|
+
mercX: Float(mercX),
|
|
577
|
+
mercY: Float(mercY),
|
|
578
|
+
texU: tex_u,
|
|
579
|
+
texV: tex_v,
|
|
580
|
+
index: validVertexCount
|
|
581
|
+
)
|
|
582
|
+
|
|
583
|
+
vertexGrid[row][col] = vInfo
|
|
584
|
+
|
|
585
|
+
vertices.append(Float(mercX))
|
|
586
|
+
vertices.append(Float(mercY))
|
|
587
|
+
vertices.append(tex_u)
|
|
588
|
+
vertices.append(tex_v)
|
|
589
|
+
|
|
590
|
+
validVertexCount += 1
|
|
591
|
+
} else {
|
|
592
|
+
vertexGrid[row][col] = nil
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if vertices.isEmpty {
|
|
598
|
+
print("❌ [LCC Geometry] No valid vertices generated")
|
|
599
|
+
return
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Generate indices
|
|
603
|
+
for row in 0..<subdivisions {
|
|
604
|
+
for col in 0..<subdivisions {
|
|
605
|
+
guard let topLeft = vertexGrid[row][col],
|
|
606
|
+
let topRight = vertexGrid[row][col + 1],
|
|
607
|
+
let bottomLeft = vertexGrid[row + 1][col],
|
|
608
|
+
let bottomRight = vertexGrid[row + 1][col + 1] else {
|
|
609
|
+
continue
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
indices.append(topLeft.index)
|
|
613
|
+
indices.append(bottomLeft.index)
|
|
614
|
+
indices.append(topRight.index)
|
|
615
|
+
|
|
616
|
+
indices.append(topRight.index)
|
|
617
|
+
indices.append(bottomLeft.index)
|
|
618
|
+
indices.append(bottomRight.index)
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
private func lccToLonLat(i: Double, j: Double, gridDef: [String: Any]) -> (lon: Double, lat: Double)? {
|
|
624
|
+
guard let projParams = gridDef["proj_params"] as? [String: Any],
|
|
625
|
+
let lat_0 = (projParams["lat_0"] as? NSNumber)?.doubleValue,
|
|
626
|
+
let lon_0 = (projParams["lon_0"] as? NSNumber)?.doubleValue,
|
|
627
|
+
let lat_1 = (projParams["lat_1"] as? NSNumber)?.doubleValue,
|
|
628
|
+
let lat_2 = (projParams["lat_2"] as? NSNumber)?.doubleValue,
|
|
629
|
+
let r_earth = (projParams["R"] as? NSNumber)?.doubleValue else {
|
|
630
|
+
print("❌ [LCC Geometry] Failed to extract LCC parameters.")
|
|
631
|
+
return nil
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
let π = Double.pi
|
|
635
|
+
let toRad = π / 180.0
|
|
636
|
+
let toDeg = 180.0 / π
|
|
637
|
+
|
|
638
|
+
let lat1_rad = lat_1 * toRad
|
|
639
|
+
let lat2_rad = lat_2 * toRad
|
|
640
|
+
let lat0_rad = lat_0 * toRad
|
|
641
|
+
let lon0_rad = lon_0 * toRad
|
|
642
|
+
|
|
643
|
+
let n: Double
|
|
644
|
+
if abs(lat_1 - lat_2) < 1e-10 {
|
|
645
|
+
n = sin(lat1_rad)
|
|
646
|
+
} else {
|
|
647
|
+
n = log(cos(lat1_rad) / cos(lat2_rad)) / log(tan(π/4.0 + lat2_rad/2.0) / tan(π/4.0 + lat1_rad/2.0))
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
let F = cos(lat1_rad) * pow(tan(π/4.0 + lat1_rad/2.0), n) / n
|
|
651
|
+
let rho_0 = r_earth * F * pow(tan(π/4.0 + lat0_rad/2.0), -n)
|
|
652
|
+
|
|
653
|
+
let x = i
|
|
654
|
+
let y = j
|
|
655
|
+
|
|
656
|
+
let rho = sqrt(x * x + (rho_0 - y) * (rho_0 - y))
|
|
657
|
+
if rho < 1e-10 {
|
|
658
|
+
return (lon: lon_0, lat: lat_0)
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
let theta = atan2(x, rho_0 - y)
|
|
662
|
+
|
|
663
|
+
let lon = lon0_rad + theta / n
|
|
664
|
+
let lat = 2.0 * atan(pow(r_earth * F / rho, 1.0 / n)) - π/2.0
|
|
665
|
+
|
|
666
|
+
let lonDeg = lon * toDeg
|
|
667
|
+
let latDeg = lat * toDeg
|
|
668
|
+
|
|
669
|
+
if !lonDeg.isFinite || !latDeg.isFinite {
|
|
670
|
+
return nil
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
return (lon: lonDeg, lat: latDeg)
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
private func generateGeometryData(gridDef: [String: Any], vertices: inout [Float], indices: inout [UInt16]) {
|
|
677
|
+
guard let gridParams = gridDef["grid_params"] as? [String: Any] else {
|
|
678
|
+
print("❌ [generateGeometryData] No grid_params found")
|
|
679
|
+
return
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// Check grid type
|
|
683
|
+
let isGFS = isGFSType(gridParams: gridParams)
|
|
684
|
+
let isLCC = isLCCType(gridDef: gridDef)
|
|
685
|
+
|
|
686
|
+
if isGFS {
|
|
687
|
+
// GFS path remains unchanged
|
|
688
|
+
let subdivisions = 120
|
|
689
|
+
let verticesPerRow = (subdivisions * 3) + 1
|
|
690
|
+
let TILE_SIZE: Double = 512.0
|
|
691
|
+
|
|
692
|
+
for row in 0...subdivisions {
|
|
693
|
+
for col in 0...(subdivisions * 3) {
|
|
694
|
+
let v_interp = Float(row) / Float(subdivisions)
|
|
695
|
+
let u_interp = Float(col) / Float(subdivisions)
|
|
696
|
+
let lon = -540.0 + Double(u_interp) * 1080.0
|
|
697
|
+
let lat = -90.0 + Double(v_interp) * 180.0
|
|
698
|
+
|
|
699
|
+
let merc = lonLatToMercator(lon: lon, lat: lat, tileSize: TILE_SIZE)
|
|
700
|
+
vertices.append(contentsOf: [merc.x, merc.y])
|
|
701
|
+
|
|
702
|
+
let tex_u = Float((lon + 180.0) / 360.0)
|
|
703
|
+
let tex_v = 1.0 - v_interp
|
|
704
|
+
vertices.append(contentsOf: [tex_u, tex_v])
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
for row in 0..<subdivisions {
|
|
709
|
+
for col in 0..<(subdivisions * 3) {
|
|
710
|
+
let tl = UInt16(row * verticesPerRow + col)
|
|
711
|
+
let tr = tl + 1
|
|
712
|
+
let bl = UInt16((row + 1) * verticesPerRow + col)
|
|
713
|
+
let br = bl + 1
|
|
714
|
+
indices.append(contentsOf: [tl, bl, tr, tr, bl, br])
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
return
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if isLCC {
|
|
721
|
+
print("🗺️ [generateGeometryData] Using LCC projection path")
|
|
722
|
+
generateLCCGeometry(gridDef: gridDef, vertices: &vertices, indices: &indices)
|
|
723
|
+
return
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// Generic Grid Path (MRMS, regional models, etc.)
|
|
727
|
+
print("🗺️ [generateGeometryData] Using generic regional grid path")
|
|
728
|
+
|
|
729
|
+
let nx = gridParams["nx"] as? Int ?? 0
|
|
730
|
+
let ny = gridParams["ny"] as? Int ?? 0
|
|
731
|
+
let lon_first = gridParams["lon_first"] as? Double ?? 0.0
|
|
732
|
+
let lat_first = gridParams["lat_first"] as? Double ?? 90.0
|
|
733
|
+
let dx = gridParams["dx_degrees"] as? Double ?? 0.0
|
|
734
|
+
let dy = gridParams["dy_degrees"] as? Double ?? 0.0
|
|
735
|
+
let lon_last = gridParams["lon_last"] as? Double ?? (lon_first + Double(nx - 1) * dx)
|
|
736
|
+
let lat_last = gridParams["lat_last"] as? Double ?? (lat_first + Double(ny - 1) * dy)
|
|
737
|
+
|
|
738
|
+
let lat_span = lat_last - lat_first
|
|
739
|
+
let isSouthToNorth = lat_span > 0
|
|
740
|
+
|
|
741
|
+
let data_lon_first_180 = lon_first > 180 ? lon_first - 360 : lon_first
|
|
742
|
+
let data_lon_last_180 = lon_last > 180 ? lon_last - 360 : lon_last
|
|
743
|
+
let data_lon_range = data_lon_last_180 - data_lon_first_180
|
|
744
|
+
|
|
745
|
+
let subdivisions_x = 120
|
|
746
|
+
let subdivisions_y = 60
|
|
747
|
+
let verticesPerRow = subdivisions_x + 1
|
|
748
|
+
let TILE_SIZE: Double = 512.0
|
|
749
|
+
|
|
750
|
+
let worldCopies = (data_lon_range > 300) ? [-1, 0, 1] : [0]
|
|
751
|
+
|
|
752
|
+
for world_copy in worldCopies {
|
|
753
|
+
let vertexStartIndex = UInt16(vertices.count / 4)
|
|
754
|
+
let lon_offset = Double(world_copy) * 360.0
|
|
755
|
+
|
|
756
|
+
for row in 0...subdivisions_y {
|
|
757
|
+
for col in 0...subdivisions_x {
|
|
758
|
+
let v_interp = Float(row) / Float(subdivisions_y)
|
|
759
|
+
let u_interp = Float(col) / Float(subdivisions_x)
|
|
760
|
+
|
|
761
|
+
let vertex_lon = data_lon_first_180 + (Double(u_interp) * data_lon_range)
|
|
762
|
+
let vertex_lat = lat_first + (Double(v_interp) * lat_span)
|
|
763
|
+
|
|
764
|
+
let mercX_normalized = ((vertex_lon + lon_offset) + 180.0) / 360.0
|
|
765
|
+
let clampedLat = max(-85.05112878, min(85.05112878, vertex_lat))
|
|
766
|
+
let sinLatitude = sin(clampedLat * .pi / 180.0)
|
|
767
|
+
let mercY_normalized = 0.5 - log((1 + sinLatitude) / (1 - sinLatitude)) / (4 * .pi)
|
|
768
|
+
let mercX = mercX_normalized * TILE_SIZE
|
|
769
|
+
let mercY = mercY_normalized * TILE_SIZE
|
|
770
|
+
|
|
771
|
+
vertices.append(contentsOf: [Float(mercX), Float(mercY)])
|
|
772
|
+
|
|
773
|
+
let tex_u = u_interp
|
|
774
|
+
let tex_v = isSouthToNorth ? (1.0 - v_interp) : v_interp
|
|
775
|
+
|
|
776
|
+
vertices.append(contentsOf: [tex_u, tex_v])
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
for row in 0..<UInt16(subdivisions_y) {
|
|
781
|
+
for col in 0..<UInt16(subdivisions_x) {
|
|
782
|
+
let tl = vertexStartIndex + row * UInt16(verticesPerRow) + col
|
|
783
|
+
let tr = tl + 1
|
|
784
|
+
let bl = vertexStartIndex + (row + 1) * UInt16(verticesPerRow) + col
|
|
785
|
+
let br = bl + 1
|
|
786
|
+
|
|
787
|
+
if isSouthToNorth {
|
|
788
|
+
indices.append(contentsOf: [tl, bl, tr, tr, bl, br])
|
|
789
|
+
} else {
|
|
790
|
+
indices.append(contentsOf: [tl, tr, bl, bl, tr, br])
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
private func isGFSType(gridParams: [String: Any]) -> Bool {
|
|
798
|
+
return (gridParams["lon_first"] as? Double) == 0.0 &&
|
|
799
|
+
abs((gridParams["lat_first"] as? Double) ?? -1) == 90.0
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
private func lonLatToMercator(lon: Double, lat: Double, tileSize: Double) -> (x: Float, y: Float) {
|
|
803
|
+
let mercX_normalized = (lon + 180.0) / 360.0
|
|
804
|
+
let clampedLat = max(-85.05112878, min(85.05112878, lat))
|
|
805
|
+
let sinLatitude = sin(clampedLat * .pi / 180.0)
|
|
806
|
+
let mercY_normalized = 0.5 - log((1.0 + sinLatitude) / (1.0 - sinLatitude)) / (4.0 * .pi)
|
|
807
|
+
|
|
808
|
+
return (x: Float(mercX_normalized * tileSize), y: Float(mercY_normalized * tileSize))
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// MARK: - Internal methods for CustomLayerHost (called by wrapper)
|
|
812
|
+
|
|
813
|
+
internal func internalRenderingWillStart(_ metalDevice: MTLDevice, colorPixelFormat: UInt, depthStencilPixelFormat: UInt) {
|
|
814
|
+
print("🟢 [GridRenderLayer] renderingWillStart called")
|
|
815
|
+
self.device = metalDevice
|
|
816
|
+
self.commandQueue = metalDevice.makeCommandQueue()
|
|
817
|
+
|
|
818
|
+
let bundle = Bundle(for: GridRenderLayer.self)
|
|
819
|
+
|
|
820
|
+
// Determine if we're running on simulator or device
|
|
821
|
+
#if targetEnvironment(simulator)
|
|
822
|
+
let metallibName = "Shaders-simulator"
|
|
823
|
+
#else
|
|
824
|
+
let metallibName = "Shaders-device"
|
|
825
|
+
#endif
|
|
826
|
+
|
|
827
|
+
// Try to load pre-compiled metallib for the current platform
|
|
828
|
+
let defaultLibrary: MTLLibrary?
|
|
829
|
+
if let metallibUrl = bundle.url(forResource: metallibName, withExtension: "metallib"),
|
|
830
|
+
let library = try? metalDevice.makeLibrary(URL: metallibUrl) {
|
|
831
|
+
print("✅ [GridRenderLayer] Loaded pre-compiled metallib (\(metallibName))")
|
|
832
|
+
defaultLibrary = library
|
|
833
|
+
}
|
|
834
|
+
// Fall back to compiling from .metal source (for development with npm link)
|
|
835
|
+
else if let metalUrl = bundle.url(forResource: "Shaders", withExtension: "metal"),
|
|
836
|
+
let source = try? String(contentsOf: metalUrl),
|
|
837
|
+
let library = try? metalDevice.makeLibrary(source: source, options: nil) {
|
|
838
|
+
print("✅ [GridRenderLayer] Compiled Metal shader from source")
|
|
839
|
+
defaultLibrary = library
|
|
840
|
+
}
|
|
841
|
+
// Neither worked
|
|
842
|
+
else {
|
|
843
|
+
print("❌ [GridRenderLayer] Could not find or compile Metal shaders")
|
|
844
|
+
print(" Bundle path: \(bundle.bundlePath)")
|
|
845
|
+
return
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
guard let library = defaultLibrary else {
|
|
849
|
+
print("❌ [GridRenderLayer] Failed to create Metal library")
|
|
850
|
+
return
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
let vertexFunction = library.makeFunction(name: "vertex_main")
|
|
854
|
+
let fragmentFunction = library.makeFunction(name: "fragment_main")
|
|
855
|
+
|
|
856
|
+
// Set up vertex descriptor
|
|
857
|
+
let vertexDescriptor = MTLVertexDescriptor()
|
|
858
|
+
vertexDescriptor.attributes[0].format = .float2 // position (x, y)
|
|
859
|
+
vertexDescriptor.attributes[0].offset = 0
|
|
860
|
+
vertexDescriptor.attributes[0].bufferIndex = 0
|
|
861
|
+
|
|
862
|
+
vertexDescriptor.attributes[1].format = .float2 // texCoord (u, v)
|
|
863
|
+
vertexDescriptor.attributes[1].offset = MemoryLayout<Float>.size * 2
|
|
864
|
+
vertexDescriptor.attributes[1].bufferIndex = 0
|
|
865
|
+
|
|
866
|
+
vertexDescriptor.layouts[0].stride = MemoryLayout<Float>.size * 4 // 2 floats for pos + 2 for texCoord
|
|
867
|
+
vertexDescriptor.layouts[0].stepFunction = .perVertex
|
|
868
|
+
|
|
869
|
+
let pipelineDescriptor = MTLRenderPipelineDescriptor()
|
|
870
|
+
pipelineDescriptor.vertexDescriptor = vertexDescriptor
|
|
871
|
+
pipelineDescriptor.vertexFunction = vertexFunction
|
|
872
|
+
pipelineDescriptor.fragmentFunction = fragmentFunction
|
|
873
|
+
|
|
874
|
+
pipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormat(rawValue: colorPixelFormat) ?? .bgra8Unorm
|
|
875
|
+
pipelineDescriptor.depthAttachmentPixelFormat = MTLPixelFormat(rawValue: depthStencilPixelFormat) ?? .depth32Float_stencil8
|
|
876
|
+
pipelineDescriptor.stencilAttachmentPixelFormat = MTLPixelFormat(rawValue: depthStencilPixelFormat) ?? .depth32Float_stencil8
|
|
877
|
+
|
|
878
|
+
pipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
|
|
879
|
+
pipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
|
|
880
|
+
pipelineDescriptor.colorAttachments[0].alphaBlendOperation = .add
|
|
881
|
+
pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
|
|
882
|
+
pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .sourceAlpha
|
|
883
|
+
pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
|
|
884
|
+
pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha
|
|
885
|
+
|
|
886
|
+
do {
|
|
887
|
+
self.pipelineState = try metalDevice.makeRenderPipelineState(descriptor: pipelineDescriptor)
|
|
888
|
+
} catch {
|
|
889
|
+
print("❌ [GridRenderLayer] Failed to create pipeline state: \(error)")
|
|
890
|
+
return
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
let dataSamplerDesc = MTLSamplerDescriptor()
|
|
894
|
+
dataSamplerDesc.minFilter = .nearest
|
|
895
|
+
dataSamplerDesc.magFilter = .nearest
|
|
896
|
+
self.dataSamplerState = metalDevice.makeSamplerState(descriptor: dataSamplerDesc)
|
|
897
|
+
|
|
898
|
+
let colormapSamplerDesc = MTLSamplerDescriptor()
|
|
899
|
+
colormapSamplerDesc.minFilter = .nearest
|
|
900
|
+
colormapSamplerDesc.magFilter = .nearest
|
|
901
|
+
colormapSamplerDesc.sAddressMode = .clampToEdge
|
|
902
|
+
self.colormapSamplerState = metalDevice.makeSamplerState(descriptor: colormapSamplerDesc)
|
|
903
|
+
|
|
904
|
+
print("🟢 [GridRenderLayer] Metal setup complete")
|
|
905
|
+
|
|
906
|
+
// Process any pending updates that came in before Metal was ready
|
|
907
|
+
if let pendingGeometry = pendingGeometryUpdate {
|
|
908
|
+
print("🟡 [GridRenderLayer] Processing pending geometry update")
|
|
909
|
+
updateGeometry(corners: pendingGeometry.corners, gridDef: pendingGeometry.gridDef)
|
|
910
|
+
pendingGeometryUpdate = nil
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
if let pendingColormap = pendingColormapUpdate {
|
|
914
|
+
print("🟡 [GridRenderLayer] Processing pending colormap update")
|
|
915
|
+
updateColormapTexture(colormapAsBase64: pendingColormap)
|
|
916
|
+
pendingColormapUpdate = nil
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
if let pendingData = pendingDataUpdate {
|
|
920
|
+
print("🟡 [GridRenderLayer] Processing pending data update")
|
|
921
|
+
updateDataTexture(data: pendingData.data, nx: pendingData.nx, ny: pendingData.ny,
|
|
922
|
+
scale: pendingData.scale, offset: pendingData.offset,
|
|
923
|
+
missing: pendingData.missing, scaleType: pendingData.scaleType)
|
|
924
|
+
pendingDataUpdate = nil
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
internal func internalRender(_ parameters: CustomLayerRenderParameters, mtlCommandBuffer: MTLCommandBuffer, mtlRenderPassDescriptor: MTLRenderPassDescriptor) {
|
|
928
|
+
guard isVisible,
|
|
929
|
+
let pipeline = pipelineState,
|
|
930
|
+
let vertices = vertexBuffer,
|
|
931
|
+
let indices = indexBuffer,
|
|
932
|
+
let dataTex = dataTexture,
|
|
933
|
+
let colormapTex = colormapTexture,
|
|
934
|
+
indexCount > 0,
|
|
935
|
+
let encoder = mtlCommandBuffer.makeRenderCommandEncoder(descriptor: mtlRenderPassDescriptor) else {
|
|
936
|
+
|
|
937
|
+
// OPTIMIZATION: Change log message to be more informative and less alarming.
|
|
938
|
+
// This is an expected state during initial load.
|
|
939
|
+
if (pipelineState != nil) { // Only log if Metal is set up
|
|
940
|
+
print("🟡 [GridRenderLayer] internalRender: Waiting for all resources to be ready before drawing.")
|
|
941
|
+
}
|
|
942
|
+
return
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
let needsLinear = (uniforms.smoothing != 0)
|
|
946
|
+
if isDataSamplerLinear != needsLinear {
|
|
947
|
+
let samplerDesc = MTLSamplerDescriptor()
|
|
948
|
+
samplerDesc.minFilter = needsLinear ? .linear : .nearest
|
|
949
|
+
samplerDesc.magFilter = needsLinear ? .linear : .nearest
|
|
950
|
+
dataSamplerState = device.makeSamplerState(descriptor: samplerDesc)
|
|
951
|
+
isDataSamplerLinear = needsLinear
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// Apply zoom scale transformation
|
|
955
|
+
let zoom = parameters.zoom
|
|
956
|
+
let scale = Float(pow(2.0, zoom))
|
|
957
|
+
|
|
958
|
+
let matrixArray = parameters.projectionMatrix
|
|
959
|
+
var floatArray = matrixArray.map { $0.floatValue }
|
|
960
|
+
|
|
961
|
+
floatArray[0] *= scale // X scale
|
|
962
|
+
floatArray[1] *= scale // X rotation
|
|
963
|
+
floatArray[2] *= scale // X Z-component
|
|
964
|
+
floatArray[3] *= scale // X translation
|
|
965
|
+
floatArray[4] *= scale // Y rotation
|
|
966
|
+
floatArray[5] *= scale // Y scale
|
|
967
|
+
floatArray[6] *= scale // Y Z-component
|
|
968
|
+
floatArray[7] *= scale // Y translation
|
|
969
|
+
floatArray[8] *= scale // Z X-component
|
|
970
|
+
floatArray[9] *= scale // Z Y-component
|
|
971
|
+
floatArray[10] *= scale // Z scale
|
|
972
|
+
floatArray[11] *= scale // Z translation
|
|
973
|
+
|
|
974
|
+
let mvp = matrix_float4x4(
|
|
975
|
+
SIMD4<Float>(floatArray[0], floatArray[1], floatArray[2], floatArray[3]),
|
|
976
|
+
SIMD4<Float>(floatArray[4], floatArray[5], floatArray[6], floatArray[7]),
|
|
977
|
+
SIMD4<Float>(floatArray[8], floatArray[9], floatArray[10], floatArray[11]),
|
|
978
|
+
SIMD4<Float>(floatArray[12], floatArray[13], floatArray[14], floatArray[15])
|
|
979
|
+
)
|
|
980
|
+
|
|
981
|
+
// Add depth state
|
|
982
|
+
let depthStencilDescriptor = MTLDepthStencilDescriptor()
|
|
983
|
+
depthStencilDescriptor.depthCompareFunction = .always
|
|
984
|
+
depthStencilDescriptor.isDepthWriteEnabled = false
|
|
985
|
+
let depthStencilState = device.makeDepthStencilState(descriptor: depthStencilDescriptor)
|
|
986
|
+
|
|
987
|
+
encoder.setRenderPipelineState(pipeline)
|
|
988
|
+
encoder.setDepthStencilState(depthStencilState!)
|
|
989
|
+
encoder.setVertexBuffer(vertices, offset: 0, index: 0)
|
|
990
|
+
encoder.setVertexBytes([mvp], length: MemoryLayout<matrix_float4x4>.size, index: 1)
|
|
991
|
+
|
|
992
|
+
var mutableUniforms = uniforms
|
|
993
|
+
encoder.setFragmentBytes(&mutableUniforms, length: MemoryLayout<FragmentUniforms>.stride, index: 0)
|
|
994
|
+
encoder.setFragmentTexture(dataTex, index: 0)
|
|
995
|
+
encoder.setFragmentTexture(colormapTex, index: 1)
|
|
996
|
+
encoder.setFragmentSamplerState(dataSamplerState, index: 0)
|
|
997
|
+
encoder.setFragmentSamplerState(colormapSamplerState, index: 1)
|
|
998
|
+
|
|
999
|
+
encoder.drawIndexedPrimitives(type: .triangle, indexCount: indexCount, indexType: .uint16, indexBuffer: indices, indexBufferOffset: 0)
|
|
1000
|
+
|
|
1001
|
+
encoder.endEncoding()
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
deinit {
|
|
1005
|
+
print("🔴 [GridRenderLayer] deinit called for layer: \(id)")
|
|
1006
|
+
|
|
1007
|
+
// Clean up all resources
|
|
1008
|
+
frameCache.removeAll()
|
|
1009
|
+
vertexBuffer = nil
|
|
1010
|
+
indexBuffer = nil
|
|
1011
|
+
dataTexture = nil
|
|
1012
|
+
colormapTexture = nil
|
|
1013
|
+
device = nil
|
|
1014
|
+
commandQueue = nil
|
|
1015
|
+
pipelineState = nil
|
|
1016
|
+
dataSamplerState = nil
|
|
1017
|
+
colormapSamplerState = nil
|
|
1018
|
+
|
|
1019
|
+
// Break the reference cycle
|
|
1020
|
+
hostWrapper = nil
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
internal func internalRenderingWillEnd() {
|
|
1024
|
+
print("🟢 [GridRenderLayer] renderingWillEnd called")
|
|
1025
|
+
vertexBuffer = nil
|
|
1026
|
+
indexBuffer = nil
|
|
1027
|
+
dataTexture = nil
|
|
1028
|
+
colormapTexture = nil
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
extension GridRenderLayer {
|
|
1033
|
+
// Override to prevent KVC crashes during cleanup
|
|
1034
|
+
open override func value(forUndefinedKey key: String) -> Any? {
|
|
1035
|
+
print("⚠️ [GridRenderLayer] Attempted to access undefined key: \(key)")
|
|
1036
|
+
return nil
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
open override func setValue(_ value: Any?, forUndefinedKey key: String) {
|
|
1040
|
+
print("⚠️ [GridRenderLayer] Attempted to set undefined key: \(key)")
|
|
1041
|
+
// Silently ignore instead of crashing
|
|
1042
|
+
}
|
|
1043
|
+
}
|